Symfony 5 - 存储库 Class 从自定义 BaseRepository Class 扩展而不是 ServiceEntityRepository
Symfony 5 - Repository Class extend from custom BaseRepository Class instead of ServiceEntityRepository
假设我们有两个存储库 classes:
class CarrierRepository extends ServiceEntityRepository
{
const ENTITY = 'carrier';
/** @var PaginatorInterface $paginator */
private $paginator;
public function __construct(ManagerRegistry $registry, PaginatorInterface $paginator)
{
$this->paginator = $paginator;
parent::__construct($registry, Carrier::class);
}
.
.
.
class LocationRepository extends ServiceEntityRepository
{
const ENTITY = 'location';
/** @var PaginatorInterface $paginator */
private $paginator;
public function __construct(ManagerRegistry $registry, PaginatorInterface $paginator)
{
$this->paginator = $paginator;
parent::__construct($registry, Location::class);
}
.
.
.
并且在这两个存储库 classes 中,我们具有相同的逻辑,如下所示:
public function search(array $searchParams)
{
$parameters = [];
$qb = $this->createQueryBuilder(self::ENTITY);
foreach ($searchParams['data'] as $key => $searchParam) {
if (!empty($searchParam['param'])) {
$entity = self::ENTITY;
$operator = 'LIKE';
$column = $searchParam['key'];
$parameters[$searchParam['key']] = '%'.$searchParam['param'].'%';
.
.
.
如您所见,两个存储库 class 具有相同的依赖关系和相同的逻辑 - 除了实体 class - 在一个 class 中它是“载体”并且在另一个是“位置”。
我认为将其合并到 BaseRepository class 中是个好主意,如下所示:
class BaseRepository extends ServiceEntityRepository
{
private $entity;
/** @var PaginatorInterface $paginator */
private $paginator;
public function __construct($entity, ManagerRegistry $registry, PaginatorInterface $paginator)
{
$this->entity = $entity;
$this->paginator = $paginator;
parent::__construct($registry, $this->entity);
}
public function search(array $searchParams)
{
$parameters = [];
$qb = $this->createQueryBuilder(self::ENTITY);
foreach ($searchParams['data'] as $key => $searchParam) {
if (!empty($searchParam['param'])) {
$entity = self::ENTITY;
$operator = 'LIKE';
$column = $searchParam['key'];
$parameters[$searchParam['key']] = '%'.$searchParam['param'].'%';
.
.
.
并扩展我的其他两个存储库而不是
ServiceEntityRepository
像这样使用我的 BaseRepository(CarrierRepository 的示例):
class CarrierRepository extends BaseRepository
{
const ENTITY = 'carrier';
/** @var PaginatorInterface $paginator */
private $paginator;
public function __construct(ManagerRegistry $registry, PaginatorInterface $paginator)
{
$this->paginator = $paginator;
parent::__construct(Carrier::class, $registry, $paginator);
}
.
.
.
这不起作用 - 它会给我这个错误:
Cannot autowire service "App\Repository\BaseRepository": argument
"$entity" of method "__construct()" has no type-hint, you should
configure its value explicitly.
问题:
我如何为所有使用相同属性和逻辑的 EntityRepositories 实现 BaseRepository,这样我就不必一次又一次地在我的所有 Repository classes 中实现整个逻辑?
我想要一个基本存储库,其中包含整个逻辑,我的所有存储库 classes 都可以使用相同的代码。
下面是我制作 BaseRepository 的方法:
abstract class BaseRepository extends ServiceEntityRepository
{
protected string $entityClass;
public function __construct(ManagerRegistry $registry, string $entityClass)
{
$this->entityClass = $entityClass;
parent::__construct($registry, $entityClass);
}
}
class CompanyUserRepository extends BaseRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, CompanyUser::class);
}
}
重点是使 BaseRepository
抽象化,禁用此 class 的“自动装配”。
假设我们有两个存储库 classes:
class CarrierRepository extends ServiceEntityRepository
{
const ENTITY = 'carrier';
/** @var PaginatorInterface $paginator */
private $paginator;
public function __construct(ManagerRegistry $registry, PaginatorInterface $paginator)
{
$this->paginator = $paginator;
parent::__construct($registry, Carrier::class);
}
.
.
.
class LocationRepository extends ServiceEntityRepository
{
const ENTITY = 'location';
/** @var PaginatorInterface $paginator */
private $paginator;
public function __construct(ManagerRegistry $registry, PaginatorInterface $paginator)
{
$this->paginator = $paginator;
parent::__construct($registry, Location::class);
}
.
.
.
并且在这两个存储库 classes 中,我们具有相同的逻辑,如下所示:
public function search(array $searchParams)
{
$parameters = [];
$qb = $this->createQueryBuilder(self::ENTITY);
foreach ($searchParams['data'] as $key => $searchParam) {
if (!empty($searchParam['param'])) {
$entity = self::ENTITY;
$operator = 'LIKE';
$column = $searchParam['key'];
$parameters[$searchParam['key']] = '%'.$searchParam['param'].'%';
.
.
.
如您所见,两个存储库 class 具有相同的依赖关系和相同的逻辑 - 除了实体 class - 在一个 class 中它是“载体”并且在另一个是“位置”。 我认为将其合并到 BaseRepository class 中是个好主意,如下所示:
class BaseRepository extends ServiceEntityRepository
{
private $entity;
/** @var PaginatorInterface $paginator */
private $paginator;
public function __construct($entity, ManagerRegistry $registry, PaginatorInterface $paginator)
{
$this->entity = $entity;
$this->paginator = $paginator;
parent::__construct($registry, $this->entity);
}
public function search(array $searchParams)
{
$parameters = [];
$qb = $this->createQueryBuilder(self::ENTITY);
foreach ($searchParams['data'] as $key => $searchParam) {
if (!empty($searchParam['param'])) {
$entity = self::ENTITY;
$operator = 'LIKE';
$column = $searchParam['key'];
$parameters[$searchParam['key']] = '%'.$searchParam['param'].'%';
.
.
.
并扩展我的其他两个存储库而不是
ServiceEntityRepository
像这样使用我的 BaseRepository(CarrierRepository 的示例):
class CarrierRepository extends BaseRepository
{
const ENTITY = 'carrier';
/** @var PaginatorInterface $paginator */
private $paginator;
public function __construct(ManagerRegistry $registry, PaginatorInterface $paginator)
{
$this->paginator = $paginator;
parent::__construct(Carrier::class, $registry, $paginator);
}
.
.
.
这不起作用 - 它会给我这个错误:
Cannot autowire service "App\Repository\BaseRepository": argument "$entity" of method "__construct()" has no type-hint, you should configure its value explicitly.
问题: 我如何为所有使用相同属性和逻辑的 EntityRepositories 实现 BaseRepository,这样我就不必一次又一次地在我的所有 Repository classes 中实现整个逻辑? 我想要一个基本存储库,其中包含整个逻辑,我的所有存储库 classes 都可以使用相同的代码。
下面是我制作 BaseRepository 的方法:
abstract class BaseRepository extends ServiceEntityRepository
{
protected string $entityClass;
public function __construct(ManagerRegistry $registry, string $entityClass)
{
$this->entityClass = $entityClass;
parent::__construct($registry, $entityClass);
}
}
class CompanyUserRepository extends BaseRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, CompanyUser::class);
}
}
重点是使 BaseRepository
抽象化,禁用此 class 的“自动装配”。