Search code examples
laravelcollectionsmany-to-manyhas-many-through

Laravel: How to display Has Many Through Many to Many based on the number of nested relationships


I am facing a small difficulty in finding the best way to get nested relationships through two many-to-many many relationships.

I have 3 models: Article, Keyword and Subject with the following relationships:

Article <-> Keyword (many to many);

Article <-> Subject (many to many).

What I am trying to do is getting one subject's keywords based on all the subject's articles so I can display them as a bubble with scalable size.

The code so far:

$subject = Subject::with('articles.keywords')->find($id);
    $keywordsArray = $subject->articles->pluck('keywords');
    $keywords = (new Collection($keywordsArray))->collapse()->groupBy('id');

return $keywords; // returns the collection with all the duplicate keywords
return $keywords->unique('id') // returns unique keywords.

I know to return the count mapping from the collection like this:

$keywordsCount = (new Collection($keywordsArray))->collapse()->groupBy('id')->map(function($item, $key){
        return $item->count();
    });
    return $keywordsCount; // returns ex: {"1":2,"2":2,"3":2,"6":1}

Everything works, the only question that remains is: how do I merge the unique keywords with $keywordsCount, or, what is the best way to utilize these 2 so I can resize the keyword's bubble based on that count.

Many thanks in advance and godspeed.


Solution

  • It depends on how often you'll need to retrieve that merged information, but for that collection you've retrieved now you can always simply assign the count as a temporary attribute to every current keyword instance in the collection. Alternatively, you can also just pack both up in an array, for which matter I'd simply do something like using the zip() collection method:

    return $keywords->unique('id')->zip($keywordsCount);
    

    which will create a collection of coupled arrays like [['keyword1', 1], ['keyword2', 3], ...] thus merging the information as you wished.