Php 原则2-如何处理不同步的数据库/实体
我正在开发一个PHPWeb应用程序,希望使用Doctrine 2.0实现ORM功能。然而,我在处理一种特定类型的查询时遇到了很大的问题 考虑一个包含Foo和Bar实体的简单域模型。一个Foo实体包含许多条,并且一条条可能被标记为活动条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
/** @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,具体取决于集合是否已加载。请查收。