dea*_*ase 7 php doctrine filter doctrine-orm
如何在实体中执行查询?
namespace Entities\Members;
/**
* @Entity(repositoryClass="\Entities\Member\MembersRepository")
* @Table(name="Members")
* @HasLifecycleCallbacks
*/
class Members extends \Entities\AbstractEntity
{
/**
* @Id @Column(name="id", type="bigint",length=15)
* @GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @Column(name="userid", type="bigint", length=26, nullable=true)
*/
protected $userid;
/**
* @Column(name="fname", type="string", length=255,nullable=true)
*/
protected $fname;
/**
* @OneToMany(targetEntity="\Entities\Users\Wall", mappedBy="entry", cascade={"persist"})
*/
protected $commententries;
public function __construct()
{
$this->commententries = new \Doctrine\Common\Collections\ArrayCollection();
}
}
Run Code Online (Sandbox Code Playgroud)
示例我想在这个实体中有一个函数叫做:filter()
我希望能够过滤commententries集合.它应该返回具有某种条件的集合id=1.基本上它应该过滤从连接查询接收的数据.
所以像这样:
$this->commententries->findBy(array('id' => 1));
Run Code Online (Sandbox Code Playgroud)
但显然这不起作用.
Bor*_*éry 21
你的ArrayCollection已经实现了一个filter()方法,你需要传递一个Closure来让它工作你的实体(这里是commentEntries).
$idsToFilter = array(1,2,3,4);
$member->getComments()->filter(
function($entry) use ($idsToFilter) {
if (in_array($entry->getId(), $idsToFilter)) {
return true;
}
return false;
}
);
Run Code Online (Sandbox Code Playgroud)
(未测试)
请注意,此类方法将迭代并急切加载所有注释,因此,如果用户有很多,则可能是一个很大的瓶颈;
在大多数情况下,您希望使用自定义存储库,您可以在其中放置此类逻辑.
正如timdev建议的那样,您可以创建一个MemberService,它将通过了解EntityManager来包装此类调用.
将实体与Peristance Layer分开是对Doctrine 1的重大改进,你不应该破坏这个规则.
tim*_*dev 12
一般来说,你不应该这样做.
作为经验法则,实体不应该直接了解实体管理者(或通过某些中间对象).
其原因主要是可测试性,但根据我的经验,它有助于以其他方式保持组织.
我会通过设计一个为您处理查找的服务类来实现它.你的控制器(或其他)会像这样驱动它:
<?php
// create a new service, injecting the entitymanager. if you later wanted
// to start caching some things, you might inject a cache driver as well.
$member = $em->find('Member',$member_id); //get a member, some how.
$svc = new MemberService($em);
$favoriteCommentaries = $svc->getFavoriteCommentaries($member);
Run Code Online (Sandbox Code Playgroud)
正如我在评论中提示的那样,如果您稍后决定要添加缓存(例如,通过memcached)以避免频繁查找,那么您可以在此服务类附近或此服务类中执行此操作.这使您的实体保持简洁,易于测试.由于您在构造时将实体管理器注入服务,因此您可以根据需要进行模拟.
getFavoriteCommentaries()可以使用各种实现.一个微不足道的是将它代理到Member :: getFavoriteCommentaries(),它实际上会加载所有内容,然后过滤掉"最喜欢的".这可能不会特别好地扩展,因此您可以通过使用EM来获取所需的数据来改进它.
使用自定义存储库进行查询
您不应该在实体中编写查询,但是您应该使用存储库.这也在学说文档7.8.8自定义存储库中进行了解释.它允许您在中心点上构建自定义查询并保持实体定义清晰.
使用条件过滤集合:
但是如果你想在get你可以使用的方法中过滤你的集合内部Criteria.您可以Criteria在Doctrine文档中阅读如何使用8.8过滤集合.要像你想要的那样过滤会看起来像这样:
在您的实体类的顶部声明Criteria该类
use Doctrine\Common\Collections\Criteria
Run Code Online (Sandbox Code Playgroud)
在您的getCommentEntries方法中使用类来过滤:
public function getCommentEntries()
{
$criteria = Criteria::create()
->where(Criteria::expr()->eq('id', 1));
$filteredCommentEntries = $this->commententries->matching($criteria);
return $filteredCommentEntries;
}
Run Code Online (Sandbox Code Playgroud)