0

I'm looking to build a list of tags in my blogging application? I want to select all tags, and if that tag exists more than once, only select it once?

This is how I get all tags! How do I get each tag only once?

$tags = Tag::all(); 

2 Answers2

0

Queries

If you're just looking for a distinct list of the tag names, you can combine the distinct() method and the pluck() method:

$tags = Tag::distinct()->pluck('name');

This will give you a Collection of all of the unique tag names in your system.

If you actually need to have the Tag model instances, you can try two things.

First, if you have completely duplicate tag rows, you can just add distinct() to your tag query (since you need to modify the query, you'll need to change from using all() to get() (read more here):

$tags = Tag::distinct()->get();

Second, if your tags have other non distinct information (ids, timestamps, etc), that won't work. If that's the case, you'll need to use a subquery to select the tags you want:

$tags = Tag::whereIn('id', Tag::groupBy('name')->selectRaw('MAX(id)'))->get();

That will give you fully populated Tag model instances for your unique set of names.

Collections

Finally, if you already have a collection of Tag instances, and you wanted to get a unique set based on the name, you can use the unique method on the collection.

// somewhere
$tags = Tag::get();

// somewhere else
$tags = $tags->unique('name');

If you don't already have the collection, make sure to use one of the query builder methods above. If you use the collection method, you have to build and hydrate all the Tag model instances first, and then do the unique processing. You don't want to fetch and hydrate 10000 Tag model instances to end up with 30 unique Tags in the end, when you could fetch just those 30 from the database in the first place.

patricus
  • 59,488
  • 15
  • 143
  • 145
  • This method does not get unique models, they have different primary key and timestamps. – dparoli Aug 03 '19 at 14:39
  • @dparoli Thank you for pointing that out. They don't have to have ids and timestamps, but the point is taken. I have updated my answer with more methods and more information. – patricus Aug 03 '19 at 15:52
0

You can use the unique() method on the collection, i.e.:

$tags = Tag::all()->unique('name'); 

Use your descriptor field instead of name.

The distinct() method is better used with a limited selection of fields, like:

DB::table('tags')->distinct()->get(['name']);

If you use distinct() on the Model like Tag::distinct()->get(); you will get all the tags because they have different ids and timestamps even if they have the same name or description because, in that case, the select is on all the fields.

With the model you have to limit the fields returned like this:

Tag::distinct()->get(['name']);
dparoli
  • 8,891
  • 1
  • 30
  • 38