Наличие настраиваемого репозитория, не связанного с сущностью в Symfony

У меня есть файл DefaultRepository, в котором можно разместить все общие запросы.

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

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

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

Залить репозиторий. Вы не должны использовать getRepo для чего-либо, что достаточно актуально.

Cerad 31.10.2018 23:06

Что вы имеете в виду под «родным SQL»? Пожалуйста, более конкретно опишите, что вы хотите сделать. Например, вы можете добавить немного сахара с помощью создания и обработки QueryBuilder.

Mcsky 01.11.2018 00:58
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Symfony Station Communiqué - 17 февраля 2023 г
Symfony Station Communiqué - 17 февраля 2023 г
Это коммюнике первоначально появилось на Symfony Station , вашем источнике передовых новостей Symfony, PHP и кибербезопасности.
Управление ответами api для исключений на Symfony с помощью KernelEvents
Управление ответами api для исключений на Symfony с помощью KernelEvents
Много раз при создании api нам нужно возвращать клиентам разные ответы в зависимости от возникшего исключения.
0
2
1 154
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

У вас может быть собственный общий «репозиторий», но вы не сможете получить его через 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, который вы вводите в качестве службы в свой контроллер. Таким образом становится более ясно, что это на самом деле не связано с какой-либо сущностью, но это что-то свое. Это может сделать этот подход более управляемым, когда у вас много запросов.

Я использую эту строку в контроллере: $ query = $ this-> get ('app.my_repository') -> searchAdvance ($ var, $ ‌ var1, $ var2, $ var3); Но это ошибка: «Ошибка типа: слишком мало аргументов для функции Doctrine \ ORM \ EntityRepository :: __ construct (), 1 передан в / var / www / html / amalia / var / cache / dev / appDevDebugProjectContain‌ er.php on строка 431 и ожидается ровно 2 "В чем ошибка?"

juanitourquiza 05.11.2018 18:16

Вам необходимо настроить репозиторий на вашем services.yml. Кажется, у вас есть 2 аргумента вместо 1 в моем примере. Если у вас более новая версия Symfony (3.4 или 4.0 и выше), вы можете использовать для этого автоматическое подключение: symfony.com/doc/current/service_container/autowiring.html В противном случае вам придется настроить конфигурацию, которую я добавил выше.

dbrumann 06.11.2018 08:13
Ответ принят как подходящий

Вам нужен не репозиторий. Репозиторий связан с 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();
    }
}

Это ошибка: «Примечание: неопределенная переменная: queryManager». В чем проблема?

juanitourquiza 05.11.2018 17:53

Вероятно, у вас где-то есть опечатка ... Отсутствует "$" или что-то в этом роде.

Vincent 06.11.2018 09:27

Это не работает так, как вы указываете для вызова с контроллера, на данный момент у меня это так: $ query = $ em-> getRepository ('BackendBundle: Users') -> searchAdvance ($ va‌ r, $ var1, $ var2, $ var3) ‌; Но как это было бы использовать ваше решение?

juanitourquiza 06.11.2018 17:12

Мое решение полагается на автоматическое подключение для внедрения службы. Сервис не является репозиторием, поэтому вы не можете вызвать его из метода $ em-> getRepository.

Vincent 06.11.2018 17:15

Ok. Теперь я использую службу в контроллере: $ query = $ this-> get ('app.queriesmanager') -> searchAdvance ($ var, ‌ $ var1, $ var2, $ var3); но показать эту ошибку: «Ошибка типа: аргумент 1, переданный в AppBundle \ Services \ QueriesManager :: __ construct (), должен реализовывать интерфейс Doctrine \ ORM \ EntityManagerInterface, экземпляр Symfony \ Component \ HttpFoundation \ Session \ Session, указанный в / var / www / html / amalia / var / cache / dev / appDevDebugProjectContain er.php в строке 532 "Строка такова: публичная функция __construct (EntityManagerInterface $ entityManager) {// File QueriesManager.php

juanitourquiza 06.11.2018 17:47

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

Это решение для меня: 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

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

Другие вопросы по теме