Laravel-excel: [PROPOSITION] Importez des éléments sans enregistrer directement

Créé le 24 janv. 2019  ·  9Commentaires  ·  Source: Maatwebsite/Laravel-Excel

Conditions préalables

Versions

  • Version PHP: 7.1.9
  • Version Laravel: 5.7.19
  • Version du package: 3.0+

La description

L'importation de modèles doit être possible sans les enregistrer directement. Il devrait également être possible de renvoyer autre chose que des modèles à partir d'une importation.

Je ne peux actuellement pas mettre à niveau de 2.1.30 à 3.0.0 ou supérieur. Je dois pouvoir importer un ensemble de modèles sans les enregistrer. J'utilise ceci pour des tests. De plus, j'ai un test où une ligne contient des informations pour créer deux modèles liés (de classes différentes). Actuellement, je ne peux avoir qu'un seul modèle par ligne. La restructuration du fichier CSV n'est pas possible ici.

IMO, 3.0.0+ est trop étroitement concentré sur la situation idéale où un fichier CSV correspond à une table et une ligne correspond à un modèle, et chaque modèle doit être enregistré instantanément. Ce n'était pas le cas pour 2.X, et je ne sais pas pourquoi il a été changé.

Notez que je ne veux pas rester sur 2.1.30, car cela nécessite le package abandonné phpoffice/phpexcel .

Exemple

Une méthode supplémentaire doit être ajoutée à la façade Excel , qui a la même signature que import , mais renvoie des modèles au lieu de les enregistrer. Exemple:

$users = Excel::load(new UsersImport, 'users.xlsx');

De plus, une méthode item doit être ajoutée aux classes d'importation, qui peuvent renvoyer n'importe quel type au lieu de seulement des modèles.

question

Commentaire le plus utile

@WouterFlorijn vous pouvez essayer cette approche pour obtenir un tableau à partir de votre fichier:

$array = Excel::toArray([], 'file.xlsx');

Tous les 9 commentaires

Utiliser ToModel n'est qu'une façon de traiter les importations. Il s'agit simplement d'une option qui facilite les insertions d'un modèle par rangée.

Si vous souhaitez gérer différentes structures et d'une manière similaire à la version 2.1, vous devez utiliser ToCollection : https://laravel-excel.maatwebsite.nl/3.1/imports/collection.html In la méthode de collecte, vous obtenez une collection de lignes similaire à celle obtenue dans la version 2.1.

Si vous voulez obtenir les modèles uniquement dans le contrôleur et non dans votre objet d'importation (pas vraiment une approche recommandée), il existe la méthode ::toCollection , qui renvoie la ligne brute (aucune conversion en modèles n'est effectuée) à votre contrôleur .
(https://laravel-excel.maatwebsite.nl/3.1/imports/basics.html#importing-to-array-or-collection)

$users = Excel::toCollection(new UsersImport, 'users.xlsx');

@patrickbrouwers merci pour votre réponse. Donc, si je comprends bien, utiliser Excel::import sur une importation qui implémente ToCollection retournera une collection de modèles sans les enregistrer? Si tel est le cas, cela n'est pas clairement indiqué dans la documentation, comme l'exemple en bas de https://laravel-excel.maatwebsite.nl/3.1/imports/collection.html est le suivant:

public function import() 
{
    Excel::import(new UsersImport, 'users.xlsx');
}

La valeur de retour n'est stockée nulle part, ce qui implique que la collection importée de modèles est enregistrée directement (ou du moins que la méthode a des effets secondaires). Sinon, il serait inutile d'appeler import sans affecter la valeur de retour à une variable, n'est-ce pas?

@WouterFlorijn Non, ::import() ne retournera jamais de lignes ou de modèles. Seul Excel::toCollection() fait.

Utiliser la préoccupation ToCollection est quelque chose de différent de l'utilisation de Excel::toCollection() .
Lors de l'implémentation de ToCollection l'importation entière est encapsulée dans l'objet Import. Le retour de quelque chose dans ToCollection ne sera pas retourné au contrôleur.

@patrickbrouwers Juste pour revenir, je pense toujours que nous nous comprenons mal. Ce que je recherche simplement, c'est une méthode qui renvoie une collection de modèles, sans les enregistrer. Je ne veux pas traiter les lignes dans mon contrôleur, je voudrais le faire dans une classe d'importation. Jusqu'à présent, je n'ai pas trouvé cela.

L'idée:

TransactionsImport.php:

<?php

namespace App\Imports;

use App\Banks\Transaction;
use Carbon\Carbon;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithHeadingRow;

class TransactionsImport implements ToModel, WithHeadingRow
{
    public function model(array $row)
    {
        $transaction = new Transaction;
        $transaction->amount = $row['amount'];
        $transaction->currency = $row['currency'];

        return $transaction;
    }
}

TransactionsController.php:

...
$transactions = Excel::someFunction(new TransactionsImport, 'path/to/file.csv');
// $transactions is a Collection of Transaction models that are not saved to the database yet.
...

J'ai également trouvé deux problèmes avec la fonction toCollection :

  1. Il renvoie une Collection avec un seul élément, qui est une autre Collection qui contient une Collection pour chaque ligne.
  2. Il prend un argument d'importation, ce qui est inutile dans les cas où vous souhaitez simplement renvoyer les lignes en tant que collections.

Ce que je recherche simplement, c'est une méthode qui renvoie une collection de modèles, sans les enregistrer. Je ne veux pas traiter les lignes dans mon contrôleur, je voudrais le faire dans une classe d'importation. Jusqu'à présent, je n'ai pas trouvé cela.

Peut-être que ces documents vous sont utiles:
Gérer vous-même la persistance
Concepts d'architecture

@WouterFlorijn vous pouvez essayer cette approche pour obtenir un tableau à partir de votre fichier:

$array = Excel::toArray([], 'file.xlsx');

@WouterFlorijn vous pouvez essayer cette approche pour obtenir un tableau à partir de votre fichier:

$array = Excel::toArray([], 'file.xlsx');

C'est exactement ce que je cherchais.

+1 pour cette demande. Je ne pense pas que les méthodes model () et collection () devraient sauver quoi que ce soit. Il doit renvoyer les données d'un fichier Excel / CSV dans une collection (ou tableau) de modèles / tableaux. La persistance doit être gérée séparément, ou du moins être un choix.

Mon cas d'utilisation: je souhaite obtenir la date minimum et maximum à partir d'enregistrements dans un CSV. Si cela chevauche un fichier CSV importé existant, il ne doit rien importer avant que l'utilisateur ne confirme que le chevauchement est correct.

Edit: Ah, je réponds à un problème fermé. Comment avez-vous géré ce @WouterFlorijn?

Vous pouvez facilement y parvenir vous-même déjà en gardant l'état dans la classe d'importation, vous pouvez encapsuler la méthode toModels dans un trait et la réutiliser dans toutes vos exportations.

new UsersImport implements ToModel, WithHeadingRow
{
    use Importable;

    protected array $models;

    public function model(array $row)
    {
         $this->models[] = new User($row);
    }

    public toModels(string $filename): array
    {
       $this->import($filename);

        return $this->models;
    }
}
$nonPersistedUsers = (new UsersImport)->toModels('users.xlsx');
Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

matthewslouismarie picture matthewslouismarie  ·  3Commentaires

kurianic picture kurianic  ·  3Commentaires

ellej16 picture ellej16  ·  3Commentaires

amine8ghandi8amine picture amine8ghandi8amine  ·  3Commentaires

rossjcooper picture rossjcooper  ·  3Commentaires