Symfony - Доктрина ORM

В веб-фреймворке Symfony модель играет важную роль. Это субъекты хозяйствования. Они либо предоставляются клиентами, либо извлекаются из серверной базы данных, обрабатываются в соответствии с бизнес-правилами и сохраняются обратно в базу данных. Это данные, представленные Views. Давайте узнаем о моделях и о том, как они взаимодействуют с серверной системой в этой главе.

Модель базы данных

Нам нужно сопоставить наши модели с элементами внутренней реляционной базы данных, чтобы безопасно и эффективно получать и сохранять модели. Это сопоставление может быть выполнено с помощью инструмента объектно-реляционного сопоставления (ORM). Symfony предоставляет отдельный пакет,DoctrineBundle, который интегрирует Symfony со сторонним инструментом ORM для баз данных PHP, Doctrine.

Доктрина ORM

По умолчанию фреймворк Symfony не предоставляет никаких компонентов для работы с базами данных. Но он тесно интегрируется сDoctrine ORM. Doctrine содержит несколько библиотек PHP, используемых для хранения баз данных и отображения объектов.

Следующий пример поможет вам понять, как работает Doctrine, как настроить базу данных и как сохранять и извлекать данные.

Пример Doctrine ORM

В этом примере мы сначала настроим базу данных и создадим объект Student, а затем выполним с ним некоторые операции.

Для этого нам необходимо придерживаться следующих шагов.

Шаг 1: Создайте приложение Symfony

Создайте приложение Symfony, dbsample используя следующую команду.

symfony new dbsample

Шаг 2: настройте базу данных

Обычно информация о базе данных настраивается в файле «app / config / parameters.yml».

Откройте файл и добавьте следующие изменения.

parameter.yml

parameters: 
   database_host: 127.0.0.1 
   database_port: null
   database_name: studentsdb 
   database_user: <user_name> 
   database_password: <password> 
   mailer_transport: smtp 
   mailer_host: 127.0.0.1 
   mailer_user: null 
   mailer_password: null 
   secret: 037ab82c601c10402408b2b190d5530d602b5809 
   
   doctrine: 
      dbal: 
      driver:   pdo_mysql 
      host:     '%database_host%' 
      dbname:   '%database_name%' 
      user:     '%database_user%' 
      password: '%database_password%' 
      charset: utf8mb4

Теперь Doctrine ORM может подключаться к базе данных.

Шаг 3: Создайте базу данных

Выполните следующую команду, чтобы создать базу данных «studentdb». Этот шаг используется для привязки базы данных в Doctrine ORM.

php bin/console doctrine:database:create

После выполнения команды автоматически создается пустая база данных «studentdb». Вы можете увидеть следующий ответ на своем экране.

Created database `studentsdb` for connection named default

Шаг 4: Информация о карте

Информация о сопоставлении - это не что иное, как «метаданные». Это набор правил, которые информируют Doctrine ORM о том, как класс Student и его свойства сопоставляются с конкретной таблицей базы данных.

Что ж, эти метаданные могут быть указаны в нескольких различных форматах, включая YAML, XML, или вы можете напрямую передать класс Student с помощью аннотаций. Это определяется следующим образом.

Student.php

Добавьте в файл следующие изменения.

<?php  
namespace AppBundle\Entity;  

use Doctrine\ORM\Mapping as ORM;  
/** 
   * @ORM\Entity 
   * @ORM\Table(name = "students") 
*/ 
class Student { 
   /** 
      * @ORM\Column(type = "integer") 
      * @ORM\Id 
      * @ORM\GeneratedValue(strategy = "AUTO") 
   */ 
   private $id;  
    
   /** 
      * @ORM\Column(type = "string", length = 50) 
   */ 
   private $name;  
   
   /** 
     * @ORM\Column(type = "text") 
     */ 
   private $address; 
}

Здесь имя таблицы необязательно. Если имя таблицы не указано, оно будет определено автоматически на основе имени класса сущности.

Шаг 5: привяжите объект

Doctrine создает для вас простые классы сущностей. Это поможет вам построить любую сущность.

Выполните следующую команду, чтобы создать объект.

php bin/console doctrine:generate:entities AppBundle/Entity/Student

Тогда вы увидите следующий результат, и объект будет обновлен.

Generating entity "AppBundle\Entity\Student" 
   > backing up Student.php to Student.php~ 
   > generating AppBundle\Entity\Student

Student.php

<?php 
namespace AppBundle\Entity; 

use Doctrine\ORM\Mapping as ORM;  
/** 
   * @ORM\Entity 
   * @ORM\Table(name="students") 
*/ 
class Student { 
   /** 
      * @ORM\Column(type="integer") 
      * @ORM\Id 
      * @ORM\GeneratedValue(strategy="AUTO") 
   */ 
   private $id;  
    
   /** 
      * @ORM\Column(type = "string", length = 50) 
   */ 
   private $name; 
    
   /** 
      * @ORM\Column(type = "text") 
   */
   private $address; 
    
   /** 
      * Get id 
      * 
      * @return integer 
   */ 
   public function getId() { 
      return $this->id; 
   }  
    
   /** 
      * Set name 
      * 
      * @param string $name 
      * 
      * @return Student 
   */ 
    
   public function setName($name) { 
      $this->name = $name;  
      return $this; 
   }  
    
   /** 
      * Get name 
      * 
      * @return string 
   */ 
    
   public function getName() { 
      return $this->name; 
   }  
    
   /**
      * Set address 
      * 
      * @param string $address 
      * 
      * @return Student 
   */ 
    
   public function setAddress($address) { 
      $this->address = $address;  
      return $this; 
   }  
    
