如何在实体中执行查询?
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(); } }
示例我想在这个实体中有一个函数叫做:filter()
我希望能够过滤commententries
集合.它应该返回具有某种条件的集合id=1
.基本上它应该过滤从连接查询接收的数据.
所以像这样:
$this->commententries->findBy(array('id' => 1));
但显然这不起作用.
你的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; } );
(未测试)
请注意,此类方法将迭代并急切加载所有注释,因此,如果用户有很多,则可能是一个很大的瓶颈;
在大多数情况下,您希望使用自定义存储库,您可以在其中放置此类逻辑.
正如timdev建议的那样,您可以创建一个MemberService,它将通过了解EntityManager来包装此类调用.
将实体与Peristance Layer分开是对Doctrine 1的重大改进,你不应该破坏这个规则.
一般来说,你不应该这样做.
作为经验法则,实体不应该直接了解实体管理者(或通过某些中间对象).
其原因主要是可测试性,但根据我的经验,它有助于以其他方式保持组织.
我会通过设计一个为您处理查找的服务类来实现它.你的控制器(或其他)会像这样驱动它:
find('Member',$member_id); //get a member, some how. $svc = new MemberService($em); $favoriteCommentaries = $svc->getFavoriteCommentaries($member);
正如我在评论中提示的那样,如果您稍后决定要添加缓存(例如,通过memcached)以避免频繁查找,那么您可以在此服务类附近或此服务类中执行此操作.这使您的实体保持简洁,易于测试.由于您在构造时将实体管理器注入服务,因此您可以根据需要进行模拟.
getFavoriteCommentaries()可以使用各种实现.一个微不足道的是将它代理到Member :: getFavoriteCommentaries(),它实际上会加载所有内容,然后过滤掉"最喜欢的".这可能不会特别好地扩展,因此您可以通过使用EM来获取所需的数据来改进它.
使用自定义存储库进行查询
您不应该在实体中编写查询,但是您应该使用存储库.这也在学说文档7.8.8自定义存储库中进行了解释.它允许您在中心点上构建自定义查询并保持实体定义清晰.
使用条件过滤集合:
但是如果你想在get
你可以使用的方法中过滤你的集合内部Criteria
.您可以Criteria
在Doctrine文档中阅读如何使用8.8过滤集合.要像你想要的那样过滤会看起来像这样:
在您的实体类的顶部声明Criteria
该类
use Doctrine\Common\Collections\Criteria
在您的getCommentEntries
方法中使用类来过滤:
public function getCommentEntries() { $criteria = Criteria::create() ->where(Criteria::expr()->eq('id', 1)); $filteredCommentEntries = $this->commententries->matching($criteria); return $filteredCommentEntries; }