Как сгенерировать сущности из существующей базы данных

Caution

Функция, описанная в этой статье, не работает в современных приложениях Symfony, в которых нет пакетов. Обходным решением является временное создание пакета. См. doctrine/doctrine#729, чтобы узнать детали. Более того, эта функция, для генерирования сущностей из существующей БД, будет полностью удалена в следующей версии Doctrine.

Когда вы начинаете работать над новым проектом, использующим базу данных, две разных ситуации всплывают естественным образом. В большинстве случаев, модель базы данных строится и планируется с нуля. Однако, иногда вы будете начинать с существующей и, вероятнее всего, не поддающейся изменениям, моделью БД. К счастью, Doctrine имеет массу инструментов, чтобы помочь сгенерировать классы модели из вашей существующей базы данных.

Note

Как гласит документация инструментов Doctrine, обратное проективрование - это единоразовый процесс, чтобы начать проект. Doctrine способен конвертировать приблизительно 70-80% необходимой информации отображения, основываясь на полях, индексах и ограничениях сторонних ключей. Doctrine не может обнаружить инверсные ассоциации, типы наследования, сущности со сторонними ключами в качестве основных или семантически операции над ассоциациями такие как каскад или события жизненного цикла. Некоторая дополнительная работа над созданными сущностями понадобится позже, чтобы подстроить каждую из них под спецификации вашей модели домена.

Этот туториал предполагает, что вы использете простое приложение-блог со следующими двумя таблицами: blog_post и blog_comment. Запись комментариев связана с записью постов блягодаря ограничению стороннего ключа.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
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;

Перед тем, как углубляться в инструкцию, убедитесь в том, что параметры соединения вашей БД правильно установлены в файле .env.

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

1
$ php bin/console doctrine:mapping:import --force AppBundle xml

Этот инструмент командной строки просит Doctrine вникнуть в БД и сгенерировать XML-файлы метаданных под папкой src/Resources/config/doctrine вашего пакета. Это генерирует два файла: BlogPost.orm.xml и BlogComment.orm.xml.

Tip

Также возможно генерировать файлы метаданных в YAML-формате, изменяя последний аргумент на yml.

Сгенерированный BlogPost.orm.xml файл метаданных выглядит следующим образом:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<?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="App\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>

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

1
2
// генерирует классы сущностей с отображениями аннотаций
$ php bin/console doctrine:mapping:convert annotation ./src

Caution

Если вы хотите использовать аннотации, вы должны удалить файлы XML (или YAML) после выполнения этой команды. Это необходимо, так как невозможно смешивать форматы конфигурации отображений

Например, новосозданный класс сущности BlogComment выглядит следующим образом:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// src/Entity/BlogComment.php
namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @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 конвертирует все поля таблицы в чисто приватные и аннотированные свойства класса. Наиболее впечатляющим является то, что он также обнаружил отношения с классом сущности BlogPost, основываясь на ограничения стороннего ключа. Следовательно, вы можете найти приватное свойство $post отображенное с сущностью BlogPost в классе сущности BlogComment.

Note

Если вы хотите иметь отношение один-ко-многим, то вам понадобится добавить его вручную к сущности или к сгенерированным файлами XML или YAML. Добавьте раздел по специфическим сущностями для отношений один-ко-многим, определяющий части inversedBy и mappedBy.

Сгенерированные сущности теперь готовы к использованию. Повеселитесь!

Эта документация является переводом официальной документации Symfony и предоставляется по свободной лицензии CC BY-SA 3.0.