Задача простая — загрузить CSV и разпарсить его. Кроме того нужно сохраните этот файл и сделать запись, каким пользователем это было сделано. Приступим.
Код метода в контроллере, я объясню его чуть ниже:
public function importProcess(UploadImportModelRequest $request)
{
$originalFile = $request->file('import_file');
$import = Import::create([
'filename' => $originalFile->getClientOriginalName(),
'user_id' => auth()->id(),
]);
$file = $import->addMediaFromRequest('import_file')
->toMediaCollection('imports');
$filename = storage_path('app/' . $file->id . '/' . $file->file_name);
$reader = new \SpreadsheetReader($filename);
foreach ($reader as $row) {
// Парсим строки...
}
}
Пояснение 1. Валидация FormRequest
Видите класс UploadImportModelRequest в параметрах? Это помогает нам проверить, существует ли файл, и является ли он CSV или TXT.
app/Http/Requests/UploadImportModelRequest.php:
class UploadImportModelRequest extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'import_file' => [
'required',
'file',
'mimes:csv,txt'
],
];
}
}
Пояснение 2. Загрузить файл при помощи Laravel MediaLibrary
Этот пакет для загрузки файлов в Laravel самый популярный и вот почему — вы можете сделать массу вещей всего всего лишь несколькими строками кода.
Но для начала нам нужно сохранить запись импорта и получить для нее объект модели Eloquent:
$originalFile = $request->file('import_file');
$import = Import::create([
'filename' => $originalFile->getClientOriginalName(),
'user_id' => auth()->id(),
]);
Поэтому мы сохраняем исходное имя файла, каким бы оно ни было, например «dummy import test.csv» или что-то в этом роде. Позже я покажу, почему этот «оригинал» важен.
Результатом этого Eloquent запроса является объект $import, и здесь пригодится Laravel MediaLibrary — одной строкой кода мы можем сохранить файл в папку, а также назначить этот файл объекту $import:
$file = $import->addMediaFromRequest('import_file')
->toMediaCollection('imports');
В результата имеем:
- Новая запись БД, хранящаяся в таблице «media» с именем файла и отношением к объекту $import;
- Папка, созданная в storage/app, с идентификатором этой «медиа» записи;
- Внутри этой новой папки хранится загруженный файл;
- Этот «медиа» объект возвращается в $file.
Пояснение 3. Получение РЕАЛЬНОГО имени файла и парсинг CSV
Важно, что Laravel MediaLibrary фактически переименовывает файл, чтобы сделать его «sluggable» (ЧПУ), поэтому фактическое имя файла отличается от исходного. Смотрите разницу в имени файла и записи в таблице БД «медиа»:

Вот почему нам нужно прочитать файл CSV с новым именем, хранящимся внутри объекта $file.
$filename = storage_path('app/' . $file->id . '/' . $file->file_name);
$reader = new \SpreadsheetReader($filename);
foreach ($reader as $row) {
// Парсим строки...
}
Как видите, мы теперь обращаемся к файлу как storage/[media.id]/[media.file_name].
В этом примере я не буду подробно разбирать парсинг CSV, поскольку он очень индивидуален, но я рекомендую использовать пакет Spreadsheet Reader — он довольно старый, но по некоторым причинам работает гораздо быстрее, чем Laravel Excel или другие.
Автор: Povilas Korop
Перевод: Алексей Широков
Наш Телеграм-канал — следите за новостями о Laravel.
