Laravel Love

El paquete Laravel Love nos permite simplificar la gestión de las reacciones de Me gusta y No me gusta en los modelos de Eloquent. Con él podemos hacer que cualquier modelo pueda enviar reacciones a otros modelos, y que estos puedan recibirlas fácilmente. A continuación te enseñaremos cómo trabajar con Laravel Love en una aplicación.

Nueva instalación

Vamos a comenzar haciendo una nueva instalación de Laravel ejecutando el siguiente comando en la terminal:

composer create-project laravel/laravel love

Si tienes dudas o problemas con la instalación te invito a observar la Instalación de Composer y Laravel  en el Curso de Laravel desde cero.

Es necesario además que se enlace el proyecto a una base de datos editando el archivo .env ubicado en la raíz del proyecto y colocando las credenciales necesarias para la conexión.

Configuración del proyecto

Para comenzar, nuestro proyecto solo tendrá un modelo adicional que será Post, el cual recibirá las reacciones de los usuarios (Me gusta o No me gusta).  Para crearlo ejecutaremos el siguiente comando, donde además le indicaremos que también queremos una migración junto con un Model Factory:

php artisan make:model Post -mf

Seguidamente debemos agregar las relaciones correspondientes en los modelos, comenzamos agregando la relación en el modelo User:

public function posts()
{
  return $this->hasMany(Post::class);
}

Continuamos ahora agregando la relación en el modelo Post :

public function user()
{
  return $this->belongsTo(User::class);
}

Vamos a rellenar la migración recién creada para la tabla posts de la siguiente forma:

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

Seguimos ahora con la preparación del Model Factory PostFactory creado por el comando ejecutado anteriormente colocando el siguiente código:

use Faker\Generator as Faker;

$factory->define(App\Post::class, function (Faker $faker) {
  return [
    'title' => $faker->title,
    'body' => $faker->realText(400)
  ];
});

Por último, vamos a editar el archivo database/seeders/DatabaseSeeder.php para crear unos datos de prueba.  Evitaremos crear seeders para no extendernos pero tú puedes hacerlo siguiendo el tutorial sobre Inserción de datos con los seeders de Laravel del Curso de Laravel desde cero.

public function run()
{
  factory(\App\User::class, 10)->create()->each(function ($user) {
    $user->posts()->saveMany(factory(\App\Post::class, 3)->make());
  });
}

Con el código escrito anteriormente estaríamos creando 10 usuarios con 3 artículos en posesión de cada uno.

Instalación del paquete Laravel Love

Para instalar el paquete debemos ejecutar el siguiente comando en nuestra terminal:

composer require cybercog/laravel-love

Para utilizar este paquete requieres una versión 5.6 de Laravel como mínimo.

El paquete nos trae una migración. Si deseas realizar cambios en las migraciones, primero debemos publicarlas en la aplicación con el siguiente comando:

php artisan vendor:publish --provider="Cog\Laravel\Love\Providers\LoveServiceProvider" --tag=migrations

Finalmente ejecutamos las migraciones y los seeders con el comando:

php artisan migrate --seed

Configuración del paquete en los modelos

Una de las cosas que me parece muy interesante del paquete es que podemos hacerle saber a un modelo si tienen la posibilidad de dar likes/dislikes, recibirlos o ambos. Esto se puede hacer gracias a las Interfaces (Contracts) y a los Traits que vienen incluidos en el paquete.

Vamos a comenzar definiendo que nuestro modelo Post puede recibir likes/dislikes de esta forma:

use Illuminate\Database\Eloquent\Model;
use Cog\Laravel\Love\Likeable\Models\Traits\Likeable;
use Cog\Contracts\Love\Likeable\Models\Likeable as LikeableContract;

class Post extends Model implements LikeableContract
{
    use Likeable;

    public function user()
    {
        return $this->belongsTo(User::class);
    }
}

Con esto le indicamos al modelo que debe implementar la interfaz Cog\Contracts\Love\Likeable\Models\LikeableLaravel y que use el trait Cog\Laravel\Love\Likeable\Models\Traits\Likeable que contiene los métodos para darle la facultad de recibir likes/dislikes.

Ahora le decimos a nuestro modelo User que tienen la posibilidad de dar likes y dislikes:

use Illuminate\Notifications\Notifiable;
use Cog\Laravel\Love\Liker\Models\Traits\Liker;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Cog\Contracts\Love\Liker\Models\Liker as LikerContract;

class User extends Authenticatable implements LikerContract
{
    use Notifiable, Liker;

    protected $fillable = [
        'name', 'email', 'password',
    ];

    protected $hidden = [
        'password', 'remember_token',
    ];

    public function posts()
    {
        return $this->hasMany(Post::class);
    }
}

Muestra del funcionamiento

