Php Symfony-正在使用的注入条令存储库
据 就像Php Symfony-正在使用的注入条令存储库,php,symfony,doctrine-orm,symfony-3.4,Php,Symfony,Doctrine Orm,Symfony 3.4,据 就像 acme.custom_repository: class: Doctrine\ORM\EntityRepository factory: ['@doctrine.orm.entity_manager', getRepository] arguments: - 'Acme\FileBundle\Model\File' 但我有个例外 无效的服务“acme.custom_存储库”:类 “实体管理器5AA02DE170F88_546a8d27f194
acme.custom_repository:
class: Doctrine\ORM\EntityRepository
factory: ['@doctrine.orm.entity_manager', getRepository]
arguments:
- 'Acme\FileBundle\Model\File'
但我有个例外
无效的服务“acme.custom_存储库”:类
“实体管理器5AA02DE170F88_546a8d27f194334ee012bfe64f629947b07e4919_uuuCG\uuuuu\document\ORM\EntityManager”
不存在
在Symfony 3.4中如何执行此操作
更新:
EntityClass实际上是一个有效的类FQCN(当然也在phpstorm上使用了复制引用),只是重命名了它,因为其中有一个公司名称:)。不管怎样,我还是更新了它
解决方案
布鲁姆的作品完美。
如果不使用自动布线,则服务定义如下:
Acme\AcmeBundle\Respository\MyEntityRepository:
arguments:
- '@Doctrine\Common\Persistence\ManagerRegistry'
- Acme\AcmeBundle\Model\MyEntity # '%my_entity_class_parameter%'
检查参数是否为有效类(具有FQCN或捆绑简化),例如:
acme.custom_repository:
class: Doctrine\ORM\EntityRepository
factory:
- '@doctrine.orm.entity_manager'
- getRepository
arguments:
- Acme\MainBundle\Entity\MyEntity
或
希望这有助于正确创建自定义存储库
首先,您需要创建repository自定义类,该类从doctrine扩展默认存储库:
use Doctrine\ORM\EntityRepository;
class UserRepository extends EntityRepository
{
// your own methods
}
然后在实体类中需要此注释:
/**
* @ORM\Entity(repositoryClass="MyDomain\Model\UserRepository")
*/
然后在.yml文件中定义存储库:
custom_repository:
class: MyDomain\Model\UserRepository
factory: ["@doctrine", getRepository]
arguments:
- Acme\FileBundle\Model\File
确保存储库定义中的类
指向自定义存储库类,而不是条令\ORM\EntityRepository
将自定义服务注入自定义存储库:
在自定义存储库上为服务创建自定义设置器
使用条令\ORM\EntityRepository
class UserRepository extends EntityRepository
{
protected $paginator;
public function setPaginator(PaginatorInterface $paginator)
{
$this->paginator = $paginator;
}
}
然后像这样注入它们:
custom_repository:
class: MyDomain\Model\UserRepository
factory: ["@doctrine", getRepository]
arguments:
- Acme\FileBundle\Model\File
calls:
- [setPaginator, ['@knp_paginator']]
<?php
namespace App\Database\Repository\Post;
use App\Database\Repository\Repository;
use App\Entity\Blog\Post;
/**
* Class PostRepository
* @package App\Database\Repository
*/
class PostRepository extends Repository
{
public function test()
{
dd(99999, $this->getEntityName());
}
}
将存储库注入服务:
在使用Symfony 3.4时,可以使用一种更简单的方法,即使用
ServiceEntityRepository
。只需实现您的存储库,让它扩展
classServiceEntityRepository
,您就可以简单地注入它。(至少在使用自动布线时——我没有将其用于经典DI配置,但我认为它也应该工作。)
换言之:
namespace App\Repository;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Common\Persistence\ManagerRegistry;
class ExampleRepository extends ServiceEntityRepository
{
/**
* @param ManagerRegistry $managerRegistry
*/
public function __construct(ManagerRegistry $managerRegistry)
{
parent::__construct($managerRegistry, YourEntity::class);
}
}
现在,在没有任何DI配置的情况下,您可以在任何地方注入存储库,包括控制器方法
一个警告(同样适用于您尝试注入存储库的方式):如果重新设置条令连接,您将有一个对过时存储库的引用。但是,我承认这是一个风险,否则我将无法直接注入存储库。到目前为止,我在这里看到的解决方案还不错。我从另一个角度看它。因此,我的解决方案允许您保持存储库干净,sorta强制执行一致的项目结构,并且您可以保持自动连接 这就是我在Symfony 5中解决它的方法 目标 我们希望拥有自动连接的存储库,并希望尽可能保持它们的干净。我们也希望他们是超级容易使用 问题 我们需要找出一种方法来告诉存储库它应该使用的实体 解决方案 解决方案很简单,包括以下几点:
Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository
类公共字符串$entity
属性<?php
namespace App\Database\Repository;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
use Laminas\Code\Reflection\ClassReflection;
use Symfony\Component\Finder\Finder;
/**
* Class Repository
* @package App\Database\Repository
*/
abstract class Repository extends ServiceEntityRepository
{
/** @var string */
private const REPOSITORY_FILE = 'repository';
/** @var string */
public string $entity = '';
/** @var string */
public string $defaultEntitiesLocation;
/** @var string */
public string $defaultEntitiesNamespace;
/**
* Repository constructor.
*
* @param ManagerRegistry $registry
* @param $defaultEntitiesLocation
* @param $defaultEntitiesNamespace
* @throws \Exception
*/
public function __construct(
ManagerRegistry $registry,
$defaultEntitiesLocation,
$defaultEntitiesNamespace
) {
$this->defaultEntitiesLocation = $defaultEntitiesLocation;
$this->defaultEntitiesNamespace = $defaultEntitiesNamespace;
$this->findEntities();
parent::__construct($registry, $this->entity);
}
/**
* Find entities.
*
* @return bool
* @throws \ReflectionException
*/
public function findEntities()
{
if (class_exists($this->entity)) {
return true;
}
$repositoryReflection = (new ClassReflection($this));
$repositoryName = strtolower(preg_replace('/Repository/', '', $repositoryReflection->getShortName()));
$finder = new Finder();
if ($finder->files()->in($this->defaultEntitiesLocation)->hasResults()) {
foreach ($finder as $file) {
if (strtolower($file->getFilenameWithoutExtension()) === $repositoryName) {
if (!empty($this->entity)) {
throw new \Exception('Entity can\'t be matched automatically. It looks like there is' .
' more than one ' . $file->getFilenameWithoutExtension() . ' entity. Please use $entity
property on your repository to provide entity you want to use.');
}
$namespacePart = preg_replace(
'#' . $this->defaultEntitiesLocation . '#',
'',
$file->getPath() . '/' . $file->getFilenameWithoutExtension()
);
$this->entity = $this->defaultEntitiesNamespace . preg_replace('#/#', '\\', $namespacePart);
}
}
}
}
}
Post
将是我们的实体,PostRepository
是我们的存储库。请注意,Repository
这个词不是必须的。如果它在那里,它将被移除custom_repository:
class: MyDomain\Model\UserRepository
factory: ["@doctrine", getRepository]
arguments:
- Acme\FileBundle\Model\File
calls:
- [setPaginator, ['@knp_paginator']]
<?php
namespace App\Database\Repository\Post;
use App\Database\Repository\Repository;
use App\Entity\Blog\Post;
/**
* Class PostRepository
* @package App\Database\Repository
*/
class PostRepository extends Repository
{
public function test()
{
dd(99999, $this->getEntityName());
}
}
这可能会有帮助:遗憾的是没有。。。同样的例外,如果您碰巧使用多个实体管理器,您也需要稍微小心一点。如果同一个实体类属于多个管理器,那么您无法预测最终将使用哪个管理器。现在如何使用存储库?你能扩展这个答案吗?典型用法:构造函数注入。只需在代码中定义“public function_uu构造(ExampleRepository$repo){}”,依赖关系将在不进行配置的情况下得到解决。
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
bind:
$defaultEntitiesLocation: '%kernel.project_dir%/src/Entity'
$defaultEntitiesNamespace: 'App\Entity'
<?php
namespace App\Database\Repository\Post;
use App\Database\Repository\Repository;
use App\Entity\Blog\Post;
/**
* Class PostRepository
* @package App\Database\Repository
*/
class PostRepository extends Repository
{
public function test()
{
dd(99999, $this->getEntityName());
}
}