Développer mieux en
PHP avec
HugoHamon-ForumPHPAFUP2010–Paris–10/11/2010
Qui  suis-­‐‑je  ?	
v  Hugo HAMON (@hhamon)
v  Responsable des formations à
v  Premiers pas avec PHP en 2002
v  Secrétaire de l’AFUP
v  Auteur du site Apprendre-PHP.com
v  Coauteur & contributeur à des ouvrages Eyrolles
Symfony, un framework
professionnel !
Le projet symfony…
symfony 1.0 symfony 1.1 symfony 1.4 Symfony 2.0
License MIT
Version actuelle 1.0.22 1.1.9 1.4.8 2.0.0 - PR
Date de sortie Octobre 2005 Juin 2008 Novembre 2009 Mars 2011
Support Terminé Terminé Fin 2012 ?
Stabilité Stable Stable Stable Presque stable
Production Oui Oui Oui Bientôt
Documentation Oui Oui Oui En cours
Ø  Documentation Open-Source
Ø  API stable et fiable
Ø  Communauté active
Ø  Plugins Open-Source
Ø  Développeurs sur le marché
Ø  Formation & Consulting
Un  riche  écosystème
Ils  utilisent  symfony
Résoudre les
problématiques du
développement web.
Industrialiser les développements1.
Industrialiser	
§ Développer plus vite
§ Développer mieux
§ Réduire les coûts de développement
§ Favoriser la réutilisabilité du code
§ Simplifier les opérations de maintenance
§ Simplifier les déploiements
Coût  de  développement	
Dv	
T	
$	
Dev
Test
Coût  de  maintenance	
C	
M	
T	
D	
$$$	
Compréhension
Test
Déploiement
Modification
Coût	
Développement	
$	
Coût	
Maintenance	
$$$	
Compréhension	
Correction	
Test	
Déploiement	
Développement	
Test
Objectifs  ?	
Moins  de  
Code	
Moins  de  
complexité	
Moins  de  
bogues	
Plus  de  
Productivité	
Plus  de  
temps
Automatiser  des  tâches  pénibles
Déboguer  plus  vite	
Web DebugToolbar
² Requêtes SQL
² Logs
² Variables d’environnement ($_GET, $_POST, $_COOKIE…)
² Configuration de PHP
² Timers
² Variables de configuration de Symfony
Stack traces
Déboguer  plus  vite  (Symfony2)	
Profiler
Journalisation  des  logs	
² Requêtes SQL, en-têtes envoyés, exceptions attrapées…
Simplifier  les  déploiements	
$ php symfony project:deploy production --go
[production]
host=123.456.7.8
user=hhamon
port=22
path=/var/www/www.monsite.com
Déploiement automatisé avec une connexion SSH + RSYNC
Configuration des serveurs de déploiement dans un fichier INI
Favoriser le travail en équipe2.
Arborescence  connue	
$ tree -L 1 -F
.
|-- apps/
|-- cache/
|-- config/
|-- data/
|-- lib/
|-- log/
|-- plugins/
|-- symfony*
|-- test/
`-- web/
9 directories, 1 file
q  Applications
q  Cache
q  Configuration globale
q  Données du projet
q  Classes PHP
q  Journaux de logs
q  Plugins installés
q  Tests automatisés
q  Fichiers publics
Conventions  de  codage	
q  Nommage des fichiers
q  Nommage des variables
q  Philosophie de codage
q  Même outillage pour tout le monde
Architecture  MVC
# apps/frontend/modules/post/actions/actions.class.php
class postActions extends sfActions
{
public function executeIndex(sfWebRequest $request)
{
$this->posts = PostTable::getInstance()->getMostRecents(10);
}
}
Couche Contrôleur :
CoucheVue :
# apps/frontend/modules/post/templates/indexSuccess.php	
<?php foreach ($posts as $post) : ?>	
<h2><?php echo $post->getTitle() ?></h2>	
<div class="content">	
<?php echo simple_format_text($post->getContent()) ?>	
</div>	
<?php endforeach ?>
# lib/model/doctrine/PostTable.class.php
class PostTable extends Doctrine_Table
{
public function getMostRecents($limit)
{
return $this->
createQuery('a')->
where('a.is_published = ?', true)->
orderBy('a.published_at desc')->
limit($limit)->
execute();
}
}
Couche Modèle (Doctrine ORM) :
Ne pas réinventer la roue3.
Configuration  des  URLs	
q Optimisation pour les SEO
q Faciles à bookmarker, mémoriser ou échanger
q Masquent l’implémentation technique
http://www.domain.tld/blog.php?action=show&id=12546
http://www.domain.tld/blog/2010/11/10/forum-php-afup
URL PHP
URL Symfony
Configuration  YAML  des  URLs	
signin:
url: /:sf_culture/login
param: { module: authentication, action: login }
requirements: { sf_culture: (?:en|fr) }
signout:
url: /:sf_culture/logout
param: { module: authentication, action: logout }
requirements: { sf_culture: (?:en|fr) }
my_account:
url: /:sf_culture/account
param: { module: home, action: showAccount }
requirements: { sf_culture: (?:en|fr) }
products:
url: /:sf_culture/shop/:page
param: { module: product, action: index, page: 1 }
requirements: { sf_culture: (?:en|fr), page: d+ }
Accès  aux  bases  de  données	
§  Projets matures
§  Pilotés par F. Zaninotto & J.Wage
§  Abstraction de BDD & ORM
§  PDO pour couche basse
§  Nombreuses BDD supportées
§  Génération de code et behaviors
§  API abstraite et OO de requêtes SQL
§  Migrations
ORM  /  Active  Record	
$speaker = new Speaker();
$speaker->setFirstName('Hugo');
$speaker->setLastName('Hamon');
$conference = new Conference();
$conference->setSpeaker($speaker);
$conference->setTitle('Introduction à symfony');
$conference->setSchedule('2010-11-10 09:00:00');
$conference->save();
Sauvegarde des deux enregistrements en BDD
Traitement  des  formulaires	
§ Simplifier la création et la validation des formulaires
§ API entièrement orientée objet
§ Flexible et extensible
§ Intégration avec les ORMs
§ Nombreux validateurs et « widgets » livrés
§ Simplicité d’utilisation pour les intégrateurs web
class ContactForm extends sfForm
{
public function configure()
{
$this->setWidgets(array(
'email' => new sfWidgetFormInputText(),
'message' => new sfWidgetFormTextarea()
));
$this->setValidators(array(
'email' => new sfValidatorEmail(),
'message' => new sfValidatorString()
));
$this->widgetSchema->setNameFormat('contact[%s]');
}
}
class contactActions extends sfActions	
{	
public function executeProcessForm(sfWebRequest $request)	
{	
$this->forward404Unless($request->getMethod('post'));	
	
$this->form = new ContactForm();	
$this->form->bind($request->getParameter('contact'));	
	
if ($this->form->isValid())	
{	
$values = $this->form->getValues();	
	
// ... do something	
	
$this->redirect('contact/thankYou');	
}	
}	
}
I18N  &  L10N	
§ Sites multilingues
§ Formatage de dates, monnaies, nombres…
§ Gestion des pluriels
§ Localisation des chaînes de l’interface
§ Support des tables I18N par les ORMs
§ Gestion automatique de la culture de l’utilisateur
I18N  &  L10N	
<p>
<?php echo __('Hello, my name is %name%', array(
'%name%' => 'Hugo’
)) ?>.
</p>
<p>
It costs <?php echo format_currency(125990, 'EUR') ?>.
</p>
<p>
There are <?php echo format_number(1350) ?> people here.
</p>
Authentification  et  ACLs	
§ Authentification de l’utilisateur
§ Gestion des droits d’accès
$user->setAuthenticated(true);
$user->isAuthenticated();
$user->addCredentials(array('AUTHOR', 'PUBLISHER'));
$user->hasCredential('PUBLISHER');
Envoi  d’emails	
§ Intégration de Swift Mailer
§ API orientée objet
§ Flexible et extensible
§ Support des files d’attente de mails
§ Entièrement configurable
§ Intégration avec les ORMs
Envoi  d’emails	
$mail = $this->getMailer()->compose(	
'you@example.com', 	
'me@example.com', 	
'Hell You!', 	
"Hey guy, what's up ?"	
);	
	
$mail->setPriority(3);	
$mail->attach(Swift_Attachment::fromPath('file.pdf'));	
	
$this->getMailer()->send($mail);	
Le mailer est entièrement configurable
Sécurité de l’application4.
Sécurité	
q Echappement automatique des variables de vue
q Sécurisation des formulaires avec des jetons uniques
q Requêtes préparées par les ORMs
$speaker = Doctrine_Query::create()->
from('Speaker s')->
where('s.last_name LIKE ?', '%Hamon%')->
fetchOne();
Configuration  d’Apache	
q Accès au répertoire web/ depuis un navigateur
<VirtualHost *:80>
ServerName www.my-domain.com
DocumentRoot "/path/to/SymfonyProject/web"
<Directory "/path/to/SymfonyProject/web">
AllowOverride All
Allow from All
</Directory>
Alias /sf /path/to/SymfonyProject/lib/vendor/symfony/data/web/sf
<Directory "/path/to/SymfonyProject/lib/vendor/symfony/data/web/sf">
AllowOverride All
Allow from All
</Directory>
</VirtualHost>
Générer des backoffices5.
Admin  Generator	
q Génération de backoffice
q Liste
q Ajout
q Modification
q Suppression
q Filtres de recherche
q Pagination
q Entièrement configurable
q Gestion des droits d’accès
q Extensible / Surchargeable
Admin  Generator	
$ php symfony doctrine:generate-admin backend Product
generator:
class: sfDoctrineGenerator
param:
# ...
config:
actions:
_edit: { credentials: [ADMIN_PRODUCTS] }
fields:
name: { label: Nom du produit }
reference: { label: Référence }
price: { label: Prix }
is_published: { label: Publication ? }
categories_list: { label: Catégories }
list:
batch_actions:
unlinkCategories:
credentials: [[ADMIN_PRODUCTS, EDIT_PRODUCT]]
label: Rendre orphelins
_delete:
credentials: [ADMIN_PRODUCTS]
Configuration  en  YAML
Etendre les fonctionnalités6.
Ligne  de  commandes	
q Le framework de tâches automatisées peut accueillir de
nouvelles commandes personnalisées.
Ligne  de  commandes	
class sfGuardAddPermissionTask extends sfBaseTask	
{	
protected function configure()	
{	
// ...	
	
$this->namespace = 'guard';	
$this->name = 'add-permission';	
$this->briefDescription = 'Adds a new permission';	
}	
	
protected function execute($arguments = array(), 	
$options = array())	
{	
// ...	
}	
}
Plugins  communautaires	
q Près d’un millier de plugins Open-Source disponibles
q Faciles à installer et à utiliser
Composants  de  Zend  Framework	
q Intégration des composants du Zend Framework
q Outils éprouvés et testés
q Interopérabilité entre les deux projets
q Zend_Soap, Zend_Lucene, Zend_Service_Twitter…
q Obtenez que le meilleur des deux mondes J
Garantir la qualité du code7.
Tests  unitaires	
q Symfony 1.x : Lime
q Symfony 2.x : PHPUnit 3.5
q Vérifier que le code est correct
q Faciliter la détection des bogues et des régressions
q Documenter le code
Tests  unitaires
Tests  fonctionnels	
q Vérifier les fonctionnalités de l’application
q Simuler un scénario de navigation sur le site
q Tester toutes les couches (request, response, user…)
q API qui simule un véritable navigateur web
q Syntaxe verbeuse et intuitive
Tests  fonctionnels	
include(dirname(__FILE__).'/../../bootstrap/functional.php');	
	
$browser = new sfTestFunctional(new sfBrowser());	
	
$browser->	
get('/en/contact')->	
	
with('response')->isStatusCode(200)->	
	
click('send', array(	
'contact' => array(	
'name' => '',	
'email' => 'foo',	
'message' => 'Lorem ipsum...' 	
)	
), array('_with_csrf' => true));
Tests  fonctionnels
Performances & scalabilité8.
Rôle  du  cache  de  symfony	
q Cache de la configurationYAML
q Cache des dictionnaires de traduction XLIFF
q Cache des pages HTML
q Cache des requêtes SQL (Doctrine)
q => Répondre plus vite à une requête HTTP
Performances  de  Symfony2	
q  Bénéfices des optimisations apportées à PHP 5.3
q  Conteneur d’Injection de Dépendances
q Chargement à la demande des objets
q Limitation de l’occupation mémoire
q  Cache HTTP performant et très flexible
q Performances accrues avec un Reverse Proxy (Varnish / Squid)
q Support des ESI – Edge Side Includes – RFC 2616
Surcharge  du  coeur	
q Possibilité de redéfinir la configuration de symfony
q Ex : Request, Response, User, Cache, I18N, Mailer…
dev:
mailer:
param:
delivery_strategy: none
transport:
class: Swift_NullTransport
Contribuer à Symfony9.
Contribuer  au  projet	
q Documentation (blog, traductions…)
q Canaux de discussion (IRC, forums, mailing lists, twitter)
q Code source (patches, bogues)
q Plugins
q Conférences
q Bouche à oreille
Merci !
Sensio S.A.
92-98, boulevardVictor Hugo
92 115 Clichy Cedex
FRANCE
Tél. : +33 1 40 99 80 80
www.sensiolabs.com - www.symfony-project.org - trainings.sensiolabs.com

Mieux Développer en PHP avec Symfony

  • 1.
    Développer mieux en PHPavec HugoHamon-ForumPHPAFUP2010–Paris–10/11/2010
  • 2.
    Qui  suis-­‐‑je  ? v Hugo HAMON (@hhamon) v  Responsable des formations à v  Premiers pas avec PHP en 2002 v  Secrétaire de l’AFUP v  Auteur du site Apprendre-PHP.com v  Coauteur & contributeur à des ouvrages Eyrolles
  • 3.
  • 4.
    Le projet symfony… symfony1.0 symfony 1.1 symfony 1.4 Symfony 2.0 License MIT Version actuelle 1.0.22 1.1.9 1.4.8 2.0.0 - PR Date de sortie Octobre 2005 Juin 2008 Novembre 2009 Mars 2011 Support Terminé Terminé Fin 2012 ? Stabilité Stable Stable Stable Presque stable Production Oui Oui Oui Bientôt Documentation Oui Oui Oui En cours
  • 5.
    Ø  Documentation Open-Source Ø API stable et fiable Ø  Communauté active Ø  Plugins Open-Source Ø  Développeurs sur le marché Ø  Formation & Consulting Un  riche  écosystème
  • 6.
  • 7.
  • 8.
  • 9.
    Industrialiser § Développer plus vite § Développermieux § Réduire les coûts de développement § Favoriser la réutilisabilité du code § Simplifier les opérations de maintenance § Simplifier les déploiements
  • 10.
  • 11.
  • 12.
  • 13.
    Objectifs  ? Moins  de  Code Moins  de   complexité Moins  de   bogues Plus  de   Productivité Plus  de   temps
  • 14.
  • 15.
  • 16.
    ² Requêtes SQL ² Logs ² Variables d’environnement($_GET, $_POST, $_COOKIE…) ² Configuration de PHP ² Timers ² Variables de configuration de Symfony
  • 17.
  • 18.
    Déboguer  plus  vite (Symfony2) Profiler
  • 19.
    Journalisation  des  logs ² RequêtesSQL, en-têtes envoyés, exceptions attrapées…
  • 20.
    Simplifier  les  déploiements $php symfony project:deploy production --go [production] host=123.456.7.8 user=hhamon port=22 path=/var/www/www.monsite.com Déploiement automatisé avec une connexion SSH + RSYNC Configuration des serveurs de déploiement dans un fichier INI
  • 21.
  • 22.
    Arborescence  connue $ tree-L 1 -F . |-- apps/ |-- cache/ |-- config/ |-- data/ |-- lib/ |-- log/ |-- plugins/ |-- symfony* |-- test/ `-- web/ 9 directories, 1 file q  Applications q  Cache q  Configuration globale q  Données du projet q  Classes PHP q  Journaux de logs q  Plugins installés q  Tests automatisés q  Fichiers publics
  • 23.
    Conventions  de  codage q Nommage des fichiers q  Nommage des variables q  Philosophie de codage q  Même outillage pour tout le monde
  • 24.
  • 25.
    # apps/frontend/modules/post/actions/actions.class.php class postActionsextends sfActions { public function executeIndex(sfWebRequest $request) { $this->posts = PostTable::getInstance()->getMostRecents(10); } } Couche Contrôleur : CoucheVue : # apps/frontend/modules/post/templates/indexSuccess.php <?php foreach ($posts as $post) : ?> <h2><?php echo $post->getTitle() ?></h2> <div class="content"> <?php echo simple_format_text($post->getContent()) ?> </div> <?php endforeach ?>
  • 26.
    # lib/model/doctrine/PostTable.class.php class PostTableextends Doctrine_Table { public function getMostRecents($limit) { return $this-> createQuery('a')-> where('a.is_published = ?', true)-> orderBy('a.published_at desc')-> limit($limit)-> execute(); } } Couche Modèle (Doctrine ORM) :
  • 27.
  • 28.
    Configuration  des  URLs q Optimisationpour les SEO q Faciles à bookmarker, mémoriser ou échanger q Masquent l’implémentation technique http://www.domain.tld/blog.php?action=show&id=12546 http://www.domain.tld/blog/2010/11/10/forum-php-afup URL PHP URL Symfony
  • 29.
    Configuration  YAML  des URLs signin: url: /:sf_culture/login param: { module: authentication, action: login } requirements: { sf_culture: (?:en|fr) } signout: url: /:sf_culture/logout param: { module: authentication, action: logout } requirements: { sf_culture: (?:en|fr) } my_account: url: /:sf_culture/account param: { module: home, action: showAccount } requirements: { sf_culture: (?:en|fr) } products: url: /:sf_culture/shop/:page param: { module: product, action: index, page: 1 } requirements: { sf_culture: (?:en|fr), page: d+ }
  • 30.
    Accès  aux  bases de  données §  Projets matures §  Pilotés par F. Zaninotto & J.Wage §  Abstraction de BDD & ORM §  PDO pour couche basse §  Nombreuses BDD supportées §  Génération de code et behaviors §  API abstraite et OO de requêtes SQL §  Migrations
  • 31.
    ORM  /  Active Record $speaker = new Speaker(); $speaker->setFirstName('Hugo'); $speaker->setLastName('Hamon'); $conference = new Conference(); $conference->setSpeaker($speaker); $conference->setTitle('Introduction à symfony'); $conference->setSchedule('2010-11-10 09:00:00'); $conference->save(); Sauvegarde des deux enregistrements en BDD
  • 32.
    Traitement  des  formulaires § Simplifierla création et la validation des formulaires § API entièrement orientée objet § Flexible et extensible § Intégration avec les ORMs § Nombreux validateurs et « widgets » livrés § Simplicité d’utilisation pour les intégrateurs web
  • 33.
    class ContactForm extendssfForm { public function configure() { $this->setWidgets(array( 'email' => new sfWidgetFormInputText(), 'message' => new sfWidgetFormTextarea() )); $this->setValidators(array( 'email' => new sfValidatorEmail(), 'message' => new sfValidatorString() )); $this->widgetSchema->setNameFormat('contact[%s]'); } }
  • 34.
    class contactActions extendssfActions { public function executeProcessForm(sfWebRequest $request) { $this->forward404Unless($request->getMethod('post')); $this->form = new ContactForm(); $this->form->bind($request->getParameter('contact')); if ($this->form->isValid()) { $values = $this->form->getValues(); // ... do something $this->redirect('contact/thankYou'); } } }
  • 35.
    I18N  &  L10N § Sitesmultilingues § Formatage de dates, monnaies, nombres… § Gestion des pluriels § Localisation des chaînes de l’interface § Support des tables I18N par les ORMs § Gestion automatique de la culture de l’utilisateur
  • 36.
    I18N  &  L10N <p> <?phpecho __('Hello, my name is %name%', array( '%name%' => 'Hugo’ )) ?>. </p> <p> It costs <?php echo format_currency(125990, 'EUR') ?>. </p> <p> There are <?php echo format_number(1350) ?> people here. </p>
  • 37.
    Authentification  et  ACLs § Authentificationde l’utilisateur § Gestion des droits d’accès $user->setAuthenticated(true); $user->isAuthenticated(); $user->addCredentials(array('AUTHOR', 'PUBLISHER')); $user->hasCredential('PUBLISHER');
  • 38.
    Envoi  d’emails § Intégration deSwift Mailer § API orientée objet § Flexible et extensible § Support des files d’attente de mails § Entièrement configurable § Intégration avec les ORMs
  • 39.
    Envoi  d’emails $mail =$this->getMailer()->compose( 'you@example.com', 'me@example.com', 'Hell You!', "Hey guy, what's up ?" ); $mail->setPriority(3); $mail->attach(Swift_Attachment::fromPath('file.pdf')); $this->getMailer()->send($mail); Le mailer est entièrement configurable
  • 40.
  • 41.
    Sécurité q Echappement automatique desvariables de vue q Sécurisation des formulaires avec des jetons uniques q Requêtes préparées par les ORMs $speaker = Doctrine_Query::create()-> from('Speaker s')-> where('s.last_name LIKE ?', '%Hamon%')-> fetchOne();
  • 42.
    Configuration  d’Apache q Accès aurépertoire web/ depuis un navigateur <VirtualHost *:80> ServerName www.my-domain.com DocumentRoot "/path/to/SymfonyProject/web" <Directory "/path/to/SymfonyProject/web"> AllowOverride All Allow from All </Directory> Alias /sf /path/to/SymfonyProject/lib/vendor/symfony/data/web/sf <Directory "/path/to/SymfonyProject/lib/vendor/symfony/data/web/sf"> AllowOverride All Allow from All </Directory> </VirtualHost>
  • 43.
  • 44.
    Admin  Generator q Génération debackoffice q Liste q Ajout q Modification q Suppression q Filtres de recherche q Pagination q Entièrement configurable q Gestion des droits d’accès q Extensible / Surchargeable
  • 45.
    Admin  Generator $ phpsymfony doctrine:generate-admin backend Product
  • 46.
    generator: class: sfDoctrineGenerator param: # ... config: actions: _edit:{ credentials: [ADMIN_PRODUCTS] } fields: name: { label: Nom du produit } reference: { label: Référence } price: { label: Prix } is_published: { label: Publication ? } categories_list: { label: Catégories } list: batch_actions: unlinkCategories: credentials: [[ADMIN_PRODUCTS, EDIT_PRODUCT]] label: Rendre orphelins _delete: credentials: [ADMIN_PRODUCTS] Configuration  en  YAML
  • 47.
  • 48.
    Ligne  de  commandes q Leframework de tâches automatisées peut accueillir de nouvelles commandes personnalisées.
  • 49.
    Ligne  de  commandes classsfGuardAddPermissionTask extends sfBaseTask { protected function configure() { // ... $this->namespace = 'guard'; $this->name = 'add-permission'; $this->briefDescription = 'Adds a new permission'; } protected function execute($arguments = array(), $options = array()) { // ... } }
  • 50.
    Plugins  communautaires q Près d’unmillier de plugins Open-Source disponibles q Faciles à installer et à utiliser
  • 51.
    Composants  de  Zend Framework q Intégration des composants du Zend Framework q Outils éprouvés et testés q Interopérabilité entre les deux projets q Zend_Soap, Zend_Lucene, Zend_Service_Twitter… q Obtenez que le meilleur des deux mondes J
  • 52.
  • 53.
    Tests  unitaires q Symfony 1.x: Lime q Symfony 2.x : PHPUnit 3.5 q Vérifier que le code est correct q Faciliter la détection des bogues et des régressions q Documenter le code
  • 54.
  • 55.
    Tests  fonctionnels q Vérifier lesfonctionnalités de l’application q Simuler un scénario de navigation sur le site q Tester toutes les couches (request, response, user…) q API qui simule un véritable navigateur web q Syntaxe verbeuse et intuitive
  • 56.
    Tests  fonctionnels include(dirname(__FILE__).'/../../bootstrap/functional.php'); $browser =new sfTestFunctional(new sfBrowser()); $browser-> get('/en/contact')-> with('response')->isStatusCode(200)-> click('send', array( 'contact' => array( 'name' => '', 'email' => 'foo', 'message' => 'Lorem ipsum...' ) ), array('_with_csrf' => true));
  • 57.
  • 58.
  • 59.
    Rôle  du  cache de  symfony q Cache de la configurationYAML q Cache des dictionnaires de traduction XLIFF q Cache des pages HTML q Cache des requêtes SQL (Doctrine) q => Répondre plus vite à une requête HTTP
  • 60.
    Performances  de  Symfony2 q Bénéfices des optimisations apportées à PHP 5.3 q  Conteneur d’Injection de Dépendances q Chargement à la demande des objets q Limitation de l’occupation mémoire q  Cache HTTP performant et très flexible q Performances accrues avec un Reverse Proxy (Varnish / Squid) q Support des ESI – Edge Side Includes – RFC 2616
  • 61.
    Surcharge  du  coeur q Possibilitéde redéfinir la configuration de symfony q Ex : Request, Response, User, Cache, I18N, Mailer… dev: mailer: param: delivery_strategy: none transport: class: Swift_NullTransport
  • 62.
  • 63.
    Contribuer  au  projet q Documentation(blog, traductions…) q Canaux de discussion (IRC, forums, mailing lists, twitter) q Code source (patches, bogues) q Plugins q Conférences q Bouche à oreille
  • 64.
    Merci ! Sensio S.A. 92-98,boulevardVictor Hugo 92 115 Clichy Cedex FRANCE Tél. : +33 1 40 99 80 80 www.sensiolabs.com - www.symfony-project.org - trainings.sensiolabs.com