PHP Laravel:如何在将 xl/csv 导入 mysql 时避免重复数据?

Posted

技术标签:

【中文标题】PHP Laravel:如何在将 xl/csv 导入 mysql 时避免重复数据?【英文标题】:PHP Laravel : How to Avoid duplicate data while importing xl/ csv into mysql? 【发布时间】:2016-08-10 05:16:04 【问题描述】:

我想将 csv 文件导入数据库,其中名称应始终唯一意味着如果发现任何重复的标题,则应避开该行并转到下一行。 如何使用 Laravel Controller 实现?

这是我使用的导入 csv/xl 的控制器:

 public function importExcel()
    
        if(Input::hasFile('import_file'))
            $path = Input::file('import_file')->getRealPath();
            $data = Excel::load($path, function($reader) 
            )->get();
            if(!empty($data) && $data->count())
                foreach ($data as $key => $value) 
                    $insert[] = ['title' => $value->title, 'description' => $value->description];
                
                if(!empty($insert))
                    DB::table('items')->insert($insert);
                  //  dd('Insert Record successfully.');
                
            
        
        return back();    
    

【问题讨论】:

为什么要让它变得复杂? mysql 内置了处理 CSV 的工具 - 在文件中加载数据 我不清楚你的答案,请你详细说明一下? 阅读 mysql 的 LOAD DATA INFILE。关键是使用正确的工具完成工作 【参考方案1】:

对 Matt Borja 的 answer 进行了一些改进。这也将检查表中较早的数据。

public function importExcel()

    // Get current data from items table
    $titles = Item::lists('title')->toArray();

    if(Input::hasFile('import_file'))
        $path = Input::file('import_file')->getRealPath();
        $data = Excel::load($path, function($reader) 
        )->get();

        if(!empty($data) && $data->count())
            $insert = array();

            foreach ($data as $key => $value) 
                // Skip title previously added using in_array
                if (in_array($value->title, $titles))
                    continue;

                $insert[] = ['title' => $value->title, 'description' => $value->description];

                // Add new title to array
                $titles[] = $value->title;
            

            if(!empty($insert))
                DB::table('items')->insert($insert);
              //  dd('Insert Record successfully.');
            
        
    
    return back();    

【讨论】:

我已更改为您的代码,但出现以下错误:FatalThrowableError in ItemController.php line 89: Cannot access protected property Maatwebsite\Excel\Collections\RowCollection::$title It's in the line if (in_array($value->title, $titles)) 该错误是针对 $value->title 部分的,它实际上在您的原始代码中。这适用于您的代码,它无法从 excel 文件中访问标题值。 在本地检查了代码,它工作正常。没有收到类似的错误。【参考方案2】:

在将数据插入数据库之前,您可以对数组变量 $insert[] 应用 array_unique() 函数。它会返回给你唯一的数组。

或者使表中的列唯一,使其不能接受重复值。

【讨论】:

如果我将列键设置为唯一,我会在导入数据时看到唯一键约束错误,而我使用 array() 唯一但它显示数组到字符串转换错误!【参考方案3】:

我通常维护以前添加的项目的索引,如果我已经为它编制了索引,则跳过当前的迭代(重新添加)。

在您的示例中,大致如下:

 public function importExcel()
    
        // Index titles
        $titles = [];

        if(Input::hasFile('import_file'))
            $path = Input::file('import_file')->getRealPath();
            $data = Excel::load($path, function($reader) 
            )->get();

            if(!empty($data) && $data->count())
                foreach ($data as $key => $value) 

                    // Skip title previously added using array_key_exists or in_array
                    if (array_key_exists($value->title, $titles))
                        continue;

                    $insert[] = ['title' => $value->title, 'description' => $value->description];

                    // Index added title
                    $titles[$value->title] = true; // or array_push
                

                if(!empty($insert))
                    DB::table('items')->insert($insert);
                  //  dd('Insert Record successfully.');
                
            
        
        return back();    
    

【讨论】:

我已将其更改为您的代码,但它仍然在数据库中保留重复值! 好吧,如果它们以前是导入的,它并不意味着要清理它。此时我会进行一些“打印”调试以验证$insert[] 数组不包含任何重复的标题。我还将在此方法开头的某处将 $insert 初始化为一个空数组,以确保它不会拾取任何全局变量等。不过,如果您要清理以前导入的重复记录,一个好的开始可能审核这些记录:SELECT title, COUNT(*) AS total FROM items GROUP BY title ORDER BY total DESC

以上是关于PHP Laravel:如何在将 xl/csv 导入 mysql 时避免重复数据?的主要内容,如果未能解决你的问题,请参考以下文章

作曲家和 laravel 7 不适用于 php 8.1 [关闭]

Laravel 在 Doctype 之前显示一个空行

我在将 klaviyo 与 laravel 集成时遇到了这个错误

laravel-filemanager 在将应用程序从本地主机传输到实时主机后显示错误

如何在将文件包含在 PHP 中之前安全地评估文件的内容

Laravel - 使用 Redirect::route() 添加斜杠