Wrapper une application Zend 1 dans Symfony2

Et non le blog n’est pas mort ;)
Pour ceux qui auraient loupé un épisode, j’ai changé en début d’année de boulot pour retrouver le monde du PHP à 100%. Nouvelles têtes, nouveaux locaux, nouveau projet et forcément nouvelle plateforme… en Zend.
Il y a 5 ans, c’était un choix qui se discutait, mais aujourd’hui la plateforme a force d’évolution mérite sincèrement une grosse remise à plat, dans tous les sens du terme. C’est donc l’occasion pour repartir sur … du Symfony2 of course : )
Même si on me fait confiance sur cette décision, forcément on va pas arrêter de mettre à jour la plateforme actuelle sous prétexte qu’il faut passer sur Symfony.
Me voici en piste pour trouver la meilleur solution pour faire ça en douceur. L’idée des component Symfony arrive forcément très vite dans mon esprit. Je test avec le composant « Command », une formalité effectivement. Mais, autant, je vois bien le principe de migrer une appli PHP classique vers les components Symfony, autant, partir de Zend me semble pas si trivial.
Je me suis alors rappelé une présentation lors du symfony live 2011 de Marc Weistroff (aka futurecat) qui avait utiliser Symfony2 pour intégrer la possibilité d’utiliser des ESI dans une app symfony.
Me voici parti avec l’idée d’embarquer mon application Zend actuelle, dans une nouvelle appli Symfony2. L’appli Symfony2 serait donc l’application « master » qui lancerait l’appli Zend quand elle ne saurait pas répondre à une requête. Dans un premier temps d’ailleurs, l’appli Zend sera lancé dans tous les cas et l’appli Symfony2 ne prendra le relai que sur les pages ne répondant pas un code http 200.
Voici le principe grosso modo que j’ai utilisé:
On place un listener sur kernel.request avec une priorité suffisante pour prendre le dessus sur le routing Symfony.
parameters:
atipik_zend_wrapper.class: Atipik\ZendWrapperBundle\HttpKernel\ZendListener
services:
atipik_zend_wrapper.listener.request:
class: %atipik_zend_wrapper.class%
arguments: [%kernel.root_dir%]
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest, priority: 254 }Le listener en question qui finalement ne fait qu’instancier mon wrapper, lance la requête et retourne une Response si on a un code HTTP 200.
<?php namespace Atipik\ZendWrapperBundle\HttpKernel; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpFoundation\Response; class ZendListener { public $root_dir; public function __construct($root_dir) { $this->root_dir = $root_dir; } public function onKernelRequest(GetResponseEvent $event) { $applicationZend = new ZendWrapper(realpath($this->root_dir.'/../vendor/cityzen/www/application')); $response = $applicationZend->dispatch(); if ($response->getHttpResponseCode() == 200) { $event->setResponse(new Response($response)); } } }
Et le wrapper, qui reprend en fait le index.php de mon appli zend (pas écrit par moi, me demander à quoi ça sert :D). Au préalable j’ai bien sur mis dans vendor le code de mon app Zend, et autoloadé le prefixe Zend:
<?php namespace Atipik\ZendWrapperBundle\HttpKernel; class ZendWrapper { public $application, $bootstrap, $response; public function __construct($application_path) { if (!defined('APPLICATION_PATH')) { define('APPLICATION_PATH', $application_path); } if (!defined('APPLICATION_ENV')) { define('APPLICATION_ENV', 'development'); } if (!defined('APPLICATION_PARTNER')) { define('APPLICATION_PARTNER', 'cityzenbox'); } if (!defined('DISPLAY_ERRORS')) { define('DISPLAY_ERRORS', false); } set_include_path(implode(PATH_SEPARATOR, array( dirname(APPLICATION_PATH) . '/library', get_include_path() ))); $this->init(); } public function init() { $this->application = new \Zend_Application( APPLICATION_ENV, APPLICATION_PATH . '/config/config.php' ); $this->bootstrap = $this->application->bootstrap()->getBootstrap(); $this->front = $this->bootstrap->getResource('FrontController'); $default = $this->front->getDefaultModule(); if (null === $this->front->getControllerDirectory($default)) { throw new Zend_Application_Bootstrap_Exception( 'No default controller directory registered with front controller' ); } $this->front->setParam('bootstrap', $this->bootstrap); } public function dispatch() { $this->front->returnResponse(true); return $this->front->dispatch(); } }
Et là, on peut désormais voir notre site, avec la débug bar Symfony !

Au final, cela un reste un Proof of Concept, et ce n’est pas la solution retenue. Du coup, on peut envisager de pousser plus loin, en alimentant la débug bar avec les infos de Zend.
Mais c’est toujours intéressant (de mon point de vue) de voir avec quelle facilité Symfony2 peut-être utilisé avec n’importe quelle type d’application désormais. La souplesse c’est sans doute ça qui fait aujourd’hui le succès de Symfony, nan ?
Note : Le code date de Avril et donc de Symfony 2.0.12
Tags: PHP, symfony2, wrapper, zend
2 Réponses
Laisser un message

Bonjour,
je suis curieux de connaître la solution employé finalement (à moins qu’il ne soit plus question de Symfony 2).
Pour ma part, cette solution ne colle pas à mon projet qui est d’intégrer une appli php « procédurale » (sans urlrewrite ni bootstrap) dans un projet Symfony 2.
J’ai rajouté quelques tours de passe-passe dans le .htaccess pour avoir l’impression d’être dans la même appli et surtout j’ai utilisé une directive prepend pour faire le pont avec sf2.
Je me demandais s’il y avait encore d’autres manières de faire des crossover entre applications ?
[...] ne pas essayer ZendWrapperBundle ? Mon application est un peu « oldschool » en php [...]