sistema real notificaciones for example content con ciclo php laravel laravel-5 laravel-5.3

php - real - Laravel 5.3-Notificación única para la colección de usuarios(seguidores)



real time notifications laravel (2)

Cuando tengo un único usuario notifiable , se inserta una sola entrada en la tabla de notifications , junto con un mail / sms enviado que funciona perfectamente a través de los canales.

El problema es cuando tengo una colección de user , una lista de usuarios de 1k que me siguen y publico una actualización. Esto es lo que sucede cuando se utiliza el rasgo Notifiable como se sugiere para el caso de varios usuarios:

  1. 1k mails / sms enviados (el problema no está aquí)
  2. 1k entradas de notificación agregadas a la tabla de notifications la base de datos

Parece que agregar 1k notificaciones a la tabla de notificaciones de la base de datos no es una solución óptima. Dado que los datos de toArray son los mismos, y todo lo demás en la tabla de notifications la base de datos es el mismo para las filas de 1k, con la única diferencia es el notifiable_id del user notifiable_type .

Una solución óptima fuera de la caja sería:

  1. Laravel reconocería el hecho de que se trata de una array notifiable_type
  2. Guarde una notificación única como user_array o user con user_array 0 (cero solo se usaría para indicar que es un usuario con múltiples notificaciones)
  3. Cree / use otra tabla notifications_read usando la notification_id se acaba de crear como foreign_key e inserte filas de 1k, solo de estos campos:

    notification_id read_at

Espero que ya haya una forma de hacerlo ya que estoy en este punto de mi aplicación y me encantaría usar los Notificaciones y canales integrados para esta situación, ya que estoy disparando las notificaciones de emails / sms , lo cual está bien para repetir Creo que 1k veces, pero es la entrada de los mismos datos en la base de datos el problema que debe optimizarse.

¿Alguna idea / idea de cómo proceder en esta situación?


Actualizado 2017-01-14: implementado enfoque más correcto

Ejemplo rápido:

