Существует два основных типа отношений / ассоциаций:
- 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 готова сохранять отношения в связные таблицы.