Jose Luis Arellano
que mal curso, no explica nada, el código ya lo tiene hecho no lo va construyendo.
Mariano Gastón Paduani
La verdad que decepcionante hasta ahora
Aprende a usar eventos y listeners en Laravel para automatizar acciones clave: crear un evento cuando un producto es calificado, dispararlo desde un tray y responder con un email de notificación. Verás cómo intervienen EventServiceProvider, el arreglo listen, el helper event, el constructor del evento, el método broadcastOn y los getters.
¿Qué es el manejo de eventos en Laravel y para qué sirve?
Los eventos permiten reaccionar a acciones del usuario dentro del ciclo de vida de la aplicación. Cada acción (clic, teclas) genera un objeto de evento, y un listener captura ese evento para ejecutar lógica.
¿Dónde se registran en EventServiceProvider?
El corazón está en EventServiceProvider dentro de app/providers. Ahí, el arreglo listen mapea eventos con listeners. Ya existe un ejemplo: cuando se registra un usuario, se envía un email de verificación. Ese patrón guía el registro de tus propios eventos.
¿Qué hace un listener y cuándo actúa?
Un listener tiene un constructor para inyectar servicios y un método handle con la lógica. Escucha un evento específico y se ejecuta cuando ese evento se dispara.
¿Cómo crear y estructurar un evento personalizado en Laravel?
Primero se crea el evento con PHP Artisan make event. En el caso explicado, se define un evento para cuando se califique una entidad, llamado "model rated". El archivo queda en la carpeta events y contiene un constructor y el método broadcast on (no usado por ahora).
Luego se añade el disparo del evento al tray "can rate". Dentro del método "rate", después de completar la operación, se dispara con el helper event creando una instancia de "model rate rated" con: el calificador (this), el modelo calificado (parámetro) y el score.
¿Dónde y cómo dispararlo con el helper event?
Se coloca el disparo al final del método "rate" del tray. Se usa el helper event con la nueva instancia del evento y los tres datos: quien califica, el modelo calificado y la puntuación.
¿Cómo escuchar el evento y enviar una notificación por email?
Se crea un listener con php artisan make listener para enviar un correo a quienes hayan creado productos cuando estos sean calificados. El listener recibe solo el evento "model rated" y en el método handle ejecuta la lógica.
notify.¿Qué incluye la notificación por correo?
Se crea con PHP Artisan mail notification. La notificación recibe tres datos: el nombre del calificador, el nombre del producto y el score. El email muestra un mensaje como: "[nombre] ha calificado tu producto [producto] con [score] estrellas". Ejemplo: "Sergio ha calificado tu producto Sarasa con cinco estrellas".
qualifier name (string), product name, score.¿Cómo registrar el mapeo evento-listener?
Con el evento y el listener listos, se registran en EventServiceProvider dentro del arreglo listen: el evento "Model rated Class" y su listener "Send email model rated notification". Tras esto, solo queda probar.
¿Te animas a implementar el evento "un rate model" que se dispara cuando un usuario califica un producto? Comparte tus dudas o avances en los comentarios.
Otra forma de generar eventos y listeners directamente es escribiendolos en el EventServiceProvider con su namespace completo dentro del array de eventos y Laravel tiene un comando especial para generar ambos directamente lo cual puede ser un poco mas productivo en terminos de crear codigo mas rapido el comando es:
php artisan event:generate
Jose Luis Arellano
que mal curso, no explica nada, el código ya lo tiene hecho no lo va construyendo.
Mariano Gastón Paduani
La verdad que decepcionante hasta ahora
Agustin Erwin Sigfrido Devesa
Events: ACCIONES que ocurren por usuarios. Ejemplo: USUARIO se REGISTRA.
Listeners: DISPARADORES a través de los EVENTOS. Ejemplo: ENVIAR mail debido a una REGISTRACIÓN.
Brian Sánchez Izquierdo
Juan Guillermo Perez Cardozo
aca al profe si le falto explicar como probar ese event y listener, sera investigar. platzi no esta poniendo atencion a la calidad de los cursos
Alejandro Madrid Felizzola
Pasan años, y no mejoran o corrigen.
Regynald Zambrano
Creo que en esta clase no hemos seguido una convención de nombres.
Carlos Eduardo Gomez García
Interesante, se pueden manejar eventos con Laravel, eso si no lo sabía 🤔
Dejo el enlace con el commit de esta clase en Laravel 8
Alejandro Madrid Felizzola
¿Porque se envía el parámetro $this en la siguiente parte?:
event(new ModelRated($this, $model, $score));
Luis Cano
$this hace referencia al parametro $qualifier del constructor de la clase ModelRated usado por el trait CanRate, y el modelo User usa el trait CanRate. Asi que al final $this es el usuario que califica.
Yo sé, este curso en general esta muy mal planteado y deja mas dudas que respuestas pese a ser de nivel avanzado, creo que Platzi ya deberia retirarlo o ponerlo como contenido opcional en la ruta PHP.
Kenneth Angulo L
Juan David Rueda Quiroga
En php 8.2 podemos escribir el constructor de una forma mucho mejor
public function __construct( public readonly Model $qualifier, public readonly Model $rateable, public readonly float $score, ) { // }
De esa forma no es necesario usar getters o setter
Joel alexander
Cual es el git del proyecto
Néstor Iván Cepeda Munevar
Hola, aquí lo tienes https://github.com/sojeda/platzi-ecommerce-api/
Jean Nuñez
Eventos todas la acciones que user inicia
Tomas Goldenberg
reto php artisan make:event ModelUnrated Utils/CanRate //disparar evento en el method unrate php artisan make:listener SendEmailModelUnratedNotification php artisan make:notification ModelUnratedNotification agregamos nuestro evento al event provider
Earvin Saúl Pérez Ramos
Estoy haciendo un proyecto en Laravel y tengo la siguiente estructura de tablas
Product id name image code Price id product_id purchase_price sale_price
Warehouse id name user_id address
product_warehouse product_id warehouse_id product_quantity price_id
La ultima tabla la utilizo como tabla pivote y me permite obtener los productos que tiene un almacén, como se puede ver es una tabla pivote, pero me gustaría obtener el precio del producto utilizando el price_id de dicha tabla pivote. No se si alguien me podría asesorar me ayudaría mucho, intente usar el HasOneTrought desde el producto hacia el precio con el warehouse pero no me funciono, o si alguien tendría una mejor idea para resolver esto ''' public function price(){ return $this->hasOneThrough(Price::class,Warehouse::class,'product_id','price_id'); } ''' Saludos
Kenneth Angulo L
Asi podemos probar rapidamente, usando la interfaz web, en este caso el log reporta que el evento se disparo:
En el constructor del evento ModelRated reporto hacia el log:
public function __construct(Model $qualifier, Model $rateable, float $score)
{
$this->qualifier = $qualifier;
$this->rateable = $rateable;
$this->score = $score;
Log::info('ModelRated event fired.', ['qualifier' => $qualifier, 'rateable' => $rateable, 'score' => $score]);
}
Comparto mi solución al reto: Primera parte - Prueba de Unrate Siguiendo TDD primero creamos una prueba para testear que un usuario en efecto pueda quitar su calificación de un producto:
public function test_unrating_model() { $this->withoutExceptionHandling(); $user = User::factory()->create(); $product = Product::factory()->create(); $user->rate( $product, 5 ); $user->unrate( $product ); $rating = Rating::first(); $this->assertEmpty( $rating ); }
Creamos un usuario y un producto, le damos un calificación y luego la borramos, comprobamos que ya no exista más esa calificación, les dejo el commit en mi repositorio: test_unrating_model . Segunda parte - método unrate del Trait CanRate Como los usuarios tiene el trait CanRate, hace sentido que definamos el método para borrar calificación dentro de esa clase:
public function unrate( Model $model ) { // $rating = \App\Models\Rating::query() // ->where( 'qualifier_id', $this->id ) // ->where( 'rateable_id', $model->id ) // ->first(); // $rating->delete(); $this->ratings( $model->getMorphClass() )->detach( $model->getKey() ); event( new ModelUnrated( $this, $model ) ); return true; }
llegué a una solución diferente a la que el profe, pero me pareció más elegante la de él por lo que la usé también, cabe aclarar que en este método dispararemos el evento del reto. Dejo el commit de mi repositorio: método unrate . Tercera parte - creación del evento Pues creamos el evento que guardara y expondrá el nombre del qualifier (quien quitó su calificación) y el nombre del rateable (producto al cual se le quitó calificación):
<?php namespace App\Events; use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Broadcasting\PresenceChannel; use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Database\Eloquent\Model; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; class ModelUnrated { use Dispatchable, InteractsWithSockets, SerializesModels; public $qualifier; public $rateable; /** * Create a new event instance. * * @return void */ public function __construct( Model $qualifier, Model $rateable ) { $this->qualifier = $qualifier; $this->rateable = $rateable; } public function getQualifier(): Model { return $this->qualifier; } public function getRateable(): Model { return $this->rateable; } /** * Get the channels the event should broadcast on. * * @return \Illuminate\Broadcasting\Channel|array */ public function broadcastOn() { return new PrivateChannel('channel-name'); } }
. Cuarta parte - Creación del Listener Vamos a crear el Listener que se encargara de atender el evento cuando este se dispare, para enviar una notificación por email que informe el nombre de quien quitó su calificación y a que producto:
<?php namespace App\Events; use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Broadcasting\PresenceChannel; use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Database\Eloquent\Model; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; class ModelUnrated { use Dispatchable, InteractsWithSockets, SerializesModels; public $qualifier; public $rateable; /** * Create a new event instance. * * @return void */ public function __construct( Model $qualifier, Model $rateable ) { $this->qualifier = $qualifier; $this->rateable = $rateable; } public function getQualifier(): Model { return $this->qualifier; } public function getRateable(): Model { return $this->rateable; } /** * Get the channels the event should broadcast on. * * @return \Illuminate\Broadcasting\Channel|array */ public function broadcastOn() { return new PrivateChannel('channel-name'); } }
les dejo el commit en mi repositorio: creación de listener
. Quinta parte - Creación de la notificación creamos una notificación donde el constructor guarda los valores anteriormente mencionados en variable privadas y redactamos el contenido del correo:
<?php namespace App\Notifications; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Notification; class ModelUnratedNotification extends Notification { use Queueable; private $qualifierName; private $rateableName; /** * Create a new notification instance. * * @return void */ public function __construct( string $qualifierName, string $rateableName ) { $this->qualifierName = $qualifierName; $this->rateableName = $rateableName; } /** * Get the notification's delivery channels. * * @param mixed $notifiable * @return array */ public function via($notifiable) { return ['mail']; } /** * Get the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { return (new MailMessage) ->line( "El usuario {$this->qualifierName} ha removido su calificación de tu producto {$this->rateableName}" ); } /** * Get the array representation of the notification. * * @param mixed $notifiable * @return array */ public function toArray($notifiable) { return [ // ]; } }
Les dejo el commit de mi repositorio: notificación . Sexta parte - Declaramos el evento y el listener en Laravel
ModelUnrated::class => [ SendEmailModelUnratedNotification::class ] ]
y estamos listos para seguir!