Для модуля Application сущности (по общепринятому стандарту) хранятся в каталоге Entity
под корневым каталогом модуля. Классы сущностей содержатся в пространстве имен Application\Entity
.
Начнем с создания сущности Post
. Создайте файл Post.php под каталогом Entity.
(Если вы еще не создали каталог Entity, самое время это сделать.)
Поместите в этот файл следующий код:
<?php
namespace Application\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Этот класс представляет собой пост в блоге.
* @ORM\Entity
* @ORM\Table(name="post")
*/
class Post
{
// Константы статуса поста.
const STATUS_DRAFT = 1; // Черновик.
const STATUS_PUBLISHED = 2; // Опубликованный пост.
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(name="id")
*/
protected $id;
/**
* @ORM\Column(name="title")
*/
protected $title;
/**
* @ORM\Column(name="content")
*/
protected $content;
/**
* @ORM\Column(name="status")
*/
protected $status;
/**
* @ORM\Column(name="date_created")
*/
protected $dateCreated;
// Возвращает ID данного поста.
public function getId()
{
return $this->id;
}
// Задает ID данного поста.
public function setId($id)
{
$this->id = $id;
}
// Возвращает заголовок.
public function getTitle()
{
return $this->title;
}
// Задает заголовок.
public function setTitle($title)
{
$this->title = $title;
}
// Возвращает статус.
public function getStatus()
{
return $this->status;
}
// Устанавливает статус.
public function setStatus($status)
{
$this->status = $status;
}
// Возвращает содержимое поста.
public function getContent()
{
return $this->content;
}
// Задает содержимое поста.
public function setContent($content)
{
$this->content = $content;
}
// Возвращает дату создания данного поста.
public function getDateCreated()
{
return $this->dateCreated;
}
// Задает дату создания данного поста.
public function setDateCreated($dateCreated)
{
$this->dateCreated = $dateCreated;
}
}
В этом фрагменте кода находятся:
Константы статуса (строки 14 и 15). Они удобным образом представляют возможные значения,
которые может получить свойство $status
(1 для черновика (draft), 2 для опубликованного поста (published)).
Protected-свойства класса сущности ($title
, $content
, $dateCreated
и т.д.). Это данные,
которые содержит типичный пост в блоге (свойства и их краткое описание см. в таблице 12.2 ниже).
Обратите внимание, что для свойств используется (по общепринятому стандарту) "верблюжий" (camel-case) регистр (например,
$dateCreated
), в то время как для столбцов БД используются "канонизированные" имена (в нижнем регистре и с нижними подчеркиваниями, разделяющими слова, например,date_created
).
Свойства | Сопоставляемый столбец | Описание |
---|---|---|
$id |
id |
Уникальный идентификатор данного поста. |
$title |
title |
Заголовок данного поста. |
$content |
content |
Содержимое данного поста. |
$status |
status |
Статус (черновик/опубликован) данного поста. |
$dateCreated |
date_created |
Дата создания данного поста. |
Класс сущности и его свойства, помеченные аннотациями DocBlock, читаются ORM Doctrine во время выполнения. Тем самым, ORM знает, каким образом устанавливать соответствие между этой сущностью с ее свойствами и таблицей базы данных с ее столбцами.
Класс сущности имеет геттеры и сеттеры (строки 45-102) для обращения к protected-свойствам и их изменения (методы и их краткое описание см. в таблице 12.3).
Метод | Описание |
---|---|
getId() |
Возвращает ID данного поста. |
setId($id) |
Задает ID данного поста. |
getTitle() |
Возвращает заголовок. |
setTitle($title) |
Задает заголовок. |
getStatus() |
Возвращает статус (черновик/опубликован). |
setStatus($status) |
Устанавливает статус. |
getContent() |
Возвращает содержимое поста. |
setContent($content) |
Задает содержимое поста. |
getDateCreated() |
Возвращает дату создания данного поста. |
setDateCreated() |
Задает дату создания данного поста. |
Обратите внимание на то, что мы не помечаем методы класса сущности аннотациями Doctrine. В этом просто нет необходимости. Однако, если хотите, вы можете помечать методы обычными комментариями и аннотациями Docblock не из Doctrine.
Аналогично сущности Post
, далее мы создаем классы сущностей Comment и
Tag` в каталоге
Entity. Для этого сперва создайте файл Comment.php и поместите в него следующий код:
<?php
namespace Application\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Этот класс представляет собой комментарий, относящийся к посту блога.
* @ORM\Entity
* @ORM\Table(name="comment")
*/
class Comment
{
/**
* @ORM\Id
* @ORM\Column(name="id")
* @ORM\GeneratedValue
*/
protected $id;
/**
* @ORM\Column(name="content")
*/
protected $content;
/**
* @ORM\Column(name="author")
*/
protected $author;
/**
* @ORM\Column(name="date_created")
*/
protected $dateCreated;
// Возвращает ID данного комментария.
public function getId()
{
return $this->id;
}
// Задает ID данного комментария.
public function setId($id)
{
$this->id = $id;
}
// Возвращает текст комментария.
public function getContent()
{
return $this->content;
}
// Устанавливает статус.
public function setContent($content)
{
$this->content = $content;
}
// Возвращает имя автора.
public function getAuthor()
{
return $this->author;
}
// Задает имя автора.
public function setAuthor($author)
{
$this->author = $author;
}
// Возвращает дату создания этого комментария.
public function getDateCreated()
{
return $this->dateCreated;
}
// Задает дату создания этого комментария.
public function setDateCreated($dateCreated)
{
$this->dateCreated = $dateCreated;
}
}
Теперь создайте файл Tag.php и поместите в него следующий код:
<?php
namespace Application\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Этот класс представляет собой тег.
* @ORM\Entity
* @ORM\Table(name="tag")
*/
class Tag
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(name="id")
*/
protected $id;
/**
* @ORM\Column(name="name")
*/
protected $name;
// Возвращает ID данного тега.
public function getId()
{
return $this->id;
}
// Задает ID данного тега.
public function setId($id)
{
$this->id = $id;
}
// Возвращает имя.
public function getName()
{
return $this->name;
}
// Задает имя.
public function setName($name)
{
$this->name = $name;
}
}
Так как сущности Comment
и Tag
аналогичны сущности Post
, мы не будем разбирать фрагменты кода выше.
Заметьте, мы не создаем сущность для вспомогательной таблицы
post_tag
. Эта таблица будет косвенно использоваться далее в этой главе при определении отношений между сущностями.
Теперь используем аннотации, чтобы определить отношения между сущностями. Если помните, между нашими сущностями существуют два отношения:
Post
и Comment
;Post
и Tag
. Для задания отношения между двумя сущностями в Doctrine, добавьте private-свойство вместе с аннотацией Docblock.
Детальную информацию об отношениях между сущностями в Doctrine можно прочесть на этой странице документации Doctrine.
Первым делом, давайте определим отношение «один-ко-многим» между сущностями Post
и Comment
. Внесите
следующие изменения в файл Post.php:
<?php
// ...
use Doctrine\Common\Collections\ArrayCollection;
use Application\Entity\Comment;
/**
* Этот класс представляет собой пост в блоге.
* @ORM\Entity
* @ORM\Table(name="post")
*/
class Post
{
// ...
/**
* @ORM\OneToMany(targetEntity="\Application\Entity\Comment", mappedBy="post")
* @ORM\JoinColumn(name="id", referencedColumnName="post_id")
*/
protected $comments;
/**
* Конструктор.
*/
public function __construct()
{
$this->comments = new ArrayCollection();
}
/**
* Возвращает комментарии для этого поста.
* @return array
*/
public function getComments()
{
return $this->comments;
}
/**
* Добавляет новый комментарий к этому посту.
* @param $comment
*/
public function addComment($comment)
{
$this->comments[] = $comment;
}
}
Как видите из фрагмента выше, мы добавили свойство $comments
(строка 19). Это
свойство будет коллекцией комментариев, относящихся к определенному посту.
Мы инициализируем свойство $comments
в конструкторе класса (строки 24-27),
создав новый экземпляр класса Doctrine\Common\Collections\ArrayCollection
.
ArrayCollection
в Doctrine - это массив объектов, похожий на обычныймассив
PHP, но с дополнительными особенностями, необходимыми Doctrine. Он реализован в компоненте Doctrine\Common.
В строках 15-18 мы добавляем аннотации Doctrine к свойству $comments
, тем самым сообщая Doctrine, как
получать все комментарии к посту:
@ORM\OneToMany
определяет отношение «один-ко-многим» между сущностями Post
и Comment
.
the (target) Comment
entity.@ORM\JoinColumn
указывает, какой столбец использовать для присоединения к таблицам,
связанным с сущностями.Метод getComments()
(строки 33-36) позволяет получить все комментарии, связанные с постом.
Помимо этого, мы добавили метод addComment()
(строки 42-45) для добавления нового комментария
к посту. Как видите, мы используем оператор []
, точно так же, как и с обычным PHP-массивом.
Затем мы определяем другую часть этого отношения, изменяя сущность Comment
следующим образом:
<?php
// ...
use Doctrine\Common\Collections\ArrayCollection;
// ...
class Comment
{
/**
* @ORM\ManyToOne(targetEntity="\Application\Entity\Post", inversedBy="comments")
* @ORM\JoinColumn(name="post_id", referencedColumnName="id")
*/
protected $post;
/*
* Возвращает связанный пост.
* @return \Application\Entity\Post
*/
public function getPost()
{
return $this->post;
}
/**
* Задает связанный пост.
* @param \Application\Entity\Post $post
*/
public function setPost($post)
{
$this->post = $post;
$post->addComment($this);
}
}
В этом фрагменте мы добавили private-свойство $post
к классу сущности. Это не коллекция, а один
экземпляр класса Post
, так как один комментарий всегда принадлежит одному посту.
Теги аннотаций @ORM\ManyToOne
и @ORM\JoinColumn
аналогичны тем, что мы рассмотрели выше.
Теперь давайте определим отношение между сущностями Post
и Tag
. Для этого отношения мы косвенно
используем вспомогательную таблицу post_tag
.
Измените сущность Post
следующим образом:
<?php
//...
use Application\Entity\Tag;
//...
class Post
{
//...
/**
* @ORM\ManyToMany(targetEntity="\Application\Entity\Tag", inversedBy="posts")
* @ORM\JoinTable(name="post_tag",
* joinColumns={@ORM\JoinColumn(name="post_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="tag_id", referencedColumnName="id")}
* )
*/
protected $tags;
// Конструктор.
public function __construct()
{
//...
$this->tags = new ArrayCollection();
}
// Возвращает теги для данного поста.
public function getTags()
{
return $this->tags;
}
// Добавляет новый тег к данному посту.
public function addTag($tag)
{
$this->tags[] = $tag;
}
// Удаляет связь между этим постом и заданным тегом.
public function removeTagAssociation($tag)
{
$this->tags->removeElement($tag);
}
}
В коде выше мы делаем следующее:
$tags
;$tags
аннотациями Docblock с помощью тегов аннотаций @ORM\ManyToMany
и @ORM\JoinTable
;getTags()
, addTag()
и removeTagAssociation()
.После этого измените сущность Tag
таким образом:
<?php
//...
use Doctrine\Common\Collections\ArrayCollection;
class Tag
{
// ...
/**
* @ORM\ManyToMany(targetEntity="\Application\Entity\Post", mappedBy="tags")
*/
protected $posts;
// Конструктор.
public function __construct()
{
$this->posts = new ArrayCollection();
}
// Возвращает посты, связанные с данным тегом.
public function getPosts()
{
return $this->posts;
}
// Добавляет пост в коллекцию постов, связанных с этим тегом.
public function addPost($post)
{
$this->posts[] = $post;
}
}
В этом фрагменте мы аналогичным образом определяем другую часть отношения, а также геттер и сеттер для извлечения коллекции постов, связанных с тегом, и добавления постов, связанных с заданным тегом.
Чтобы сообщить Doctrine, где найти сущности для модуля Application (или другого вашего модуля), добавьте следующий код в файл module.config.php:
<?php
namespace Application;
use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
return [
// ...
'doctrine' => [
'driver' => [
__NAMESPACE__ . '_driver' => [
'class' => AnnotationDriver::class,
'cache' => 'array',
'paths' => [__DIR__ . '/../src/Entity']
],
'orm_default' => [
'drivers' => [
__NAMESPACE__ . '\Entity' => __NAMESPACE__ . '_driver'
]
]
]
]
];
В строке 2 данного фрагмента мы указываем пространство имен Application
. Это должно
быть имя текущего модуля.
Обратите внимание на то, что обычно мы не указываем пространство имен в файлах конфигурации, но в данном случае удобно это сделать. После того, как мы определили пространство имен, мы можем использовать плейсхолдер
__NAMESPACE__
.
В строке 8 находится ключ doctrine
, и под ним подключ driver
.
В строке 13 мы сообщаем ORM Doctrine, что наши сущности хранятся
в каталоге Entity под корневым каталогом модуля src.