L3 Info : PHP et Applications Web
 
◃  Ch. 11 Some old Stuff (chapitre non maintenu)  ▹
 

ORM

  • ORM : Object Relational Mapper
  • Symfony utilise Doctrine
  • Les entités sont des classes qui correspondent aux tables des BD dans lesquelles :
    • les attributs d'instances sont associées aux colonnes,
    • des annotations (commentaires associés au code) décrivent les liens entre classe et table ou entre attributs et colonnes
    • les accesseurs et modifieurs sont définis.
  • Configuration de la base de données :
    • Fichier app/config/parameters.yml
      parameters:
          database_host: ust-infoserv.univlehavre.lan
          database_port: null
          database_name: xy123456
          database_user: xy123456
          database_password: *****
                          (...)
  • Création d'une entité en ligne de commande :
    $ php bin/console doctrine:generate:entity
    
      Welcome to the Doctrine2 entity generator
    
    This command helps you generate Doctrine2 entities.
    
    First, you need to give the entity name you want to generate.
    You must use the shortcut notation like AcmeBlogBundle:Post.
    
    The Entity shortcut name: AppBundle:Collectivite
    
    Determine the format to use for the mapping information.
    
    Configuration format (yml, xml, php, or annotation) [annotation]:
    
    Instead of starting with a blank entity, you can add some fields now.
        Note that the primary key will be added automatically (named id).
    
    Available types: array, simple_array, json_array, object,
    boolean, integer, smallint, bigint, string, text, datetime, datetimetz,
    date, time, decimal, float, binary, blob, guid.
    
    New field name (press <return> to stop adding fields): col_code
    Field type [string]: string
    Field length [255]: 3
    Is nullable [false]:
    Unique [false]: true
    
    New field name (press <return> to stop adding fields): col_nom
    Field type [string]:
    Field length [255]: 50
    Is nullable [false]:
    Unique [false]:
    
    New field name (press <return> to stop adding fields): col_population
    Field type [string]: integer
    Is nullable [false]:
    Unique [false]:
    
    New field name (press <return> to stop adding fields): col_superficie
    Field type [string]: integer
    Is nullable [false]:
    Unique [false]:
    
    New field name (press <return> to stop adding fields): col_region
    Field type [string]:
    Field length [255]: 30
    Is nullable [false]:
    Unique [false]:
    
    New field name (press <return> to stop adding fields):
    
      Entity generation
    
      created ./src/AppBundle/Entity/Collectivite.php
    > Generating entity class src/AppBundle/Entity/Collectivite.php: OK!
    > Generating repository class src/AppBundle/Repository/CollectiviteRepository.php: OK!
    
    
      Everything is OK! Now get to work :).
    
  • Classe AppBundle/Entity/Collectivite.php :
    namespace AppBundle\Entity;
    
    use Doctrine\ORM\Mapping as ORM;
    
    /**
      * Collectivite
      *
      * @ORM\Table(name="collectivite")
      * @ORM\Entity(repositoryClass="AppBundle\Repository\CollectiviteRepository")
      */
    class Collectivite
    {
        /**
         * @var int
         *
         * @ORM\Column(name="id", type="integer")
         * @ORM\Id
         * @ORM\GeneratedValue(strategy="AUTO")
            */
        private $id;
    
        /**
         * @var string
         *
         * @ORM\Column(name="col_code", type="string", length=3, unique=true)
         */
        private $colCode;
    
        /**
         * @var string
         *
         * @ORM\Column(name="col_nom", type="string", length=50)
         */
        private $colNom;
    
        /**
         * @var int
         *
         * @ORM\Column(name="col_population", type="integer")
         */
        private $colPopulation;
    
        /**
         * @var int
         *
         * @ORM\Column(name="col_superficie", type="integer")
         */
        private $colSuperficie;
    
        /**
         * @var string
         *
         * @ORM\Column(name="col_region", type="string", length=30)
         */
        private $colRegion;
    
    
        /**
         * Get id
         *
         * @return int
         */
        public function getId()
        {
            return $this->id;
        }
    
                /* (...) suite des getters et des setters */
    
    
  • validation / maj des schemas
    $ php bin/console doctrine:schema:validate
    $ php bin/console doctrine:schema:update [ --force | --dump-sql ]
    
    Table produite sur le SGBD :
    mysql> describe collectivite;
    +----------------+-------------+------+-----+---------+----------------+
    | Field          | Type        | Null | Key | Default | Extra          |
    +----------------+-------------+------+-----+---------+----------------+
    | id             | int(11)     | NO   | PRI | NULL    | auto_increment |
    | col_code       | varchar(3)  | NO   | UNI | NULL    |                |
    | col_nom        | varchar(50) | NO   |     | NULL    |                |
    | col_population | int(11)     | NO   |     | NULL    |                |
    | col_superficie | int(11)     | NO   |     | NULL    |                |
    | col_region     | varchar(30) | NO   |     | NULL    |                |
    +----------------+-------------+------+-----+---------+----------------+
    6 rows in set (0,00 sec)
    
  • Rien n'empêche de construire soit même ses entités.
  • Les annotations en détail
  • Controleur et gestion des actions CRUD
    • Exemple sur l'entité LivreSF mappé sur une table LivreSF
    • mysql> describe livresf;
      +-------------+--------------+------+-----+---------+----------------+
      | Field       | Type         | Null | Key | Default | Extra          |
      +-------------+--------------+------+-----+---------+----------------+
      | liv_num     | int(11)      | NO   | PRI | NULL    | auto_increment |
      | liv_titre   | varchar(100) | NO   |     | NULL    |                |
      | auteursf_id | int(11)      | YES  | MUL | NULL    |                |
      +-------------+--------------+------+-----+---------+----------------+
      3 rows in set (0,00 sec)
      
      
    • Controlleur LivreSFController
      namespace AppBundle\Controller;
      
      use AppBundle\Entity\LivreSF;
      use Symfony\Component\HttpFoundation\Response;
      use Symfony\Component\Routing\Annotation\Route;
      
      class LivreSFController extends DefaultController { 
    • Création d'une entité
          /**
           * @Route("livresf/create")
           */*/
          public function createAction() {
              // you can fetch the EntityManager via $this->getDoctrine()
              // or you can add an argument to your action: createAction(EntityManagerInterface $em)
              $entityManager = $this->getDoctrine()->getManager();
      
              $livresf = new LivreSF();
              $livresf->setLivTitre('Le cerveau solitaire');
      
              // tells Doctrine you want to (eventually) save the Product (no queries yet)
              $entityManager->persist($livresf);
      
              // actually executes the queries (i.e. the INSERT query)
              $entityManager->flush();
      
              return new Response('Saved new livresf with liv_num '.$livresf->getLivNum());
          }
      
    • Accès à une entité
           /**
           * @Route("livresf/{livresfId}")
           */
          public function showAction($livresfId)
          {
              $livresf = $this->getDoctrine()
                  ->getRepository(LivreSF::class)
                  ->find($livresfId);
      
              if (!$livresf) {
                  throw $this->createNotFoundException(
                      'No livresf found for id '.$livresfId
                  );
              }
              else {
                  return $this->render('livresf.html.twig', array(
                      'liv_num' => $livresf->getLivNum(), 'liv_titre' => $livresf->getLivTitre(),
                       ));
              }
          }
      
    • Accès à toutes les entités
           /**
           * @Route("livresf", name = "accueil")
           */
          public function showAllAction()
          {
              $lesLivresf = $this->getDoctrine()
                  ->getRepository(LivreSF::class)
                  ->findAll();
      
              return $this->render('leslivresf.html.twig', array(
                  'leslivressf' => $lesLivresf
                  ));
      
          }
    • Mise à jour d'une entité
          /**
           * @Route("livresf/update/{livresfId}")
           */
          public function updateAction($livresfId)
          {
              $entityManager = $this->getDoctrine()->getManager();
              $livresf = $entityManager->getRepository(LivreSF::class)->find($livresfId);
      
              if (!$livresf) {
                  throw $this->createNotFoundException(
                      'No livresf found for id '.$livresfId
                  );
              }
              $titres = array('Le cerveau solitaire', 'Le voyageur de l\'inconnu', 'Les mutants', 'La galaxie noire');
              if ($livresfId <= sizeof($titres))
                  $livresf->setLivTitre($titres[$livresfId - 1]);
              else
                  $livresf->setLivTitre('titre inconnu');
              $entityManager->flush();
      
              return $this->redirectToRoute('accueil');
          }
      
    • Suppression d'une entité
          /**
           * @Route("livresf/delete/{livresfId}")
           */
          public function deleteAction($livresfId)
          {
              $entityManager = $this->getDoctrine()->getManager();
              $livresf = $entityManager->getRepository(LivreSF::class)->find($livresfId);
      
              if (!$livresf) {
                  throw $this->createNotFoundException(
                      'No livresf found for id '.$livresfId
                  );
                  }
              else {
                  $entityManager->remove($livresf);
                  $entityManager->flush();
              }
              return $this->redirectToRoute('accueil');
          }
      
    • Filtre sur une entité
           /**
           * @Route("livresf/select/{livresfTitre}")
           */
          public function selectAction($livresfTitre)
          {
              $entityManager = $this->getDoctrine()->getManager();
              $livresf = $entityManager->getRepository(LivreSF::class)->findOneBy(array('liv_titre' => $livresfTitre));
      
              if (!$livresf) {
                  throw $this->createNotFoundException(
                      'No livresf found for titre '.$livresfTitre
                  );
                  }
              else {
                  return $this->render('livresf.html.twig', array(
                      'liv_num' => $livresf->getLivNum(), 'liv_titre' => $livresf->getLivTitre()
                  ));
              }
          }
      
      
    • Plein d'autres méthodes pour interroger la table : findOneBycolname(), findBycolname(), ...
      doctrine query language
  • Associations One To Many avec une table AuteurSF
    • Modification Entite LivreSF :
          /**
           * @ORM\ManyToOne(targetEntity="AuteurSF", inversedBy="livres")
           * @ORM\JoinColumn(name="auteursf_id", referencedColumnName="id")
           */
           private $auteur;
    • Entite AuteurSF :
      use Doctrine\Common\Collections\ArrayCollection;
      /**
       * @ORM\Entity
       * @ORM\Table(name="auteursf")
       */
      class AuteurSF
      {
          /**
           * @ORM\Column(type="integer")
           * @ORM\Id
           * @ORM\GeneratedValue(strategy="AUTO")
           */
          private $id;
      
      
          /**
           * @ORM\Column(type="string", length=100)
           */
          private $aut_nom;
      
          /**
           * @ORM\Column(type="string", length=100)
           */
          private $aut_prenom;
      
          /**
           * @ORM\OneToMany(targetEntity="LivreSF", mappedBy="auteur")
           */
          private $livres;
      
          public function __construct()
          {
              $this->livres = new ArrayCollection();
          }
                      
  • Demo