Skip to content

Commit 69a53bf

Browse files
Merge pull request #6 from yabhq/feat/slugify
Slugify trait
2 parents 760fa22 + 64446a2 commit 69a53bf

File tree

8 files changed

+183
-28
lines changed

8 files changed

+183
-28
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
/vendor/
2+
.phpunit.result.cache
3+
build/report.junit.xml

.phpunit.result.cache

-1
This file was deleted.

build/report.junit.xml

-27
This file was deleted.

src/Traits/Slugify.php

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<?php
2+
3+
namespace Yab\Mint\Traits;
4+
5+
use Illuminate\Support\Str;
6+
use Illuminate\Database\Query\Builder;
7+
8+
trait Slugify
9+
{
10+
public static function bootSlugify()
11+
{
12+
static::creating(function ($model) {
13+
if (is_null($model->slug)) {
14+
$model->slug = Str::slug($model->name);
15+
}
16+
$model->slug = self::checkModelSlug($model->slug);
17+
});
18+
19+
static::updating(function ($model) {
20+
if ($model->getOriginal('slug') !== $model->slug) {
21+
$model->slug = self::checkModelSlug($model->slug);
22+
}
23+
});
24+
}
25+
26+
/**
27+
* Check that the slug doesn't already exist if updating
28+
*
29+
* @param string $slug
30+
*
31+
* @return string
32+
*/
33+
public static function checkModelSlug(string $slug): string
34+
{
35+
if (self::slugExists($slug)) {
36+
return $slug . '-' . uniqid();
37+
}
38+
return $slug;
39+
}
40+
41+
/**
42+
* Check if the slug exists
43+
*
44+
* @param string $slug
45+
*
46+
* @return bool
47+
*/
48+
public static function slugExists(string $slug): bool
49+
{
50+
return self::withoutGlobalScopes()->where('slug', $slug)->exists();
51+
}
52+
53+
/**
54+
* Return the model by the slug
55+
*
56+
* @param \Illuminate\Database\Query\Builder $scope
57+
* @param string $slug
58+
*
59+
* @return \Illuminate\Database\Query\Builder
60+
*/
61+
public function scopeBySlug(Builder $scope, string $slug): Builder
62+
{
63+
return $scope->where('slug', $slug);
64+
}
65+
66+
/**
67+
* Get the route key for the model.
68+
*
69+
* @return string
70+
*/
71+
public function getRouteKeyName()
72+
{
73+
return 'slug';
74+
}
75+
}

tests/Factories/SlugModelFactory.php

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
use Yab\Mint\Tests\Models\SlugModel;
4+
5+
$factory->define(SlugModel::class, function () {
6+
return [
7+
'name' => 'Sample Name'
8+
];
9+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
use Illuminate\Support\Facades\Schema;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Database\Migrations\Migration;
6+
7+
class CreateSlugModelsTable extends Migration
8+
{
9+
/**
10+
* Run the migrations.
11+
*
12+
* @return void
13+
*/
14+
public function up()
15+
{
16+
Schema::create('slug_models', function (Blueprint $table) {
17+
$table->increments('id');
18+
$table->string('name');
19+
$table->string('slug');
20+
$table->timestamps();
21+
});
22+
}
23+
24+
/**
25+
* Reverse the migrations.
26+
*
27+
* @return void
28+
*/
29+
public function down()
30+
{
31+
Schema::dropIfExists('slug_models');
32+
}
33+
}

tests/Models/SlugModel.php

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace Yab\Mint\Tests\Models;
4+
5+
use Yab\Mint\Traits\Slugify;
6+
use Illuminate\Database\Eloquent\Model;
7+
8+
class SlugModel extends Model
9+
{
10+
use Slugify;
11+
12+
protected $fillable = [
13+
'name',
14+
];
15+
}

tests/SlugifyTest.php

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
namespace Yab\Mint\Tests;
4+
5+
use Yab\Mint\Tests\TestCase;
6+
use Yab\Mint\Tests\Models\SlugModel;
7+
8+
class SlugifyTest extends TestCase
9+
{
10+
/** @test */
11+
public function a_newly_created_model_has_a_slug_automatically_computed()
12+
{
13+
$model = factory(SlugModel::class)->create([
14+
'name' => 'Slugify Me'
15+
]);
16+
17+
$this->assertDatabaseHas('slug_models', [
18+
'id' => $model->id,
19+
'name' => 'Slugify Me',
20+
'slug' => 'slugify-me',
21+
]);
22+
}
23+
24+
/** @test */
25+
public function duplicate_slugs_are_handled_gracefully()
26+
{
27+
$model = factory(SlugModel::class)->create([
28+
'name' => 'Sample Name'
29+
]);
30+
31+
$modelSameName = factory(SlugModel::class)->create([
32+
'name' => 'Sample Name'
33+
]);
34+
35+
$this->assertDatabaseHas('slug_models', [
36+
'id' => $model->id,
37+
'name' => 'Sample Name',
38+
'slug' => 'sample-name',
39+
]);
40+
41+
$this->assertDatabaseHas('slug_models', [
42+
'id' => $modelSameName->id,
43+
'name' => 'Sample Name',
44+
]);
45+
46+
$this->assertTrue(str_contains($modelSameName->slug, 'sample-name-'));
47+
$this->assertEquals(25, strlen($modelSameName->slug));
48+
}
49+
}

0 commit comments

Comments
 (0)