   /** 
      * Get address 
      * 
      * @return string 
   */ 
   
   public function getAddress() { 
      return $this->address; 
   } 
}

Шаг 6. Проверка карты

После создания сущностей вы должны проверить сопоставления с помощью следующей команды.

php bin/console doctrine:schema:validate

Это даст следующий результат -

[Mapping]  OK - The mapping files are correct. 
[Database] FAIL - The database schema is not in sync with the current mapping file

Поскольку мы не создали таблицу студентов, сущность не синхронизирована. Давайте создадим таблицу студентов с помощью команды Symfony на следующем шаге.

Шаг 7: Создайте схему

Doctrine может автоматически создавать все таблицы базы данных, необходимые для объекта Student. Это можно сделать с помощью следующей команды.

php bin/console doctrine:schema:update --force

После выполнения команды вы увидите следующий ответ.

Updating database schema... 
Database schema updated successfully! "1" query was executed

Эта команда сравнивает то, как должна выглядеть ваша база данных, с тем, как она выглядит на самом деле, и выполняет операторы SQL, необходимые для обновления схемы базы данных до того места, где она должна быть.

Теперь снова проверьте схему, используя следующую команду.

php bin/console doctrine:schema:validate

Это даст следующий результат -

[Mapping]  OK - The mapping files are correct. 
[Database] OK - The database schema is in sync with the mapping files

Шаг 8: геттер и сеттер

Как видно из раздела «Привязать сущность», следующая команда генерирует все методы получения и установки для класса Student.

$ php bin/console doctrine:generate:entities AppBundle/Entity/Student

Шаг 9: сохраните объекты в базе данных

Теперь мы сопоставили объект Student с соответствующей таблицей Student. Теперь у нас должна быть возможность сохранять объекты Student в базе данных. Добавьте следующий метод в StudentController пакета.

StudentController.php

<?php  
namespace AppBundle\Controller; 

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; 
use Symfony\Bundle\FrameworkBundle\Controller\Controller; 
use Symfony\Component\HttpFoundation\Response;  
use AppBundle\Entity\Student; 

class StudentController extends Controller { 
   /** 
      * @Route("/student/add") 
   */ 
   public function addAction() { 
      $stud = new Student(); 
      $stud->setName('Adam'); 
      $stud->setAddress('12 north street'); 
      $doct = $this->getDoctrine()->getManager();
      
      // tells Doctrine you want to save the Product 
      $doct->persist($stud);
      
      //executes the queries (i.e. the INSERT query) 
      $doct->flush(); 
      
      return new Response('Saved new student with id ' . $stud->getId()); 
   } 
}

Здесь мы получили доступ к диспетчеру доктрин с помощью метода getManager () через getDoctrine () базового контроллера, а затем сохраняем текущий объект с помощью метода persist () диспетчера доктрин. persist() добавляет команду в очередь, но flush() метод выполняет фактическую работу (сохраняя объект студента).

Шаг 10: выборка объектов из базы данных

Создайте функцию в StudentController, которая будет отображать сведения о студенте.

StudentController.php

/** 
   * @Route("/student/display") 
*/ 
public function displayAction() { 
   $stud = $this->getDoctrine() 
   ->getRepository('AppBundle:Student') 
   ->findAll();
   return $this->render('student/display.html.twig', array('data' => $stud)); 
}

Шаг 11: Создайте представление

Давайте создадим представление, указывающее на отображение действия. Перейдите в каталог представлений и создайте файл «display.html.twig». Добавьте в файл следующие изменения.

display.html.twig

<style> 
   .table { border-collapse: collapse; } 
   .table th, td { 
      border-bottom: 1px solid #ddd; 
      width: 250px; 
      text-align: left; 
      align: left; 
   } 
</style> 

<h2>Students database application!</h2>  
<table class = "table">  
   <tr>  
      <th>Name</th>  
      <th>Address</th>  
   </tr>  
   {% for x in data %} 
   <tr>  
      <td>{{ x.Name }}</td>   
      <td>{{ x.Address }}</td>   
   </tr>  
   {% endfor %} 
</table>

Вы можете получить результат, запросив URL-адрес «http: // localhost: 8000 / student / display» в браузере.

На экране появится следующий вывод:

Шаг 12: Обновите объект

Чтобы обновить объект в StudentController, создайте действие и добавьте следующие изменения.

/** 
   * @Route("/student/update/{id}") 
*/ 
public function updateAction($id) { 
   $doct = $this->getDoctrine()->getManager(); 
   $stud = $doct->getRepository('AppBundle:Student')->find($id);  
   
   if (!$stud) { 
      throw $this->createNotFoundException( 
         'No student found for id '.$id 
      ); 
   } 
   $stud->setAddress('7 south street'); 
   $doct->flush(); 
   
   return new Response('Changes updated!'); 
}

Теперь запросите URL-адрес «http: // localhost: 8000 / Student / update / 1», и он выдаст следующий результат.

На экране появится следующий вывод:

Шаг 13: удалить объект

Удаление объекта аналогично и требует вызова метода remove () диспетчера сущностей (доктрины).

Это можно сделать с помощью следующей команды.

/** 
   * @Route("/student/delete/{id}") 
*/ 
public function deleteAction($id) { 
   $doct = $this->getDoctrine()->getManager(); 
   $stud = $doct->getRepository('AppBundle:Student')->find($id);  
    
   if (!$stud) { 
      throw $this->createNotFoundException('No student found for id '.$id); 
   }  
    
   $doct->remove($stud); 
   $doct->flush();  
   
   return new Response('Record deleted!'); 
}