Laravel-excel: 【提案】直接保存せずにアイテムをインポートする

作成日 2019年01月24日  ·  9コメント  ·  ソース: Maatwebsite/Laravel-Excel

前提条件

バージョン

  • PHPバージョン:7.1.9
  • Laravelバージョン:5.7.19
  • パッケージバージョン:3.0以降

説明

モデルを直接保存しなくても、モデルをインポートできるはずです。 インポートからモデル以外のものを返すことも可能であるはずです。

現在、2.1.30から3.0.0以降にアップグレードできません。 モデルを保存せずにインポートできるようにする必要があります。 私はこれをテストに使用します。 また、(異なるクラスの)2つの関連モデルを作成するための情報が行に含まれているテストがあります。 現在、1行に1つのモデルしか持てません。 ここでは、CSVファイルを再構築することはできません。

IMO、3.0.0 +は、1つのCSVファイルが1つのテーブルに対応し、1つの行が1つのモデルに対応し、すべてのモデルを即座に保存する必要があるという理想的な状況に焦点を当てすぎています。 2.Xの場合はそうではなく、なぜ変更されたのかわかりません。

放棄されたphpoffice/phpexcelパッケージが必要なため、2.1.30に留まりたくないことに注意してください。

Excelファサードに追加のメソッドを追加する必要があります。これは、 importと同じ署名を持ちますが、モデルを保存する代わりに返します。 例:

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

さらに、インポートクラスにitemメソッドを追加する必要があります。このメソッドは、モデルだけでなく任意の型を返すことができます。

question

最も参考になるコメント

@WouterFlorijnこのアプローチを試して、ファイルから配列を取得できます。

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

全てのコメント9件

ToModelは、インポートを処理する1つの方法にすぎません。 これは、行ごとに1つのモデルを簡単に挿入できるようにするオプションです。

さまざまな構造をバージョン2.1と同様の方法で処理する場合は、 ToCollectionを使用する必要があります: https

インポートオブジェクトではなくコントローラーでのみモデルを取得する場合(実際には推奨されるアプローチではありません)、 ::toCollectionメソッドがあります。このメソッドは、生の行(モデルへの変換は行われません)をコントローラーに返します。 。
(https://laravel-excel.maatwebsite.nl/3.1/imports/basics.html#importing-to-array-or-collection)

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

@patrickbrouwersお返事ありがとうToCollectionを実装するインポートでExcel::importを使用すると、モデルを保存せずにモデルのコレクションが返されますか? その場合、 https

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

戻り値はどこにも保存されません。これは、インポートされたモデルのコレクションが直接保存されることを意味します(または、少なくともメソッドに副作用があることを意味します)。 そうでなければ、戻り値を変数に割り当てずにimportを呼び出すの

@WouterFlorijnいいえ、 ::import()は行やモデルを返すことはありません。 Excel::toCollection()がそうします。

ToCollection懸念事項を使用することは、 Excel::toCollection()を使用することとは異なります。
ToCollection実装すると、インポート全体がImportオブジェクト内にカプセル化されます。 ToCollection何かを返しても、コントローラーには返されません。

@patrickbrouwers戻って

アイデア:

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.
...

また、 toCollection関数に

  1. 単一のアイテムを含むコレクションを返します。これは、各行のコレクションを含む別のコレクションです。
  2. import引数を取ります。これは、行をコレクションとして返したい場合には役に立ちません。

私が単に探しているのは、モデルを保存せずにモデルのコレクションを返すメソッドです。 コントローラで行を処理したくないので、Importクラスで処理したいと思います。 今のところ私はこれを見つけていません。

おそらく、これらのドキュメントはあなたに役立ちます:
永続性を自分で処理する
アーキテクチャの概念

@WouterFlorijnこのアプローチを試して、ファイルから配列を取得できます。

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

@WouterFlorijnこのアプローチを試して、ファイルから配列を取得できます。

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

それがまさに私が探していたものです。

このリクエストの+1。 model()メソッドとcollection()メソッドは何も保存するべきではないと思います。 Excel / CSVファイルからモデル/配列のコレクション(または配列)にデータを返す必要があります。 永続性は個別に処理するか、少なくとも選択する必要があります。

私のユースケース:CSVのレコードから最小日と最大日を取得したい。 これが既存のインポートされたCSVと重複する場合、ユーザーが重複が正しいことを確認するまで、何もインポートしないでください。

編集:ああ、私は閉じた問題に対応しています。 この@WouterFlorijnをどのように処理しましたか?

インポートクラス内に状態を保持することで、これを自分で簡単に実現できます。 toModelsメソッドをトレイト内にラップして、すべてのエクスポートで再利用できます。

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');
このページは役に立ちましたか?
0 / 5 - 0 評価