Задача простая — загрузить 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.