Back to Home

PaEndpointBundle - An Alternative to Symfony Controllers

php · symfony · bundle

PaEndpointBundle - An Alternative to Symfony Controllers

    The primary way to handle requests in Symfony is through controllers . With the ability to describe routing directly in controllers (annotations), life has become even better. But the use of annotations in the inheritance of controllers causes problems - for each child controller it is necessary to re-register the routing. But in a crud application, a situation is typical when there is a base controller and many daughter ones that inherit the logic of the base controller, and routes for which could be generated automatically.

    An attempt to improve the standard Symfony controllers was DunglasActionBundle. This bundle assumes that the controller has only one __invoke () method, which allows you to use the class name as the name of the route, which is very convenient. For example, you can generate url as follows:

    $route->generate(MyController::class, ['paramName' => 'value']);
    

    But this bundle does not solve the problem of controller inheritance. Therefore, our own bundle was written that solves all these problems - PaEndpointBundle. Bundle

    features:

    • Simple controller interface - only one execute (Request $ request) method: Response
    • Convenient url generation by class name - $ router-> url (SomeEndpoint :: class)
    • Convenience of refactoring - when renaming or moving the controller, no additional actions are required, for example, changing the name of the route
    • No need to specify the name of the route (but you can if necessary)

    The main concept of the bundle is Endpoint - the entry point to the application (in the terminology of symfony - a controller with a single action). An example of a simple Endpoint:

    use PaLabs\EndpointBundle\EndpointInterface;
    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpFoundation\Response;
    class TextEndpoint implements EndpointInterface {
        public function routes()
        {
           return new Route('/cool_message');
        }
        public function execute(Request $request): Response
        {
           return new Response('Hello, world');
        }
    }
    

    This endpoint processes requests at your.server / cool_message and returns a response with the text 'Hello, world'.

    For endpoint to work, just register it as a service in symfony. You don’t need to do anything else - the bundle itself will detect the endpoint and add its routes to the general list of application routes.

    If necessary, set your own name for the route, this can be done as follows:

    public function routes()
        {
           return new EndpointRoute('my_route_name', new Route('/cool_message'));
        }
    

    , after which it can be used with a standard symfony router, or in templates.

    Since the routes () method in endpoint is a regular class method, it can use any logic to generate routes, for example, generate routes depending on some system settings, enable or disable routes as needed, create a collection of routes.

    The class EndpointRouter is used to generate urls . Usage example:

    class SomeService { 
      protected $router;
      public function __construct(EndpointRouter $router) {
        $this->router = $router;
      }
      public function doWork() {
        // ...
        $url = $endpointRouter->url(TextEndpoint::class);
      }
    }
    

    Even if a custom route name was specified in TextEndpoint, $ router-> url (TextEndpoint :: class) will still work. This is achieved by caching routes. Of course, if more than one route was specified for the endpoint, it will not work to generate a url by class name and you will have to use the name of the route.

    Examples of using bundles can be found in the demo application .
    I hope that PaEndpointBundle or its ideas will be useful to symfony developers.

    Read Next