我究竟如何在Symfony2/Doctrine中创建自定义EntityManager?

VKB*_*VKB 6 php symfony doctrine-orm

Symfony/Doctrine的新人.亲切地指导我.

要求:要创建一个自定义的EntityManager,它会覆盖一些方法,比如删除(而不是删除,我想在我的类中执行更新和修改像isValid这样的参数,以便永远不删除记录)和find(查找)一个非零isValid等记录,并使用它而不是Doctrine的EntityManager.

我开始阅读这个帖子: 有没有办法在Symfony2中指定Doctrine2 Entitymanager实现类?并发现user2563451的答案并不那么简单.当他谈到不遵循某些方法时,我迷路了(再次没有要修改的文件的位置).

我查看了EntityManager.php,它特别告诉我不要使用扩展EntityManager类.而是要求扩展EntityManagerDecorator.在查看EntityManagerDecorator时,它内部没有可用的方法(比如我在EntityManager中找到的create,persist等)这是否意味着我需要为每个Entity Manager功能创建新方法?

由于没有明确的方法来完成这项工作,我很困惑,让这件事情开始了.另外,Doctrine cookbook对我来说没有多大用处,因为它没有任何信息可以达到这个目的.

因此,有关扩展EntityManagerDecorator或EntityManager的任何帮助都表示赞赏.

如果你能为我提供一步一步的指导,那就最好了.

谢谢 !

编辑1:我的要求是使用我的自定义EntityManager而不是Doctrine的EntityManager(EM),并根据我的要求修改那些'remove'和'find'方法.我不确定是否需要重用Doctrine EM提供的功能或从头开始编写.

小智 5

我认为您可能会将管理器与存储库混淆。

EntityManager 实际上只不过是用于管理特定实体或实体集合的服务。

存储库扩展\Doctrine\ORM\EntityRepository并告诉 Doctrine 如何将您的实体存储在数据库中。

您可以使用这两者的组合来实现您想要的。

例如。让我们以我们的实体 Foo

class Foo
{
    //...other properties

    protected $isValid;

    //...Getters and setters
}
Run Code Online (Sandbox Code Playgroud)

然后我们有一个 Foo 经理。

class FooManager
{
    protected $class;
    protected $orm;
    protected $repo;

    public function __construct(ObjectManager $orm , $class)
    {
        $this->orm = $orm;
        $this->repo = $orm->getRepository($class);

        $metaData = $orm->getClassMetadata($class);
        $this->class = $metaData->getName();
    }

    public function create()
    {
        $class = $this->getClass();
        $foo = new $class;

        return $foo;
    }

    public function findBy(array $criteria)
    {
        return $this->repo->findOneBy($criteria);
    }

    public function refreshFoo(Foo $foo)
    {
        $this->orm->refresh($foo);
    }

    public function updateFoo(Foo $foo, $flush = true)
    {   
        $this->orm->persist($foo);
        if($flush)
        {
            $this->orm->flush();
        }
    }

    public function getClass()
    {
        return $this->class;
    }
}
Run Code Online (Sandbox Code Playgroud)

我们有一些用于创建和更新对象的基本功能。现在,如果您想“删除”它而不实际删除它,您可以在管理器中添加以下功能。

public function remove(Foo $foo)
{
    $foo->setIsValid(false);
    return $this->update($foo);
}
Run Code Online (Sandbox Code Playgroud)

这样,我们将isValid字段更新为 false 并将其持久化到数据库中。您可以像使用控制器中的任何服务一样使用它。

class MyController extends Controller
{
    public function someAction()
    {
        $fooManager = $this->get('my_foo_manager');
        $newFoo = $fooManager->create();

        //...
        $fooManager->remove($newFoo);
    }
}
Run Code Online (Sandbox Code Playgroud)

所以现在我们有了删除部分。

接下来,我们只想找到isValid设置为 TRUE 的实体。

老实说,我处理这个问题的方式甚至不是修改查找,而是在您的控制器中

if(!$foo->getIsValid())
{
    //Throw some kind of error.  Or redirect to an error page.
}
Run Code Online (Sandbox Code Playgroud)

但如果你想以另一种方式做到这一点。你可以做一个回购。

use Doctrine\ORM\EntityRepository;
class FooRepository extends EntityRepository
{
    public function find($id, $lockMode = LockMode::NONE, $lockVersion = null)
    {
        //Some custom doctrine query.
    }
}
Run Code Online (Sandbox Code Playgroud)

我们用我们自己的覆盖了 EntityRepository 的原生 find() 函数。

最后,我们将所有这些都注册到了正确的位置。对于经理,您必须提供服务。

services:
    my_foo_manager:
        class: AppBundle\Manager\FooManager
        arguments: [ "@doctrine.orm.entity_manager" , 'AppBundle\Entity\Foo']
Run Code Online (Sandbox Code Playgroud)

对于存储库,您必须repositoryClass在实体的 ORM 定义中指定。

AppBundle\Entity\Foo:
    type: entity
    repositoryClass: AppBundle\Entity\FooRepository
    table: foos
    id:
        id:
            type: integer
            generator: {strategy: AUTO}
            options: {unsigned: true}
    fields:
        isValid:
            type: boolean
Run Code Online (Sandbox Code Playgroud)

了解所有这些后,您现在可以使用实体做一些非常酷的事情。我希望这有帮助。祝你好运!