Symfony - Doctrine ORM


在 Symfony Web 框架中,模型扮演着重要的角色。他们是商业实体。它们要么由客户提供,要么从后端数据库获取,根据业务规则进行操作并保留回数据库中。它们是Views呈现的数据。让我们在本章中了解模型以及它们如何与后端系统交互。

数据库模型

我们需要将模型映射到后端关系数据库项,以安全有效地获取和持久化模型。此映射可以使用对象关系映射 (ORM) 工具来完成。Symfony 提供了一个单独的包DoctrineBundle,它将 Symfony 与第三方 PHP 数据库 ORM 工具Doctrine集成。

ORM 学说

默认情况下,Symfony 框架不提供任何使用数据库的组件。但是,它与Doctrine ORM紧密集成。Doctrine 包含几个用于数据库存储和对象映射的 PHP 库。

以下示例将帮助您了解 Doctrine 的工作原理、如何配置数据库以及如何保存和检索数据。

学说 ORM 示例

在这个例子中,我们将首先配置数据库并创建一个Student对象,然后在其中执行一些操作。

为此,我们需要遵循以下步骤。

第 1 步:创建 Symfony 应用程序

使用以下命令创建 Symfony 应用程序dbsample 。

symfony 新 dbsample

第 2 步:配置数据库

一般情况下,数据库信息配置在“app/config/parameters.yml”文件中。

打开文件并添加以下更改。

参数.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 步:创建数据库

发出以下命令生成“studentsdb”数据库。这一步用于Doctrine ORM中绑定数据库。

php bin/console doctrine:database:create

执行命令后,它会自动生成一个空的“studentsdb”数据库。您可以在屏幕上看到以下响应。

Created database `studentsdb` for connection named default

第四步:地图信息

映射信息只不过是“元数据”。它是一组规则,准确地告知 Doctrine ORM Student 类及其属性如何映射到特定的数据库表。

好吧,这个元数据可以用多种不同的格式指定,包括 YAML、XML,或者您可以使用注释直接传递 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

学生.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 步:Getter 和 Setter

如绑定实体部分所示,以下命令生成 Student 类的所有 getter 和 setter。

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

第 9 步:将对象持久保存到数据库

现在,我们已将 Student 实体映射到其相应的 Student 表。我们现在应该能够将 Student 对象持久保存到数据库中。将以下方法添加到捆绑包的 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()); 
   } 
} 

在这里,我们通过基本控制器的 getDoctrine() 使用 getManager() 方法访问条令管理器,然后使用条令管理器的 persist() 方法持久化当前对象。persist()方法将命令添加到队列中,但flush()方法执行实际工作(保留学生对象)。

第10步:从数据库中获取对象

在 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步:创建视图

让我们创建一个指向显示操作的视图。移动到views目录并创建一个文件“display.html.twig”。在文件中添加以下更改。

显示.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!'); 
}