Laravel-excel: [QUESTION] après l'événement d'importation

Créé le 7 déc. 2018  ·  24Commentaires  ·  Source: Maatwebsite/Laravel-Excel

Conditions préalables

Versions

  • Version PHP: 7.2
  • Version Laravel: 5.7
  • Version du paquet: 3.1

La description

J'ai du mal à faire fonctionner l'événement après l'importation. L'événement ne se déclenche jamais. :(
La feuille après fonctionne bien, qu'est-ce que je fais de mal?

J'ai essayé à la fois les événements de registre et les événements de registre automatique.

Mon code

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

Commentaire le plus utile

La prochaine version (actuellement 3.1-dev) prendra en charge les événements Before / AfterImport pour la lecture des morceaux. Il ajoutera également l'événement ImportFailed qui est déclenché lorsque l'un des travaux de bloc échoue. (https://twitter.com/patrickbrouwers/status/1114166252711415808)

N'hésitez pas à le tester sur la branche 3.1 et faites-moi savoir s'il fonctionne comme excepté.

Tous les 24 commentaires

J'ai le même problème. Il semble que l'événement AfterImport ne soit jamais déclenché si vous implémentez le WithChunkReading .

Cela semble être également vrai pour l'événement BeforeImport

J'ai jeté un coup d'œil rapide au code et je ne vois aucun code qui déclenchera cet événement dans la classe ChunkReader.

Et quand j'y pense, il n'y a pas de bonne solution pour ça. Peut-être qu'une solution pourrait être d'annoncer un seul travail à la chaîne pour qu'elle déclenche la méthode afterImport?

Avons-nous des réponses à ce sujet? :)

Oui, nous avons identifié cela comme un bogue. Nous verrons si nous pouvons trouver une solution pour cela dans une prochaine version.

@GlennM En parlant de cela, j'aimerais voir s'il existe un moyen d'implémenter également un événement BeforeChunk et AfterChunk, pour pouvoir mettre à jour une interface graphique frontale de progression au fur et à mesure que cela fonctionne ... , devrait être le nombre total + les morceaux totaux + le morceau actuel (juste pour les pensées), la plupart de mes fichiers sont effectués via l'interface graphique mais sont assez volumineux, donc pouvoir leur donner une sorte de "c'est en cours" est mieux qu'un indéterminé barre de progression

Les sons BeforeChunk et AfterChunk sont possibles.

Les BeforeImport / AfterImport sont plus délicats. Les ajouter en tant que 2 tâches supplémentaires à la chaîne aura un impact sur les performances, car il rouvrira 2x fois le fichier. La meilleure option serait en mesure d'exécuter uniquement l'avant import sur le premier travail et l'afterimport sur le dernier travail. Je verrai si c'est possible.

+1 à l'ajout d'événements BeforeImport / AfterImport aux tâches de segment J'étais sur le point de soumettre une proposition pour ajouter ces deux emplois à la chaîne, mais on dirait que vous y êtes déjà! Votre suggestion de mettre en œuvre les événements sur le premier et le dernier travail semble également la meilleure si possible.

AfterImport ne fonctionne pas avec ShouldQueue et WithChunkReading.
De plus, ils sont requis pour les files d'attente, donc un événement à la fin de l'exécution d'une file d'attente n'est pas implémenté.

avec la suggestion de documentation:

$ import-> queue ('users.xlsx') -> chaîne ([
nouveau NotifyUserOfCompletedImport (request () -> user ()),
]);

Chacun des éléments de la file d'attente est déclenché le: NotifyUserOfCompletedImport

Alguma sugestão?

J'ai rencontré le même problème. Résolu le problème en créant un Job implémentant ShouldQueue, puis en exécutant l'importation à partir de celui-ci et en effectuant les actions nécessaires (qui autrement seraient dans l'événement afterImport) une fois l'importation terminée. L'importation a configuré les insertions de lots et la lecture de bloc et est exécutée de manière synchrone dans le Job.

L'un des avantages de ce qui précède est que je peux facilement contrôler quel travailleur de file d'attente exécute le travail.

et un autre avantage (très important) est que je peux importer des fichiers XLS avec le travail en file d'attente. Quelque chose qui n'est pas possible si vous utilisez l'approche standard avec l'implémentation de ShouldQueue dans la classe Import elle-même.

J'ai la même question 。。。 comment puis-je faire ... s'il vous plaît

@ zxl2006001 Avec la documentation mise à jour de @patrickbrouwers, j'ai résolu mon problème avec cette logique.

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

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

Il y a en fait deux autres conséquences de la conception actuelle:

  1. En regardant la méthode de lecture des classes Reader, il n'est pas évident de savoir pourquoi beforeImport est déclenché uniquement à l'intérieur de beforeReading au lieu d'être déclenché de manière synchrone avant que les lectures de ChunkReader ne soient appelées.

  2. Dans un scénario fragmenté, vous pouvez enchaîner un travail pour faire des notifications, mais comme la propriété "currentFile" est protégée, vous ne pouvez pas faire un nettoyage approprié du fichier temporaire et ce n'est pas fait automatiquement - un travail enchaîné après tout ReadChunk serait très utile à la fois avec afterImport et avec nettoyage de la température.

Avons-nous des solutions de contournement pour gérer les importations ayant échoué? La seule méthode à laquelle je peux actuellement penser consiste à utiliser l'événement d'erreur de travail global laravels.

Le problème avec cela est que je n'ai aucun contrôle sur le processus aatwebsiteExcel \ Jobs \ ReadChunk. Cela signifie que je ne peux pas transmettre à l'événement global les données dont j'ai besoin sur le travail ayant échoué.

Comment pouvons-nous gérer les erreurs lors de l'utilisation de chunkSize?

La prochaine version (actuellement 3.1-dev) prendra en charge les événements Before / AfterImport pour la lecture des morceaux. Il ajoutera également l'événement ImportFailed qui est déclenché lorsque l'un des travaux de bloc échoue. (https://twitter.com/patrickbrouwers/status/1114166252711415808)

N'hésitez pas à le tester sur la branche 3.1 et faites-moi savoir s'il fonctionne comme excepté.

Si j'utilise le pilote de file d'attente database pour les importations et que j'implémente WithChunkReading sur ma classe d'importation, cela déclenche plusieurs fois l'événement AfterImport . Est-ce le comportement attendu?

Je constate que AfterImport est déclenché deux fois après chaque importation réussie, avec le pilote de file d'attente database et la version 3.1 .

Je rencontre le déclenchement de AfterImport indéfiniment après l'exécution d'une importation réussie également avec le pilote de file d'attente database et la version 3.1

Si j'utilise le pilote de file d'attente j'implémente WithChunkReading sur ma classe d'importation, il semble déclencher l'événement

Voici le journal des erreurs:

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

Même son AfterImport est appelé deux fois.

Je rencontre également des écouteurs AfterImport appelés deux fois. Après le débogage avec xdebug, j'ai constaté que les écouteurs sont enregistrés à deux endroits:

Corrigé pour la prochaine version

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

thearabbit picture thearabbit  ·  3Commentaires

lucatamtam picture lucatamtam  ·  3Commentaires

octoxan picture octoxan  ·  3Commentaires

matthewslouismarie picture matthewslouismarie  ·  3Commentaires

amine8ghandi8amine picture amine8ghandi8amine  ·  3Commentaires