
J'ai le plaisir de vous annoncer que j'animerai deux conférences sur Symfony 2 aux RMLL 2010, qui se déroulent à Bordeaux en Juillet :
Pour plus d'infos sur les RMLL, c'est par ici : http://2010.rmll.info/
Aller au contenu Aller au menu
mercredi, avril 7 2010
Par Noël GUILBERT le mercredi, avril 7 2010, 09:40

J'ai le plaisir de vous annoncer que j'animerai deux conférences sur Symfony 2 aux RMLL 2010, qui se déroulent à Bordeaux en Juillet :
Pour plus d'infos sur les RMLL, c'est par ici : http://2010.rmll.info/
dimanche, février 21 2010
Par Noël GUILBERT le dimanche, février 21 2010, 16:05

Attention : la version actuelle du Symfony 2 est une "preview" : les choses vont changer. Cette article est donc une découverte du framework tel qu'il a été présenté lors du Symfony Live 2010.
Lors du Symfony Live 2010, Fabien Potencier a révélé la toute nouvelle version du framework : Symfony 2 (avec un "S" majuscule la v2).
Pour l'occasion, j'ai pu essayer et mettre en place quelques briques de code, notamment une version adaptée du tutorial "Easy-Ajax" de symfony (avec un "s" minuscule pour les version 1.x).
Il est donc temps de vous raconter comment Symfony fonctionne. Dans ce billet, j'utiliserai le code de l'application Shopping Cart, disponible sur github : http://github.com/noelg/symfony-demo.
Avec symfony 1.x, la structure d'un projet est assez riche : apps, cache, data, config, lib, plugins, web. Avec Symfony 2, c'est beaucoup plus simple:
Dans l'application "Shopping Cart", nous trouvons deux front-controllers dans le répertoire web/ :
Comme avec symfony 1, ils contiennent le code nécessaire pour initialiser le framework:
<?php
require_once __DIR__.'/../cart/CartKernel.php';
$kernel = new CartKernel('dev', true);
$kernel->run();
Le code est assez simple :
Le Kernel, avec Symfony 2, est l'endroit où l'ensemble de l'application est configurée :
L'autoloading est simplement chargé grâce au fichier autoload.php prévu à cet effet :
<?php
require_once __DIR__.'/../src/autoload.php';
Ce fichier est lui-même assez simple à comprendre:
<?php
require_once __DIR__.'/vendor/symfony/src/Symfony/Foundation/UniversalClassLoader.php';
use Symfony\Foundation\UniversalClassLoader;
$loader = new UniversalClassLoader();
$loader->registerNamespaces(array(
'Symfony' => __DIR__.'/vendor/symfony/src',
'Application' => __DIR__,
'Bundle' => __DIR__,
'Doctrine' => __DIR__.'/vendor/doctrine/lib',
));
$loader->registerPrefixes(array(
'Swift_' => __DIR__.'/vendor/swiftmailer/lib/classes',
'Zend_' => __DIR__.'/vendor/zend/library',
));
$loader->register();
// for Zend Framework & SwiftMailer
set_include_path(__DIR__.'/vendor/zend/library'.PATH_SEPARATOR.__DIR__.'/vendor/swiftmailer/lib'.PATH_SEPARATOR.get_include_path());
On utilise ici la classe UniversalClassLoader, qui est une implémentation permettant de charger les classes respectant:
Deux méthodes sont appellées :
Si vous voulez ajouter des bibliothèques, vous devrez sans doute modifier ce fichier.
Dans Symfony 2, un bundle est l'équivalent de "plugin" avec symfony 1. Les bundles utilisés par l'application sont définis par la méthode registerBundles():
<?php
/* ... */
class CartKernel extends Kernel
{
/* ... */
public function registerBundles()
{
return array(
new Symfony\Foundation\Bundle\KernelBundle(),
new Symfony\Framework\WebBundle\Bundle(),
new Symfony\Framework\ZendBundle\Bundle(),
new Symfony\Framework\SwiftmailerBundle\Bundle(),
new Symfony\Framework\DoctrineBundle\Bundle(),
new Bundle\CartBundle\Bundle(),
);
}
}
Dans cette application, plusieurs bundles sont utilisés:
Deux autres méthodes sont définies pour configurer le routing et l'injecteur de dépendances :
public function registerContainerConfiguration()
{
$loader = new ContainerLoader($this->getBundleDirs());
return $loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml');
}
public function registerRoutes()
{
$loader = new RoutingLoader($this->getBundleDirs());
return $loader->load(__DIR__.'/config/routing.yml');
}
Encore une fois, le code est facile à comprendre, il n'y a rien de magique : on charge les fichiers config_*.yml et routing.yml. Et comme leur noms l'indiquent, ils permettent de configurer l'application et le routing.
kernel.config: ~
web.web: ~
web.templating: ~
web.user:
class: Bundle\CartBundle\User
Avec symfony 1, les fichiers de configuration sont plus nombreux (settings.yml, app.yml, factories.yml, filters.yml, etc), et nécessitent un peu de connaissance dès lors qu'on souhaite les customiser. Avec Symfony 2, un seul fichier : config.yml.
homepage:
pattern: /
defaults: { _bundle: WebBundle, _controller: Default, _action: index }
cart:
resource: CartBundle/Resources/config/routing.xml
Le fichier routing.yml est similaire à ce que l'on trouve dans symfony 1. La seule différence est dans le nommage des paramètres. Une fonctionnalité supplémentaire est de pouvoir charger un fichier de routing externe. C'est le cas ici, où l'on charge le fichier de routing du bundle CartBundle.
Un bundle, je l'ai dis plus tôt, est un "plugin". La différence majeure avec symfony 1, c'est qu'ils ont une place de premier choix dans Symfony 2 : tout est bundle, et tout doit être dans un implémenté dans un bundle. Plusieurs types de bundles sont possibles :
La structure d'un bundle est la suivante:
Rappelez-vous, les bundles sont initialisés dans le kernel :
<?php
/* ... */
class CartKernel extends Kernel
{
/* ... */
public function registerBundles()
{
return array(
/* ... */
new Bundle\CartBundle\Bundle(),
);
}
}
Avec Symfony 2, tout est explicite. La configuration du bundle se fait donc dans cette classe. Par exemple, le bundle "WebBundle" de Symfony implémente une méthode buildContainer() pour étendre l'injecteur de dépendance :
# src/vendor/symfony/src/Symfony/Framework/WebBundle/Bundle.php
class Bundle extends BaseBundle
{
public function buildContainer(ContainerInterface $container)
{
Loader::registerExtension(new WebExtension());
$dirs = array('%kernel.root_dir%/views/%%bundle%%/%%controller%%/%%name%%%%format%%.php');
foreach ($container->getParameter('kernel.bundle_dirs') as $dir)
{
$dirs[] = $dir.'/%%bundle%%/Resources/views/%%controller%%/%%name%%%%format%%.php';
}
$container->setParameter('templating.loader.filesystem.path', $dirs);
}
}
Symfony est un framework MVC (enfin, presque). On trouve donc plusieurs éléments :
Les contrôleurs doivent être placés das le répertoire Controllers du bundle, et les méthodes d'action doivent être suffixées par "Action". Avec symfony 1, elles sont préfixées par "execute".
Voici un extrait du contrôleur CartController du bundle CartBundle:
# src/Bundle/CartBundle/Controller/CartController.php
namespace Bundle\CartBundle\Controller;
use Symfony\Framework\WebBundle\Controller;
use Bundle\CartBundle\Model\Product;
class CartController extends Controller
{
public function indexAction()
{
return $this->render('CartBundle:Cart:index', array(
'products' => Product::findAll(),
'cart' => $this->getUser()->getCart()
));
}
/* ... */
}
Dans le répertoire "Resources" d'un bundle, on peut avoir plusieurs répertoires:
Une attention particulière a été apporté sur la facilité d'approche du framework. Pour cela, beaucoup de choses "magiques" avec symfony 1, sont désormais explicites : l'appréhension d'une application Symfony est donc beaucoup plus facile. De plus, grâce à ce tutorial, vous pourrez apprendre à l'utiliser en quelques dizaines de minutes. Je vous invite également à jeter un oeil au code de l'application Shopping Cart.