Laravel-excel: [ПРЕДЛОЖЕНИЕ] Импортировать элементы без сохранения напрямую

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

Предпосылки

Версии

  • Версия PHP: 7.1.9
  • Версия Laravel: 5.7.19
  • Версия пакета: 3.0+

Описание

Импорт моделей должен быть возможен без их непосредственного сохранения. Также должна быть возможность вернуть что-либо, кроме моделей, из импорта.

В настоящее время я не могу обновиться с 2.1.30 до 3.0.0 или выше. Мне нужно иметь возможность импортировать набор моделей без их сохранения. Я использую это для тестов. Кроме того, у меня есть тест, в котором строка содержит информацию для создания двух связанных моделей (разных классов). В настоящее время у меня может быть только одна модель в строке. Реструктуризация CSV-файла здесь невозможна.

IMO 3.0.0+ слишком сфокусирован на идеальной ситуации, когда один файл CSV соответствует одной таблице, а одна строка соответствует одной модели, и каждая модель должна быть сохранена мгновенно. В 2.X этого не было, и я не знаю, почему это было изменено.

Обратите внимание, что я не хочу оставаться на 2.1.30, потому что для этого требуется брошенный пакет phpoffice/phpexcel .

Пример

К фасаду Excel следует добавить дополнительный метод, который имеет ту же сигнатуру, что и import , но возвращает модели вместо их сохранения. Пример:

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

Кроме того, к классам импорта следует добавить метод item , который может возвращать любой тип, а не только модели.

question

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

@WouterFlorijn, вы можете попробовать этот подход, чтобы получить массив из вашего файла:

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

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

Использование ToModel - это всего лишь один из способов борьбы с импортом. Это просто вариант, который упрощает вставку одной модели в строку.

Если вы хотите обрабатывать разные структуры и способом, аналогичным версии 2.1, вам нужно использовать ToCollection : https://laravel-excel.maatwebsite.nl/3.1/imports/collection.html В Метод сбора вы получите набор строк, аналогичный тому, который был у вас в 2.1.

Если вы хотите получить модели только в контроллере, а не в вашем объекте импорта (на самом деле не рекомендуемый подход), тогда есть метод ::toCollection , который возвращает необработанную строку (преобразование в модели не выполняется) вашему контроллеру. .
(https://laravel-excel.maatwebsite.nl/3.1/imports/basics.html#importing-to-array-or-collection)

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

@patrickbrouwers благодарит за ответ. Итак, если я правильно понимаю, использование Excel::import при импорте, которое реализует ToCollection , вернет коллекцию моделей без их сохранения? Если это так, то это четко не указано в документации, так как пример внизу https://laravel-excel.maatwebsite.nl/3.1/imports/collection.html выглядит следующим образом:

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

Возвращаемое значение нигде не сохраняется, подразумевая, что импортированная коллекция моделей сохраняется напрямую (или, по крайней мере, у метода есть побочные эффекты). Иначе было бы бесполезно вызывать import без присвоения возвращаемого значения переменной, верно?

@WouterFlorijn Нет, ::import() никогда не вернет никаких строк или моделей. Только Excel::toCollection() делает.

Использование ToCollection отличается от использования Excel::toCollection() .
При реализации ToCollection весь импорт инкапсулируется в объект Import. Возврат чего-либо в ToCollection не будет возвращен контроллеру.

@patrickbrouwers Просто вернусь, я все еще думаю, что мы не понимаем друг друга. Я просто ищу метод, который возвращает коллекцию моделей без их сохранения. Я не хочу обрабатывать строки в своем контроллере, я хотел бы сделать это в классе импорта. Пока я этого не нашел.

Идея:

ТранзакцииImport.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;
    }
}

ТранзакцииController.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. Он принимает аргумент импорта, который бесполезен в случаях, когда вы просто хотите вернуть строки как коллекции.

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

Возможно, эти документы будут вам полезны:
Самостоятельная работа с настойчивостью
Архитектурные концепции

@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 рейтинги

Смежные вопросы

rossjcooper picture rossjcooper  ·  3Комментарии

octoxan picture octoxan  ·  3Комментарии

contifico picture contifico  ·  3Комментарии

vandolphreyes picture vandolphreyes  ·  3Комментарии

ellej16 picture ellej16  ·  3Комментарии