Создание связи (отношения) один ко многим в Doctrine.

Существует два основных типа отношений / ассоциаций:

  • 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 готова сохранять  отношения в связные таблицы.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *