Migrating Silex Middlewares to Symfony

Silex middlewares are lightweight event listeners that allow developers to run code before or after the request is processed by the controller. Symfony does not have that feature, so before we can migrate our Silex application to Symfony, we need to refactor middlewares into something Symfony understands.


Note: This is part one of a series on articles on migrating Silex applications to Symfony. Other parts:


Middlewares might be a Silex-only feature, but under the hood, they are executed as event listeners. In fact, Silex even uses the same core events as full-stack Symfony. This is why we can replace middlewares with equivalent event subscribers that will work in Silex and Symfony alike.

Event Listeners vs. Event Subscribers

Silex middlewares just like event listeners in Symfony are simple callables, that are registered for a specific event. Neither the middleware nor the event listener “knows” what event they listen on. That information has to be provided on registration.

Event subscribers on the other hand implement a static method that returns that configuration. In other words, they configure themselves upon registration. When switching over to Symfony, we can directly reuse a subscriber without the need of migrating any configuration for it. This is why I suggest to turn all middlewares into event subscribers.

Application Middlewares

Application middlewares are easy to migrate. They are registered by passing a callable to one of the following methods of the Application instance: before(), after()and finish(). The corresponding kernel events are: kernel.request, kernel.response and kernel.terminate.

Note that middlewares are only executed on the master request wheras the first two event types are triggered on sub-requests as well. If you don’t want your new subscriber to execute on sub-requests, you specifically need to catch that case.

Silex wraps our middleware before passing it to the event dispatcher. The wrapper maps properties like request and response of the event object to parameters of the middleware. Our new event subscriber will receive the original event object instead.

Inside a before middleware, Silex allows us to “short-circuit the request handling” by returning a Response object. We can achieve the same effect by simply setting the response on the event object instead.

Inside an after middleware we can replace the response by returning a new one. An equal event subscriber would again set the response on the event instead.

Examples of how application middlewares are migrated can be found in OpenCFP pull requests #871 and #887.

Route Middlewares

Route middlewares are a bit tricky. They are registered by calling before() and after() on a route instead of the Application instance. Route middlewares are registered on the same events as their application counterparts, but they are only executed if the route they have been registered on was matched! Also, the event priorities are hardcoded for route middlewares.

To simulate that behavior, we can simply replace the before()/after() call with value('some_attribute', true). This way, the router will set an attribute some_attribute on the request. Your event subscriber can check for this attribute to determine whether it should be executed or not. Alternatively, you could as well check the attribute _route which should contain the name of the matched route.

For an example on how a route middleware is migrated, have a look at OpenCFP pull requests #867 and #888.

Other Event Listeners

The Application class also offers the methods on(), error() and view() to register callables as event listeners. The event registration here is pretty straightforward. There is no fancy wrapper logic applied to the callable.

OpenCFP pull request #866 is an example of how an error listener is converted into an event subscriber.

tl;dr

Silex’ middlewares are a handy feature to run code before or after a controller is executed. Symfony does not have that feature, so we refactor middlewares into event subscribers that are compatible with both frameworks.

Like what you read? Give Alexander M. Turek a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.