Получение связных сущностей из БД при помощи ленивой загрузки Doctrine в фреймворке Symfony.

ORM Doctrine прекрасно интергрирована с фреймворком Symfony и позволяет не думать о базе данных, а манипулировать непосредственно с объектами.

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

Выборка сущностей OneToMany и ManyToOne.

Когда вам нужно выбрать связанные объекты Many To One, ваш рабочий процесс выглядит так же, легко как и в случае с одним объектом. Сначала получите объект $product, а затем получите доступ к связанному объекту Category:

use App\Entity\Product;
// ...

public function show($id)
{
    $product = $this->getDoctrine()
        ->getRepository(Product::class)
        ->find($id);

    // ...

    $categoryName = $product->getCategory()->getName();

    // ...
}

В этом примере вы сначала запрашиваете объект Product на основе идентификатора продукта. Это выдает запрос только для данных о продукте $product. Позже, когда вы вызываете $product->getCategory()->getName() , Doctrine молча делает второй запрос, чтобы найти категорию, связанную с этим продуктом. Он готовит объект $category и возвращает его вам.

Важным является тот факт, что у вас есть доступ к связанной с продуктом категории, но данные категории фактически сразу не извлекаются, пока вы не запросите категорию (то есть она «загружена лениво»). Ленивая загрузка позволяет не делать сразу без надобности лишний запрос к БД, тем самым уменьшая нагрузку на БД.

Поскольку мы сопоставили необязательную сторону OneToMany, вы также можете выполнить запрос в другом направлении:

public function showProducts($id)
{
    $category = $this->getDoctrine()
        ->getRepository(Category::class)
        ->find($id);

    $products = $category->getProducts();

    // ...
}

В этом случае происходит то же самое: сначала вы запрашиваете один объект Category. Затем вы получаете доступ к продуктам, Doctrine выполняет второй запрос для получения связанных объектов Product. Разумеется этого дополнительного запроса можно избежать, используя JOIN.

Отношения сущностей и Proxy Classes.

Такая «ленивая загрузка» возможна, потому что, когда это необходимо, Doctrine вместо связного объекта, возвращает «прокси» объект вместо истинного объекта. Посмотрите еще раз на приведенный выше пример:
$product = $this->getDoctrine()
    ->getRepository(Product::class)
    ->find($id);

$category = $product->getCategory();

// prints "Proxies\AppEntityCategoryProxy"
dump(get_class($category));
die();

Этот прокси-объект расширяет настоящий объект Category, и выглядит и действует точно так же, как он. Разница заключается в том, что с помощью прокси-объекта Doctrine может отложить запрос реальных данных категории до тех пор, пока вам действительно не понадобятся эти данные (например, пока вы не вызовете $category->getName()).

Прокси-классы создаются Doctrine и хранятся в каталоге кеша. Возможно, вы даже никогда не заметите, что ваш объект $category на самом деле является прокси-объектом.

Разумеется, если вам сразу нужно извлекать данные о продукте и категории, то это доступно через объединение JOIN. В этом случае Doctrine вернет истинный объект Category, поскольку ничего не нужно загружать с помощью ленивой загрузки.

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

Ваш адрес email не будет опубликован.