Импорт моделей должен быть возможен без их непосредственного сохранения. Также должна быть возможность вернуть что-либо, кроме моделей, из импорта.
В настоящее время я не могу обновиться с 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
, который может возвращать любой тип, а не только модели.
Использование 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
:
Я просто ищу метод, который возвращает коллекцию моделей без их сохранения. Я не хочу обрабатывать строки в своем контроллере, я хотел бы сделать это в классе импорта. Пока я этого не нашел.
Возможно, эти документы будут вам полезны:
Самостоятельная работа с настойчивостью
Архитектурные концепции
@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');
Самый полезный комментарий
@WouterFlorijn, вы можете попробовать этот подход, чтобы получить массив из вашего файла:
$array = Excel::toArray([], 'file.xlsx');