Наличие собственного репозитория, не связанного с сущностью в Symfony - PullRequest
0 голосов
/ 31 октября 2018

У меня есть файл DefaultRepository для размещения всех общих запросов.

Можно ли иметь собственный репозиторий, не связанный с сущностью в Symfony? Я хотел бы вставить в него некоторый нативный SQL, который не вписывается в другие репозитории (это может относиться к абстрактной или иерархии сущностей).

Как код контроллера:

$this->getDoctrine()->getRepositoty(/* ??? */) should be replaced?

Ответы [ 3 ]

0 голосов
/ 01 ноября 2018

То, что вы хотите, не является хранилищем. Репозиторий связан с Entity в Doctrine и предоставляет такие функции, как «findOneBy» и т. Д. Вне контекста сущности это не имеет смысла. Если вам нужно сохранить пользовательские запросы, вы все равно можете добавить сервис и добавить в него Doctrine Manager (или только те хранилища сущностей, которые вам нужны). Затем вы можете легко использовать свой сервис в контроллере.

В вашем файле services.yaml у вас будет что-то вроде этого:

services:
    App\Services\QueriesManager:
        autowire: true

Ваш сервис будет выглядеть так (App \ Services \ QueriesManager)

<?php

namespace App\Services;

use Doctrine\ORM\EntityManagerInterface;

class QueriesManager {
    protected $entityManager;

    __construct(EntityManagerInterface $entityManager) {
        $this->entityManager = $entityManager;
    }

    public function getSpecialQueryResult() {
        $qb = $this->entityManager->createQueryBuilder();
        $qb->select(...)
           ->where(...)
        return $qb->getQuery()->getResult();
    }
}

И в вашем контроллере вы можете просто указать подсказку для метода, который хотите использовать, например:

class MyController {
    public function indexAction($param1, \App\Services\QueriesManager $queriesManager) {
        return $queriesManager->getSpecialQueryResult();
    }
}
0 голосов
/ 06 ноября 2018

Спасибо за ваши ответы.

Это решение для меня: https://stackoverflow.com/a/53098008/2400373

Используйте symfony 3.3.x Здесь я кратко излагаю, как решить мою проблему

Файл service.yml:

//service.yml
services:
     app.queriesmanager:
          class: AppBundle\Services\QueriesManager
          autowire: true

Файл AppBundle \ Services \ QueriesManager.php

//AppBundle\Services\QueriesManager.php
<?php

namespace AppBundle\Services;

use Doctrine\ORM\EntityManagerInterface;

class QueriesManager  {
    protected $entityManager;

    public function __construct(EntityManagerInterface $entityManager) {
        $this->entityManager = $entityManager;
    }

    public function searchAdvance($var,$var1,$var2,$var3)
    {
        $dql1 = "";
        $dql2 = "";
        $dql = "SELECT pl
                      FROM BackendBundle:Products p
                      JOIN BackendBundle:Pricelist pl
                      WITH p.peachitemid =  pl.peachitemid
                      WHERE p.hasimages =  1
                      AND p.active = 'FALSE'
                      AND p.imagesamazon1 = 1
                      AND p.imagesamazon2 = 1
                      AND (p.descriptionforsales like '%$var%' OR p.itemid like '%$var%')";

        if ($var1 != "select") {
            $dql1 = " AND p.newcategory='$var1' AND p.newsubcategory='$var2' ";
        }
        if ($var3 == "150") {
            $dql2 = " AND pl.retail < 150";
        }
        if ($var3 == "200") {
            $dql2 = " AND pl.retail > 150 AND pl.retail < 250 ";
        }
        if ($var3 == "250") {
            $dql2 = " AND pl.retail > 250 ";
        }

        $dql1 .= $dql2;
        $dql .= $dql1;
        $query=$this->entityManager->createQuery($dql);
        $query = $query->getResult();
        return $query;

    }
}

Файл DefaultController.php

//Use the service in controller
$query=$this->get('app.queriesmanager')->searchAdvance($var,$var1,$var2,$var3);

Обновление

Для symfony 4.x вам нужно изменить строки в сервисе

app.queriesmanager:
        class: App\Services\QueriesManager
        public: true

Спасибо вам, и я надеюсь, что вы можете помочь.

0 голосов
/ 01 ноября 2018

У вас может быть собственный общий «репозиторий», но вы не сможете получить его через Doctrine EntityManager. Вместо этого вы вводите его непосредственно в контроллер.

Ваш репозиторий может выглядеть примерно так:

class MyRepository implements RepositoryInterface
{
    private $entityManager;

    public function __construct(EntityManagerInterface $entityManager)
    {
        $this->entityManager = $entityManager;
    }

    public function findFoo()
    {
        $builder = $this->entityManager->createQueryBuilder();

        $query = $builder->... // build query

        return $query->getResult();
    }

    // Implement the generic find-methods defined by the interface
}

Реализация интерфейса не обязательна, когда вы используете репозиторий напрямую, но он сделает его более знакомым. Внедрив entityManager, вы можете просто вызывать другие репозитории для извлечения данных или создавать конструктор запросов для написания собственных запросов.

В вашем контроллере вы затем добавите хранилище или получите его из контейнера, например, как это:

class FooController extends Controller
{
    private $repository;

    public function __construct(MyRepository $repository)
    {
        $this->repository = $repository;
    }

    public function indexAction(Request $request)
    {
        $foo = $this->repository->findFoo();
    }
}

Вы также можете определить свой репозиторий как сервис:

# app/config/services.yml
services:
    app.my_repository:
        class: App\Repository\MyRepository
        arguments:
            - '@doctrine.orm.entity_manager'

и затем получить ваш репозиторий в контроллерах с помощью вспомогательного метода, а не внедрять его:

$this->get('app.my_repository');

Обратите внимание, что:

  • Поскольку вы не можете реально использовать методы, определенные RepositoryInterface, так как вы не хотите работать с одной сущностью, где, например, findOneBy имеет смысл, возможно, имеет смысл не реализовывать интерфейс.
  • Вы также можете дать этим классам другое имя. Например, вы можете поместить каждый запрос в свой собственный класс и иметь класс FindFooQuery, который вы вводите в качестве службы в свой контроллер. Таким образом, становится более ясным, что это на самом деле не связано с сущностью, но это своего рода вещь. Это может сделать этот подход более управляемым, когда у вас много запросов.
...