原则 2,实体内部查询

2022-01-16 00:00:00 filter php doctrine doctrine-orm

如何在实体中执行查询?

How do I perform queries in an entity?

namespace EntitiesMembers;

/**
 * @Entity(repositoryClass="EntitiesMemberMembersRepository")
 * @Table(name="Members")
 * @HasLifecycleCallbacks
 */
class Members extends EntitiesAbstractEntity
{
    /**
     * @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="EntitiesUsersWall", mappedBy="entry", cascade={"persist"}) 
     */
    protected $commententries;

    public function __construct()
    {
        $this->commententries = new DoctrineCommonCollectionsArrayCollection();
    }
}

示例我想在这个实体内有一个名为:filter() 的函数我希望能够过滤 commententries 集合.它应该返回具有特定条件的集合,例如 id=1.基本上它应该过滤从连接查询接收到的数据.

Example I would like to have a function inside this entity called: filter() and I want to be able to filter the commententries collection. It should return a collection with a certain condition such id=1. Basically it should be filtering the data received from the join query.

所以是这样的:

$this->commententries->findBy(array('id' => 1));

但这显然行不通.

推荐答案

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

Generally speaking, you shouldn't do this.

根据经验,实体不应该知道实体管理器(直接或通过一些中间对象).

Entities, as a rule of thumb, should not know about the entitymanager (directly, or via some intermediary object).

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

The reason for this is mostly testability, but in my experience, it helps keeps things organized in other ways.

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

I'd approach it by designing a service class that handles the lookups for you. Your controller (or whatever) would drive it like this:

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

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

As I hint in the comment, if you decide later that you want to add caching (via memcached, for instance) to avoid frequent lookups, you'd do that somewhere near or in this service class. This keeps your entities nice and simple, and easily testable. Since you inject your entitymanager into the service at construction-time, you can mock that as needed.

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

getFavoriteCommentaries() could use various implementations. A trivial one would be to proxy it to Member::getFavoriteCommentaries(), which would actually load everything, and then filter out the "favorite" ones. That probably won't scale particularly well, so you could improve it by using the EM to fetch just the data you need.

相关文章