Para comenzar ejecutamos en la terminal el siguiente comando para generar un sistema de login y registro:

php artisan make:auth

Continuamos ahora editando nuestras rutas quedando nuestro archivo routes/web.php de esta forma:

Route::get('/', function () {
    return view('welcome');
});

Auth::routes();

Route::get('/home', 'HomeController@index')->name('home');

Route::group(['middleware' => 'auth'], function () {
    Route::resource('posts', 'PostController');

    Route::get('posts/{post}/like', 'PostController@like')->name('posts.like');
    Route::get('posts/{post}/unlike', 'PostController@unlike')->name('posts.unlike');

    Route::get('posts/{post}/dislike', 'PostController@dislike')->name('posts.dislike');
    Route::get('posts/{post}/undislike', 'PostController@undislike')->name('posts.undislike');
});

Procedemos a crear un controlador llamado PostController ejecutando el comando php artisan make:controller PostController y lo dejamos así:

<?php

namespace App\Http\Controllers;

use App\Post;

class PostController extends Controller
{
    public function index()
    {
        $posts = Post::all();

        return view('posts.index', compact('posts'));
    }

    public function show(Post $post)
    {
        return view('posts.show', compact('post'));
    }

    public function like(Post $post)
    {
        $post->likeBy();

        return back();
    }

    public function unlike(Post $post)
    {
        $post->unlikeBy();

        return back();
    }

    public function dislike(Post $post)
    {
        $post->dislikeBy();

        return back();
    }

    public function undislike(Post $post)
    {
        $post->undislikeBy();

        return back();
    }
}

Como se puede notar el modelo Post tiene algunos métodos del paquete gracias al trait Likeable que hemos implementado anteriormente. Los métodos likeBy, unlikeBy, dislikeBy y undislikeBy pueden recibir un usuario de forma opcional pero al no pasarlo se toma el usuario autentificado.

Seguidamente agregaremos un par vistas, comenzando por la vista resources/views/posts/index.blade.php:

@extends('layouts.app')

@section('content')
    <div class="container">
        <div class="row justify-content-center">
            <div class="col-md-8">
                <div class="card">
                    <div class="card-header">Posts</div>

                    <div class="card-body">
                        <ul>
                        @foreach ($posts as $post)
                            <li>
                                <a href="{{ route('posts.show', $post) }}">{{ $post->title }}</a>
                            </li>
                        @endforeach
                        </ul>
                    </div>
                </div>
            </div>
        </div>
    </div>
@endsection

Y continuamos con la vista resources/views/posts/show.blade.php:

@extends('layouts.app')

@section('content')
    <div class="container">
        <div class="row justify-content-center">
            <div class="col-md-8">
                <div class="card">
                    <div class="card-header">{{ $post->title }}</div>

                    <div class="card-body">
                        {{ $post->body }}
                    </div>

                    <div class="card-footer">
                        @if (! $post->liked)
                            <a href="{{ route('posts.like', $post) }}" class="btn btn-primary btn-sm">({{ $post->likesCount }}) Me gusta</a>
                        @else
                            <a href="{{ route('posts.unlike', $post) }}" class="btn btn-primary btn-sm">({{ $post->likesCount }}) Te gusta</a>
                        @endif

                        @if (! $post->disliked)
                            <a href="{{ route('posts.dislike', $post) }}" class="btn btn-secondary btn-sm">({{ $post->dislikesCount }}) No me gusta</a>
                        @else
                            <a href="{{ route('posts.undislike', $post) }}" class="btn btn-secondary btn-sm">({{ $post->dislikesCount }}) Te disgusta</a>
                        @endif
                    </div>
                </div>
            </div>
        </div>
    </div>
@endsection

Por último, agregamos un enlace en nuestra plantilla resources/views/layouts/app.blade.php para hacer referencia al listado de posts:

<li class="nav-item">
  <a class="nav-link" href="{{ route('posts.index') }}">Posts</a>
</li>

Finalmente, tendremos un listado de posts en la dirección /posts donde al dar clic sobre el enlace de cada uno podemos observar el post y los botones que hemos colocado anteriormente como se muestra a continuación:

Resultado Laravel Love en Styde

Puedes obtener todo el código del tutorial en este repositorio de GitHub. Si deseas conocer más sobre este paquete puedes visitar su repositorio oficial.

Con esto terminamos este tutorial, si tienes alguna duda, sugerencia o alguna pregunta puedes hacerla en los comentarios y con gusto te estaremos ayudando. Por favor no olvides compartir este contenido en tus redes sociales para seguir apoyándonos a seguir ofreciendo contenido gratuito como esté a toda la comunidad.

Suscríbete a nuestro boletín

Te enviaremos publicaciones con consejos útiles y múltiples recursos para que sigas aprendiendo.

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