symfony Repository -- Что это? -- Пример реализации (репозиторий)

Что это

Repository в Symfony - класс, соответствующий классу Entity и содержащий методы типа findBy(), делающие запросы к БД.

  • Сам RepositoryClass. Если в вашем коде часто делается один и тот же запрос, можно вынести его в Repository:
    <?php
    
    namespace AppBundle\Repository;
    
    use Doctrine\ORM\EntityRepository;
    use AppBundle\Entity\Category;
    use AppBundle\Entity\CategoryProduct;
    
    class ProductRepository extends EntityRepository
    {
        /**
         * @param Category $category
         * 
         * @return array
         */
        public function findByCategory(Category $category): array
        {
            $categoryProductRelations = $this->getEntityManager()
                    ->getRepository(CategoryProduct::class)
                    ->findBy([
                        'category' => $category,
                    ]);
            
            return array_map(function ($relation) {
                              $relation->getProduct();
                }, $categoryProductRelations); 
        }
    }

    О том, как работает функция array_map() можно прочитать в документации PHP

  • Класс сущности, для которого создан репозиторий (называется также - Product). Не забудьте добавить в аннотацию Entity опцию repositoryClass, иначе может быть получена такая ошибка.
    /**
     * @ORM\Entity(repositoryClass="AppBundle\Repository\ProductRepository")
     * 
     * @ORM\Table(name="product")
     */
    class Product 
  • Предпочтительно в сервисе или контроллере вызвать метод репозитория, создавая объект репозитория в качестве поля:
    private $productRepository;
    
        public function __construct(ProductRepository)
        {
            $this->productRepository = $productRepository;
        }
    
        public function smth()
        {
            $products = $this->productRepository->findByCategory($category);
        }

    В Symfony3 (или в случае если ваш репозиторий не загружаются автоматически в контейнер (autowiring)) вызывать можно так:

    $productsInCategory = $em->getRepository(Product::class)
                            ->findByCategory($category);

Нестандартный пример использования

Можно использовать репозиторий для упаковки промежуточных запросов между тремя сущностями (достаём третью через вторую).
Теперь поясню: Представим ситуацию, когда вам нужно добавить в таблицу связи Many To Many какие-то дополнительные данные. Это невозможно при создании ManyToMany, но есть обходной путь.

Создаём 2 связи OneToMany с промежуточной таблицей (которую тоже создаём вручную, как сущность, туда же добавляем нужные нам поля). По сути это таже many-to-many связь. Единственное, чего недостаёт - это возможность обращаться непосредственно к связанной сущности, минуя промежуточную. Вооооооот... Эти промежуточные запросы мы и положим в репозиторий, обернув методом с красивым говорящим названием.

Код класса Repository, выполняющего эту задачу вы уже видели выше:
есть сущности Продукт и Категория. И есть сущность ПродуктКатегория, содержащая в себе не только информацию о связи сущнностей, но и дополнительные поля.

Источники

Официальная документация о репозиториях
Нестандартный метод Many To Many

vedro-compota's picture

Repository в Symfony - класс, соответствующий классу Entity и содержащий методы типа findBy(), делающие запросы к БД.

  1. спасибо)
  2. поправил заголовок - добавил русский эквивалент слова

_____________
матфак вгу и остальная классика =)