SlideShare une entreprise Scribd logo
1  sur  114
Télécharger pour lire hors ligne
Introduction à Symfony2
•  Hugo HAMON (@hhamon)

•  Responsable des formations Sensio Labs
•  Secrétaire Général de l’AFUP

•  10 ans de développement web dont 8 avec PHP
•  Coauteur d’ouvrages Eyrolles
•  Apprendre-PHP.com / HugoHamon.com
Qu’est-ce que Symfony2 ?
Un framework web
PHP 5.3
Objectifs ?
•  Développer plus vite et mieux
•  Faciliter le travail en équipe
•  Pérenniser les applications
•  Simpli er la maintenance et les évolutions
•  Se concentrer sur la logique métier

•  Ne pas réinventer la roue !
Symfony2 intègre
les meilleurs outils
Open-Source PHP
Symfony Components

Dependency Injection Container
      Request Handler
      Event Dispatcher
          Console
           YAML
             …
Zend Framework
   PHPUnit
   Doctrine2
  Swift Mailer
      Twig
Différences avec
 symfony 1.x ?
Même philosophie,
     Même outillage,
    Moins de concepts,
    Plus de exibilité
Performances accrues 
Où en est-on
aujourd’hui ?
•  Version ALPHA

•  Briques logicielles manquantes

•  Documentation incomplète

•  L’API peut encore beaucoup évoluer

•  Version stable repoussée à début Mars 2011
Je veux tester Symfony2 !
git clone http://github.com/symfony/symfony-sandbox.git

            http://www.symfony-reloaded.org
Je veux développer un projet client
    maintenant avec Symfony2 ?


  A ta place, je ne ferai pas ça…
Quel outillage ?
•  Sécurité             •  Extensibilité
•  Architecture MVC     •  I18N & L10N
•  URLs élégantes       •  Authenti cation et ACLs
•  DBAL & ORM           •  Tests unitaires
•  Outils de débogage   •  Tests fonctionnels
•  Formulaires          •  Cache
•  Con guration         •  Admin Generator
Architecture d’un projet
       Symfony2
Un Projet Symfony2 est un répertoire
qui se compose d’une Application, d’un
     jeu de Bundles et de librairies.
.
|--   LICENSE
|--   README
|--   app/
|     |-- AppCache.php
|     |-- AppKernel.php        Répertoire	
  de	
  l’Applica0on	
  
|     |-- cache/
|     |-- config/
|     |-- console
|     |-- logs/
|     |-- phpunit.xml.dist
|     `-- views/
|--   bin/
|     |-- create_sandbox.sh
|     |-- install_vendors.sh
|     |-- prepare_vendors.sh
|     `-- update_vendors.sh
|--   src/
|     |-- Application/
|     |-- Bundle/                Code	
  de	
  l’Applica0on	
  +	
  	
  
|     |-- autoload.php                    Bundles	
  +	
  	
  
|     `-- vendor/                  Librairies	
  externes	
  
`--   web/
      |-- bundles/
      |-- check.php
      |-- index.php                     Dossier	
  public	
  
      `-- index_dev.php
Une Application est un répertoire qui
contient la con guration pour un jeu de
            Bundles donné.
Structure d’une application
app/
|-- AppCache.php
|-- AppKernel.php
                                  The	
  AppKernel	
  class	
  is	
  the	
  
|-- cache/
                              	
  main	
  class	
  of	
  the	
  applica0on	
  
|-- config/
|    |-- config.yml
|    |-- config_dev.yml
|    |-- config_test.yml
|    |-- routing.yml
                                      Configura0on	
  files	
  
|    `-- routing_dev.yml
|-- console
|-- logs/
|    `-- dev.log
|-- phpunit.xml.dist         Logs	
  and	
  applica0on	
  templates	
  
`-- views/
     |-- layout.php
Un Bundle est un ensemble structuré et cohérent
  de chiers qui implémentent une fonctionnalité
(un blog, un forum, …) et qui peut facilement être
       partagé avec d’autres développeurs.
symfony 1.x => Plugins
Symfony 2.x => Bundles
+ BlogBundle/                        Code	
  source	
  du	
  bundle	
  :	
  contrôleurs	
  
|-- Controller/
|   `-- BlogController.php                    modèles,	
  formulaires…	
  
|-- Entity/
|   `-- Post.php
|-- Form/
|   `-- PostForm.php                    Le	
  fichier	
  BlogBundle.php	
  est	
  
|-- BlogBundle.php
|-- Model/
                                      obligatoire	
  et	
  con0ent	
  la	
  classe	
  qui	
  
|   `-- PostRepository.php                      déclare	
  le	
  bundle.	
  
|-- Resources/
|   |-- config/
|   |   `-- routing.yml
|   |-- views/
|   |   `-- Blog/
                                       Un	
  bundle	
  peut	
  contenir	
  de	
  la	
  
|   |       |-- showPost.php         configura0on,	
  des	
  templates	
  et	
  des	
  
