【问题标题】:How to skip blank rows in a csv file during import in Laravel如何在 Laravel 导入期间跳过 csv 文件中的空白行
【发布时间】:2020-05-20 00:28:44
【问题描述】:

在导入 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]
        ));
    }

【问题讨论】:

  • 为什么不检查插入数据库的 foreach 循环中的字段是否不为空?
  • 是的,谢谢,很抱歉不清楚。这就是我正在尝试做的事情,但它对我没有用,这就是我希望获得帮助的事情。

标签: laravel csv import


【解决方案1】:

我不相信这是正确的方法,我希望有人过来并给出正确的答案,但这是我的肮脏黑客。在我的数据集中,我有一个姓氏列,所有具有任何功能用途的记录都必须有一个姓氏,所以我放了一个 -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 中所有行的过程,无论它们是否有数据,但它只保存那些具有姓氏值的记录。这完成了我所需要的,但我知道必须有一种更清洁的方法来做到这一点。

我相信应该有一种方法可以做到这一点,其中只有当行/记录中的所有值都为空时才应该跳过记录。因此,如果有一个值,它将插入并创建一个条目,但如果一行中的所有值都是空的,它将跳过条目。希望有人会在某个时候出现并提供更雄辩的解决方案。

【讨论】:

    猜你喜欢
    • 2014-01-05
    • 1970-01-01
    • 2013-09-24
    相关资源
    最近更新 更多