Php 原则2-如何处理不同步的数据库/实体

Php 原则2-如何处理不同步的数据库/实体,php,orm,doctrine-orm,Php,Orm,Doctrine Orm,我正在开发一个PHPWeb应用程序,希望使用Doctrine 2.0实现ORM功能。然而,我在处理一种特定类型的查询时遇到了很大的问题 考虑一个包含Foo和Bar实体的简单域模型。一个Foo实体包含许多条,并且一条条可能被标记为活动条 /** @Entity */ class Foo { /** @OneToMany(targetEntity="Bar", mappedBy="foo") */ protected $bars; /** Returns Bars mark

我正在开发一个PHPWeb应用程序,希望使用Doctrine 2.0实现ORM功能。然而,我在处理一种特定类型的查询时遇到了很大的问题

考虑一个包含Foo和Bar实体的简单域模型。一个Foo实体包含许多条,并且一条条可能被标记为活动条

/** @Entity */
class Foo
{
    /** @OneToMany(targetEntity="Bar", mappedBy="foo") */
    protected $bars;

    /** Returns Bars marked as active. */
    public function getActiveBars()
    {
        // XXX What goes here?
    }
}

/** @Entity */
class Bar
{
    /** @ManyToOne(targetEntity="Foo", inversedBy="bar") */
    protected $foo;

    /** @Column(type="boolean") */
    protected $active;

    /** ...setter omitted for clarity... */
}
我的问题是:在getActiveBars方法中应该放置什么代码

下面的代码工作正常,但当数据库中有许多非活动的Bar对象时,性能将成为一个问题。迭代Bar集合会导致对数据库执行大型查询

function getActiveBars()
{
    $ret = array();
    foreach($this->bars as $bar) {
        if ($bar->isActive()) $ret[] = $bar;
    }
    return $ret;
}

在getActiveBar中执行DQL查询,如SELECT b FROM Bar l,其中b.active=true和b.foo=:foo似乎是解决方案,但是这样的查询不会检测到在调用EntityManagerflush之前对Bar所做的任何未完成的更改,因为DQL是针对数据库执行的。

这可能不是世界末日。如果Foo::bar已加载、已修改且尚未提交回数据库,那么您唯一的选择就是迭代

如果没有加载Foo::bar,那么它肯定没有被修改,所以您可以查询数据库

最后,如果已经加载、修改并提交了bars,bars集合的大小可能会决定是抓取还是迭代更好

让我好奇的是,有一种方法可以让实体判断集合中的成员是否已加载

在您的示例中,似乎暗示代理的ArrayCollection Foo:bar不会通过instanceof ArrayCollection测试。所以你可以试着变得聪明,比如:

     class Foo {   
       public function getActiveBars(){
         if ($this->bars instanceof \Doctrine\Common\Collection\ArrayCollection){
           //get active bars by iterating over $this->bars
         }else{
           //get active bars by DQL, and avoid loading $this->bars (for now).
         }
       }
     }

从2.3版开始,Doctrine就开始使用DQL或数组搜索过滤ArrayCollection,具体取决于集合是否已加载。请查收。