banner-eloquent-sluggable

Como pudimos ver hace algún tiempo en nuestro post sobre URLs amigables y rutas con slugs en Laravel, un slug es una versión simplificada del texto de un enlace de manera que éste sea más legible y pueda ser un identificador más apropiado, especialmente para el posicionamiento en los buscadores (SEO). En la lección de  hoy vamos a probar el paquete Eloquent-Sluggable que nos ofrece algunos otras funcionalidades adicionales en cuanto a la creación de slugs personalizadas dentro de nuestras aplicaciones de Laravel.

Instalación

Ejecutamos por consola en el directorio raíz de la aplicación:

composer require cviebrock/eloquent-sluggable

NOTA: Eloquent-Sluggable usa traits, por tanto necesitas tener instalado PHP 5.4 o más reciente. Si estás usando 5.3 entonces utiliza la versión “1.*” del paquete, siguiendo las instrucciones del repositorio.

luego ejecutamos composer update  para instalar el paquete.

Actualiza array de ‘providers’ para agregar el service provider en config/app.php:

Cviebrock\EloquentSluggable\SluggableServiceProvider::class,

Por último, ejecutamos php artisan vendor:publish  para se copie el archivo de configuración (sluggable.php) en el directorio config.

Preparación

Para realizar los ejemplos vamos a crear un modelo Post con el cual trabajaremos, no sin antes confirmar que tenemos la configuración de una base de datos para el proyecto en el archivo .env:

php artisan make:model Post -m

Con la opción -m le estamos indicando que también cree la migración del modelo, ahora modificamos dicho archivo, ubicado en database/migrations, colocando lo siguiente:

public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title');
            $table->text('content');
            $table->integer('user_id')->unsigned();
            $table->foreign('user_id')->references('id')->on('users');
            $table->timestamps();
        });
    }
public function down()
    {
        Schema::drop('posts');
    }

ejecutamos la migración php artisan migrate 

Actualizar tus modelos de Eloquent

Se puede usar Eloquent-Sluggable en cualquier modelo de tu aplicación sólo se debe adaptar al paquete primero. Para ello:

  1. La clase del modelo debe implementar SluggableInterface
  2. Usar su trait
  3. Crear una propiedad protected llamada $sluggable, donde se colocarán las configuraciones del modelo.

Para nuestro ejemplo, el archivo app/Post.php:

namespace App;

use Illuminate\Database\Eloquent\Model;
use Cviebrock\EloquentSluggable\SluggableInterface;
use Cviebrock\EloquentSluggable\SluggableTrait;

class Post extends Model implements SluggableInterface
{
    use SluggableTrait;

    protected $sluggable = [
        'build_from' => 'title',
        'save_to'    => 'slug',
    ];
}

build_from indica el atributo a partir del cual se generará el slug y save_to indica el atributo en la tabla donde se guardará el slug creado.

Como en la migración que creamos anteriormente no tenemos el atributo slug debemos crearlo bien sea manualmente o por medio del comando proporcionado por el paquete:

php artisan sluggable:table posts

y luego

php artisan migrate

Esto hace que se ejecute una migración para agregar el atributo, que por defecto es slug, si se quiere un nombre diferente se debe indicar así php artisan sluggable:table posts slug_column , sólo debe asegurarse que save_to esté definido con esa nombre del atributo.

De esta manera ya el modelo tiene el slug con el cual podemos trabajar.

Uso

Vamos a crear unos posts de ejemplo agregando lo siguiente al archivo ModelFactories.php que se encuentra en el directorio database/factories:

$factory->define(App\Post::class, function (Faker\Generator $faker) {
	return [
		'title'   => $faker->sentence,
		'content' => $faker->paragraph,
                'user_id' => $faker->rand(1,10)
	];
});

En este caso, no tenemos que asignarle un valor al atributo slug pues éste se creará automáticamente.

Ahora podemos crear 20 posts y 10 users agregando en el archivo database/seeds/DatabaseSeeder.php:

public function run()
    {
        Model::unguard();
        factory(App\User::class, 10)->create();
        factory(App\Post::class, 20)->create();
        Model::reguard();
    }

ejecutamos por consola:

php artisan db:seed

y al verificar en la base de datos ya tenemos el slug para cada post creado:

tabla-posts-con-slugs-creados
Si lo que queremos es obtener el slug de un post:

$post = App\Post::find(1);
$slug = $post->slug;

y si no sabes el nombre del atributo que tiene el slug:

$slug = $post->getSlug();

También el trait nos proporciona un helper para obtener un post a partir del slug

$post = Post::findBySlug(‘slug-del-post-que-se-quiere-encontrar’);

Archivo de Configuración

En el archivo de config/sluggable.php se encuentran un conjunto de opciones que permiten a este paquete ser bastante flexible para trabajar con los slugs, allí se configuran de manera global pero si uno de los modelos necesita algo en particular se puede colocar en la propiedad $sluggable del modelo.  Por defecto en ese archivo tiene:

return [
    'build_from'      => null,
    'save_to'         => 'slug',
    'max_length'      => null,
    'method'          => null,
    'separator'       => '-',
    'unique'          => true,
    'include_trashed' => false,
    'on_update'       => false,
    'reserved'        => null,
];

build_from

Es el campo o array de campos que se usarán para construir el slug. Es decir, que puede permitir crearlo a partir de un atributo del modelo, así como de un accessor. Por ejemplo:

class User extends Model implements SluggableInterface
{
    use SluggableTrait;

    protected $sluggable = [
        'build_from' => 'fullname',
    ]

    public function getFullnameAttribute() {
        return $this->first_name . ' ' . $this->last_name;
    }
}

Se puede referenciar de campos de otros modelos relacionados usando la notación de punto. Para generar el slug de un post a partir del nombre del autor y su título:

class Post extends Model implements SluggableInterface
{
    use SluggableTrait;

    protected $sluggable = [
        'build_from' => ['author.name', 'title']
    ];

    protected $fillable = ['title'];

    public function author() {
        return $this->belongsTo('App\User');
    }
}
…
//en app/User.php
class User extends Model
{
    protected $fillable = ['name'];
}

donde el modelo User está relacionado con el modelo Post y en el modelo user existe el atributo name.

La opción max_length permite definir por medio de un entero positivo la longitud máxima de los slugs generados.

El method define el método usado para convertir el string al slug.

La opción unique es la que nos permite definir que los slugs de un modelo sean únicos agregando un valor incremental al final del slug para evitar los conflictos, esto cuando esta opción es true.

Hay muchas más características que podemos revisar en su documentación oficial.  Espero que te haya gustado y recuerda dejar tus comentarios.

Material relacionado

Regístrate hoy en Styde y obtén acceso a todo nuestro contenido.

Lección anterior Uso de Gravatar en Laravel 5.1 Lección siguiente Peticiones HTTP con Guzzle en Laravel 5.1