Я работаю с Symfony 4, у меня много репозиториев с обычным поведением, поэтому я хочу избежать повторения кода. Я попытался определить родительский класс репозитория следующим образом:
<?php
namespace App\Repository;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Symfony\Bridge\Doctrine\RegistryInterface;
class AppRepository extends ServiceEntityRepository {
public function __construct(RegistryInterface $registry, $entityClass) {
parent::__construct($registry, $entityClass);
}
// Common behaviour
}
Таким образом, я мог бы определить его дочерние классы, например:
<?php
namespace App\Repository;
use App\Entity\Test;
use App\Repository\AppRepository;
use Symfony\Bridge\Doctrine\RegistryInterface;
class TestRepository extends AppRepository {
public function __construct(RegistryInterface $registry) {
parent::__construct($registry, Test::class);
}
}
Но я получаю такую ошибку:
Cannot autowire service "App\Repository\AppRepository": argument "$entityClass" of method "__construct()" must have a type-hint or be given a value explicitly.
Я попытался установить подсказку типа, например string, object, но это не сработало.
Есть ли способ определить общий репозиторий?
заранее спасибо
Это сработало !!! Большое спасибо. Добавил в services.yaml exclude: '../src/{Entity,Migrations,Tests,Repository/AppRepository.php}'.. Если вы хотите добавить Его как ответ, чтобы я мог отметить его как правильный!
Почему бы вам просто не создать соответствующий репозиторий для каждой из ваших сущностей?
Поскольку это общая система, которая может взаимодействовать с разными СУБД, поэтому в ней много изменений синтаксиса, поэтому у меня есть общий запрос, например, для выполнения хранимых процедур, которые «предварительно проверяют» СУБД. Если мне придется выполнять эту логику во всех моих репозиториях, это приведет к многократному повторению кода.
У меня был тот же вопрос «почему». Совместное использование кода в репозиториях имеет тенденцию к беспорядку. Но если это сработает, тогда ладно. Также можно рассмотреть возможность использования черты характера.
черта хорошее предложение! Но я не могу его использовать, так как мне нужно подготовить исполняемый SQL. В моем случае у меня CALL <sp_name> (<params>) для MySQL и ORACLE; и EXEC <sp_name> <params> для SQL Server. И оба выдают разные исключения из-за драйверов ODBC. Так что с этим универсальным репозиторием я могу легко справиться с этим, не проверяя везде! : D
Просто примечание: нет необходим для реализации __construct() в AppRepository: ServiceEntityRepository::__construct() имеет ту же сигнатуру и будет фактически выполнен.






Одна из "ловушек" autowire заключается в том, что по умолчанию autowire ищет все классы в src и пытается превратить их в сервисы. В некоторых случаях он в конечном итоге выбирает классы, такие как ваш AppRepository, которые не предназначены для обслуживания, а затем терпит неудачу, когда пытается их автоматически подключить.
Наиболее распространенное решение - явно исключить эти классы:
# config/services.yaml
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php,Repository/AppRepository.php}'
Другой подход, который должен работать (не тестировался), - сделать AppRepository абстрактным. Autowire игнорирует абстрактные классы. Репозитории немного сложны, и наличие абстрактных классов, расширяющих не абстрактные классы, несколько необычно.
Просто сделайте свой AppRepository абстрактным, например
abstract class AppRepository {}
Просто исключите AppRepository из файла services.yaml. Процесс autowire пытается подключить его, поэтому вам нужно сказать ему, чтобы он игнорировал его.