原则 2、实体内部查询
如何在实体中执行查询?
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));
但显然这是行不通的。
How do I perform queries in an entity?
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();
}
}
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.
So something like this:
$this->commententries->findBy(array('id' => 1));
But obviously this does not work.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您的 ArrayCollection 已经实现了一个 filter() 方法,您需要传递一个 Closure 来让它工作您的实体(这里是 commentEntries)。
(未经测试)
请注意,此类方法将迭代并热切加载您的所有评论,因此如果用户有很多评论,则可能会成为一个大瓶颈;
在大多数情况下,您希望使用自定义存储库,您可以在其中放置此类逻辑。
正如 timdev 建议的那样,您可以创建一个 MemberService,它将通过了解 EntityManager 来包装此类调用。
将实体与持久层分离是对原则 1 的重大改进,您不应该违反该规则。
Your ArrayCollection already implements a filter() method, you need to pass a Closure to get it to work your entities (here, the commentEntries).
(not tested)
Note that such method will iterate and eager load over all your Comments, so in case where a User has a lot it may be a big bottleneck;
In most case, you want to use a custom repositories, where you can place such logic.
As timdev suggested, you can create a MemberService which will wrap such call by being aware of the EntityManager.
Separating Entities from the Peristance Layer is a big improvement over Doctrine 1, and you should not break that rule.
一般来说,您不应该这样做。
根据经验,实体不应该(直接或通过某些中间对象)了解实体管理器。
这样做的原因主要是可测试性,但根据我的经验,它有助于以其他方式保持事物的组织性。
我会通过设计一个为您处理查找的服务类来解决这个问题。你的控制器(或其他什么)会像这样驱动它:
正如我在评论中暗示的那样,如果你稍后决定添加缓存(例如通过memcached)以避免频繁查找,你会在附近或附近的某个地方这样做这个服务等级。这使您的实体保持美观、简单,并且易于测试。由于您在构建时将实体管理器注入到服务中,因此您可以根据需要对其进行模拟。
getFavoriteCommentaries() 可以使用各种实现。一个简单的方法是将其代理给 Member::getFavoriteCommentaries(),它实际上会加载所有内容,然后过滤掉“最喜欢的”评论。这可能不会很好地扩展,因此您可以通过使用 EM 只获取您需要的数据来改进它。
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:
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() 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.
使用自定义存储库进行查询
您不应在实体中编写查询,但应该为此使用存储库。这也在学说文档中进行了解释7.8.8 自定义存储库。它将允许您在中心位置构建自定义查询并保持实体定义干净。
使用条件过滤集合:
但是,如果您想在
get
方法中过滤集合内的内容,则可以使用Criteria
。您可以在 Doctrine 文档中阅读如何使用Criteria
8.8 过滤集合。要像您想要的那样进行过滤,看起来像这样:在实体类的顶部声明
Criteria
类在您的
getCommentEntries
方法中使用该类进行过滤:Use a custom repository for queries
You should not write queries in your entities, but you should use a repository for that. This is also explained in the doctrine documentation 7.8.8 Custom Repositories. It will allows you to build your custom queries on a central spot and keeps your entity definitions clean.
Use criteria to filter collections:
But if you want to filter inside your collection in a
get
method you can useCriteria
. You can read on how to useCriteria
in the Doctrine documentation 8.8 Filtering collections. To filter like you want to do would look something like this:Declare at the top of your entity class the
Criteria
classIn your
getCommentEntries
method use the class to filter:你的问题确实很难理解,请尝试在以后如何组织你的问题。例如,您说“返回相同的结果”但“过滤”,这可能意味着任何内容。您是否想使用相同的结果集(为什么您会选择这样做),并且仅使用 array_filter 或 array_walk 来过滤结果,或者您实际上想使用条件连接?这是非常暧昧的。
不管怎样..回答(读你的问题四遍后)。
Your question was really hard to understand, please try and work on how you structure your questions in the future. For instance, you say "return back the same result" but "filter", which could mean anything. Do you want to use the same result set (why on earth would you ever choose to do that), and just use array_filter or array_walk to filter the results or do you actually want to use a conditional join? It's incredibly ambiguous.
Anyway.. answer ( after reading your question 4 times).
我同意“蒂姆德夫”。您不应该在实体类中定义查询。我定义服务类的方法支持实体是存储库类。例如:用户(实体--YourBundle/Entity/User.php)将拥有UserRepository(服务类--YourBundle/Repository/UserRepository.php)。你的“过滤器”方法应该在这里。您只需将该服务类映射到您的实体类中即可。在您的控制器中,您始终可以通过其存储库访问“过滤器”。 Symfony2 书 中记录了非常详细的信息
I agree with "timdev". You shouldn't define query in your entities class. My way to define a service class support the entities are repository classes. For example: User (entity -- YourBundle/Entity/User.php) will have UserRepository (service class -- YourBundle/Repository/UserRepository.php). Your "filter" method should be in here. You just need to map this service class in your entity class. In your controller, you can always access the "filter" via its repository. It's documented very detail in the Symfony2 book