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:
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.
Regístrate hoy en Styde y obtén acceso a todo nuestro contenido.