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.
$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, поскольку ничего не нужно загружать с помощью ленивой загрузки.