notiziephp.it

Annuncio di laravel-sluggable v4 con URL auto-riparanti

Traduzione da Spatie
29 Aprile 2026 Tempo di lettura: 5 minuti
Annuncio di laravel-sluggable v4 con URL auto-riparanti

Il pacchetto spatie/laravel-sluggable esiste da quasi un decennio. Uno slug è la parte leggibile di un URL che identifica un record, come announcing-laravel-sluggable-v4-with-self-healing-urls nell'URL di questo post. Il pacchetto ne genera uno per qualsiasi modello Eloquent quando lo salvi, derivato da un titolo o da un altro campo di testo, e nella maggior parte dei casi non devi pensarci.

Abbiamo appena rilasciato la v4, che aggiunge alcune cose di cui vale la pena parlare. Lasciami fare una panoramica.

Generare slug con un attribute

Per la maggior parte dei modelli, la generazione dello slug è meccanica. Scegli un campo sorgente, scegli un campo di destinazione, fatto. Nella v4 puoi esprimere tutto questo con un attribute sul modello.

use Spatie\Sluggable\Attributes\Sluggable;
use Illuminate\Database\Eloquent\Model;
#[Sluggable(from: 'title', to: 'slug')]
class Post extends Model
{
}

Tutto qui. Nessun trait, nessun metodo getSlugOptions(). Salva un Post e il pacchetto compila lo slug:

$post = Post::create(['title' => 'ActiveRecord is awesome']);
$post->slug; // "activerecord-is-awesome"

URL auto-riparanti

Immagina questo. Pubblichi un nuovo post intitolato "Anouncing v4 of laravel-sluggable". Lo slug diventa anouncing-v4-of-laravel-sluggable, condividi il link, alcune persone lo aggiungono ai preferiti. Cinque minuti dopo noti la n mancante e correggi il titolo. Lo slug viene rigenerato in announcing-v4-of-laravel-sluggable, e ora tutti quelli che hanno cliccato la prima versione finiscono su un 404.

La risposta abituale è una tabella di redirect: memorizzi il vecchio slug, lo inoltri a quello nuovo. Funziona, ma ogni rinomina aggiunge una riga, e dopo un po' è un altro pezzo in movimento da mantenere.

Gli URL auto-riparanti risolvono questo problema in modo diverso. La route key combina lo slug con la primary key, così lo slug è decorativo e l'id è ciò che identifica effettivamente il record.

use Spatie\Sluggable\Attributes\Sluggable;
use Spatie\Sluggable\HasSlug;
use Illuminate\Database\Eloquent\Model;
#[Sluggable(from: 'title', to: 'slug', selfHealing: true)]
class Post extends Model
{
    use HasSlug;
}

Se il tuo post ha slug hello-world e id 5, l'URL diventa /posts/hello-world-5. Rinomina il post in Greetings, World e l'URL canonico diventa /posts/greetings-world-5. I vecchi link continuano a funzionare perché il pacchetto riesce ancora a trovare il record tramite l'id, e invia un redirect permanente al nuovo URL canonico.

Il codice di stato del redirect è 308 Permanent Redirect. Nella v3 era 301. Il motivo del cambiamento è che 301 può silenziosamente retrocedere PUT, PATCH e DELETE a GET quando viene seguito, il che ti fa ottenere un 405 Method Not Allowed se il nuovo URL non accetta GET. 308 mantiene il metodo intatto.

Action sovrascrivibili

La generazione dello slug e il formato dell'URL auto-riparante sono ora espressi come tre action: una per generare lo slug, una per costruire la route key auto-riparante e una per estrarla di nuovo. Tutte e tre possono essere sostituite tramite config/sluggable.php. L'esempio seguente personalizza le due action auto-riparanti; il generatore di slug rimane sul comportamento predefinito.

Il caso d'uso che avevo in mente erano URL auto-riparanti che mettono l'id per primo. Supponi di volere /posts/5-hello-world invece di /posts/hello-world-5. Estendi l'action builder predefinita e metti l'identificatore davanti:

namespace App\Sluggable;
use Spatie\Sluggable\Actions\BuildSelfHealingRouteKeyAction;
class IdFirstBuildAction extends BuildSelfHealingRouteKeyAction
{
    public function execute(string $slug, int|string $identifier, string $separator): string
    {
        if ($slug === '') {
            return (string) $identifier;
        }
        return "{$identifier}{$separator}{$slug}";
    }
}

L'extractor ha bisogno della logica inversa. L'action predefinita cerca l'ultimo separatore, perché gli slug possono contenere essi stessi il separatore, quindi sostituiscila con una che legge l'identificatore dalla parte iniziale:

namespace App\Sluggable;
use Illuminate\Support\Str;
use Spatie\Sluggable\Actions\ExtractIdentifierFromSelfHealingRouteKeyAction;
class IdFirstExtractAction extends ExtractIdentifierFromSelfHealingRouteKeyAction
{
    public function execute(string $value, string $separator): array
    {
        $identifier = Str::before($value, $separator);
        if ($identifier === $value || ! ctype_digit($identifier)) {
            return ['slug' => $value, 'identifier' => null];
        }
        return [
            'slug' => Str::after($value, $separator),
            'identifier' => $identifier,
        ];
    }
}

Str::before restituisce la stringa originale quando il separatore non è presente, ed è così che viene rilevato il caso senza separatore. Il controllo ctype_digit rifiuta i valori in cui il prefisso non è numerico, quindi i modelli con primary key non numeriche come gli ULID devono sostituirlo con una regex.

Collega entrambe al config e hai finito:

// config/sluggable.php
'build_self_healing_route_key' => App\Sluggable\IdFirstBuildAction::class,
'extract_identifier_from_self_healing_route_key' => App\Sluggable\IdFirstExtractAction::class,

Il riferimento completo, inclusa una variante più semplice in maiuscolo e un generatore di slug personalizzato, si trova nella documentazione sulle action da sovrascrivere.

Una skill Boost inclusa

Laravel Boost è un MCP server del team di Laravel che espone al tuo assistente AI i pacchetti installati nella tua applicazione e le loro versioni, così i prompt producono codice che si adatta al tuo stack invece di snippet Laravel generici. I pacchetti possono includere le proprie skill Boost, e Boost le scopre automaticamente.

Questo pacchetto viene fornito con una skill sluggable-development che guida il tuo assistente nell'aggiunta di un modello sluggable: scegliere il campo sorgente, decidere se hai bisogno di URL auto-riparanti, generare la migration e applicare l'attribute o il trait sul modello. Se hai installato Boost, questo è il modo più semplice per aggiungere un nuovo modello sluggable al tuo progetto.

In conclusione

Puoi trovare il pacchetto su GitHub e la documentazione completa sul nostro sito di documentazione. Arrivi dalla v3? La guida all'aggiornamento copre le breaking changes (principalmente versioni minime e una migrazione da callable a Closure).

Questo è uno dei tanti pacchetti che abbiamo creato in Spatie. Se vuoi supportare il nostro lavoro open source, valuta di acquistare uno dei nostri prodotti a pagamento.

Condividi su: LinkedIn

Altri articoli recenti