DDC-1007: Add ability to filter a association #1592

Closed
doctrinebot opened this Issue Jan 31, 2011 · 14 comments

2 participants

@doctrinebot

Jira issue originally created by user enumag:

Note: I used critical priority for this issue because this is one of the most criticised things about Doctrine 2 worldwide.


The worst thing about Doctrine 2 is, that you can do almost nothing through methods like Category::getArticles();.
For example, you have the Category and want to output all the articles. Fine, nothing easier:

foreach ($category->getArticles() as $article) {
echo $article->name;
}

OK. And now I need only "visible" articles (others are hidden for now). And here it is. You need DQL even for this easy task. Without DQL you can't do nothing, but using DQL (or QueryBuilder) everywhere is very very bad. Simply there is no way to write method like getVisibleArticles(). (Except selecting all and using some filter, but that's nonsense.)

The solution would be some kind of smart collections (but i don't mind if you come up with something different):

public function getArticles($visibility = 0, $limit = NULL) {
return $this->articles->filter('visibility', $visibility)->limit($limit);
}

Of course when you need any AND, OR, XOR, IN, LIKE and so DQL is needed. This should be for some simple things only.

@doctrinebot

Comment created by @beberlei:

Note: I used critical priority for this issue because this is one of the most criticised things about Doctrine 2 worldwide.

By which standard are you making this assumption?

@doctrinebot

Issue was closed with resolution "Duplicate"

@doctrinebot

Comment created by enumag:

Just some examples:

http://www.doctrine-project.org/docs/orm/2.0/en/reference/limitations-and-known-issues.html#restricing-associations
http://groups.google.com/group/doctrine-user/browse_thread/thread/d013705a109d7e44
http://stackoverflow.com/questions/4214286/doctrine-2-association

You need to use DQL even for the most easiest tasks. There is no way to implement methods like "getVisibleArticles", everything must be done through repositories and DQL. Therefor the associations are almost useless as they are now.

There is almost always need for some filter and this logic should be in entities themselves. I mean I of course can make new repository class for every entity, but then why are we using ORM which makes every task even more difficult then it is without the ORM?

I've been looking for some way to manually modify the SQL query used to load the collection, but found none.

//EDIT:
This is also related. There would be no need for such crutches if this issue is solved.
http://www.doctrine-project.org/blog/doctrine2-large-collections

@doctrinebot

Comment created by mjh_ca:

No need for this. This is exactly what custom repositories are for. [http://www.doctrine-project.org/docs/orm/2.0/en/reference/working-with-objects.html#custom-repositories]

If you don't like writing raw DQL, use the QueryBuilder class instead to build up your query.

<?php
class ArticleRepository extends EntityRepository
{
    public function getVisibleArticles()
    {
        // use Query or QueryBuilder object to build up your query here and return the results.
    }
}
@doctrinebot

Comment created by @beberlei:

I do think its very necessary to have this, but we are still evaluating how this can be done generically.

@doctrinebot

Comment created by parljohn:

I tend to agree. I have just spent an unfortunate amount of time trying to figure out how to filter an association without loading the whole thing. I figured i could easily use a custom repository and was headed down that path until it dawned on me that I'm breaking the whole point of doctrine to use an Entity Manager inside of an existing entity... which is the only way I can call a custom repository from inside of an entity. In order to keep my code clean I need a way to get an association and filter it without loading the whole thing. Tell me how else I would do that without breaking clean coding rules? Even if you could just use custom Collection loaders from a custom repository that would be great but it doesn't appear that when you load a collection you're not even calling a Repository to do it, if you were, I would have found a way to override that function and add some filtering devices to it. This seems to make complete sense to me? What am I missing here about Jachyms request?

@doctrinebot

Comment created by @beberlei:

There is currently no way to "just override" some function, as I said its really complicated to implement and we are evaluating the best way to do it. If you want to filter associations use DQL for now.

@doctrinebot

Comment created by parljohn:

Awesome, thanks for the quick response. Just leaves me with 2 questions then that would help me a ton:
1. How does DQL filter the association now as it is and why couldn't that be overriden in the hydration process of an association?
2. Knowing the answer to 1 is difficult for now and that I should just use DQL, how do you suggest I do that? I have an entity that cannot have its association pre-populated by a DQL, should I just get an EM from inside the entity and go from there? Just wondering what the optimal way to this is?

To clarify, I have an entity with an association that is NULL for a specific filter and I need it to stay null, but I can't because it autoloads all the other records that don't match that filter when I ask for it. I have no way to "redo" the filter I originally used in the DQL.

Thanks again for the quick response.

@doctrinebot

Comment created by @beberlei:

  1. Assocations are not loaded through DQL but through the Persisters.
  2. In DQL you can do SELECT a FROM Article a JOIN a.comments c WITH c.status = 'active' ... 3 . With Doctrine 2.1-DEV you can mark an association as EXTRA_LAZY and use Article::$comments->slice($count, $offset) to fetch only parts of the association.
@doctrinebot

Comment created by parljohn:

So based on my clarification above, how do you suggest I call a DQL from inside of an entity? Call it inline in one my methods through an entity manager? or through an entity manager to a custom repository? I don't see any other ways, am I missing anything? My problem is the reverse of what you are solving with Extra Lazy Loading, I need a collection to stay empty based on a my DQL, but it won't! It keeps calling all associations.

@doctrinebot

Comment created by enumag:

Hi, is there a way to implement this in current Doctrine? I'm talking about this method (it should be a method of CategoryEntity):

public function getArticles($visibility = 0, $limit = NULL) { return /** what should be here? **/ }

@doctrinebot

Comment created by iamkoby:

A year later this is still highly required feature.

@doctrinebot

Comment created by alexandresalome:

Found this in documentation, related to this ticket:

http://docs.doctrine-project.org/en/latest/reference/working-with-associations.html#filtering-collections

@beberlei beberlei was assigned by doctrinebot Dec 6, 2015
@doctrinebot doctrinebot closed this Dec 6, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment