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

时间:2015-08-07 19:02:43

标签: php symfony doctrine-orm

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

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

我开始阅读这个帖子: Is there a way to specify Doctrine2 Entitymanager implementation class in Symfony2?并且发现user2563451的答案并不那么简单。当他谈到不遵循某些方法时,我迷路了(再次没有要修改的文件的位置)。

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

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

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

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

谢谢!

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

2 个答案:

答案 0 :(得分:4)

我认为您可能会将Manager与存储库混淆。

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

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

您可以结合使用这两者来实现您的目标。

例如。我们来看看我们的实体Foo

class Foo
{
    //...other properties

    protected $isValid;

    //...Getters and setters
}

然后我们有一位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;
    }
}

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

public function remove(Foo $foo)
{
    $foo->setIsValid(false);
    return $this->update($foo);
}

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

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

        //...
        $fooManager->remove($newFoo);
    }
}

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

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

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

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

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

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

我们使用自己的。(/ p>)覆盖EntityRepository的本机find()函数

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

services:
    my_foo_manager:
        class: AppBundle\Manager\FooManager
        arguments: [ "@doctrine.orm.entity_manager" , 'AppBundle\Entity\Foo']

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

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

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

答案 1 :(得分:0)

关于您的用例,您应该使用Doctrine Lifecycle Callbacks作为删除案例,并简单地在实体存储库中使用find方法。