Laravel-excel: [PREGUNTA] después del evento de importación

Creado en 7 dic. 2018  ·  24Comentarios  ·  Fuente: Maatwebsite/Laravel-Excel

Prerrequisitos

Versiones

  • Versión de PHP: 7.2
  • Versión de Laravel: 5.7
  • Versión del paquete: 3.1

Descripción

Tengo algunos problemas para que funcione el evento posterior a la importación. El evento nunca se dispara. :(
La hoja posterior funciona bien, ¿qué estoy haciendo mal?

He probado tanto los eventos de registro como los eventos de registro automático.

Mi código

namespace App\Imports;

use App\Order;
use App\Order\Address;
use Illuminate\Contracts\Queue\ShouldQueue;
use Maatwebsite\Excel\Concerns\Importable;
use Maatwebsite\Excel\Concerns\RegistersEventListeners;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithBatchInserts;
use Maatwebsite\Excel\Concerns\WithChunkReading;
use Maatwebsite\Excel\Concerns\WithCustomCsvSettings;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Events\AfterImport;
use Maatwebsite\Excel\Events\BeforeImport;

class OrderAddressImport implements
    WithHeadingRow,
    ToModel,
    WithBatchInserts,
    WithChunkReading,
    WithCustomCsvSettings,
    ShouldQueue,
    WithEvents
{
    use Importable, RegistersEventListeners;

    protected $order;

    public function __construct(Order $order)
    {
        $this->order = $order;
    }

    /**
     * <strong i="16">@param</strong> array $row
     * <strong i="17">@return</strong> Address
     */
    public function model(array $row)
    {
        $data = ['order_id' => $this->order->id];
        $data = array_merge($data, $row);

        return new Address($data);
    }


    public function batchSize() : int
    {
        return 1000;
    }

    public function chunkSize() : int
    {
        return 5000;
    }

    /**
     * <strong i="18">@return</strong> array
     */
    public function getCsvSettings(): array
    {
        return [
            'delimiter' => ';',
            'enclosure' => '',
            'input_encoding' => 'UTF-8'
        ];
    }

    public static function afterImport(AfterImport $event)
    {
       dd($event);
    }
}
bug

Comentario más útil

La próxima versión (actualmente 3.1-dev) tendrá soporte para eventos Before / AfterImport para lectura de fragmentos. También agregará el evento ImportFailed que se genera cuando falla cualquiera de los trabajos de fragmentos. (https://twitter.com/patrickbrouwers/status/1114166252711415808)

Siéntase libre de probarlo en la rama 3.1 y avíseme si funciona como exceptuado.

Todos 24 comentarios

Tengo el mismo problema. Parece que el evento AfterImport nunca se activa si está implementando el WithChunkReading .

Esto también parece ser cierto para el evento BeforeImport

Eché un vistazo rápido al código y no puedo ver ningún código que active este evento en la clase ChunkReader.

Y cuando lo pienso, no hay una buena solución para esto. ¿Quizás una solución podría ser agregar un solo trabajo a la cadena para que genere el método afterImport?

¿Tenemos alguna respuesta a este tema? :)

Sí, lo hemos identificado como un error. Veremos si podemos encontrar una solución para ello en una versión futura.

@GlennM Hablando con esto, me gustaría ver si hay una manera de implementar también un evento BeforeChunk y AfterChunk, para poder actualizar una interfaz gráfica de usuario de progreso a medida que se trabaja ... Cosas a considerar con esto , debería ser el recuento total + los fragmentos totales + el fragmento actual (solo para pensar), la mayoría de mis archivos se realizan a través de la GUI pero son bastante grandes, por lo que poder darles algún tipo de "está en progreso" es mejor que un indeterminado barra de progreso

Sonido BeforeChunk y AfterChunk posible.

BeforeImport / AfterImport son más complicados. Agregarlos como 2 trabajos adicionales a la cadena tendrá un impacto en el rendimiento, ya que volverá a abrir el archivo 2 veces más. La mejor opción sería poder ejecutar solo la importación anterior en el primer trabajo y la importación posterior en el último trabajo. Veré si eso es posible.

+1 para agregar eventos BeforeImport / AfterImport a trabajos fragmentados. Estaba a punto de enviar una propuesta para agregar estos como dos trabajos a la cadena, ¡pero parece que ya estás en eso! Su sugerencia de implementar los eventos en el primer y último trabajo también suena mejor si es posible.

AfterImport no funciona con ShouldQueue y WithChunkReading.
Además, son necesarios para las colas, por lo que no se implementa un evento al final de la ejecución de una cola.

con la sugerencia de documentación:

$ import-> queue ('users.xlsx') -> cadena ([
new NotifyUserOfCompletedImport (solicitud () -> usuario ()),
]);

Cada uno de los elementos de la cola se activa el: NotifyUserOfCompletedImport

Alguma sugestão?

Me he encontrado con el mismo problema. Lo resolvió creando un trabajo implementando ShouldQueue, luego ejecutando la importación desde él y realizando las acciones necesarias (que de lo contrario estarían en el evento afterImport) después de que finalice la importación. La importación ha configurado inserciones por lotes y lectura de fragmentos y se ejecuta sincrónicamente en el trabajo.

Uno de los beneficios de lo anterior es que puedo controlar fácilmente qué trabajador de cola está ejecutando el trabajo.

y otro beneficio (muy importante) es que puedo importar archivos XLS con el trabajo en cola. Algo que no es posible si se usa el enfoque estándar con la implementación de ShouldQueue en la propia clase Import.

Tengo la misma pregunta 。。。 ¿cómo puedo hacer ... por favor?

@ zxl2006001 Con la documentación actualizada de @patrickbrouwers resolví mi problema con esta lógica.

(new UsersImport)->queue('users.xlsx')->chain([
    new NotifyUserOfCompletedImport(request()->user()),
]); 

ver aquí: https://docs.laravel-excel.com/3.1/imports/queued.html#appending -jobs

En realidad, hay dos consecuencias más del diseño actual:

  1. Al observar el método de lectura de las clases de Reader, no es obvio por qué beforeImport se activa solo dentro de beforeReading en lugar de activarse sincrónicamente antes de que se invoquen las lecturas de ChunkReader.

  2. En un escenario fragmentado, puede encadenar un trabajo para realizar cualquier notificación, pero dado que la propiedad "currentFile" está protegida, no puede realizar una limpieza adecuada del archivo temporal y no se realiza automáticamente; un trabajo encadenado después de todos los ReadChunk sería muy útil tanto con afterImport como con limpieza de temperatura.

¿Disponemos de alguna solución alternativa para gestionar las importaciones fallidas? El único método en el que puedo pensar actualmente es usar el evento de error de trabajo global de laravels.

El problema con eso es que no tengo control sobre el proceso aatwebsiteExcel \ Jobs \ ReadChunk. Esto significa que no puedo pasar al evento global los datos que necesito sobre el trabajo fallido.

¿Cómo podemos manejar los errores al usar chunkSize?

La próxima versión (actualmente 3.1-dev) tendrá soporte para eventos Before / AfterImport para lectura de fragmentos. También agregará el evento ImportFailed que se genera cuando falla cualquiera de los trabajos de fragmentos. (https://twitter.com/patrickbrouwers/status/1114166252711415808)

Siéntase libre de probarlo en la rama 3.1 y avíseme si funciona como exceptuado.

Si utilizo el controlador de cola database para importaciones e implemento WithChunkReading en mi clase de importación, parece que desencadena el evento AfterImport varias veces. ¿Es ese el comportamiento esperado?

Estoy experimentando que AfterImport se active dos veces después de cada importación exitosa, con el controlador de cola database y la versión 3.1 .

Estoy experimentando que AfterImport se active indefinidamente después de ejecutar una importación exitosa también con el controlador de cola database y la versión 3.1

Si utilizo el controlador de cola de WithChunkReading en mi clase de importación, parece que desencadena el evento AfterImport varias veces. ¿Es ese el comportamiento esperado?

Aquí está el registro de errores:

local.ERROR: unlink(/Users/sineld/Code/project/public/uploads/tmp/laravel-excel-qfK6O5aCHxhFXioVayQbLQag5UnFKyxB.xlsx): No such file or directory {"exception":"[object] (ErrorException(code: 0):

La misma se llama a AfterImport dos veces.

También me encuentro con oyentes de AfterImport que son llamados dos veces. Después de depurar con xdebug, encontré que los oyentes están registrados en dos lugares:

Corregido para la próxima versión

¿Fue útil esta página
0 / 5 - 0 calificaciones