Subversion-Projekte lars-tiefland.laravel_shop

Revision

Revision 166 | Details | Vergleich mit vorheriger | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
166 lars 1
# Generate slugs when saving Eloquent models
2
 
3
[![Latest Version on Packagist](https://img.shields.io/packagist/v/spatie/laravel-sluggable.svg?style=flat-square)](https://packagist.org/packages/spatie/laravel-sluggable)
4
[![MIT Licensed](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE.md)
5
[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/spatie/laravel-sluggable/run-tests?label=tests)](https://github.com/spatie/laravel-sluggable/actions)
6
[![Total Downloads](https://img.shields.io/packagist/dt/spatie/laravel-sluggable.svg?style=flat-square)](https://packagist.org/packages/spatie/laravel-sluggable)
7
 
8
This package provides a trait that will generate a unique slug when saving any Eloquent model.
9
 
10
```php
11
$model = new EloquentModel();
12
$model->name = 'activerecord is awesome';
13
$model->save();
14
 
15
echo $model->slug; // outputs "activerecord-is-awesome"
16
```
17
 
18
The slugs are generated with Laravels `Str::slug` method, whereby spaces are converted to '-'.
19
 
20
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).
21
 
22
## Support us
23
 
24
[<img src="https://github-ads.s3.eu-central-1.amazonaws.com/laravel-sluggable.jpg?t=1" width="419px" />](https://spatie.be/github-ad-click/laravel-sluggable)
25
 
26
We invest a lot of resources into creating [best in class open source packages](https://spatie.be/open-source). You can support us by [buying one of our paid products](https://spatie.be/open-source/support-us).
27
 
28
We highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. You'll find our address on [our contact page](https://spatie.be/about-us). We publish all received postcards on [our virtual postcard wall](https://spatie.be/open-source/postcards).
29
 
30
## Installation
31
 
32
You can install the package via composer:
33
``` bash
34
composer require spatie/laravel-sluggable
35
```
36
 
37
## Usage
38
 
39
Your Eloquent models should use the `Spatie\Sluggable\HasSlug` trait and the `Spatie\Sluggable\SlugOptions` class.
40
 
41
The trait contains an abstract method `getSlugOptions()` that you must implement yourself.
42
 
43
Your models' migrations should have a field to save the generated slug to.
44
 
45
Here's an example of how to implement the trait:
46
 
47
```php
48
namespace App;
49
 
50
use Spatie\Sluggable\HasSlug;
51
use Spatie\Sluggable\SlugOptions;
52
use Illuminate\Database\Eloquent\Model;
53
 
54
class YourEloquentModel extends Model
55
{
56
    use HasSlug;
57
 
58
    /**
59
     * Get the options for generating the slug.
60
     */
61
    public function getSlugOptions() : SlugOptions
62
    {
63
        return SlugOptions::create()
64
            ->generateSlugsFrom('name')
65
            ->saveSlugsTo('slug');
66
    }
67
}
68
```
69
 
70
With its migration:
71
 
72
```php
73
use Illuminate\Database\Migrations\Migration;
74
use Illuminate\Database\Schema\Blueprint;
75
use Illuminate\Support\Facades\Schema;
76
 
77
class CreateYourEloquentModelTable extends Migration
78
{
79
    public function up()
80
    {
81
        Schema::create('your_eloquent_models', function (Blueprint $table) {
82
            $table->increments('id');
83
            $table->string('slug'); // Field name same as your `saveSlugsTo`
84
            $table->string('name');
85
            $table->timestamps();
86
        });
87
    }
88
}
89
 
90
```
91
 
92
### Using slugs in routes
93
 
94
To use the generated slug in routes, remember to use Laravel's [implicit route model binding](https://laravel.com/docs/5.8/routing#implicit-binding):
95
 
96
```php
97
namespace App;
98
 
99
use Spatie\Sluggable\HasSlug;
100
use Spatie\Sluggable\SlugOptions;
101
use Illuminate\Database\Eloquent\Model;
102
 
103
class YourEloquentModel extends Model
104
{
105
    use HasSlug;
106
 
107
    /**
108
     * Get the options for generating the slug.
109
     */
110
    public function getSlugOptions() : SlugOptions
111
    {
112
        return SlugOptions::create()
113
            ->generateSlugsFrom('name')
114
            ->saveSlugsTo('slug');
115
    }
116
 
117
    /**
118
     * Get the route key for the model.
119
     *
120
     * @return string
121
     */
122
    public function getRouteKeyName()
123
    {
124
        return 'slug';
125
    }
126
}
127
```
128
 
129
### Using multiple fields to create the slug
130
 
131
Want to use multiple field as the basis for a slug? No problem!
132
 
133
```php
134
public function getSlugOptions() : SlugOptions
135
{
136
    return SlugOptions::create()
137
        ->generateSlugsFrom(['first_name', 'last_name'])
138
        ->saveSlugsTo('slug');
139
}
140
```
141
 
142
### Customizing slug generation
143
 
144
You can also pass a `callable` to `generateSlugsFrom`.
145
 
146
By default the package will generate unique slugs by appending '-' and a number, to a slug that already exists.
147
 
148
You can disable this behaviour by calling `allowDuplicateSlugs`.
149
 
150
```php
151
public function getSlugOptions() : SlugOptions
152
{
153
    return SlugOptions::create()
154
        ->generateSlugsFrom('name')
155
        ->saveSlugsTo('slug')
156
        ->allowDuplicateSlugs();
157
}
158
```
159
 
160
### Limiting the length of a slug
161
 
162
You can also put a maximum size limit on the created slug:
163
 
164
```php
165
public function getSlugOptions() : SlugOptions
166
{
167
    return SlugOptions::create()
168
        ->generateSlugsFrom('name')
169
        ->saveSlugsTo('slug')
170
        ->slugsShouldBeNoLongerThan(50);
171
}
172
```
173
 
174
The slug may be slightly longer than the value specified, due to the suffix which is added to make it unique.
175
 
176
You can also use a custom separator by calling `usingSeparator`
177
 
178
```php
179
public function getSlugOptions() : SlugOptions
180
{
181
    return SlugOptions::create()
182
        ->generateSlugsFrom('name')
183
        ->saveSlugsTo('slug')
184
        ->usingSeparator('_');
185
}
186
```
187
 
188
### Setting the slug language
189
 
190
To set the language used by `Str::slug` you may call `usingLanguage`
191
 
192
```php
193
public function getSlugOptions() : SlugOptions
194
{
195
    return SlugOptions::create()
196
        ->generateSlugsFrom('name')
197
        ->saveSlugsTo('slug')
198
        ->usingLanguage('nl');
199
}
200
```
201
 
202
### Overriding slugs
203
 
204
You can also override the generated slug just by setting it to another value than the generated slug.
205
 
206
```php
207
$model = EloquentModel::create(['name' => 'my name']); //slug is now "my-name";
208
$model->slug = 'my-custom-url';
209
$model->save(); //slug is now "my-custom-url";
210
```
211
 
212
## Prevents slugs from being generated on some conditions
213
 
214
If you don't want to create the slug when the model has a state, you can use the `skipGenerateWhen` function.
215
 
216
```php
217
public function getSlugOptions() : SlugOptions
218
{
219
    return SlugOptions::create()
220
        ->generateSlugsFrom('name')
221
        ->saveSlugsTo('slug')
222
        ->skipGenerateWhen(fn () => $this->state === 'draft');
223
}
224
```
225
 
226
### Prevent slugs from being generated on creation
227
 
228
If you don't want to create the slug when the model is initially created you can set use the `doNotGenerateSlugsOnCreate()` function.
229
 
230
```php
231
public function getSlugOptions() : SlugOptions
232
{
233
    return SlugOptions::create()
234
        ->generateSlugsFrom('name')
235
        ->saveSlugsTo('slug')
236
        ->doNotGenerateSlugsOnCreate();
237
}
238
```
239
 
240
### Prevent slug updates
241
 
242
Similarly, if you want to prevent the slug from being updated on model updates, call `doNotGenerateSlugsOnUpdate()`.
243
 
244
```php
245
public function getSlugOptions() : SlugOptions
246
{
247
    return SlugOptions::create()
248
        ->generateSlugsFrom('name')
249
        ->saveSlugsTo('slug')
250
        ->doNotGenerateSlugsOnUpdate();
251
}
252
```
253
 
254
This can be helpful for creating permalinks that don't change until you explicitly want it to.
255
 
256
```php
257
$model = EloquentModel::create(['name' => 'my name']); //slug is now "my-name";
258
$model->save();
259
 
260
$model->name = 'changed name';
261
$model->save(); //slug stays "my-name"
262
```
263
 
264
### Regenerating slugs
265
 
266
If you want to explicitly update the slug on the model you can call `generateSlug()` on your model at any time to make the slug according to your other options. Don't forget to `save()` the model to persist the update to your database.
267
 
268
### Preventing overwrites
269
 
270
You can prevent slugs from being overwritten.
271
 
272
```php
273
public function getSlugOptions() : SlugOptions
274
{
275
    return SlugOptions::create()
276
        ->generateSlugsFrom('name')
277
        ->saveSlugsTo('slug')
278
        ->preventOverwrite();
279
}
280
```
281
 
282
### Using scopes
283
 
284
 
285
If you have a global scope that should be taken into account, you can define this as well with `extraScope`. For example if you have a pages table containing pages of multiple websites and every website has it's own unique slugs.
286
 
287
```php
288
public function getSlugOptions() : SlugOptions
289
{
290
    return SlugOptions::create()
291
        ->generateSlugsFrom('name')
292
        ->saveSlugsTo('slug')
293
        ->extraScope(fn ($builder) => $builder->where('scope_id', $this->scope_id));
294
}
295
```
296
 
297
### Setting the slug suffix starting index
298
 
299
By default, suffix index starts from 1, you can set starting number.
300
 
301
```php
302
public function getSlugOptions() : SlugOptions
303
{
304
    return SlugOptions::create()
305
        ->generateSlugsFrom('name')
306
        ->saveSlugsTo('slug')
307
        ->startSlugSuffixFrom(2);
308
}
309
```
310
 
311
### Integration with laravel-translatable
312
 
313
You can use this package along with [laravel-translatable](https://github.com/spatie/laravel-translatable) to generate a slug for each locale. Instead of using the `HasSlug` trait, you must use the `HasTranslatableSlug` trait, and add the name of the slug field to the `$translatable` array. For slugs that are generated from a single field _or_ multiple fields, you don't have to change anything else.
314
 
315
```php
316
namespace App;
317
 
318
use Spatie\Sluggable\HasTranslatableSlug;
319
use Spatie\Sluggable\SlugOptions;
320
use Spatie\Translatable\HasTranslations;
321
use Illuminate\Database\Eloquent\Model;
322
 
323
class YourEloquentModel extends Model
324
{
325
    use HasTranslations, HasTranslatableSlug;
326
 
327
    public $translatable = ['name', 'slug'];
328
 
329
    /**
330
     * Get the options for generating the slug.
331
     */
332
    public function getSlugOptions() : SlugOptions
333
    {
334
        return SlugOptions::create()
335
            ->generateSlugsFrom('name')
336
            ->saveSlugsTo('slug');
337
    }
338
}
339
```
340
 
341
For slugs that are generated from a callable, you need to instantiate the `SlugOptions` with the `createWithLocales` method. The callable now takes two arguments instead of one. Both the `$model` and the `$locale` are available to generate a slug from.
342
 
343
```php
344
namespace App;
345
 
346
use Spatie\Sluggable\HasTranslatableSlug;
347
use Spatie\Sluggable\SlugOptions;
348
use Spatie\Translatable\HasTranslations;
349
use Illuminate\Database\Eloquent\Model;
350
 
351
class YourEloquentModel extends Model
352
{
353
    use HasTranslations, HasTranslatableSlug;
354
 
355
    public $translatable = ['name', 'slug'];
356
 
357
    /**
358
     * Get the options for generating the slug.
359
     */
360
    public function getSlugOptions() : SlugOptions
361
    {
362
        return SlugOptions::createWithLocales(['en', 'nl'])
363
            ->generateSlugsFrom(function($model, $locale) {
364
                return "{$locale} {$model->id}";
365
            })
366
            ->saveSlugsTo('slug');
367
    }
368
}
369
 
370
```
371
 
372
#### Implicit route model binding
373
 
374
You can also use Laravels [implicit route model binding](https://laravel.com/docs/8.x/routing#implicit-binding) inside your controller to automatically resolve the model. To use this feature, make sure that the slug column matches the `routeNameKey`.
375
Currently, only some database types support JSON operations. Further information about which databases support JSON can be found in the [Laravel docs](https://laravel.com/docs/8.x/queries#json-where-clauses).
376
 
377
```php
378
namespace App;
379
 
380
use Spatie\Sluggable\HasSlug;
381
use Spatie\Sluggable\SlugOptions;
382
use Illuminate\Database\Eloquent\Model;
383
 
384
class YourEloquentModel extends Model
385
{
386
    use HasTranslations, HasTranslatableSlug;
387
 
388
    public $translatable = ['name', 'slug'];
389
 
390
    /**
391
     * Get the options for generating the slug.
392
     */
393
    public function getSlugOptions() : SlugOptions
394
    {
395
        return SlugOptions::create()
396
            ->generateSlugsFrom('name')
397
            ->saveSlugsTo('slug');
398
    }
399
 
400
    /**
401
     * Get the route key for the model.
402
     *
403
     * @return string
404
     */
405
    public function getRouteKeyName()
406
    {
407
        return 'slug';
408
    }
409
}
410
```
411
 
412
 
413
## Changelog
414
 
415
Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently.
416
 
417
## Testing
418
 
419
``` bash
420
composer test
421
```
422
 
423
## Contributing
424
 
425
Please see [CONTRIBUTING](https://github.com/spatie/.github/blob/main/CONTRIBUTING.md) for details.
426
 
427
## Security
428
 
429
If you've found a bug regarding security please mail [security@spatie.be](mailto:security@spatie.be) instead of using the issue tracker.
430
 
431
## Credits
432
 
433
- [Freek Van der Herten](https://github.com/freekmurze)
434
- [All Contributors](../../contributors)
435
 
436
## License
437
 
438
The MIT License (MIT). Please see [License File](LICENSE.md) for more information.