问题
Background
I have a List model which belongs to and has many Subscriber. And of course a Subscriber which belongs to and has many List.
Problem
I want to eager-load all subscribers from multiple lists. BUT, I am only interested in distinct subscribers, since a subscriber can have and indeed belong to multiple lists.
My attempt
I have used the distinct()
method but this hasn't yielded any joy. And I can also loop through the result set to manually slice out duplicates. Just wondering if there is a way of letting Laravel do the dirty job for me?
Code
$lists = Input::get('listsarray');
$addresses = Addressbook::with(array('subscribers' => function($query)
{
$query->where('active', '=', 1);
// $query->distinct(); //This didn't work
}))->whereIn('id', $lists)->get();
回答1:
Retrieving unique subscribers through join
I'll try my best to explain it using Lists
instead of Adressbook
, because I couldn't really understand your model and that may introduce further confusion.
If I understood your comments correctly, you are trying to retrieve all unique subscribers that have associations with lists of id IN listarray
. In that case, Eager Loading is not the proper way of doing that. Eager loading serves the purpose of pre-loading associations for a model, in order to use them later on. In your case, you are not retrieving Lists
and their Subscribers
, but rather the unique Subscribers
themselves.
$lists = Input::get('listsarray');
$subscribers = Subscriber::join('list_subscriber', 'list_subscriber.subscriber_id', '=', 'subscribers.id')
->whereIn('list_subscriber.list_id', $lists)
->groupBy('list_subscriber.subscriber_id')
->get(array('subscribers.*'));
If you also wish to retrieve all lists associated with such subscribers, you can do so:
// Simply include a with('lists') and Eloquent will eager load them
$subscribers = Subscriber::with('lists')
->join('list_subscriber', 'list_subscriber.subscriber_id', '=', 'subscribers.id')
->whereIn('list_subscriber.list_id', $lists)
->groupBy('list_subscriber.subscriber_id')
->get(array('subscribers.*'));
Eager Loading
If it's a matter of simply improving performance, you don't need to use distinct, Laravel already does it. Eloquent behaves like this:
- Fetchs all
lists
. - Iterates through
lists
building an array of uniquelist_ids
- Fetchs all
list_subscribers
usingWHERE list_id IN (X, Y, Z)
- Iterates through all
list_subscribers
building an array of uniquesubscriber_id
- Fetchs all
subscribers
usingWHERE id IN (X, Y, Z)
来源:https://stackoverflow.com/questions/18403135/eloquent-orm-eager-loading-distinct-records-in-many-to-many-relationship