Существует два основных типа отношений / ассоциаций:
- ManyToOne / OneToMany
- ManyToMany
ManyToOne/OneToMane наиболее распространенная связь, отображаемая в базе данных с помощью столбца внешнего ключа (например, столбец category_id в таблице product). На самом деле это всего лишь один тип ассоциации, но он виден с двух разных сторон отношения.
ManyToMany используется таблица соединений, и она необходима, когда обе стороны отношений могут иметь много другой стороны (например, «учащиеся» и «классы»: каждый учащийся находится во многих классах, а в каждом классе много учащихся).
Во-первых, вам нужно определить, какие отношения использовать. Если обе стороны отношения будут содержать много другой стороны (например, «студенты» и «классы»), вам необходимо отношение ManyToMany. В противном случае вам, вероятно, понадобится ManyToOne.
Существует также отношение OneToOne (например, один пользователь имеет один профиль и наоборот).На практике использование этого похоже на ManyToOne.
Ассоциация ManyToOne / OneToMany.
Предположим, что каждый продукт в вашей заявке относится только к одной категории. В этом случае вам понадобится класс Category и способ связать объект Product объектом Category.
Начните с создания Category с полем name:
php bin/console make:entity Category
New property name (press <return> to stop adding fields):
> name
Field type (enter ? to see all types) [string]:
> string
Field length [255]:
> 255
Can this field be null in the database (nullable) (yes/no) [no]:
> no
New property name (press <return> to stop adding fields):
>
(press enter again to finish)
Это сгенерирует ваш новый класс сущности:
// src/Entity/Category.php
// ...
class Category
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string")
*/
private $name;
// ... getters and setters
}
Mapping отношений Многие к Одному.
В этом примере каждая категория может быть связана со многими продуктами. Но каждый продукт может быть связан только с одной категорией. Это отношение можно обобщить следующим образом: множество товаров для одной категории (или, что то же самое, одна категория для множества товаров).
С точки зрения сущности «Продукт» это отношение «многие к одному». С точки зрения сущности Category это отношение один ко многим.
Чтобы отобразить это, сначала создайте свойство категории в классе Product с аннотацией ManyToOne. Вы можете сделать это вручную или с помощью команды make:entity, которая задаст вам несколько вопросов о ваших отношениях. Если вы не уверены в ответе, не волнуйтесь! Вы всегда можете изменить настройки позже:
php bin/console make:entity
Class name of the entity to create or update (e.g. BraveChef):
> Product
to stop adding fields):
> category
Field type (enter ? to see all types) [string]:
> relation
What class should this entity be related to?:
> Category
Relation type? [ManyToOne, OneToMany, ManyToMany, OneToOne]:
> ManyToOne
Is the Product.category property allowed to be null (nullable)? (yes/no) [yes]:
> no
Do you want to add a new property to Category so that you can access/update
getProducts()? (yes/no) [yes]:
> yes
New field name inside Category [products]:
> products
Do you want to automatically delete orphaned App\Entity\Product objects
(orphanRemoval)? (yes/no) [no]:
> no
to stop adding fields):
>
(press enter again to finish)
Это внесло изменения в две сущности. Во-первых, он добавил новое свойство category в сущность Product (и методы getter & setter):
// src/Entity/Product.php
// ...
class Product
{
// ...
/**
* @ORM\ManyToOne(targetEntity="App\Entity\Category", inversedBy="products")
*/
private $category;
public function getCategory(): ?Category
{
return $this->category;
}
public function setCategory(?Category $category): self
{
$this->category = $category;
return $this;
}
}
Это сопоставление ManyToOne требуется. Он говорит Doctrine использовать столбец category_id в таблице продуктов, чтобы связать каждую запись в этой таблице с записью в таблице категорий.
Далее, поскольку один объект Category будет относиться ко многим объектам Product, команда make: entity также добавила свойство products в класс Category, который будет содержать эти объекты:
// src/Entity/Category.php
// ...
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
class Category
{
// ...
/**
* @ORM\OneToMany(targetEntity="App\Entity\Product", mappedBy="category")
*/
private $products;
public function __construct()
{
$this->products = new ArrayCollection();
}
/**
* @return Collection|Product[]
*/
public function getProducts(): Collection
{
return $this->products;
}
// addProduct() and removeProduct() were also added
}
Отображение ManyToOne, показанное ранее, является обязательным, но это OneToMany не является обязательным: добавляйте его только в том случае, если вы хотите иметь доступ к продуктам, которые относятся к категории (это один из вопросов, которые задает make: entity вас спрашивает). В этом примере будет полезно иметь возможность вызывать $ category-> getProducts (). Если вы не хотите этого, то вам также не нужно конфигурация inversedBy или mappedBy.
Внесение изменений в БД.
Теперь выполните миграцию как обычно:
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate
Благодаря этим консольным командам создается столбец внешнего ключа category_id в таблице продукта. И Doctrine готова сохранять отношения в связные таблицы.