Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Create Symfony apps as quickly as with Laravel, keep your code framework-agnostic

Create Symfony apps as quickly as with Laravel, keep your code framework-agnostic

Slides of my talk at AFUP's Forum PHP 2016.

You’ll learn about RAD and autowiring, the ADR pattern, framework agnostic controllers, PSR-7, PSR-15 and PSR-17.

Kévin Dunglas

October 28, 2016

More Decks by Kévin Dunglas

Other Decks in Programming


  1. Symfony controllers, redesigned

  2. Kévin Dunglas •Founder of Les-Tilleuls.coop •Symfony Core Team member •API

    Platform creator •Teacher at the University of Lille 1 @dunglas
  3. Les-Tilleuls.coop •Self-managed company since 2011 •100% owned by employees •All

    benefits are equitably shared between employees •18 people, 137% growth in 2015 •We are hiring! => jobs@les-tilleuls.coop
  4. What is a Controller?

  5. By Martin Fowler http://www.martinfowler.com/eaaCatalog/modelViewController.html

  6. None
  7. The Symfony Book « A controller is a PHP function

    […] that reads information from the Symfony's Request object and creates and returns a Response object. »
  8. github.com/dunglas/forumphp2016

  9. This is Not a Controller

  10. None
  11. Rethinking Controllers… But Why?!

  12. Controllers are Too Fat •Tend to put Domain / business

    logic in the controller (bad practice) Creating services requires some Symfony skills •Methods with too much lines of code (#previousLine) •Bloated controller classes with a lot of methods •Duplicated code (e.g. to generate a Response with HTTP headers, to call the view…)
  13. None
  14. Controllers break OOP Best Practices •Magic and implicit •Container aware:

    no explicit dependencies •Hard to write SOLID controller classes •Hard to unit test controller classes •God objects (too much dependencies) Some people say « it’s OK for controllers »
  15. None
  16. Controllers are Coupled to SF It matters only for library

    developers: •Hard to reuse controller classes across projects •Cannot work with several frameworks •Cannot be distributed as standalone libs •Don’t support « standards » (PSR-7, PSR-15, PSR-17)
  17. None
  18. The ADR Pattern

  19. The ADR pattern •Stand for Action-Domain-Responder •Web-specific refinement of MVC

    •A partial solution to previous problems https://github.com/pmjones/adr
  20. The ADR pattern •Action: Connects Domain and Responder. Uses the

    request input to interact with the Domain, passes the Domain output to the responder. •Domain: The app’s business logic. Modifies states, persistence. Manipulates session and env data. •Responder: Build an HTTP response. Body content, templates, views, cookies, status code and so on.
  21. Implementing ADR in a Symfony app

  22. App’s Structure: Separating the Business Logic

  23. Action

  24. Action

  25. Responder

  26. Domain: Manager

  27. Domain: Manager

  28. Domain: Exception

  29. Domain: Notifier

  30. Services Registration

  31. Routing Configuration (Invokable Controller as a Service)

  32. Doctrine Configuration

  33. Pros •Better design and structure (= easier maintenance and better

    adaptability) •Easier to unit test (including actions and responders, thanks to explicit dependencies) •All chunks of code are independently reusables •No more duplicated code (e.g. headers) •Agnostic of the (full stack) framework: classes depend only of components (standalone libs)
  34. Cons •Worst DX: lot of configuration files (YAML or XML)

    •Harder to refactor (RAD, prototyping…): require to update the config all the time •Mandatory Symfony skills: DIC configuration, controllers as a services, YAML/XML routing…
  35. Autowired (Controllers as) Services

  36. The DIC Autowiring Subsystem •Guesses, builds and injects automatically dependencies

    of a service using PHP’s reflection API •If a service of the given type exists: it is injected •If it doesn’t exist: it is created then injected •Allows to map an interface to a default implementation •SF 2.8+, will support method injection in 3.2 •No performance impact at runtime
  37. Services Registration

  38. Services Registration: Using Autowiring

  39. A Better Developper eXperience •As easy as the the full

    stack framework’s base controller •No need for magic proxy methods (getDoctrine(), json()…) •Easier refactoring: create new classes, add new dependencies, they are automatically built and injected with 0 config (Laravel-like)
  40. Going Further with ActionBundle github.com/dunglas/DunglasActionBundle

  41. The Action Bundle •« Replacement » for the whole Symfony

    controller layer: actions, commands, event subscribers •Action classes, commands and subscribers are automatically registered as services •Autowiring is on for all those services •Configurable (scanned directories, interfaces, tags…) •250 lines of code for 180 GitHub stars (best ratio ever)
  42. Install composer require dunglas/action-bundle

  43. Configuring Only necessary because action classes are not in a

  44. Update the Routing Config…

  45. … or use Annotations

  46. No Service Registration Required!

  47. The Action Bundle Included by default in API Platform 2

    And maybe in a future Symfony version?
  48. Bonus: PSR-7 and PSR-17 compatibility

  49. PSR-7 and PSR-17 • PSR-7: HTTP Message Interface • PSR-17:

    HTTP Factories composer require symfony/psr-http-message-bridge zendframework/zend-diactoros http-interop/http-factory:dev-master http-interop/http-factory-diactoros:dev-master
  50. Register HTTP Factories

  51. Update the Action

  52. Update the Responder

  53. Bonus: PSR-15 compatibility

  54. PSR-15: HTTP Middlewares Schema by Slim framework

  55. PSR-15 composer require http-interop/http-middleware:dev-master

  56. Update the Action

  57. Update the Action

  58. Update the Responder

  59. Update the Responder

  60. Summary • Controller Autowiring and the Action Bundle improve the

    DX and ease the refactoring • ADR gives more structure to your app and is better from a design point of view • If you are a library developper, you can create standalone, framework agnostic actions working with Symfony and using PSR-7-15-17
  61. Thanks! Any questions? https://joind.in/talk/6472b github.com/dunglas @dunglas