Installation:
composer require matteoggl/linnaeus
Publish the config file (optional):
php artisan vendor:publish --provider="MatteoGgl\Linnaeus\LinnaeusServiceProvider" --tag="config"
Model Setup:
Add a slug column to your database table:
Schema::table('your_table', function (Blueprint $table) {
$table->string('slug')->unique();
});
Use the HasSlug trait in your Eloquent model:
use MatteoGgl\Linnaeus\HasSlug;
class YourModel extends Model
{
use HasSlug;
}
First Use Case:
Create a new model instance—Linnaeus automatically generates a slug (e.g., moldy-encouraging-turtle) and saves it to the slug column:
$model = YourModel::create(['name' => 'Example']);
// $model->slug is now populated
Slug Generation:
Linnaeus generates slugs in the format: {adjective}-{adjective}-{animal} by default. This happens automatically on model creation via the bootHasSlug() method in the trait.
Route Model Binding: Leverage Laravel’s implicit binding with the slug:
Route::get('/models/{model}', function (YourModel $model) {
return $model->name;
});
Access models via slugs in URLs (e.g., /models/moldy-encouraging-turtle).
Customizing Slug Structure:
Override the default structure per model by defining a slugStructure property:
class YourModel extends Model
{
use HasSlug;
protected $slugStructure = 'adjective-animal'; // Simplified format
}
Dynamic Slug Updates: To regenerate a slug (e.g., after a conflict), call:
$model->generateSlug();
$model->save();
Soft Deletes: Linnaeus respects soft deletes. Deleted models retain their slugs, preventing reuse.
Validation: Validate slug uniqueness in forms using Laravel’s built-in validation:
$request->validate(['slug' => 'required|unique:your_table']);
(Note: Linnaeus handles uniqueness automatically, but this can be useful for manual overrides.)
Seeding: Use Linnaeus in seeders to generate test data with unique slugs:
YourModel::factory()->count(10)->create();
APIs: Return slugs in API responses for user-friendly URLs:
return response()->json(['slug' => $model->slug]);
Localization:
Extend the package by adding custom word lists (adjectives, animals) in the config/linnaeus.php file under the words key.
Slug Conflicts:
Linnaeus handles conflicts by appending a random number (e.g., moldy-encouraging-turtle-123). If this happens frequently, consider:
config/linnaeus.php.adjective-adjective-adjective-animal).Database Constraints:
Ensure the slug column is marked as unique in your migration. Linnaeus will throw an error if it isn’t.
Soft Deletes:
If using SoftDeletes, Linnaeus will not reuse slugs from soft-deleted models. To force reuse, manually update the deleted_at column or override the isSlugAvailable() method in your model:
public function isSlugAvailable($slug)
{
return !static::where('slug', $slug)
->whereNull('deleted_at')
->exists();
}
Caching: Linnaeus loads word lists from the config file on each request. For high-traffic apps, cache the word lists in a static property or service container binding:
// In a service provider
$this->app->singleton('linnaeus.words', function () {
return require config_path('linnaeus.php')['words'];
});
Check Word Lists:
If slugs seem repetitive, inspect config/linnaeus.php to verify the adjectives, colors, and animals arrays. Add more entries if needed.
Override Generation:
To debug slug generation, override the generateSlug() method:
public function generateSlug()
{
$slug = parent::generateSlug();
\Log::info("Generated slug: {$slug}");
return $slug;
}
Manual Slug Assignment:
Avoid manually setting the slug attribute unless necessary, as Linnaeus manages uniqueness. If you must override:
$model->setSlug('custom-slug'); // Uses Linnaeus' validation
Custom Word Lists: Add new words to the config file or dynamically load them from a database table. Example:
// config/linnaeus.php
'words' => [
'adjectives' => array_merge(config('linnaeus.words.adjectives'), ['custom', 'words']),
],
Slug Structure: Create reusable slug structures by extending the trait:
trait CustomSlugStructure
{
public function getSlugStructure()
{
return 'color-animal-adjective';
}
}
Event Hooks: Listen for slug generation events (not built-in, but you can dispatch them):
// In your model
protected static function bootHasSlug()
{
static::created(function ($model) {
event(new SlugGenerated($model));
});
}
Performance: For large-scale apps, pre-generate slugs in batches and store them in a separate table to avoid runtime generation overhead. Example:
// Pre-generate slugs
$slugs = Linnaeus::generate(1000);
How can I help you explore Laravel packages today?