use Illuminate/Support/Facades/Notification; use App/Notifications/SomethingCoolHappen; Route::get(''/step1'', function () { // example - my followers $followers = App/User::all(); // notify them Notification::send($followers, new SomethingCoolHappen([''arg1'' => 1, ''arg2'' => 2])); }); Route::get(''/step2'', function () { // my follower $user = App/User::find(10); // check unread subnotifications foreach ($user->unreadSubnotifications as $subnotification) { var_dump($subnotification->notification->data); $subnotification->markAsRead(); } });

¿Cómo hacer que funcione?

Paso 1 - migración - crear tabla (subnotificaciones)

use Illuminate/Support/Facades/Schema; use Illuminate/Database/Schema/Blueprint; use Illuminate/Database/Migrations/Migration; class CreateSubnotificationsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create(''subnotifications'', function (Blueprint $table) { // primary key $table->increments(''id'')->primary(); // notifications.id $table->uuid(''notification_id''); // notifiable_id and notifiable_type $table->morphs(''notifiable''); // follower - read_at $table->timestamp(''read_at'')->nullable(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists(''subnotifications''); } }

Paso 2 - vamos a crear un modelo para la nueva tabla de subnotificaciones

<?php // App/Notifications/Subnotification.php namespace App/Notifications; use Illuminate/Database/Eloquent/Model; use Illuminate/Notifications/DatabaseNotification; use Illuminate/Notifications/DatabaseNotificationCollection; class Subnotification extends Model { // we don''t use created_at/updated_at public $timestamps = false; // nothing guarded - mass assigment allowed protected $guarded = []; // cast read_at as datetime protected $casts = [ ''read_at'' => ''datetime'', ]; // set up relation to the parent notification public function notification() { return $this->belongsTo(DatabaseNotification::class); } /** * Get the notifiable entity that the notification belongs to. */ public function notifiable() { return $this->morphTo(); } /** * Mark the subnotification as read. * * @return void */ public function markAsRead() { if (is_null($this->read_at)) { $this->forceFill([''read_at'' => $this->freshTimestamp()])->save(); } } }

Paso 3 - crear un canal de notificación de base de datos personalizado
Actualizado : usando la variable estática $ map para mantener la primera identificación de notificación e insertar las siguientes notificaciones (con los mismos datos) sin crear un registro en la tabla de notifications

<?php // App/Channels/SubnotificationsChannel.php namespace App/Channels; use Illuminate/Notifications/DatabaseNotification; use Illuminate/Notifications/Notification; class SubnotificationsChannel { /** * Send the given notification. * * @param mixed $notifiable * @param /Illuminate/Notifications/Notification $notification * * @return void */ public function send($notifiable, Notification $notification) { static $map = []; $notificationId = $notification->id; // get notification data $data = $this->getData($notifiable, $notification); // calculate hash $hash = md5(json_encode($data)); // if hash is not in map - create parent notification record if (!isset($map[$hash])) { // create original notification record with empty notifiable_id DatabaseNotification::create([ ''id'' => $notificationId, ''type'' => get_class($notification), ''notifiable_id'' => 0, ''notifiable_type'' => get_class($notifiable), ''data'' => $data, ''read_at'' => null, ]); $map[$hash] = $notificationId; } else { // otherwise use another/first notification id $notificationId = $map[$hash]; } // create subnotification $notifiable->subnotifications()->create([ ''notification_id'' => $notificationId, ''read_at'' => null ]); } /** * Prepares data * * @param mixed $notifiable * @param /Illuminate/Notifications/Notification $notification * * @return mixed */ public function getData($notifiable, Notification $notification) { return $notification->toArray($notifiable); } }

Paso 4 - crear una notificación
Actualizado : ahora la notificación es compatible con todos los canales, no solo con subnotificaciones

<?php // App/Notifications/SomethingCoolHappen.php namespace App/Notifications; use App/Channels/SubnotificationsChannel; use Illuminate/Bus/Queueable; use Illuminate/Notifications/Notification; use Illuminate/Contracts/Queue/ShouldQueue; use Illuminate/Notifications/Messages/MailMessage; class SomethingCoolHappen extends Notification { use Queueable; protected $data; /** * Create a new notification instance. * * @return void */ public function __construct($data) { $this->data = $data; } /** * Get the notification''s delivery channels. * * @param mixed $notifiable * @return array */ public function via($notifiable) { /** * THIS IS A GOOD PLACE FOR DETERMINING NECESSARY CHANNELS */ $via = []; $via[] = SubnotificationsChannel::class; //$via[] = ''mail''; return $via; } /** * Get the mail representation of the notification. * * @param mixed $notifiable * @return /Illuminate/Notifications/Messages/MailMessage */ public function toMail($notifiable) { return (new MailMessage) ->line(''The introduction to the notification.'') ->action(''Notification Action'', ''https://laravel.com'') ->line(''Thank you for using our application!''); } /** * Get the array representation of the notification. * * @param mixed $notifiable * @return array */ public function toArray($notifiable) { return $this->data; } }

Paso 5 - rasgo de ayudante para "seguidores"

<?php // App/Notifications/HasSubnotifications.php namespace App/Notifications; trait HasSubnotifications { /** * Get the entity''s notifications. */ public function Subnotifications() { return $this->morphMany(Subnotification::class, ''notifiable'') ->orderBy(''id'', ''desc''); } /** * Get the entity''s read notifications. */ public function readSubnotifications() { return $this->Subnotifications() ->whereNotNull(''read_at''); } /** * Get the entity''s unread notifications. */ public function unreadSubnotifications() { return $this->Subnotifications() ->whereNull(''read_at''); } }

Paso 6 - actualiza tu modelo de Usuarios
Actualizado : no requiere método de seguidores

namespace App; use App/Notifications/HasSubnotifications; use Illuminate/Notifications/Notifiable; use Illuminate/Foundation/Auth/User as Authenticatable; class User extends Authenticatable { use Notifiable; /** * Adding helpers to followers: * * $user->subnotifications - all subnotifications * $user->unreadSubnotifications - all unread subnotifications * $user->readSubnotifications - all read subnotifications */ use HasSubnotifications; /** * The attributes that are mass assignable. * * @var array */ protected $fillable = [ ''name'', ''email'', ''password'', ]; /** * The attributes that should be hidden for arrays. * * @var array */ protected $hidden = [ ''password'', ''remember_token'', ]; }


Sí, tienes razón, supongo que con el rasgo Notifiable predeterminado, puedes crear un canal personalizado .

Puede consultar la clase Illuminate/Notifications/Channels/DatabaseChannel para la creación por defecto y adoptarla en una tabla dinámica.

Espero que esto ayude a crear un nuevo canal con una tabla dinámica. Además, implemente un rasgo HasDatabasePivotNotifications (o nombre similar) a su propio rasgo Notifiable .