Laravel-excel: [QUESTION] após o evento de importação

Criado em 7 dez. 2018  ·  24Comentários  ·  Fonte: Maatwebsite/Laravel-Excel

Pré-requisitos

Versões

  • Versão PHP: 7.2
  • Versão do Laravel: 5.7
  • Versão do pacote: 3.1

Descrição

Tenho alguns problemas para fazer o evento após a importação funcionar. O evento nunca é disparado. :(
A folha posterior funciona bem, o que estou fazendo de errado?

Eu tentei os eventos de registro e os eventos de registro automático.

Meu 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

Comentários muito úteis

A próxima versão (atualmente 3.1-dev) terá suporte para eventos Before / AfterImport para leitura de blocos. Ele também adicionará ImportFailed evento que é gerado quando qualquer uma das tarefas de chunk falha. (https://twitter.com/patrickbrouwers/status/1114166252711415808)

Sinta-se à vontade para testá-lo no branch 3.1 e me avise se ele funciona como exceção.

Todos 24 comentários

Eu tenho o mesmo problema. Parece que o evento AfterImport nunca é disparado se você estiver implementando o contrato WithChunkReading .

Isso também parece ser verdade para o evento BeforeImport

Dei uma olhada rápida no código e não consigo ver nenhum código que acione esse evento na classe ChunkReader.

E quando penso nisso, não há uma solução legal para isso. Talvez uma solução pudesse ser adicionar um único trabalho à cadeia para aumentar o método afterImport.

Temos alguma resposta para este tópico? :)

Sim, identificamos isso como um bug. Veremos se podemos encontrar uma solução para isso em uma versão futura.

@GlennM Falando nisso, gostaria de ver se há uma maneira de também implementar um evento BeforeChunk e AfterChunk, para poder atualizar uma interface de progresso à medida que é trabalhado ... Coisas a considerar com isso , deve ser a contagem total + partes totais + parte atual (apenas para pensar), a maioria dos meus arquivos são feitos através da GUI, mas são bastante grandes, então ser capaz de dar a eles algum tipo de "está em andamento" é melhor do que um indeterminado Barra de progresso

Os sons BeforeChunk e AfterChunk são possíveis.

O BeforeImport / AfterImport são mais complicados. Adicioná-los como 2 tarefas extras à cadeia terá impacto no desempenho, pois irá reabrir o arquivo 2x vezes. A melhor opção seria poder executar apenas o beforeimport no primeiro trabalho e o afterimport no último trabalho. Vou ver se isso é possível.

+1 para adicionar eventos BeforeImport / AfterImport para chunk jobs. Eu estava prestes a enviar uma proposta para adicionar esses dois trabalhos à rede, mas parece que você já está nisso! Sua sugestão de implementar os eventos no primeiro e no último trabalho também soa melhor, se possível.

AfterImport não funciona com ShouldQueue e WithChunkReading.
Além disso, eles são necessários para filas, portanto, um evento no final da execução de uma fila não é implementado.

com sugestão de documentação:

$ import-> queue ('users.xlsx') -> chain ([
novo NotifyUserOfCompletedImport (request () -> user ()),
]);

Cada um dos itens da fila é disparado: NotifyUserOfCompletedImport

Alguma sugestão?

Eu tive o mesmo problema. Resolvido isso criando um Job implementando o ShouldQueue, então executando o Import a partir dele e realizando as ações necessárias (que de outra forma seriam no evento afterImport) após o término da importação. A importação configurou inserções de lote e leitura de fragmentos e é executada de forma síncrona no Trabalho.

Um dos benefícios acima é que posso controlar facilmente qual trabalhador da fila está executando o trabalho.

e outro benefício (muito importante) é que posso importar arquivos XLS com o trabalho na fila. Algo que não é possível se usar a abordagem padrão com a implementação de ShouldQueue na própria classe Import.

Eu tenho a mesma pergunta 。。。 como posso fazer ... por favor

@ zxl2006001 Com a documentação atualizada de @patrickbrouwers resolvi meu problema com essa lógica.

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

veja aqui: https://docs.laravel-excel.com/3.1/imports/queued.html#appending -jobs

Na verdade, existem mais duas consequências do design atual:

  1. Olhando para o método de leitura das classes Reader, não é óbvio por que beforeImport é disparado apenas dentro de beforeReading em vez de ser disparado de forma síncrona antes que as leituras de ChunkReader sejam invocadas.

  2. No cenário fragmentado, você pode encadear um trabalho para fazer qualquer notificação, mas como a propriedade "currentFile" está protegida, você não pode fazer a limpeza adequada do arquivo temporário e não é feito automaticamente - um trabalho encadeado depois de todos os ReadChunk seria muito útil com afterImport e com limpeza de temp.

Temos alguma solução alternativa para lidar com importações com falha? O único método que posso pensar atualmente é usando o evento de erro de trabalho global laravels.

O problema com isso é que não tenho controle sobre o processo aatwebsiteExcel \ Jobs \ ReadChunk. Isso significa que não posso transmitir ao evento global os dados de que preciso sobre o trabalho com falha.

Como podemos lidar com erros ao usar chunkSize?

A próxima versão (atualmente 3.1-dev) terá suporte para eventos Before / AfterImport para leitura de blocos. Ele também adicionará ImportFailed evento que é gerado quando qualquer uma das tarefas de chunk falha. (https://twitter.com/patrickbrouwers/status/1114166252711415808)

Sinta-se à vontade para testá-lo no branch 3.1 e me avise se ele funciona como exceção.

Se eu usar o driver de fila database para importações e implementar WithChunkReading em minha classe de importação, pare para acionar o evento AfterImport várias vezes. Esse é o comportamento esperado?

Estou experimentando AfterImport sendo disparado duas vezes após cada importação bem-sucedida, com database driver de fila e versão 3.1 .

Estou experimentando AfterImport sendo disparado indefinidamente após executar uma importação bem-sucedida também com database driver de fila e versão 3.1

Se eu usar o driver de fila redis para importações e implementar WithChunkReading na minha classe de importação, pareço acionar o evento

Aqui está o log de erros:

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

Mesmo seu AfterImport é chamado duas vezes.

Também estou encontrando ouvintes do AfterImport sendo chamados duas vezes. Depois de depurar com xdebug, descobri que os ouvintes estão registrados em dois lugares:

Corrigido para o próximo lançamento

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

rossjcooper picture rossjcooper  ·  3Comentários

kurianic picture kurianic  ·  3Comentários

pamekar picture pamekar  ·  3Comentários

contifico picture contifico  ·  3Comentários

matthewslouismarie picture matthewslouismarie  ·  3Comentários