Skip to content

Commit

Permalink
Switch so that slugging occurs after the model is saved, which allows…
Browse files Browse the repository at this point in the history
… using the primary key as a source.
  • Loading branch information
cviebrock committed Jan 15, 2021
1 parent 55b3d5a commit 0180529
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 14 deletions.
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -156,7 +156,7 @@ class Post extends Model
Of course, your model and database will need a column in which to store the slug.
You can use `slug` or any other appropriate name you want; your configuration array
will determine to which field the data will be stored. You will need to add the
column manually via your own migration.
column (which should be `NULLABLE`) manually via your own migration.

That's it ... your model is now "sluggable"!

Expand All @@ -174,7 +174,7 @@ $post = new Post([
$post->save();
```

And so is retrieving the slug:
So is retrieving the slug:

```php
echo $post->slug;
Expand Down
5 changes: 4 additions & 1 deletion composer.json
Expand Up @@ -58,5 +58,8 @@
}
},
"minimum-stability": "dev",
"prefer-stable": true
"prefer-stable": true,
"config": {
"sort-packages": true
}
}
28 changes: 17 additions & 11 deletions src/SluggableObserver.php
Expand Up @@ -15,12 +15,12 @@ class SluggableObserver
/**
* @var \Cviebrock\EloquentSluggable\Services\SlugService
*/
private $slugService;
private SlugService $slugService;

/**
* @var \Illuminate\Contracts\Events\Dispatcher
*/
private $events;
private Dispatcher $events;

/**
* SluggableObserver constructor.
Expand All @@ -36,37 +36,42 @@ public function __construct(SlugService $slugService, Dispatcher $events)

/**
* @param \Illuminate\Database\Eloquent\Model $model
* @return boolean|null
* @return boolean
*/
public function saving(Model $model)
public function saved(Model $model): bool
{
return $this->generateSlug($model, 'saving');
if ($this->generateSlug($model, 'saved')) {
return $model->saveQuietly();
}
return false;
}

/**
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $event
* @return boolean|void
* @return boolean
*/
protected function generateSlug(Model $model, string $event)
protected function generateSlug(Model $model, string $event): bool
{
// If the "slugging" event returns false, abort
if ($this->fireSluggingEvent($model, $event) === false) {
return;
return false;
}
$wasSlugged = $this->slugService->slug($model);

$this->fireSluggedEvent($model, $wasSlugged);

return $wasSlugged;
}

/**
* Fire the namespaced validating event.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $event
* @return mixed
* @return array|null
*/
protected function fireSluggingEvent(Model $model, string $event)
protected function fireSluggingEvent(Model $model, string $event): ?array
{
return $this->events->until('eloquent.slugging: ' . get_class($model), [$model, $event]);
}
Expand All @@ -76,8 +81,9 @@ protected function fireSluggingEvent(Model $model, string $event)
*
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $status
* @return void
*/
protected function fireSluggedEvent(Model $model, string $status)
protected function fireSluggedEvent(Model $model, string $status): void
{
$this->events->dispatch('eloquent.slugged: ' . get_class($model), [$model, $status]);
}
Expand Down
18 changes: 18 additions & 0 deletions tests/BaseTests.php
Expand Up @@ -10,6 +10,7 @@
use Cviebrock\EloquentSluggable\Tests\Models\PostWithCustomMethod;
use Cviebrock\EloquentSluggable\Tests\Models\PostWithCustomSeparator;
use Cviebrock\EloquentSluggable\Tests\Models\PostWithCustomSource;
use Cviebrock\EloquentSluggable\Tests\Models\PostWithIdSource;
use Cviebrock\EloquentSluggable\Tests\Models\PostWithCustomSuffix;
use Cviebrock\EloquentSluggable\Tests\Models\PostWithEmptySeparator;
use Cviebrock\EloquentSluggable\Tests\Models\PostWithForeignRuleset;
Expand Down Expand Up @@ -502,4 +503,21 @@ public function testIssue527()
$post->save();
$this->assertEquals('example-title', $post->slug);
}

/**
* Test that you can use the model's primary key
* as part of the source field.
*/
public function testPrimaryKeyInSource()
{
$post = PostWithIdSource::create([
'title' => 'My First Post'
]);
$this->assertEquals('my-first-post-1', $post->slug);

$post = PostWithIdSource::create([
'title' => 'My Second Post'
]);
$this->assertEquals('my-second-post-2', $post->slug);
}
}
26 changes: 26 additions & 0 deletions tests/Models/PostWithIdSource.php
@@ -0,0 +1,26 @@
<?php namespace Cviebrock\EloquentSluggable\Tests\Models;

/**
* Class PostWithIdSource
*
* A test model that uses the model's ID in the slug source.
*
* @package Cviebrock\EloquentSluggable\Tests\Models
*/
class PostWithIdSource extends Post
{

/**
* Return the sluggable configuration array for this model.
*
* @return array
*/
public function sluggable(): array
{
return [
'slug' => [
'source' => ['title','id']
]
];
}
}

0 comments on commit 0180529

Please sign in to comment.