Laravel-excel: [QUESTION] после события импорта

Созданный на 7 дек. 2018  ·  24Комментарии  ·  Источник: Maatwebsite/Laravel-Excel

Предпосылки

Версии

  • Версия PHP: 7.2
  • Версия Laravel: 5.7
  • Версия пакета: 3.1

Описание

У меня проблемы с работой события после импорта. Событие никогда не срабатывает. :(
После листа работает нормально, что я делаю не так?

Я пробовал как события регистрации, так и события автоматической регистрации.

Мой код

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);
    }
}

Самый полезный комментарий

В следующем выпуске (в настоящее время 3.1-dev) будет поддержка событий Before / AfterImport для чтения фрагментов. Он также добавит событие ImportFailed которое возникает при сбое любого задания фрагмента. (https://twitter.com/patrickbrouwers/status/1114166252711415808)

Не стесняйтесь протестировать его в ветке 3.1 и дайте мне знать, работает ли он как исключенный.

Все 24 Комментарий

У меня такая же проблема. Кажется, что событие AfterImport никогда не запускается, если вы реализуете WithChunkReading .

Похоже, это также верно и для события BeforeImport.

Я быстро просмотрел код и не вижу кода, который вообще запускал бы это событие в классе ChunkReader.

И когда я думаю об этом, для этого нет хорошего решения. Может быть, одним из решений могло бы стать добавление в цепочку одного задания, чтобы вызвать метод afterImport?

Есть ли у нас ответы на эту тему? :)

Да, мы определили это как ошибку. Посмотрим, сможем ли мы найти решение для этого в будущей версии.

@GlennM Говоря об этом, я хотел бы увидеть, есть ли способ также реализовать события BeforeChunk и AfterChunk, чтобы иметь возможность обновлять интерфейс интерфейса прогресса по мере его работы ... Что нужно учитывать при этом , должно быть общее количество + общее количество фрагментов + текущий фрагмент (только для размышлений), большинство моих файлов выполняется через графический интерфейс, но они довольно большие, поэтому возможность дать им какое-то «это в процессе» лучше, чем неопределенное индикатор

Возможен звук BeforeChunk и AfterChunk.

BeforeImport / AfterImport более сложны. Добавление их в качестве 2 дополнительных заданий в цепочку повлияет на производительность, так как файл будет дважды открываться повторно. Наилучший вариант - выполнить доимпорт только в первом задании и послеимпорт в последнем задании. Я посмотрю, возможно ли это.

+1 к добавлению событий BeforeImport / AfterImport в задания фрагментов. Я собирался подать предложение добавить эти две вакансии в цепочку, но похоже, что вы уже в ней! Ваше предложение реализовать события на первом и последнем задании тоже звучит лучше, если это возможно.

AfterImport не работает с ShouldQueue и WithChunkReading.
Кроме того, они необходимы для очередей, поэтому событие в конце выполнения очереди не реализуется.

с предложением документации:

$ import-> queue ('users.xlsx') -> chain ([
новый NotifyUserOfCompletedImport (запрос () -> пользователь ()),
]);

Каждый из элементов очереди запускается: NotifyUserOfCompletedImport

Alguma sugestão?

Я столкнулся с той же проблемой. Решил это, создав задание, реализующее ShouldQueue, затем запустив из него импорт и выполнив необходимые действия (которые в противном случае были бы в событии afterImport) после завершения импорта. Импорт настроил пакетную вставку и чтение фрагментов и выполняется синхронно в задании.

Одним из преимуществ вышеизложенного является то, что я могу легко контролировать, какой работник очереди выполняет задание.

и еще одно (очень важное) преимущество заключается в том, что я могу импортировать файлы XLS с заданием в очереди. То, что невозможно при использовании стандартного подхода с реализацией ShouldQueue в самом классе Import.

у меня такой же вопрос 。。。 как я могу сделать .... пожалуйста

@ zxl2006001 С обновленной документацией от @patrickbrouwers я решил свою проблему с этой логикой.

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

см. здесь: https://docs.laravel-excel.com/3.1/imports/queued.html#appending -jobs

На самом деле есть еще два следствия текущего дизайна:

  1. Глядя на метод чтения классов Reader, не очевидно, почему beforeImport запускается только внутри beforeReading, а не запускается синхронно перед вызовом чтения ChunkReader.

  2. В сценарии с фрагментами вы можете связать задание для выполнения любых уведомлений, но поскольку свойство "currentFile" защищено, вы не можете выполнить надлежащую очистку временного файла, и это не выполняется автоматически - задание, связанное после всех ReadChunk, было бы очень полезно как с afterImport, так и с временная очистка.

Есть ли у нас какие-либо обходные пути для обработки неудачного импорта? Единственный метод, о котором я сейчас могу думать, - это использование события глобальной ошибки задания laravels.

Проблема в том, что у меня нет контроля над процессом aatwebsiteExcel \ Jobs \ ReadChunk. Это означает, что я не могу передать глобальному событию нужные мне данные о неудавшейся работе.

Как мы можем обрабатывать ошибки при использовании chunkSize?

В следующем выпуске (в настоящее время 3.1-dev) будет поддержка событий Before / AfterImport для чтения фрагментов. Он также добавит событие ImportFailed которое возникает при сбое любого задания фрагмента. (https://twitter.com/patrickbrouwers/status/1114166252711415808)

Не стесняйтесь протестировать его в ветке 3.1 и дайте мне знать, работает ли он как исключенный.

Если я использую драйвер очереди database для импорта и реализую WithChunkReading в моем классе импорта, он несколько раз запускает событие AfterImport . Это ожидаемое поведение?

У меня AfterImport запускается дважды после каждого успешного импорта с драйвером очереди database и версией 3.1 .

У меня AfterImport запускается на неопределенный срок после успешного импорта, также с драйвером очереди database и версией 3.1

Если я использую драйвер очереди WithChunkReading в моем классе импорта, он несколько раз запускает событие

Вот журнал ошибок:

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

Это же ее AfterImport вызывается дважды.

Я также сталкиваюсь с тем, что слушатели AfterImport вызываются дважды. После отладки с помощью xdebug я обнаружил, что слушатели регистрируются в двух местах:

Исправлено для следующего выпуска

Была ли эта страница полезной?
0 / 5 - 0 рейтинги