Eloquent ORM Eager-loading Distinct Records in Many to Many Relationship

好久不见. 提交于 2019-12-10 16:22:44

问题


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:

  1. Fetchs all lists.
  2. Iterates through lists building an array of unique list_ids
  3. Fetchs all list_subscribers using WHERE list_id IN (X, Y, Z)
  4. Iterates through all list_subscribers building an array of unique subscriber_id
  5. Fetchs all subscribers using WHERE id IN (X, Y, Z)


来源:https://stackoverflow.com/questions/18403135/eloquent-orm-eager-loading-distinct-records-in-many-to-many-relationship

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!