Wrap up your legacy application with Symfony
Kinga Sziliagyi3 min read
At Theodo we have had several projects consisting of adding new features to an existing PHP code using Symfony1, CodeIgniter or homemade frameworks.
Rewriting these applications from scratch would be very costly and dangerous for the businesses. Therefore, we prefer
embedding the legacy code in a full-stack Symfony2 project.
By doing so we can write the new features in a the Symfony application and, if needed, migrate legacy code gradually.
Theodo Evolution
The principle is quite simple:
- let Symfony return a response to the incoming request
- if there is no matching route, delegate the request to the legacy application
- and, if still no matching, return a 404 response
Theodo Evolution is a set of tools combining the practices we have been using for several years to extend legacy applications.
In the rest of this article, I will provide a brief introduction to this bundle.
Overriding the RouterListener
Theodo Evolution interferes by overriding Symfony’s RouterListener
:
namespace Theodo\Evolution\Bundle\LegacyWrapperBundle\DependencyInjection\Compiler;
class ReplaceRouterPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
if ($container->hasDefinition('theodo_evolution_legacy_wrapper.router_listener')) {
$routerListener = $container->getDefinition('router_listener');
$definition = $container->getDefinition('theodo_evolution_legacy_wrapper.router_listener');
$definition->replaceArgument(1, $routerListener);
$container->setAlias('router_listener', 'theodo_evolution_legacy_wrapper.router_listener');
}
}
}
This custom RouterListener
starts by delegating the request handling to Symfony’s RouterListener
.
If the request does not match any controller, the legacy listener catches the NotFoundHttpException
and asks the LegacyKernel
to handle it:
namespace Theodo\Evolution\Bundle\LegacyWrapperBundle\EventListener;
class RouterListener implements EventSubscriberInterface
{
public function onKernelRequest(GetResponseEvent $event)
{
try {
$this->routerListener->onKernelRequest($event);
} catch (NotFoundHttpException $e) {
if (null !== $this->logger) {
$this->logger->info('Request handled by the '.$this->legacyKernel->getName().' kernel.');
}
$response = $this->legacyKernel->handle($event->getRequest(), $event->getRequestType(), true);
if ($response->getStatusCode() !== 404) {
$event->setResponse($response);
return $event;
}
}
}
}
LegacyKernel
Symfony’s Kernel
is an implementation of the HttpKernelInterface
and therefore has to be able to tell how to transform an incoming Request
to a Response
object.
The same is true for the LegacyKernel
. In addition, the LegacyKernel
should also know how to autoload the legacy application.
(For detailed information on autoloading take a look at the autoloading guide)
If your are about to wrap a Symfony 1.4 or a CodeIgniter application you are lucky, Theodo Evolution provides you an extension of the abstract LegacyKernel
class.
Otherwise it’s your job to implement the boot and handle functions. Before you start, have a look at the Symfony14Kernel
and CodeIgniterKernel classes.
As I said, the basic idea is quite simple: if Symfony cannot handle the incoming request let your legacy application take care of it.
However, in practice there is lot to do:
Autoloading, sharing the authentication and the database, managing legacy assets, harmonizing the layout, routing between the two applications, etc.
More about these topics soon!