Skip to content

Commit 2ecdb30

Browse files
authored
Add withAnyTagsOfType scope (#535)
* Add withAnyTagsOfType scope This update allows you to filter models that have any tags of a certain type. * Add examples to documentation
1 parent 2b36cb3 commit 2ecdb30

File tree

3 files changed

+35
-0
lines changed

3 files changed

+35
-0
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ $tag->swapOrder($anotherTag);
102102
// checking if a model has a tag
103103
$newsItem->hasTag('first tag');
104104
$newsItem->hasTag('first tag', 'some_type');
105+
106+
// Retrieve models that have tags of a
107+
Model::withAnyTagsOfType('type');
108+
Model::withAnyTagsOfType(['first type', 'second type']);
105109
```
106110

107111
Spatie is a webdesign agency based in Antwerp, Belgium. You'll find an overview of all our open source projects [on our website](https://spatie.be/opensource).

src/HasTags.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,14 @@ public function scopeWithAnyTagsOfAnyType(Builder $query, $tags): Builder
178178
);
179179
}
180180

181+
public function scopeWithAnyTagsOfType(Builder $query, string|array $type): Builder
182+
{
183+
return $query->whereHas(
184+
'tags',
185+
fn (Builder $query) => $query->whereIn('type', (array) $type)
186+
);
187+
}
188+
181189
public function tagsWithType(?string $type = null): Collection
182190
{
183191
return $this->tags->filter(fn (Tag $tag) => $tag->type === $type);

tests/HasTagsScopesTest.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
$typedTag = Tag::findOrCreate('tagE', 'typedTag');
2828
$anotherTypedTag = Tag::findOrCreate('tagF', 'typedTag');
29+
$tagWithSecondType = Tag::findOrCreate('tagG', 'secondType');
2930

3031
TestModel::create([
3132
'name' => 'model5',
@@ -36,8 +37,30 @@
3637
'name' => 'model6',
3738
'tags' => [$typedTag],
3839
]);
40+
41+
TestModel::create([
42+
'name' => 'model7',
43+
'tags' => [$typedTag, $tagWithSecondType],
44+
]);
3945
});
4046

47+
it('provides as scope to get all models that have any tags of the given types', function () {
48+
// String input
49+
$testModels = TestModel::withAnyTagsOfType('typedTag')->get();
50+
51+
expect($testModels->pluck('name')
52+
->toArray())
53+
->toContain('model5', 'model6')
54+
->not->toContain('model3', 'model7');
55+
56+
// Array input
57+
$testModels = TestModel::withAnyTagsOfType(['typedTag', 'secondType'])->get();
58+
59+
expect($testModels->pluck('name')
60+
->toArray())
61+
->toContain('model5', 'model6', 'model7')
62+
->not->toContain('model3');
63+
});
4164

4265
it('provides a scope to get all models that have any of the given tags', function () {
4366
$testModels = TestModel::withAnyTags(['tagC', 'tagD'])->get();

0 commit comments

Comments
 (0)