|   |       `-- listPost.php                    ressources	
  web.	
  
|   `-- public/
|       `-- css/
|           `-- blog.css
`-- Tests/                                   Un	
  bundle	
  peut	
  aussi	
  contenir	
  
    `-- Controller/
        `-- BlogControllerTest.php
                                             des	
  scripts	
  de	
  tests	
  PHPUnit.	
  
Sécurité
XSS
    CSRF
SQL Injections
Le dossier web/ du projet est le seul
accessible depuis un navigateur web
Routage et URLs
Le système de routage a pour rôle de
convertir une URL en une réponse web.
Elles sont propres et élégantes a n d’exposer
   des informations pertinentes et de masquer
           l’implémentation technique…

http://www.domain.com/blog/2010/09/15/symfony2-rocks
Con guration des URLs en YAML
# src/Bundle/BlogBundle/Resources/config/routing.yml

post_details:
    pattern: /blog/:year/:month/:day/:slug
    defaults: { _controller: BlogBundle:Blog:showPost }



Exemple d’URL générée
http://www.domain.com/blog/2010/09/15/symfony2-rocks
Association URL et Code ?
# src/Application/HelloBundle/Resources/config/routing.yml

hello:
  pattern: /hello/:name
  defaults: { _controller: HelloBundle:Hello:index }



# src/Application/HelloBundle/Controller/HelloController.php

namespace ApplicationHelloBundleController;

class HelloController extends Controller
{
  public function indexAction($name)
  {
    // ...
  }
}
# src/Application/HelloBundle/Resources/config/routing.yml

hello:                              Nom	
  du	
  Bundle	
  
  pattern: /hello/:name
  defaults: { _controller: HelloBundle:Hello:index }



# src/Application/HelloBundle/Controller/HelloController.php

namespace ApplicationHelloBundleController;

class HelloController extends Controller         Un	
  dossier	
  /	
  namespace	
  
{
  public function indexAction($name)
  {
    // ...
  }
}
# src/Application/HelloBundle/Resources/config/routing.yml

hello:                                Nom	
  du	
  contrôleur	
  
  pattern: /hello/:name
  defaults: { _controller: HelloBundle:Hello:index }



# src/Application/HelloBundle/Controller/HelloController.php

namespace ApplicationHelloBundleController;

class HelloController extends Controller                  Une	
  classe	
  
{
  public function indexAction($name)
  {
    // ...
  }
}
# src/Application/HelloBundle/Resources/config/routing.yml

hello:                                       Nom	
  de	
  l’ac0on	
  
  pattern: /hello/:name
  defaults: { _controller: HelloBundle:Hello:index }



# src/Application/HelloBundle/Controller/HelloController.php

namespace ApplicationHelloBundleController;

class HelloController extends Controller
{
  public function indexAction($name)
  {
    // ...
  }                  Une	
  méthode	
  
}
# src/Application/HelloBundle/Resources/config/routing.yml

hello:
  pattern: /hello/:name
  defaults: { _controller: HelloBundle:Hello:index }



# src/Application/HelloBundle/Controller/HelloController.php

namespace ApplicationHelloBundleController;

class HelloController extends Controller
{
  public function indexAction($name)
  {
    // ...
  }
}
Les paramètres peuvent être passés dans un ordre arbitraire
post_details:
  pattern: /blog/:year/:month/:day/:slug
  defaults: { _controller: BlogBundle:Blog:showPost }



namespace ApplicationBlogBundleController;

class BlogController extends Controller
{
  public function showPostAction($slug, $year)
  {
    // ...
  }
}
Architecture MVC
•  Séparation du code en trois couches
   – Logique métier dans le Modèle
   – Logique applicative dans le Contrôleur
   – Affichage dans la Vue (templates)


•  Modularité et découplage du code
•  Maintenance simpli ée sur le code source
•  Code testable unitairement et plus robuste
Les actions pour la logique applicative.

 Elles se situent dans les Contrôleurs.
๏  Une action est accessible depuis une URL

# src/Application/BlogBundle/Resources/config/routing.yml

post_show:
  pattern: /blog/article/:id/show
  defaults: { _controller: BlogBundle:Blog:show }
# src/Application/BlogBundle/Controller/BlogController.php

namespace ApplicationBlogBundleController;

use SymfonyBundleFrameworkBundleControllerController;

class BlogController extends Controller
{
    public function showAction($id)     Paramètres	
  de	
  l’url	
  
    {
        // find the article by its id
        $post = ...;

         // render the view
         return $this->render('BlogBundle:Blog:show', array('post' => $post));
    }
}
                                     Template	
  à	
  rendre	
          Variables	
  du	
  template	
  
Les templates constituent la couche de
    présentation des données, la vue.
๏  Syntaxe alternative de PHP
  ๏  Quelques brèves instructions PHP (echo, if, foreach…)
  ๏  Echappement automatique des variables

# src/Application/BlogBundle/Resources/views/Blog/show.php

<?php $view->extend('::layout') ?>         Layout	
  de	
  décora0on	
  

<h2><?php echo $post->getTitle() ?></h2>

<p>
  <?php echo $post->getContent() ?>
</p>                                   Variables	
  échappées	
  =>	
  pas	
  de	
  XSS	
  !!!	
  
Héritage de Vues
# src/Application/HelloBundle/Resources/views/Hello/index.php

<?php $view->extend('::layout') ?>

Hello <?php echo $name ?>!

                                              étend
# app/views/layout.php
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>
            <?php $view['slots']->output('title', 'Hello Application') ?>
        </title>
    </head>
    <body>
        <?php $view['slots']->output('_content') ?>
    </body>
</html>
Héritage de Vues
layout.php




             _content
                              Hello Hugo!


                                      index.php
# src/Application/HelloBundle/Resources/views/Hello/index.php
<?php $view->extend('HelloBundle::layout') ?>
Hello <?php echo $name ?>!


# src/Application/HelloBundle/Resources/views/layout.php
<?php $view->extend('::layout') ?>
<h1>Hello Application</h1>
<div>
  <?php $view['slots']->output('_content') ?>
</div>


# app/views/layout.php
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>
            <?php $view['slots']->output('title', 'Hello Application') ?>
        </title>
    </head>
    <body>
        <?php $view['slots']->output('_content') ?>
    </body>
</html>
Héritage multiple

::layout.php


                         HelloBundle::layout.php
           _content

                                                   Hello Hugo!
                                   _content
                                                        index.php
Les Slots sont des fragments dé nis
 dans un template et affichés dans un
      layout décorant ce dernier.
# src/Application/HelloBundle/Resources/views/Hello/index.php
<?php $view['slots']->set('title', 'Hello World app') ?>




# app/views/layout.php
<html>
  <head>
    <title>
       <?php $view['slots']->output('title', 'Hello Application') ?>
    </title>
  </head>
  <body>
    <?php $view['slots']->output('_content') ?>
  </body>
</html>
Symfony fournit des mécanismes simples
       pour évaluer et inclure des templates
                  dans un autre
# src/Application/HelloBundle/Resources/views/Hello/hello.php
Hello <?php echo $name ?>!

# Including another template in the current template
<?php echo $view->render('HelloBundle:Hello:hello', array('name' => $name)) ?>



                         src/Bundle/HelloBundle/Resources/views/Hello/hello.php	
  
Symfony offre également un moyen
        d’inclure le rendu d’une action depuis
                       une vue…
# src/Application/HelloBundle/Resources/views/Hello/index.php

<?php $view['actions']->output('HelloBundle:Hello:fancy', array(
  'name' => $name,
  'color' => 'green’
)) ?>
# src/Application/HelloBundle/Controller/HelloController.php

class HelloController extends Controller
{
    public function fancyAction($name, $color)
    {
        // create some object, based on the $color variable
        $object = ...;

        return $this->render('HelloBundle:Hello:fancy', array(
         'name' => $name,
         'object' => $object
        ));
    }

    // ...
}
Les aides de vue sont des objets
accessibles depuis les templates et qui
 permettent de simpli er la logique
              d’affichage
Générer une URL avec le router helper
<a href="<?php echo $view['router']->generate('hello', array(
    'name' => 'Thomas')) ?>">Greet Thomas!</a>




Inclure des feuilles de style
<head>
  <!-- ... -->
  <?php $view['stylesheets']->add('css/styles.css') ?>
  <?php echo $view['stylesheets'] ?>
</head>
Inclure des javascripts
<head>
  <!-- ... -->
  <?php $view['javascripts']->add('js/libraries.js') ?>
  <?php echo $view['javascripts'] ?>
</head>



Manipuler des ressource web (images, ash…)
<img src="<?php echo $view['assets']->getUrl('images/logo.png') ?>" src=""/>



Traduire des chaînes de l’interface
<?php echo $view['translator']->trans('Symfony is %what%!', array(
  '%what%' => 'awesome')) ?>
Con guration
3 formats de con guration

          PHP
         YAML
          XML
Quel format choisir ?
          Avantages                  Inconvénients
XML       Validation                 Verbeux
          Complétion dans les EDIs   Long à écrire
          Facile à analyser
YAML      Concis                     Besoin du composant YAML
          Facile à lire              Pas de validation
          Facile à modi er           Pas d’autocomplétion
PHP       Flexible                   Pas de validation
          Plus facile à manipuler
Con guration en YML
# app/config/routing.php	

homepage:	
    pattern: /	
    defaults: { _controller: FrameworkBundle:Default:index }	

hello:	
    resource: HelloBundle/Resources/config/routing.yml


                                             Import	
  d’une	
  autre	
  configura0on	
  
Con guration en PHP
# app/config/routing.php

use SymfonyComponentRoutingRouteCollection;
use SymfonyComponentRoutingRoute;

$collection = new RouteCollection();

$collection->addRoute('homepage', new Route('/', array(
     '_controller' => 'FrameworkBundle:Default:index',
)));

$collection->addCollection(
   $loader->import("HelloBundle/Resources/config/routing.php")
);
                                                       Import	
  d’une	
  autre	
  configura0on	
  
return $collection;
Con guration en XML
# app/config/routing.xml

<?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://www.symfony-project.org/schema/routing"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.symfony-project.org/schema/routing http://
www.symfony-project.org/schema/routing/routing-1.0.xsd">

    <route id="homepage" pattern="/">
        <default key="_controller">FrameworkBundle:Default:index</default>
    </route>

    <import resource="HelloBundle/Resources/config/routing.xml" />
</routes>

                                                      Import	
  d’une	
  autre	
  configura0on	
  
Import de chiers INI
# app/config/config_dev.yml
imports:
    - { resource: config.yml }
    - { resource: custom.ini}

zend.logger:
    priority: debug
    path:     %kernel.root_dir%/logs/%kernel.environment%.log



# app/config/custom.ini
[parameters]
dice.min = 1
dice.max = 6
Accès à la con guration depuis le code
public function diceAction()
{
    // ...

    $min = (int) $this->container->getParameter('dice.min');
    $max = (int) $this->container->getParameter('dice.max');

    // ...
}
Outils de Débogage
Parce qu’il est important pour un
développeur d’identi er rapidement les
      bogues et les problèmes !!!
Web Debug Toolbar
Logs
Traces d’exception


                                                  Trace	
  de	
  l’excep0on	
  
                                                       courrante	
  




      Trace	
  pour	
  une	
  
InvalidArgumentExcep0on	
  

                                 404	
  Status	
  Code	
  
Afficher	
  /	
  masquer	
  la	
  trace	
  d’une	
  
                                                    excep0on	
  




                                                        Logs	
  enregistrés	
  




Lien	
  vers	
  le	
  profiler	
  
Pro ler
Trace	
  de	
  l’excep0on	
  




Recherche	
  dans	
  les	
  logs	
  
Requêtes SQL
Extensibilité
http://www.symfony2bundles.org
Enregistrement de bundles
# app/AppKernel.php
class AppKernel extends Kernel
{
    // ...
    public function registerBundles()
    {
        $bundles = array(
            // ...
            // Register third party bundles
            new BundleTwitterBundleTwitterBundle(),
            new BundleForumBundleForumBundle()
        );

        // ...
        return $bundles;
    }
}
DBAL & ORM
 Doctrine2
•  Abstraction de base de données relationnelles
•  Performance
•  Plus de magie
•  Manipulation de vrais objets PHP (POPO)
•  Génération de code

•  Adapteur MongoDB disponible
๏  Con   gurer la connexion BDD en YAML
# app/config/config.yml
doctrine.dbal:
    dbname: Blog
    user:      root
    password: ~

doctrine.orm: ~


 ๏  Con   gurer la connexion BDD dans Apache
// web/.htaccess or in the vhost configuration

SetEnv SYMFONY__DOCTRINE__DBAL__USERNAME "root"
SetEnv SYMFONY__DOCTRINE__DBAL__PASSWORD "secret"
๏  Dé   nition d’une entité (table) à l’aide d’une classe PHP
namespace ApplicationBlogBundleEntity;

/**
 * @Entity(repositoryClass="ApplicationBlogBundleModelBlogPostRepository")
 * @Table(name="blog_post")
 */                                                            Annota0ons	
  
class BlogPost {
    /**
     * @Id @Column(type="integer")
     * @GeneratedValue(strategy="IDENTITY")
     */
    protected $id;

     /** @Column(length=100) */
     protected $title;

     /** @Column(type="text") */
     protected $content;
}
๏  Génération de la base de données à partir des classes PHP

$ php app/console doctrine:database:create
$ php app/console doctrine:schema:create




 ๏  Chargement des données de test

$ php app/console doctrine:data:load
๏  Les données de test sont écrites en pur PHP

# src/Application/BlogBundle/Resources/data/fixtures/doctrine/fixtures.php

use ApplicationBlogBundleEntityBlogPost;

$post1 = new BlogPost();
$post1->setTitle('My first blog post');
$post1->setContent('Lorem ipsum dolor sit amet...');

$post2 = new BlogPost();
$post2->setTitle('My second blog post');
$post2->setContent('Lorem ipsum dolor sit amet...');

$post3 = new BlogPost();
$post3->setTitle('My third blog post');
$post3->setContent('Lorem ipsum dolor sit amet...');
๏  Ecrire des requêtes DQL dans un modèle Doctrine

# src/Application/BlogBundle/Model/BlogPostRepository.php
namespace ApplicationBlogBundleModel;
use DoctrineORMEntityRepository;

class BlogPostRepository extends EntityRepository
{
    public function getHomepagePosts()
    {
        $query = $this->_em->createQuery('
          SELECT u
          FROM BlogBundle:BlogPost u
          ORDER BY u.id DESC
        ');

          return $query->getResult();
      }
}
๏  Interroger la base de données à l’aide du Modèle Doctrine

# src/Application/BlogBundle/Controller/BlogController.php
// ...
class BlogController extends Controller
{
    public function indexAction()
    {
        $em = $this['doctrine.orm.entity_manager'];

         $posts = $em->getRepository('BlogBundle:BlogPost')
                     ->getHomepagePosts();

         return $this->render('BlogBundle:Blog:index', array(
             'posts' => $posts
         ));
     }

     // ...
}
Emails
Swift Mailer
•  API Orientée Objet Open-Source
•  Support des connexions SMTP
•  Support des pièces jointes
•  Support des formats de mails (text, html…)
•  Gestion des les d’attente (spools)
•  Facile à con gurer et à étendre avec des plugins
Con gurer Swift Mailer
# app/config/config.yml

swift.mailer:
    transport:    smtp
    encryption:   ssl
    auth_mode:    login
    host:         smtp.gmail.com
    username:     your_username
    password:     your_password
Envoyer un Email
public function indexAction($name)
{                                                 Récupéra0on	
  du	
  service	
  d’envoi	
  de	
  mails	
  
    $mailer = $this['mailer'];

    $message = Swift_Message::newInstance()
         ->setSubject('Hello Email')
         ->setFrom('send@example.com')
         ->setTo('recipient@example.com')
         ->setBody($this->renderView('HelloBundle:Hello:email', array(
             'name' => $name
    )));                                   Généra0on	
  du	
  corps	
  du	
  mail	
  à	
  l’aide	
  
                                                          d’un	
  template	
  et	
  de	
  la	
  méthode	
  
    $mailer->send($message);                                         renderView()	
  
    return $this->render(...);
}
Tests Automatisés
     PHPUnit
•  Tests Unitaires et Couverture de Code

•  Garantir la qualité du code
•  Eviter les bugs et les régressions
•  Documenter le code

•  Industrialiser et professionnaliser les
   développements
๏  Exemple de script de tests unitaires dans Symfony2

# src/Application/BlogBundle/Tests/Entity/BlogPostTest.php
namespace ApplicationBlogBundleTestsEntity;
use ApplicationBlogBundleEntityBlogPost;

class BlogPostTest extends PHPUnit_Framework_TestCase
{
    public function testTitleIsSlugifiedOnce()
    {
        $slug = 'symfony2-rules-the-world';

         $post = new BlogPost();
         $post->setTitle('Symfony2 rules the world');
         $this->assertEquals($slug, $post->getSlug());

         // Slug doesn't change when it's already set
         $post->setTitle('An other title');
         $this->assertEquals($slug, $post->getSlug());
     }
}
•  Tests fonctionnels

•  Simuler des scénarios de navigation
•  Simuler un client Web (navigateur)

•  Véri er que l’application respecte le cahier des
   charges
๏  Exemple de script de tests fonctionnels dans Symfony2

class BlogControllerTest extends WebTestCase
{
    // ...
    public function testAddComment()
    {
        $this->client->followRedirects();

         $crawler = $this->client->request('GET', '/');

         // Get the first link to a post
         $link = $crawler->filter('h2.post a')->first()->link();

         // Click on the link and check there are two comments
         $crawler = $this->client->click($link);
         $this->assertTrue($crawler->filter('.comment')->count() == 2);
     }
}
๏  Simuler des requêtes GET

$crawler = $client->request('GET', '/hello/Fabien');


 ๏  Simuler des requêtes POST

$client->request('POST', '/submit', array('name' => 'Fabien')


 ๏  Simuler des uploads de    chiers en POST
$client->request('POST', '/submit',
   array('name' => 'Fabien'),
   array('photo' => '/path/to/photo')
);
๏  Simuler une requête HTTP DELETE avec des entêtes

$client->request('DELETE', '/post/12', array(), array(),
  array(
    'PHP_AUTH_USER' => 'username',
    'PHP_AUTH_PW' => 'pa$$word'
));



 ๏  Désactiver / activer les redirections HTTP

$client->followRedirects(false);
$client->followRedirect();



 ๏  Insoler le client dans un processus séparé

$client->insulate();
๏  Naviguer dans l’historique comme dans un navigateur web


$client->back();
$client->forward();
$client->reload();



 ๏  Réinitialiser le Client

$client->restart();
๏  Parcourir le DOM avec le DOM Crawler

// Nodes that match the CSS selector
$crawler->filter('h1');

// Nodes that match the XPath expression
$crawler->filterXpath('h1');

// Node for the specified index
$crawler->eq(1);

// First node
$crawler->first();

// Last node
$crawler->last();
// Siblings
$crawler->siblings();
// All following siblings
$crawler->nextAll();
// All preceding siblings
$crawler->previousAll();
// Parent nodes
$crawler->parents();
// Children
$crawler->children();
// Nodes for which the callable, a lambda, returns true
$crawler->reduce($lambda);
๏  Extraire des données sur des noeuds

// Returns the attribute value for the first node
$crawler->attr('class');

// Returns the node value for the first node
$crawler->text();

// Extracts an array of attributes for all nodes
// (_text returns the node value)
$crawler->extract(array('_text', 'href'));

// Executes a lambda for each node
// and return an array of results
$data = $crawler->each(function ($node, $i) {

      return $node->getAttribute('href');
});
๏  Simuler des clics sur des liens ou boutons

$crawler->selectLink('Click here');

$link = $crawler->link();
$client->click($link);

$links = $crawler->links();



  ๏  Poster des formulaires

// Select the submit button of a form
$crawler->selectButton('submit');

// Get a form instance
$form = $crawler->form();


// Override the default form values
$form = $crawler->form(array(
    'name'         => 'Fabien',
    'like_symfony' => true,
));
Performances
•  PHP 5.3.2 minimum
•  “ Cachy framework “
•  Cache HTTP & Proxy cache (ESI)

•  Faible consommation mémoire
•  Tous les services sont chargés à la demande
// src/Application/BlogBundle/Resources/views/layout.php

$view['actions']->output('BlogBundle:Blog:lastComments', array(), array(
  'standalone' => false
));




                    If	
  the	
  standalone	
  parameter	
  is	
  set	
  
                    to	
  false,	
  Symfony2	
  will	
  render	
  the	
  
                                     HTML	
  content	
  
// src/Application/BlogBundle/Resources/views/layout.php

$view['actions']->output('BlogBundle:Blog:lastComments', array(), array(
  'standalone' => true
));




                 If	
  the	
  standalone	
  parameter	
  is	
  set	
  to	
  
                true	
  and	
  if	
  there	
  is	
  a	
  compa0ble	
  proxy	
     <esi:include	
  src="..."	
  />	
  
                cache,	
  Symfony2	
  will	
  render	
  an	
  ESI	
  tag	
  
Edge Side Includes aka ESI...
Edge Side Includes
Questions ?
Trainings Business Unit
                          trainings@sensio.com

                                Sensio S.A.
                      92-98, boulevard Victor Hugo
                          92 115 Clichy Cedex
                                 FRANCE
                        Tél. : +33 1 40 99 80 80

www.sensiolabs.com - www.symfony-project.org - trainings.sensiolabs.com

Contenu connexe

Tendances

Orchestrez vos projets Symfony sans fausses notes
Orchestrez vos projets Symfony sans fausses notesOrchestrez vos projets Symfony sans fausses notes
Orchestrez vos projets Symfony sans fausses notesXavier Gorse
 
Presentation Symfony
Presentation SymfonyPresentation Symfony
Presentation SymfonyJeremy Gachet
 
Atelier Symfony2- Introduction
Atelier Symfony2- IntroductionAtelier Symfony2- Introduction
Atelier Symfony2- IntroductionMarwa OUNALLI
 
Symfony3 overview
Symfony3 overviewSymfony3 overview
Symfony3 overviewSymfonyMu
 
Presentation du framework symfony
Presentation du framework symfonyPresentation du framework symfony
Presentation du framework symfonyJeremy Gachet
 
Présentation de symfony - Human talks aux docks le 8 juillet 2014
Présentation de symfony - Human talks aux docks le 8 juillet 2014Présentation de symfony - Human talks aux docks le 8 juillet 2014
Présentation de symfony - Human talks aux docks le 8 juillet 2014Tony Galmiche
 
Soutenance Zend Framework vs Symfony
Soutenance Zend Framework vs SymfonySoutenance Zend Framework vs Symfony
Soutenance Zend Framework vs SymfonyVincent Composieux
 
Une application en deux heure - PHP Québec Janvier 2009
Une application en deux heure - PHP Québec Janvier 2009Une application en deux heure - PHP Québec Janvier 2009
Une application en deux heure - PHP Québec Janvier 2009Philippe Gamache
 
Exposer des services web SOAP et REST avec symfony 1.4 et Zend Framework
Exposer des services web SOAP et REST avec symfony 1.4 et Zend FrameworkExposer des services web SOAP et REST avec symfony 1.4 et Zend Framework
Exposer des services web SOAP et REST avec symfony 1.4 et Zend FrameworkHugo Hamon
 
Symfony2 Presentation
Symfony2 PresentationSymfony2 Presentation
Symfony2 Presentationyllieth
 
symfony : Un Framework Open-Source pour les Professionnels
symfony : Un Framework Open-Source pour les Professionnelssymfony : Un Framework Open-Source pour les Professionnels
symfony : Un Framework Open-Source pour les ProfessionnelsFabien Potencier
 
wallabag, comment on a migré vers symfony3
wallabag, comment on a migré vers symfony3wallabag, comment on a migré vers symfony3
wallabag, comment on a migré vers symfony3Nicolas Lœuillet
 
Atelier symfony n 1
Atelier symfony n 1Atelier symfony n 1
Atelier symfony n 1Amir Souissi
 
Utilisation optimale et professionnelle de PHP
Utilisation optimale et professionnelle de PHPUtilisation optimale et professionnelle de PHP
Utilisation optimale et professionnelle de PHPJean-Marc Fontaine
 
Symfony with angular.pptx
Symfony with angular.pptxSymfony with angular.pptx
Symfony with angular.pptxEsokia
 
Procédure de configuration et préparation de l’environnement sous windows
Procédure de configuration et préparation de l’environnement sous windowsProcédure de configuration et préparation de l’environnement sous windows
Procédure de configuration et préparation de l’environnement sous windowsAddi Ait-Mlouk
 

Tendances (20)

Orchestrez vos projets Symfony sans fausses notes
Orchestrez vos projets Symfony sans fausses notesOrchestrez vos projets Symfony sans fausses notes
Orchestrez vos projets Symfony sans fausses notes
 
Presentation Symfony
Presentation SymfonyPresentation Symfony
Presentation Symfony
 
Symfony Best Practices
Symfony Best PracticesSymfony Best Practices
Symfony Best Practices
 
Atelier Symfony2- Introduction
Atelier Symfony2- IntroductionAtelier Symfony2- Introduction
Atelier Symfony2- Introduction
 
Symfony3 overview
Symfony3 overviewSymfony3 overview
Symfony3 overview
 
Presentation du framework symfony
Presentation du framework symfonyPresentation du framework symfony
Presentation du framework symfony
 
Symfony 2 et le Web
Symfony 2 et le WebSymfony 2 et le Web
Symfony 2 et le Web
 
Présentation de symfony - Human talks aux docks le 8 juillet 2014
Présentation de symfony - Human talks aux docks le 8 juillet 2014Présentation de symfony - Human talks aux docks le 8 juillet 2014
Présentation de symfony - Human talks aux docks le 8 juillet 2014
 
Soutenance Zend Framework vs Symfony
Soutenance Zend Framework vs SymfonySoutenance Zend Framework vs Symfony
Soutenance Zend Framework vs Symfony
 
Une application en deux heure - PHP Québec Janvier 2009
Une application en deux heure - PHP Québec Janvier 2009Une application en deux heure - PHP Québec Janvier 2009
Une application en deux heure - PHP Québec Janvier 2009
 
Exposer des services web SOAP et REST avec symfony 1.4 et Zend Framework
Exposer des services web SOAP et REST avec symfony 1.4 et Zend FrameworkExposer des services web SOAP et REST avec symfony 1.4 et Zend Framework
Exposer des services web SOAP et REST avec symfony 1.4 et Zend Framework
 
Symfony2 Presentation
Symfony2 PresentationSymfony2 Presentation
Symfony2 Presentation
 
symfony : Un Framework Open-Source pour les Professionnels
symfony : Un Framework Open-Source pour les Professionnelssymfony : Un Framework Open-Source pour les Professionnels
symfony : Un Framework Open-Source pour les Professionnels
 
wallabag, comment on a migré vers symfony3
wallabag, comment on a migré vers symfony3wallabag, comment on a migré vers symfony3
wallabag, comment on a migré vers symfony3
 
PHP5 et Zend Framework
PHP5 et Zend FrameworkPHP5 et Zend Framework
PHP5 et Zend Framework
 
Laravel Blade
Laravel BladeLaravel Blade
Laravel Blade
 
Atelier symfony n 1
Atelier symfony n 1Atelier symfony n 1
Atelier symfony n 1
 
Utilisation optimale et professionnelle de PHP
Utilisation optimale et professionnelle de PHPUtilisation optimale et professionnelle de PHP
Utilisation optimale et professionnelle de PHP
 
Symfony with angular.pptx
Symfony with angular.pptxSymfony with angular.pptx
Symfony with angular.pptx
 
Procédure de configuration et préparation de l’environnement sous windows
Procédure de configuration et préparation de l’environnement sous windowsProcédure de configuration et préparation de l’environnement sous windows
Procédure de configuration et préparation de l’environnement sous windows
 

En vedette

Intégration Continue PHP avec Jenkins CI
Intégration Continue PHP avec Jenkins CIIntégration Continue PHP avec Jenkins CI
Intégration Continue PHP avec Jenkins CIHugo Hamon
 
Intégration continue des projets PHP avec Jenkins
Intégration continue des projets PHP avec JenkinsIntégration continue des projets PHP avec Jenkins
Intégration continue des projets PHP avec JenkinsHugo Hamon
 
Symfony 2 : chapitre 3 - Les modèles en Doctrine 2
Symfony 2 : chapitre 3 - Les modèles en Doctrine 2Symfony 2 : chapitre 3 - Les modèles en Doctrine 2
Symfony 2 : chapitre 3 - Les modèles en Doctrine 2Abdelkader Rhouati
 
Very lastroom symfony1 vers symfony2 en douceur
Very lastroom   symfony1 vers symfony2 en douceurVery lastroom   symfony1 vers symfony2 en douceur
Very lastroom symfony1 vers symfony2 en douceurSébastien Houzé
 
Symfony 2 : Performances et Optimisations
Symfony 2 : Performances et OptimisationsSymfony 2 : Performances et Optimisations
Symfony 2 : Performances et OptimisationsLes-Tilleuls.coop
 
Drupal 8 + Symfony 2 = une équipe gagnante
Drupal 8 + Symfony 2 = une équipe gagnanteDrupal 8 + Symfony 2 = une équipe gagnante
Drupal 8 + Symfony 2 = une équipe gagnanteVanessa David
 
Design patterns avec Symfony
Design patterns avec SymfonyDesign patterns avec Symfony
Design patterns avec SymfonyMohammed Rhamnia
 
Designing for developers
Designing for developersDesigning for developers
Designing for developersKirsten Hunter
 
The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistenceHugo Hamon
 
Speed up your developments with Symfony2
Speed up your developments with Symfony2Speed up your developments with Symfony2
Speed up your developments with Symfony2Hugo Hamon
 
Design Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleDesign Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleHugo Hamon
 
Symfony2 - Un Framework PHP 5 Performant
Symfony2 - Un Framework PHP 5 PerformantSymfony2 - Un Framework PHP 5 Performant
Symfony2 - Un Framework PHP 5 PerformantHugo Hamon
 
API 101 Workshop from APIStrat Conference
API 101 Workshop from APIStrat ConferenceAPI 101 Workshop from APIStrat Conference
API 101 Workshop from APIStrat ConferenceKirsten Hunter
 
Prototyping in the cloud
Prototyping in the cloudPrototyping in the cloud
Prototyping in the cloudKirsten Hunter
 
This stuff is cool, but...HOW CAN I GET MY COMPANY TO DO IT?
This stuff is cool, but...HOW CAN I GET MY COMPANY TO DO IT?This stuff is cool, but...HOW CAN I GET MY COMPANY TO DO IT?
This stuff is cool, but...HOW CAN I GET MY COMPANY TO DO IT?Mark Heckler
 
Symfony2 en pièces détachées
Symfony2 en pièces détachéesSymfony2 en pièces détachées
Symfony2 en pièces détachéesHugo Hamon
 
Monitor the quality of your Symfony projects
Monitor the quality of your Symfony projectsMonitor the quality of your Symfony projects
Monitor the quality of your Symfony projectsHugo Hamon
 

En vedette (20)

Intégration Continue PHP avec Jenkins CI
Intégration Continue PHP avec Jenkins CIIntégration Continue PHP avec Jenkins CI
Intégration Continue PHP avec Jenkins CI
 
Intégration continue des projets PHP avec Jenkins
Intégration continue des projets PHP avec JenkinsIntégration continue des projets PHP avec Jenkins
Intégration continue des projets PHP avec Jenkins
 
Symfony 2 : chapitre 3 - Les modèles en Doctrine 2
Symfony 2 : chapitre 3 - Les modèles en Doctrine 2Symfony 2 : chapitre 3 - Les modèles en Doctrine 2
Symfony 2 : chapitre 3 - Les modèles en Doctrine 2
 
Very lastroom symfony1 vers symfony2 en douceur
Very lastroom   symfony1 vers symfony2 en douceurVery lastroom   symfony1 vers symfony2 en douceur
Very lastroom symfony1 vers symfony2 en douceur
 
Symfony 2 : Performances et Optimisations
Symfony 2 : Performances et OptimisationsSymfony 2 : Performances et Optimisations
Symfony 2 : Performances et Optimisations
 
Drupal 8 + Symfony 2 = une équipe gagnante
Drupal 8 + Symfony 2 = une équipe gagnanteDrupal 8 + Symfony 2 = une équipe gagnante
Drupal 8 + Symfony 2 = une équipe gagnante
 
Design patterns avec Symfony
Design patterns avec SymfonyDesign patterns avec Symfony
Design patterns avec Symfony
 
Designing for developers
Designing for developersDesigning for developers
Designing for developers
 
The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistence
 
Speed up your developments with Symfony2
Speed up your developments with Symfony2Speed up your developments with Symfony2
Speed up your developments with Symfony2
 
Design Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleDesign Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et Pimple
 
Symfony2 - Un Framework PHP 5 Performant
Symfony2 - Un Framework PHP 5 PerformantSymfony2 - Un Framework PHP 5 Performant
Symfony2 - Un Framework PHP 5 Performant
 
API 101 Workshop from APIStrat Conference
API 101 Workshop from APIStrat ConferenceAPI 101 Workshop from APIStrat Conference
API 101 Workshop from APIStrat Conference
 
Quantifying fitness
Quantifying fitnessQuantifying fitness
Quantifying fitness
 
Prototyping in the cloud
Prototyping in the cloudPrototyping in the cloud
Prototyping in the cloud
 
Api 101
Api 101Api 101
Api 101
 
This stuff is cool, but...HOW CAN I GET MY COMPANY TO DO IT?
This stuff is cool, but...HOW CAN I GET MY COMPANY TO DO IT?This stuff is cool, but...HOW CAN I GET MY COMPANY TO DO IT?
This stuff is cool, but...HOW CAN I GET MY COMPANY TO DO IT?
 
Facebook appsincloud
Facebook appsincloudFacebook appsincloud
Facebook appsincloud
 
Symfony2 en pièces détachées
Symfony2 en pièces détachéesSymfony2 en pièces détachées
Symfony2 en pièces détachées
 
Monitor the quality of your Symfony projects
Monitor the quality of your Symfony projectsMonitor the quality of your Symfony projects
Monitor the quality of your Symfony projects
 

Similaire à Introduction à Symfony2

#J2Code2018 - Mettez du feu à vos applications avec CodeIgniter
#J2Code2018 - Mettez du feu à vos applications avec CodeIgniter#J2Code2018 - Mettez du feu à vos applications avec CodeIgniter
#J2Code2018 - Mettez du feu à vos applications avec CodeIgniterAtsé François-Xavier KOBON
 
Atelier symfony n 2
Atelier symfony n 2Atelier symfony n 2
Atelier symfony n 2Amir Souissi
 
Fascicule de tp atelier développement web
Fascicule de tp atelier développement webFascicule de tp atelier développement web
Fascicule de tp atelier développement webHouda TOUKABRI
 
Apache flink - prise en main rapide
Apache flink - prise en main rapideApache flink - prise en main rapide
Apache flink - prise en main rapideBilal Baltagi
 
Comment réussir son projet en Angular 1.5 ?
Comment réussir son projet en Angular 1.5 ?Comment réussir son projet en Angular 1.5 ?
Comment réussir son projet en Angular 1.5 ?Maxime Bernard
 
Php 7.4 2020-01-28 - afup
Php 7.4   2020-01-28 - afupPhp 7.4   2020-01-28 - afup
Php 7.4 2020-01-28 - afupJulien Vinber
 
Un exemple élémentaire d'application MVC en PHP
Un exemple élémentaire d'application MVC en PHPUn exemple élémentaire d'application MVC en PHP
Un exemple élémentaire d'application MVC en PHPKristen Le Liboux
 
hassclic270.ppt
hassclic270.ppthassclic270.ppt
hassclic270.pptadiouf2
 
Rich Desktop Applications
Rich Desktop ApplicationsRich Desktop Applications
Rich Desktop Applicationsgoldoraf
 
SOLID : les principes à l’origine du succès de Symfony et de vos applications
SOLID : les principes à l’origine du succès de Symfony et de vos applicationsSOLID : les principes à l’origine du succès de Symfony et de vos applications
SOLID : les principes à l’origine du succès de Symfony et de vos applicationsVladyslav Riabchenko
 
Checklist pour concevoir une application dans le cloud.10 conseils à l'attent...
Checklist pour concevoir une application dans le cloud.10 conseils à l'attent...Checklist pour concevoir une application dans le cloud.10 conseils à l'attent...
Checklist pour concevoir une application dans le cloud.10 conseils à l'attent...Alexandre Touret
 
Annotations pour les Geeks
Annotations pour les GeeksAnnotations pour les Geeks
Annotations pour les Geeksjviet
 
Spring Boot & Containers - Do's & Don'ts
Spring Boot & Containers - Do's & Don'tsSpring Boot & Containers - Do's & Don'ts
Spring Boot & Containers - Do's & Don'tsJulien Wittouck
 
Checklist pour concevoir une application dans le cloud.10 conseils à l'attent...
Checklist pour concevoir une application dans le cloud.10 conseils à l'attent...Checklist pour concevoir une application dans le cloud.10 conseils à l'attent...
Checklist pour concevoir une application dans le cloud.10 conseils à l'attent...Alexandre Touret
 
Aspect avec AspectJ
Aspect avec AspectJAspect avec AspectJ
Aspect avec AspectJsimeon
 
ZendFramework2 - Présentation
ZendFramework2 - PrésentationZendFramework2 - Présentation
ZendFramework2 - Présentationjulien pauli
 

Similaire à Introduction à Symfony2 (20)

#J2Code2018 - Mettez du feu à vos applications avec CodeIgniter
#J2Code2018 - Mettez du feu à vos applications avec CodeIgniter#J2Code2018 - Mettez du feu à vos applications avec CodeIgniter
#J2Code2018 - Mettez du feu à vos applications avec CodeIgniter
 
Atelier symfony n 2
Atelier symfony n 2Atelier symfony n 2
Atelier symfony n 2
 
Framework php « Codeignitor »
Framework php « Codeignitor » Framework php « Codeignitor »
Framework php « Codeignitor »
 
Introduction à Symfony
Introduction à SymfonyIntroduction à Symfony
Introduction à Symfony
 
Fascicule de tp atelier développement web
Fascicule de tp atelier développement webFascicule de tp atelier développement web
Fascicule de tp atelier développement web
 
Apache flink - prise en main rapide
Apache flink - prise en main rapideApache flink - prise en main rapide
Apache flink - prise en main rapide
 
Comment réussir son projet en Angular 1.5 ?
Comment réussir son projet en Angular 1.5 ?Comment réussir son projet en Angular 1.5 ?
Comment réussir son projet en Angular 1.5 ?
 
Php 7.4 2020-01-28 - afup
Php 7.4   2020-01-28 - afupPhp 7.4   2020-01-28 - afup
Php 7.4 2020-01-28 - afup
 
Un exemple élémentaire d'application MVC en PHP
Un exemple élémentaire d'application MVC en PHPUn exemple élémentaire d'application MVC en PHP
Un exemple élémentaire d'application MVC en PHP
 
hassclic270.ppt
hassclic270.ppthassclic270.ppt
hassclic270.ppt
 
Rich Desktop Applications
Rich Desktop ApplicationsRich Desktop Applications
Rich Desktop Applications
 
SOLID : les principes à l’origine du succès de Symfony et de vos applications
SOLID : les principes à l’origine du succès de Symfony et de vos applicationsSOLID : les principes à l’origine du succès de Symfony et de vos applications
SOLID : les principes à l’origine du succès de Symfony et de vos applications
 
Checklist pour concevoir une application dans le cloud.10 conseils à l'attent...
Checklist pour concevoir une application dans le cloud.10 conseils à l'attent...Checklist pour concevoir une application dans le cloud.10 conseils à l'attent...
Checklist pour concevoir une application dans le cloud.10 conseils à l'attent...
 
Lp web tp3_idse
Lp web tp3_idseLp web tp3_idse
Lp web tp3_idse
 
Annotations pour les Geeks
Annotations pour les GeeksAnnotations pour les Geeks
Annotations pour les Geeks
 
Introduction à Symfony
Introduction à SymfonyIntroduction à Symfony
Introduction à Symfony
 
Spring Boot & Containers - Do's & Don'ts
Spring Boot & Containers - Do's & Don'tsSpring Boot & Containers - Do's & Don'ts
Spring Boot & Containers - Do's & Don'ts
 
Checklist pour concevoir une application dans le cloud.10 conseils à l'attent...
Checklist pour concevoir une application dans le cloud.10 conseils à l'attent...Checklist pour concevoir une application dans le cloud.10 conseils à l'attent...
Checklist pour concevoir une application dans le cloud.10 conseils à l'attent...
 
Aspect avec AspectJ
Aspect avec AspectJAspect avec AspectJ
Aspect avec AspectJ
 
ZendFramework2 - Présentation
ZendFramework2 - PrésentationZendFramework2 - Présentation
ZendFramework2 - Présentation
 

Introduction à Symfony2

  • 2. •  Hugo HAMON (@hhamon) •  Responsable des formations Sensio Labs •  Secrétaire Général de l’AFUP •  10 ans de développement web dont 8 avec PHP •  Coauteur d’ouvrages Eyrolles •  Apprendre-PHP.com / HugoHamon.com
  • 7. •  Développer plus vite et mieux •  Faciliter le travail en équipe •  Pérenniser les applications •  Simpli er la maintenance et les évolutions •  Se concentrer sur la logique métier •  Ne pas réinventer la roue !
  • 8. Symfony2 intègre les meilleurs outils Open-Source PHP
  • 9. Symfony Components Dependency Injection Container Request Handler Event Dispatcher Console YAML …
  • 10. Zend Framework PHPUnit Doctrine2 Swift Mailer Twig
  • 12. Même philosophie, Même outillage, Moins de concepts, Plus de exibilité Performances accrues 
  • 14. •  Version ALPHA •  Briques logicielles manquantes •  Documentation incomplète •  L’API peut encore beaucoup évoluer •  Version stable repoussée à début Mars 2011
  • 15. Je veux tester Symfony2 ! git clone http://github.com/symfony/symfony-sandbox.git http://www.symfony-reloaded.org
  • 16. Je veux développer un projet client maintenant avec Symfony2 ? A ta place, je ne ferai pas ça…
  • 18. •  Sécurité •  Extensibilité •  Architecture MVC •  I18N & L10N •  URLs élégantes •  Authenti cation et ACLs •  DBAL & ORM •  Tests unitaires •  Outils de débogage •  Tests fonctionnels •  Formulaires •  Cache •  Con guration •  Admin Generator
  • 20. Un Projet Symfony2 est un répertoire qui se compose d’une Application, d’un jeu de Bundles et de librairies.
  • 21. . |-- LICENSE |-- README |-- app/ | |-- AppCache.php | |-- AppKernel.php Répertoire  de  l’Applica0on   | |-- cache/ | |-- config/ | |-- console | |-- logs/ | |-- phpunit.xml.dist | `-- views/ |-- bin/ | |-- create_sandbox.sh | |-- install_vendors.sh | |-- prepare_vendors.sh | `-- update_vendors.sh |-- src/ | |-- Application/ | |-- Bundle/ Code  de  l’Applica0on  +     | |-- autoload.php Bundles  +     | `-- vendor/ Librairies  externes   `-- web/ |-- bundles/ |-- check.php |-- index.php Dossier  public   `-- index_dev.php
  • 22. Une Application est un répertoire qui contient la con guration pour un jeu de Bundles donné.
  • 23. Structure d’une application app/ |-- AppCache.php |-- AppKernel.php The  AppKernel  class  is  the   |-- cache/  main  class  of  the  applica0on   |-- config/ | |-- config.yml | |-- config_dev.yml | |-- config_test.yml | |-- routing.yml Configura0on  files   | `-- routing_dev.yml |-- console |-- logs/ | `-- dev.log |-- phpunit.xml.dist Logs  and  applica0on  templates   `-- views/ |-- layout.php
  • 24. Un Bundle est un ensemble structuré et cohérent de chiers qui implémentent une fonctionnalité (un blog, un forum, …) et qui peut facilement être partagé avec d’autres développeurs.
  • 25. symfony 1.x => Plugins Symfony 2.x => Bundles
  • 26. + BlogBundle/ Code  source  du  bundle  :  contrôleurs   |-- Controller/ | `-- BlogController.php modèles,  formulaires…   |-- Entity/ | `-- Post.php |-- Form/ | `-- PostForm.php Le  fichier  BlogBundle.php  est   |-- BlogBundle.php |-- Model/ obligatoire  et  con0ent  la  classe  qui   | `-- PostRepository.php déclare  le  bundle.   |-- Resources/ | |-- config/ | | `-- routing.yml | |-- views/ | | `-- Blog/ Un  bundle  peut  contenir  de  la   | | |-- showPost.php configura0on,  des  templates  et  des   | | `-- listPost.php ressources  web.   | `-- public/ | `-- css/ | `-- blog.css `-- Tests/ Un  bundle  peut  aussi  contenir   `-- Controller/ `-- BlogControllerTest.php des  scripts  de  tests  PHPUnit.  
  • 28. XSS CSRF SQL Injections
  • 29. Le dossier web/ du projet est le seul accessible depuis un navigateur web
  • 31. Le système de routage a pour rôle de convertir une URL en une réponse web.
  • 32. Elles sont propres et élégantes a n d’exposer des informations pertinentes et de masquer l’implémentation technique… http://www.domain.com/blog/2010/09/15/symfony2-rocks
  • 33. Con guration des URLs en YAML # src/Bundle/BlogBundle/Resources/config/routing.yml post_details: pattern: /blog/:year/:month/:day/:slug defaults: { _controller: BlogBundle:Blog:showPost } Exemple d’URL générée http://www.domain.com/blog/2010/09/15/symfony2-rocks
  • 35. # src/Application/HelloBundle/Resources/config/routing.yml hello: pattern: /hello/:name defaults: { _controller: HelloBundle:Hello:index } # src/Application/HelloBundle/Controller/HelloController.php namespace ApplicationHelloBundleController; class HelloController extends Controller { public function indexAction($name) { // ... } }
  • 36. # src/Application/HelloBundle/Resources/config/routing.yml hello: Nom  du  Bundle   pattern: /hello/:name defaults: { _controller: HelloBundle:Hello:index } # src/Application/HelloBundle/Controller/HelloController.php namespace ApplicationHelloBundleController; class HelloController extends Controller Un  dossier  /  namespace   { public function indexAction($name) { // ... } }
  • 37. # src/Application/HelloBundle/Resources/config/routing.yml hello: Nom  du  contrôleur   pattern: /hello/:name defaults: { _controller: HelloBundle:Hello:index } # src/Application/HelloBundle/Controller/HelloController.php namespace ApplicationHelloBundleController; class HelloController extends Controller Une  classe   { public function indexAction($name) { // ... } }
  • 38. # src/Application/HelloBundle/Resources/config/routing.yml hello: Nom  de  l’ac0on   pattern: /hello/:name defaults: { _controller: HelloBundle:Hello:index } # src/Application/HelloBundle/Controller/HelloController.php namespace ApplicationHelloBundleController; class HelloController extends Controller { public function indexAction($name) { // ... } Une  méthode   }
  • 39. # src/Application/HelloBundle/Resources/config/routing.yml hello: pattern: /hello/:name defaults: { _controller: HelloBundle:Hello:index } # src/Application/HelloBundle/Controller/HelloController.php namespace ApplicationHelloBundleController; class HelloController extends Controller { public function indexAction($name) { // ... } }
  • 40. Les paramètres peuvent être passés dans un ordre arbitraire post_details: pattern: /blog/:year/:month/:day/:slug defaults: { _controller: BlogBundle:Blog:showPost } namespace ApplicationBlogBundleController; class BlogController extends Controller { public function showPostAction($slug, $year) { // ... } }
  • 42. •  Séparation du code en trois couches – Logique métier dans le Modèle – Logique applicative dans le Contrôleur – Affichage dans la Vue (templates) •  Modularité et découplage du code •  Maintenance simpli ée sur le code source •  Code testable unitairement et plus robuste
  • 43. Les actions pour la logique applicative. Elles se situent dans les Contrôleurs.
  • 44. ๏  Une action est accessible depuis une URL # src/Application/BlogBundle/Resources/config/routing.yml post_show: pattern: /blog/article/:id/show defaults: { _controller: BlogBundle:Blog:show }
  • 45. # src/Application/BlogBundle/Controller/BlogController.php namespace ApplicationBlogBundleController; use SymfonyBundleFrameworkBundleControllerController; class BlogController extends Controller { public function showAction($id) Paramètres  de  l’url   { // find the article by its id $post = ...; // render the view return $this->render('BlogBundle:Blog:show', array('post' => $post)); } } Template  à  rendre   Variables  du  template  
  • 46. Les templates constituent la couche de présentation des données, la vue.
  • 47. ๏  Syntaxe alternative de PHP ๏  Quelques brèves instructions PHP (echo, if, foreach…) ๏  Echappement automatique des variables # src/Application/BlogBundle/Resources/views/Blog/show.php <?php $view->extend('::layout') ?> Layout  de  décora0on   <h2><?php echo $post->getTitle() ?></h2> <p> <?php echo $post->getContent() ?> </p> Variables  échappées  =>  pas  de  XSS  !!!  
  • 49. # src/Application/HelloBundle/Resources/views/Hello/index.php <?php $view->extend('::layout') ?> Hello <?php echo $name ?>! étend # app/views/layout.php <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title> <?php $view['slots']->output('title', 'Hello Application') ?> </title> </head> <body> <?php $view['slots']->output('_content') ?> </body> </html>
  • 50. Héritage de Vues layout.php _content Hello Hugo! index.php
  • 51. # src/Application/HelloBundle/Resources/views/Hello/index.php <?php $view->extend('HelloBundle::layout') ?> Hello <?php echo $name ?>! # src/Application/HelloBundle/Resources/views/layout.php <?php $view->extend('::layout') ?> <h1>Hello Application</h1> <div> <?php $view['slots']->output('_content') ?> </div> # app/views/layout.php <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title> <?php $view['slots']->output('title', 'Hello Application') ?> </title> </head> <body> <?php $view['slots']->output('_content') ?> </body> </html>
  • 52. Héritage multiple ::layout.php HelloBundle::layout.php _content Hello Hugo! _content index.php
  • 53. Les Slots sont des fragments dé nis dans un template et affichés dans un layout décorant ce dernier.
  • 54. # src/Application/HelloBundle/Resources/views/Hello/index.php <?php $view['slots']->set('title', 'Hello World app') ?> # app/views/layout.php <html> <head> <title> <?php $view['slots']->output('title', 'Hello Application') ?> </title> </head> <body> <?php $view['slots']->output('_content') ?> </body> </html>
  • 55. Symfony fournit des mécanismes simples pour évaluer et inclure des templates dans un autre # src/Application/HelloBundle/Resources/views/Hello/hello.php Hello <?php echo $name ?>! # Including another template in the current template <?php echo $view->render('HelloBundle:Hello:hello', array('name' => $name)) ?> src/Bundle/HelloBundle/Resources/views/Hello/hello.php  
  • 56. Symfony offre également un moyen d’inclure le rendu d’une action depuis une vue… # src/Application/HelloBundle/Resources/views/Hello/index.php <?php $view['actions']->output('HelloBundle:Hello:fancy', array( 'name' => $name, 'color' => 'green’ )) ?>
  • 57. # src/Application/HelloBundle/Controller/HelloController.php class HelloController extends Controller { public function fancyAction($name, $color) { // create some object, based on the $color variable $object = ...; return $this->render('HelloBundle:Hello:fancy', array( 'name' => $name, 'object' => $object )); } // ... }
  • 58. Les aides de vue sont des objets accessibles depuis les templates et qui permettent de simpli er la logique d’affichage
  • 59. Générer une URL avec le router helper <a href="<?php echo $view['router']->generate('hello', array( 'name' => 'Thomas')) ?>">Greet Thomas!</a> Inclure des feuilles de style <head> <!-- ... --> <?php $view['stylesheets']->add('css/styles.css') ?> <?php echo $view['stylesheets'] ?> </head>
  • 60. Inclure des javascripts <head> <!-- ... --> <?php $view['javascripts']->add('js/libraries.js') ?> <?php echo $view['javascripts'] ?> </head> Manipuler des ressource web (images, ash…) <img src="<?php echo $view['assets']->getUrl('images/logo.png') ?>" src=""/> Traduire des chaînes de l’interface <?php echo $view['translator']->trans('Symfony is %what%!', array( '%what%' => 'awesome')) ?>
  • 62. 3 formats de con guration PHP YAML XML
  • 63. Quel format choisir ? Avantages Inconvénients XML Validation Verbeux Complétion dans les EDIs Long à écrire Facile à analyser YAML Concis Besoin du composant YAML Facile à lire Pas de validation Facile à modi er Pas d’autocomplétion PHP Flexible Pas de validation Plus facile à manipuler
  • 64. Con guration en YML # app/config/routing.php homepage: pattern: / defaults: { _controller: FrameworkBundle:Default:index } hello: resource: HelloBundle/Resources/config/routing.yml Import  d’une  autre  configura0on  
  • 65. Con guration en PHP # app/config/routing.php use SymfonyComponentRoutingRouteCollection; use SymfonyComponentRoutingRoute; $collection = new RouteCollection(); $collection->addRoute('homepage', new Route('/', array( '_controller' => 'FrameworkBundle:Default:index', ))); $collection->addCollection( $loader->import("HelloBundle/Resources/config/routing.php") ); Import  d’une  autre  configura0on   return $collection;
  • 66. Con guration en XML # app/config/routing.xml <?xml version="1.0" encoding="UTF-8" ?> <routes xmlns="http://www.symfony-project.org/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.symfony-project.org/schema/routing http:// www.symfony-project.org/schema/routing/routing-1.0.xsd"> <route id="homepage" pattern="/"> <default key="_controller">FrameworkBundle:Default:index</default> </route> <import resource="HelloBundle/Resources/config/routing.xml" /> </routes> Import  d’une  autre  configura0on  
  • 67. Import de chiers INI # app/config/config_dev.yml imports: - { resource: config.yml } - { resource: custom.ini} zend.logger: priority: debug path: %kernel.root_dir%/logs/%kernel.environment%.log # app/config/custom.ini [parameters] dice.min = 1 dice.max = 6
  • 68. Accès à la con guration depuis le code public function diceAction() { // ... $min = (int) $this->container->getParameter('dice.min'); $max = (int) $this->container->getParameter('dice.max'); // ... }
  • 70. Parce qu’il est important pour un développeur d’identi er rapidement les bogues et les problèmes !!!
  • 72. Logs
  • 73. Traces d’exception Trace  de  l’excep0on   courrante   Trace  pour  une   InvalidArgumentExcep0on   404  Status  Code  
  • 74. Afficher  /  masquer  la  trace  d’une   excep0on   Logs  enregistrés   Lien  vers  le  profiler  
  • 76. Trace  de  l’excep0on   Recherche  dans  les  logs  
  • 80. Enregistrement de bundles # app/AppKernel.php class AppKernel extends Kernel { // ... public function registerBundles() { $bundles = array( // ... // Register third party bundles new BundleTwitterBundleTwitterBundle(), new BundleForumBundleForumBundle() ); // ... return $bundles; } }
  • 81. DBAL & ORM Doctrine2
  • 82. •  Abstraction de base de données relationnelles •  Performance •  Plus de magie •  Manipulation de vrais objets PHP (POPO) •  Génération de code •  Adapteur MongoDB disponible
  • 83. ๏  Con gurer la connexion BDD en YAML # app/config/config.yml doctrine.dbal: dbname: Blog user: root password: ~ doctrine.orm: ~ ๏  Con gurer la connexion BDD dans Apache // web/.htaccess or in the vhost configuration SetEnv SYMFONY__DOCTRINE__DBAL__USERNAME "root" SetEnv SYMFONY__DOCTRINE__DBAL__PASSWORD "secret"
  • 84. ๏  Dé nition d’une entité (table) à l’aide d’une classe PHP namespace ApplicationBlogBundleEntity; /** * @Entity(repositoryClass="ApplicationBlogBundleModelBlogPostRepository") * @Table(name="blog_post") */ Annota0ons   class BlogPost { /** * @Id @Column(type="integer") * @GeneratedValue(strategy="IDENTITY") */ protected $id; /** @Column(length=100) */ protected $title; /** @Column(type="text") */ protected $content; }
  • 85. ๏  Génération de la base de données à partir des classes PHP $ php app/console doctrine:database:create $ php app/console doctrine:schema:create ๏  Chargement des données de test $ php app/console doctrine:data:load
  • 86. ๏  Les données de test sont écrites en pur PHP # src/Application/BlogBundle/Resources/data/fixtures/doctrine/fixtures.php use ApplicationBlogBundleEntityBlogPost; $post1 = new BlogPost(); $post1->setTitle('My first blog post'); $post1->setContent('Lorem ipsum dolor sit amet...'); $post2 = new BlogPost(); $post2->setTitle('My second blog post'); $post2->setContent('Lorem ipsum dolor sit amet...'); $post3 = new BlogPost(); $post3->setTitle('My third blog post'); $post3->setContent('Lorem ipsum dolor sit amet...');
  • 87. ๏  Ecrire des requêtes DQL dans un modèle Doctrine # src/Application/BlogBundle/Model/BlogPostRepository.php namespace ApplicationBlogBundleModel; use DoctrineORMEntityRepository; class BlogPostRepository extends EntityRepository { public function getHomepagePosts() { $query = $this->_em->createQuery(' SELECT u FROM BlogBundle:BlogPost u ORDER BY u.id DESC '); return $query->getResult(); } }
  • 88. ๏  Interroger la base de données à l’aide du Modèle Doctrine # src/Application/BlogBundle/Controller/BlogController.php // ... class BlogController extends Controller { public function indexAction() { $em = $this['doctrine.orm.entity_manager']; $posts = $em->getRepository('BlogBundle:BlogPost') ->getHomepagePosts(); return $this->render('BlogBundle:Blog:index', array( 'posts' => $posts )); } // ... }
  • 90. •  API Orientée Objet Open-Source •  Support des connexions SMTP •  Support des pièces jointes •  Support des formats de mails (text, html…) •  Gestion des les d’attente (spools) •  Facile à con gurer et à étendre avec des plugins
  • 91. Con gurer Swift Mailer # app/config/config.yml swift.mailer: transport: smtp encryption: ssl auth_mode: login host: smtp.gmail.com username: your_username password: your_password
  • 92. Envoyer un Email public function indexAction($name) { Récupéra0on  du  service  d’envoi  de  mails   $mailer = $this['mailer']; $message = Swift_Message::newInstance() ->setSubject('Hello Email') ->setFrom('send@example.com') ->setTo('recipient@example.com') ->setBody($this->renderView('HelloBundle:Hello:email', array( 'name' => $name ))); Généra0on  du  corps  du  mail  à  l’aide   d’un  template  et  de  la  méthode   $mailer->send($message); renderView()   return $this->render(...); }
  • 94. •  Tests Unitaires et Couverture de Code •  Garantir la qualité du code •  Eviter les bugs et les régressions •  Documenter le code •  Industrialiser et professionnaliser les développements
  • 95. ๏  Exemple de script de tests unitaires dans Symfony2 # src/Application/BlogBundle/Tests/Entity/BlogPostTest.php namespace ApplicationBlogBundleTestsEntity; use ApplicationBlogBundleEntityBlogPost; class BlogPostTest extends PHPUnit_Framework_TestCase { public function testTitleIsSlugifiedOnce() { $slug = 'symfony2-rules-the-world'; $post = new BlogPost(); $post->setTitle('Symfony2 rules the world'); $this->assertEquals($slug, $post->getSlug()); // Slug doesn't change when it's already set $post->setTitle('An other title'); $this->assertEquals($slug, $post->getSlug()); } }
  • 96. •  Tests fonctionnels •  Simuler des scénarios de navigation •  Simuler un client Web (navigateur) •  Véri er que l’application respecte le cahier des charges
  • 97. ๏  Exemple de script de tests fonctionnels dans Symfony2 class BlogControllerTest extends WebTestCase { // ... public function testAddComment() { $this->client->followRedirects(); $crawler = $this->client->request('GET', '/'); // Get the first link to a post $link = $crawler->filter('h2.post a')->first()->link(); // Click on the link and check there are two comments $crawler = $this->client->click($link); $this->assertTrue($crawler->filter('.comment')->count() == 2); } }
  • 98. ๏  Simuler des requêtes GET $crawler = $client->request('GET', '/hello/Fabien'); ๏  Simuler des requêtes POST $client->request('POST', '/submit', array('name' => 'Fabien') ๏  Simuler des uploads de chiers en POST $client->request('POST', '/submit', array('name' => 'Fabien'), array('photo' => '/path/to/photo') );
  • 99. ๏  Simuler une requête HTTP DELETE avec des entêtes $client->request('DELETE', '/post/12', array(), array(), array( 'PHP_AUTH_USER' => 'username', 'PHP_AUTH_PW' => 'pa$$word' )); ๏  Désactiver / activer les redirections HTTP $client->followRedirects(false); $client->followRedirect(); ๏  Insoler le client dans un processus séparé $client->insulate();
  • 100. ๏  Naviguer dans l’historique comme dans un navigateur web $client->back(); $client->forward(); $client->reload(); ๏  Réinitialiser le Client $client->restart();
  • 101. ๏  Parcourir le DOM avec le DOM Crawler // Nodes that match the CSS selector $crawler->filter('h1'); // Nodes that match the XPath expression $crawler->filterXpath('h1'); // Node for the specified index $crawler->eq(1); // First node $crawler->first(); // Last node $crawler->last();
  • 102. // Siblings $crawler->siblings(); // All following siblings $crawler->nextAll(); // All preceding siblings $crawler->previousAll(); // Parent nodes $crawler->parents(); // Children $crawler->children(); // Nodes for which the callable, a lambda, returns true $crawler->reduce($lambda);
  • 103. ๏  Extraire des données sur des noeuds // Returns the attribute value for the first node $crawler->attr('class'); // Returns the node value for the first node $crawler->text(); // Extracts an array of attributes for all nodes // (_text returns the node value) $crawler->extract(array('_text', 'href')); // Executes a lambda for each node // and return an array of results $data = $crawler->each(function ($node, $i) { return $node->getAttribute('href'); });
  • 104. ๏  Simuler des clics sur des liens ou boutons $crawler->selectLink('Click here'); $link = $crawler->link(); $client->click($link); $links = $crawler->links(); ๏  Poster des formulaires // Select the submit button of a form $crawler->selectButton('submit'); // Get a form instance $form = $crawler->form(); // Override the default form values $form = $crawler->form(array( 'name' => 'Fabien', 'like_symfony' => true, ));
  • 106. •  PHP 5.3.2 minimum •  “ Cachy framework “ •  Cache HTTP & Proxy cache (ESI) •  Faible consommation mémoire •  Tous les services sont chargés à la demande
  • 107. // src/Application/BlogBundle/Resources/views/layout.php $view['actions']->output('BlogBundle:Blog:lastComments', array(), array( 'standalone' => false )); If  the  standalone  parameter  is  set   to  false,  Symfony2  will  render  the   HTML  content  
  • 108. // src/Application/BlogBundle/Resources/views/layout.php $view['actions']->output('BlogBundle:Blog:lastComments', array(), array( 'standalone' => true )); If  the  standalone  parameter  is  set  to   true  and  if  there  is  a  compa0ble  proxy   <esi:include  src="..."  />   cache,  Symfony2  will  render  an  ESI  tag  
  • 109. Edge Side Includes aka ESI...
  • 111.
  • 112.
  • 114. Trainings Business Unit trainings@sensio.com Sensio S.A. 92-98, boulevard Victor Hugo 92 115 Clichy Cedex FRANCE Tél. : +33 1 40 99 80 80 www.sensiolabs.com - www.symfony-project.org - trainings.sensiolabs.com