Symfony - Doctrine ORM
在 Symfony Web 框架中,模型起着重要作用。它们是业务实体。它们要么由客户提供,要么从后端数据库获取,根据业务规则进行操作并持久保存回数据库。它们是视图呈现的数据。让我们在本章中了解模型以及它们如何与后端系统交互。
数据库模型
我们需要将模型映射到后端关系数据库项,以安全高效地获取和持久保存模型。可以使用对象关系映射 (ORM) 工具完成此映射。 Symfony 提供了一个单独的包 DoctrineBundle,它将 Symfony 与第三方 PHP 数据库 ORM 工具 Doctrine 集成在一起。
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:创建数据库
发出以下命令生成"studentsdb"数据库。此步骤用于在 Doctrine ORM 中绑定数据库。
php bin/console doctrine:database:create
执行命令后,它会自动生成一个空的"studentsdb"数据库。您可以在屏幕上看到以下响应。
为名为 default 的连接创建数据库 `studentsdb`
步骤 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 可以自动创建学生实体所需的所有数据库表。可以使用以下命令完成此操作。
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。
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(); // 告诉 Doctrine 你想要保存产品 $doct->persist($stud); //执行查询(即 INSERT 查询) $doct->flush(); return new Response('Saved new student with id ' . $stud->getId()); } }
在这里,我们通过基础控制器的 getDoctrine() 使用 getManager() 方法访问了教义管理器,然后使用教义管理器的 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:创建视图
让我们创建一个指向显示操作的视图。转到 views 目录并创建一个文件"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:删除对象
删除对象类似,它需要调用实体(doctrine)管理器的 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!'); }