es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Cómo puedo preservar el estado del modelo en múltiples escuchadores de Laravel/Lumen que reciben un evento?

Usando Lumen 5.5, PHP 7.3

Mi objetivo es extender la funcionalidad existente en un modelo mientras mantengo la limpieza del código. Usar el patrón Evento/Listener tenía sentido, pero me encontré con problemas de diseño en los que necesito acceso al estado original del modelo en el listener. Parece que ese estado no es accesible.

Cómo comenzó: este método en un modelo (sanitizado para la vista pública) lo “reinicia” asignando nulo a algunos atributos. No hay problemas con esto.


     public function reset()
     {
         $this->association_id = null;
         $this->associated_at = null;
         $this->save();
     }

Cómo va: Agregué una implementación de evento para poder agregar una nueva funcionalidad a los listeners.

     public function reset()
     {
         $this->association<em>id = null;
         $this->associated</em>at = null;
         $this->save();

<pre><code>     event(new ResetEvent($this));
}
</code></pre>

Evento

     class ResetEvent
     {
         public $myModel;</p>

<pre><code>     public function __construct($myModel)
     {
         $this->myModel = $myModel;
     }
</code></pre>

<p>}

Listener

     class ResetListener
     {
         public function handle(ResetEvent $event)
         {
             $association<em>id = $event->myModel->association</em>id;
             // O...
             $association<em>id = $event->myModel->getOriginal('association</em>id');</p>

<pre><code>         // Realizar nueva funcionalidad...
     }
 </code> </pre>

 <p>}

DESAFÍO

El listener necesita acceso al valor association_id del modelo. Desafortunadamente, esto ya no está disponible después de que se llama el método save() del método reset del modelo. Intenté usar el método getOriginal() en el modelo desde el listener, pero el valor allí también era nulo. Parece que debería haber funcionado.

Tenga en cuenta que esta implementación utiliza eventos síncronos; no hay un sistema externo de cola asíncrona involucrado.

OPCIONES

Una opción es cambiar la intención y el nombre de ResetEvent a ResetRequestEvent y usar un listener para realizar la modificación de atributos en el modelo y otro para realizar la nueva funcionalidad que estoy agregando. Es posible que esto lleve o no a condiciones de carrera si el modelo se pasa a los listeners por referencia.

Otra opción podría ser una forma que aún no he aprendido de preservar el estado del modelo a medida que se pasa al evento. Viene a la mente los objetos de transferencia de datos en el estilo de Java, pero eso suena como si fuera esquivando las comodidades proporcionadas por el marco.

Buscando ideas para seguir cualquiera de las opciones.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Solución para mantener el estado del modelo en Lumen 5.5

    Si desea mantener el estado del modelo después de llamar al método save() en Lumen 5.5, una solución posible es usar un método fresh() para recargar el modelo desde la base de datos con su estado original. De esta manera, aún puede acceder a sus atributos y sus valores originales en su escucha.

    Aquí hay una versión actualizada de su código que demuestra este enfoque:

    class MyModel extends Model
    {
        public function reset()
        {
            $this->association_id = null;
            $this->associated_at = null;
            $this->save();
    
            event(new ResetEvent($this->fresh()));
        }
    }
    
    class ResetListener
    {
        public function handle(ResetEvent $event)
        {
            $original_association_id = $event->myModel->getOriginal('association_id');
    
            // Hacer nueva funcionalidad...
        }
    }
    

    Como puede ver, ahora llamamos a $this->fresh() después de guardar el modelo para obtener una copia fresca de él desde la base de datos con su estado original. Luego pasamos esta copia fresca al constructor de ResetEvent, para que el oyente del evento pueda acceder al estado original del modelo.

    Tenga en cuenta que este enfoque incurrirá en una consulta adicional a la base de datos para volver a cargar el modelo, lo que puede ser aceptable o no dependiendo de su caso de uso.

    Opciones alternativas

    Como ha señalado, otro enfoque sería dividir el ResetEvent en múltiples eventos, cada uno con su propio oyente que realiza una acción específica. Esta puede ser una buena opción si desea mantener sus eventos y oyentes simples y enfocados.

    Otra opción sería usar un objeto de transferencia de datos (DTO) para pasar el estado del modelo al ResetEvent. Esto puede ser más complejo, pero permitiría pasar solo el estado necesario al evento, en lugar de todo el modelo, lo que podría ser una ventaja en términos de rendimiento si el modelo es grande. Sin embargo, esto requeriría código adicional para asignar el DTO de vuelta al modelo original, lo que puede no valer la pena dependiendo de su caso de uso.

    En última instancia, el mejor enfoque dependerá de sus requisitos y limitaciones específicos.

Comments are closed.