Skip to content

Commit 26bd614

Browse files
authored
Merge pull request #284 from mkeremcansev/main
Add Fallback Locale and Additional Query Support to `findBySlug`
2 parents ed4a927 + 613c876 commit 26bd614

File tree

2 files changed

+80
-5
lines changed

2 files changed

+80
-5
lines changed

src/HasSlug.php

+21-5
Original file line numberDiff line numberDiff line change
@@ -190,15 +190,31 @@ protected function generateSubstring($slugSourceString)
190190
return substr($slugSourceString, 0, $this->slugOptions->maximumLength);
191191
}
192192

193-
public static function findBySlug(string $slug, array $columns = ['*'])
193+
public static function findBySlug(string $slug, array $columns = ['*'], callable $additionalQuery = null)
194194
{
195195
$modelInstance = new static();
196196
$field = $modelInstance->getSlugOptions()->slugField;
197197

198-
$field = in_array(HasTranslatableSlug::class, class_uses_recursive(static::class))
199-
? "{$field}->{$modelInstance->getLocale()}"
200-
: $field;
198+
$query = static::query();
201199

202-
return static::where($field, $slug)->first($columns);
200+
if (in_array(HasTranslatableSlug::class, class_uses_recursive(static::class))) {
201+
$currentLocale = $modelInstance->getLocale();
202+
$fallbackLocale = config('app.fallback_locale');
203+
204+
$currentField = "{$field}->{$currentLocale}";
205+
$fallbackField = "{$field}->{$fallbackLocale}";
206+
207+
$query->where($currentField, $slug);
208+
209+
$query->orWhere($fallbackField, $slug);
210+
} else {
211+
$query->where($field, $slug);
212+
}
213+
214+
if (is_callable($additionalQuery)) {
215+
$additionalQuery($query);
216+
}
217+
218+
return $query->first($columns);
203219
}
204220
}

tests/HasSlugTest.php

+59
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
use Spatie\Sluggable\SlugOptions;
55
use Spatie\Sluggable\Tests\TestSupport\TestModel;
66
use Spatie\Sluggable\Tests\TestSupport\TestModelSoftDeletes;
7+
use Spatie\Sluggable\Tests\TestSupport\TranslatableModel;
78

89
it('will save a slug when saving a model', function () {
910
$model = TestModel::create(['name' => 'this is a test']);
@@ -349,3 +350,61 @@ public function getSlugOptions(): SlugOptions
349350

350351
expect($savedModel->id)->toEqual($model->id);
351352
});
353+
354+
it('can customize query using additionalQuery parameter in findBySlug', function () {
355+
$model = new class () extends TestModel {
356+
public function getSlugOptions(): SlugOptions
357+
{
358+
return parent::getSlugOptions()->saveSlugsTo('url');
359+
}
360+
};
361+
362+
$model->url = 'custom-slug';
363+
$model->other_field = 'active';
364+
$model->save();
365+
366+
$savedModel = $model::findBySlug('custom-slug', ['*'], function ($query) {
367+
$query->where('other_field', 'active');
368+
});
369+
370+
expect($savedModel)
371+
->not->toBeNull()
372+
->and($savedModel->id)
373+
->toEqual($model->id);
374+
375+
$noMatch = $model::findBySlug('custom-slug', ['*'], function ($query) {
376+
$query->where('status', 'inactive');
377+
});
378+
379+
expect($noMatch)->toBeNull();
380+
});
381+
382+
it('can find models using findBySlug with fallback locale', function () {
383+
config()->set('app.fallback_locale', 'en');
384+
app()->setLocale('tr');
385+
386+
$model = new class () extends TranslatableModel {
387+
public function getSlugOptions(): SlugOptions
388+
{
389+
return parent::getSlugOptions()->saveSlugsTo('slug');
390+
}
391+
};
392+
393+
$model->slug = ['en' => 'english-slug', 'tr' => 'turkish-slug'];
394+
$model->name = ['en' => 'English Name', 'tr' => 'Turkish Name'];
395+
$model->save();
396+
397+
$foundModelInCurrentLocale = $model::findBySlug('turkish-slug');
398+
399+
expect($foundModelInCurrentLocale)
400+
->not->toBeNull()
401+
->and($foundModelInCurrentLocale->id)
402+
->toEqual($model->id);
403+
404+
$foundModelInFallbackLocale = $model::findBySlug('english-slug');
405+
406+
expect($foundModelInFallbackLocale)
407+
->not->toBeNull()
408+
->and($foundModelInFallbackLocale->id)
409+
->toEqual($model->id);
410+
});

0 commit comments

Comments
 (0)