Как пропустить пустые строки в CSV-файле во время импорта в Laravel - PullRequest
0 голосов
/ 04 февраля 2020

Во время импорта файла CSV моя функция импорта создает запись базы данных для каждой строки файла импорта. Это означает, что если пользователь оставил пустую строку в файле, то процесс импорта создает пустую запись в базе данных. Как его разработать таким образом, чтобы импортер идентифицировал пустые / нулевые строки в CSV-файле, пропускал эти пустые / нулевые строки и создавал запись и импортировал строку только в том случае, если строка содержит данные?

Вот Контроллер для функции импорта:

public function process(Request $request)
    {
        $filename = $request->input('filename', false);
        $path = storage_path('app/csv_import/'.$filename);

        $hasHeader = $request->input('hasHeader', false);
        $isAddingNewReligiousBackground = $request->input('is_adding_new_religious_background', false);

        $fields = $request->input('fields', false);
        $fields = array_flip(array_filter($fields));

        $modelName = $request->input('modelName', false);
        $model = 'App\\'.$modelName;

        $reader = new SpreadsheetReader($path);
        $insert = [];
        $update = [];
        $tags = [];

        $team_id = $request->input('church_id');
        $custom_fields = CustomField::where('created_by_team_id', $team_id)->get();

        foreach ($reader as $key => $row) {
            if ($hasHeader && $key == 0) {
                continue;
            }

            $tmp = [];
            $meta = [];
            foreach ($fields as $header => $k) {
                $tmp[$header] = $row[$k];
            }

            $tmp['created_by_id'] = auth()->user()->id;
            $tmp['created_by_team_id'] = $team_id;
            $tmp['created_at'] = now();

            if ($modelName == 'Interest') {
                $this->translateReligiousBackgroud($tmp, $isAddingNewReligiousBackground);
                $meta = $this->processInterestMeta($tmp, $custom_fields);
                $existing = Interest::matchingInterest((object) $tmp, $request->input('church_id'));
                if ($existing) {
                    $update[] = $existing;
                    $tagsArr = array_filter((array) $request->input('interest_tags'));
                    foreach (\DB::table('interest_tag')->where('interest_id', $existing->id)->get() as $tag) {
                        $tagsArr[] = $tag->tag_id;
                    }
                    $existing->interest_tags()->sync(array_filter($tagsArr));
                    if (! empty($meta)) {
                        $existing->syncMeta($meta);
                    }
                } else {
                    $tmp['meta'] = $meta;
                    $insert[] = $tmp;
                }
            } else {
                $insert[] = $tmp;
            }
        }

        $for_insert = array_chunk($insert, 10000); // this was 100, but the chunking was causing the system to only import the first 100 records, even though the success message said it imported all of them - LW 1/25/2019
        foreach ($for_insert as $insert_item) {
            if ($modelName == 'Interest') {
                foreach ($insert_item as $item) {
                    $interest = new $model;
                    foreach ($item as $field => $value) {
                        if ($field != 'meta') {
                            $interest->$field = $value;
                        }
                    }
                    $interest->created_by_id = auth()->user()->id;
                    $interest->created_by_team_id = $request->input('church_id');
                    $interest->save();

                    // For some reason, created_by_team_id was null on initial save, do it again
                    $interest->created_by_team_id = $request->input('church_id');
                    $interest->save();

                    // deal with tags
                    $interest->interest_tags()->sync(array_filter((array) $request->input('interest_tags')));

                    // deal with custom fields
                    if (! empty($item['meta'])) {
                        $interest->syncMeta($item['meta']);
                    }
                }
            } else {
                $model::insert($insert_item);
            }
        }
        $rows = count($insert);
        $updates = count($update);
        $table = Str::plural($modelName);

        File::delete($path);

        $redirect = $request->input('redirect', false);

        return redirect()->to($redirect)->with('message', trans(($updates > 0 ? 'global.app_imported_rows_to_table_with_updates' : 'global.app_imported_rows_to_table'),
            ['rows' => $rows, 'updates' => $updates, 'table' => $table]
        ));
    }

1 Ответ

0 голосов
/ 06 февраля 2020

Я не верю, что это правильный путь, и я надеюсь, что кто-то придет и даст правильный ответ, но это мой грязный хак. В моем наборе данных у меня есть столбец для фамилии, и все записи, имеющие какое-либо функциональное назначение, должны иметь фамилию, поэтому я добавляю оператор -if- if (!empty($interest['lastname'])), проверяющий, чтобы "фамилия" не была пустой перед сохранением.

         $for_insert = array_chunk($insert, 10000); // this was 100, but the chunking was causing the system to only import the first 100 records, even though the success message said it imported all of them - LW 1/25/2019
        foreach ($for_insert as $insert_item) {
            if ($modelName == 'Interest') {
                foreach ($insert_item as $item) {
                    $interest = new $model;
                    foreach ($item as $field => $value) {
                        if ($field != 'meta') {
                            $interest->$field = $value;
                        }
                    }
                    $interest->created_by_id = auth()->user()->id;
                    $interest->created_by_team_id = $request->input('church_id');
                    if (!empty($interest['lastname']))
                    {
                        $interest->save();
                    }
                    // For some reason, created_by_team_id was null on initial save, do it again
                    $interest->created_by_team_id = $request->input('church_id');
                    if (!empty($interest['lastname']))
                    {
                        $interest->save();
                    } 

Таким образом, система проходит процесс импорта всех строк в CSV, независимо от того, имеют они данные или нет, но сохраняет только те записи, которые имеют значение фамилии. Это выполняет то, что мне нужно, но я знаю, что должен быть более чистый способ сделать это.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...