📜 ⬆️ ⬇️

How to make framework-independent controllers?

Controllers are generally considered to be the most related classes in an application. As a rule, based on the request data, they receive or save the data in a database, then convert the data or the result of saving into HTML, which acts as a response to the client who made the request.

It turns out that the controllers are everywhere, they connect those parts of the application that are usually quite independent of each other. This greatly increases the connectedness of the controllers: among their dependencies is the Doctrine entity manager, Twig template engine, the base controller from the FrameworkBundle, and so on.

In this post I will show that this level of connectedness is completely unnecessary. I'll show you how to significantly reduce connectivity by taking just a few simple steps. As a result, we get a controller that can be reused in different types of applications, for example, based on Silex or even Drupal.

Part I: Do not use standard controllers.


')
Excessive Connectivity: Inheritance from the Base Controller

Basically, the controller classes that I come across inherit from the Controller class from the FrameworkBundle:

use Symfony\Bundle\FrameworkBundle\Controller\Controller; class MyController extends Controller { ... } 


The base controller class adds several useful shortcuts, such as createNotFoundException () and redirect (). It also automatically makes your controller the successor of ContainerAware (“aware” of the container), as a result of which the Dependency Injection Container (DIC) will be automatically injected into the controller. From the container you can get any service you need.

Do not use helper methods!

All this, of course, seems very convenient, but if a little less lazy, you can significantly reduce connectivity. There is nothing wrong with throwing out these auxiliary methods: the bodies of most of them still consist of just one line (look at the basic controller to see what is really happening there!). You can easily replace calls to these methods with a code of them:

 class MyController extends Controller { public function someAction() { // : throw $this->createNotFoundException($message); // : throw new NotFoundHttpException($message); } } 


Use dependency injection

If you no longer use helper methods from the parent class of the controller, then you can take another step to get rid of this unnecessary inheritance. Instead of getting the dependencies from the container, inject them manually in the constructor:

 class MyController extends Controller { public function someAction() { $this->get('doctrine')->getManager(...)->persist(...); } } //  : use Doctrine\Common\Persistence\ManagerRegistry; class MyController extends Controller { public function __construct(ManagerRegistry $doctrine) { $this->doctrine = $doctrine; } public function someAction() { $this->doctrine->getManager(...)->persist(...); } } 


Make your controller a service.

You also need to make sure that the new controller service is assembled not just by calling the new operator, as the ControllerResolver normally does, and all dependencies of your controller are correctly injected. To do this, you need to declare the service:

 services: my_controller: class: MyController arguments: - @doctrine 

And the routing settings also need to be corrected. If you use annotations:

 /** * @Route(service="my_controller") */ class MyController extends Controller { ... } 

And if your routing is saved in a YML configuration file:

 my_action: path: /some/path defaults: _controller: my_controller:someAction 


Finally, it is no longer necessary to inherit from the standard symphony controller, we also do not need the controller to know anything about the DI container, since all its dependencies are injected into the arguments of the constructor. And we are no longer dependent on the helper methods of the base class, which means that now we can finally remove the extends Controller along with the use-expression from the class declaration of our controller:

 class MyController { } 


This is how we get a lot of bonus points for unlinked code!

In the next post we will talk about annotations and how our code will become even less related if we get rid of them.

Source: https://habr.com/ru/post/227781/


All Articles