當(dāng)開始使用一個工作于一個全新的項目的數(shù)據(jù)庫,自然而然就有兩個不同的結(jié)果。大部分情況下,數(shù)據(jù)庫模型的設(shè)計和建立從零開始。然而有些時候,您將是從一個已存在且不變的模型上開始。幸運的是,Doctrine 有一大堆的工具來幫助從您已存在的數(shù)據(jù)中生成模型類。
正如 Doctrine 工具文檔所說的,逆向工程是開始一個項目的一次性過程。Doctrine 能夠轉(zhuǎn)換 70 - 80% 基于領(lǐng)域、表單和外檢約束的必要映射信息。Doctrine 不能夠發(fā)現(xiàn)逆關(guān)聯(lián)、繼承類型、作為主鍵的外鍵實體或者語義操作關(guān)聯(lián)例如級聯(lián)或者生命周期事件。在生成實體之后還有一些必要的額外工作來設(shè)計每一個適合您的域模型特性。
本教程假設(shè)您正在使用一個有以下兩個表格的簡單的博客應(yīng)用程序:blog_post 和 blog_comment。由于外鍵約束的原因,評論記錄與后續(xù)記錄相鏈接。
CREATE TABLE `blog_post` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`title` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
`content` longtext COLLATE utf8_unicode_ci NOT NULL,
`created_at` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE `blog_comment` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`post_id` bigint(20) NOT NULL,
`author` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
`content` longtext COLLATE utf8_unicode_ci NOT NULL,
`created_at` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `blog_comment_post_id_idx` (`post_id`),
CONSTRAINT `blog_post_id` FOREIGN KEY (`post_id`) REFERENCES `blog_post` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
在投入到教程之前,確保您的數(shù)據(jù)庫連接參數(shù)在 app/config/parameters.yml 文件中正確設(shè)置(或者不管您的數(shù)據(jù)庫配置在哪里),并確保您已經(jīng)初始化了一個將要群集您實體類的包。在本教程中假設(shè)存在并位于 src/Acme/BlogBundle 文件夾。
從已存在數(shù)據(jù)庫創(chuàng)建實體類的第一步是讓 Doctrine 內(nèi)省數(shù)據(jù)庫并生成相應(yīng)的元數(shù)據(jù)文件。元數(shù)據(jù)文件描述了在表字段生成的實體類。
$ php app/console doctrine:mapping:import --force AcmeBlogBundle xml
這個命令行工具讓 Doctrine 來內(nèi)省數(shù)據(jù)庫并在包的 src/Acme/BlogBundle/Resources/config/doctrine 文件夾中生成 XML 元數(shù)據(jù)文件。這生成兩個文件:BlogPost.orm.xml 和 BlogComment.orm.xml。
通過把最后一個參數(shù)改為 yml 來生成 YAML 格式的元數(shù)據(jù)文件也是可能的。
生成的 BlogPost.orm.xml 元數(shù)據(jù)文件看起來如下:
<?xml version="1.0" encoding="utf-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Acme\BlogBundle\Entity\BlogPost" table="blog_post">
<id name="id" type="bigint" column="id">
<generator strategy="IDENTITY"/>
</id>
<field name="title" type="string" column="title" length="100" nullable="false"/>
<field name="content" type="text" column="content" nullable="false"/>
<field name="createdAt" type="datetime" column="created_at" nullable="false"/>
</entity>
</doctrine-mapping>
一旦元數(shù)據(jù)文件生成,您可以通過執(zhí)行以下兩個命令讓 Doctrine 創(chuàng)建相關(guān)的實體類。
$ php app/console doctrine:mapping:convert annotation ./src
$ php app/console doctrine:generate:entities AcmeBlogBundle
第一個命令生成注釋映射的實體類。但是如果您想使用 YAML 或者 XML 而不是注釋,您應(yīng)該只執(zhí)行第二個命令。
如果您想使用注釋,您可以安全地在運行了這兩個命令后刪除 XML(或 YAML)文件。
例如,新創(chuàng)建的 BlogComment 實體類看起來如下:
// src/Acme/BlogBundle/Entity/BlogComment.php
namespace Acme\BlogBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Acme\BlogBundle\Entity\BlogComment
*
* @ORM\Table(name="blog_comment")
* @ORM\Entity
*/
class BlogComment
{
/**
* @var integer $id
*
* @ORM\Column(name="id", type="bigint")
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var string $author
*
* @ORM\Column(name="author", type="string", length=100, nullable=false)
*/
private $author;
/**
* @var text $content
*
* @ORM\Column(name="content", type="text", nullable=false)
*/
private $content;
/**
* @var datetime $createdAt
*
* @ORM\Column(name="created_at", type="datetime", nullable=false)
*/
private $createdAt;
/**
* @var BlogPost
*
* @ORM\ManyToOne(targetEntity="BlogPost")
* @ORM\JoinColumn(name="post_id", referencedColumnName="id")
*/
private $post;
}
正如您可以看到的,Doctrine 將所有的表字段轉(zhuǎn)化成為純私有和帶注釋的類屬性。最令人印象深刻的是它同樣發(fā)現(xiàn)了與基于外鍵約束的 BlogPost 實體類的關(guān)系。因此,您可以在 $post 實體類中找到用 BlogPost 實體映射的一個私有的 $post 屬性。
如果您想有一對多的關(guān)系,您需要手動將其添加到實體或者生成的 XML 或 YAML 文件。在具體的實體上添加一個區(qū)段使一對多定義 inversedBy 和 mappedBy 塊。
現(xiàn)在可以使用生成的實體了。玩得開心!