当前位置:  开发笔记 > 编程语言 > 正文

学说2,查询实体内部

如何解决《学说2,查询实体内部》经验,为你挑选了3个好方法。

如何在实体中执行查询?

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));

但显然这不起作用.



1> Boris Guéry..:

你的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的重大改进,你不应该破坏这个规则.



2> timdev..:

一般来说,你不应该这样做.

作为经验法则,实体不应该直接了解实体管理者(或通过某些中间对象).

其原因主要是可测试性,但根据我的经验,它有助于以其他方式保持组织.

我会通过设计一个为您处理查找的服务类来实现它.你的控制器(或其他)会像这样驱动它:

find('Member',$member_id); //get a member, some how.
$svc = new MemberService($em);

$favoriteCommentaries = $svc->getFavoriteCommentaries($member);

正如我在评论中提示的那样,如果您稍后决定要添加缓存(例如,通过memcached)以避免频繁查找,那么您可以在此服务类附近或此服务类中执行此操作.这使您的实体保持简洁,易于测试.由于您在构造时将实体管理器注入服务,因此您可以根据需要进行模拟.

getFavoriteCommentaries()可以使用各种实现.一个微不足道的是将它代理到Member :: getFavoriteCommentaries(),它实际上会加载所有内容,然后过滤掉"最喜欢的".这可能不会特别好地扩展,因此您可以通过使用EM来获取所需的数据来改进它.



3> Wilt..:

使用自定义存储库进行查询

您不应该在实体中编写查询,但是您应该使用存储库.这也在学说文档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;
}

推荐阅读
罗文彬2502852027
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有