将CSV文件导入Laravel控制器并将数据插入两个表

时间:2016-02-05 09:03:26

标签: php laravel csv laravel-5

所以我是Laravel的一个完整的菜鸟,我在这里尝试一些东西。我想将CSV文件导入到两个表中,我有一个名为lists的表,它将获取列表名称和client_id

然后我有一个名为customers的表,它将获得姓名联系号码以及client_idlist_id

我想要实现的是导入一个CSV文件,该文件将获取文件名并将其存储在列表中,然后通过CSV文件创建一个数组,并将数据导入到customers表中,其中包含列表和客户端ID& #39; S

我完成了第一部分,它正确地插入到列表中,我现在如何从存储/文档中的CSV创建一个数组,然后将其插入到customers表中?

namespace App\Http\Controllers;

use Input;
use DB;
use Illuminate\Http\Request;
use App\Http\Requests\ListsRequest;
use App\Lists;
use App\Clients;
use App\Http\Requests;
use App\Http\Controllers\Controller;

class ListsController extends Controller {

    public function index()
    {
        // $list_items = Lists::all();
        $clients = Clients::all();

        return view('lists.show', compact('clients'));
    }

    public function store(Requests\ListsRequest $request)
    {
        $input = $request->input();
        Lists::create($input);

        if (Input::hasFile('name'))
        {

            $file = Input::file('name');
            $name = time() . '-' . $file->getClientOriginalName();

            $path = storage_path('documents');

            $file->move($path, $name);

            // All works up to here
            // All I need now is to create an array
            // from the CSV and insert into the customers database
        }
    }
}

我选择使用我接受的答案,但我也使用了另一个答案并让它像这样工作。

public function store(Requests\ListsRequest $request)
{
    $input = $request->input();
    $client_id = $request->input('client_id');

    if (Input::hasFile('name'))
    {
        $file = Input::file('name');
        $name = time() . '-' . $file->getClientOriginalName();
        $path = storage_path('documents');

        Lists::create(['client_id' => $client_id, 'name' => $name]);

        $reader = Reader::createFromPath($file->getRealPath());
        // Create a customer from each row in the CSV file
        $headers = array();

        foreach ($reader as $index => $row)
        {
            if ($index === 0)
            {
                $headers = $row;
            } else
            {
                $data = array_combine($headers, $row);
                Customers::create($data);
            }
        }

        $file->move($path, $name);

        return view('clients');
    }
}

3 个答案:

答案 0 :(得分:27)

有三个步骤可以读取CSV文件并将其导入Laravel的数据库中。

  1. 阅读CSV文件
  2. 将其转换为数组
  3. 最后在我们的数据库中创建记录。
  4. 在开始之前,我已经创建了一个示例test.csv文件并将其放在我的公共文件夹下的文件夹中:

    name,email,password
    user1,email1@email.com,pasxxxxxxxxxword
    user2,email2@email.com,pasxxxxxxxxxword
    user3,email3@email.com,pasxxxxxxxxxword
    

    步骤1和2;我创建了一个名为csvToArray的辅助函数,我现在把它放在我的控制器中(这个函数的灵感来自于这个link)它只是读取CSV文件并将其转换为数组:

    function csvToArray($filename = '', $delimiter = ',')
    {
        if (!file_exists($filename) || !is_readable($filename))
            return false;
    
        $header = null;
        $data = array();
        if (($handle = fopen($filename, 'r')) !== false)
        {
            while (($row = fgetcsv($handle, 1000, $delimiter)) !== false)
            {
                if (!$header)
                    $header = $row;
                else
                    $data[] = array_combine($header, $row);
            }
            fclose($handle);
        }
    
        return $data;
    }
    

    第3步;这是我的最后一步,读取数组并将其插入我们的数据库中:

    public function importCsv()
    {
        $file = public_path('file/test.csv');
    
        $customerArr = $this->csvToArray($file);
    
        for ($i = 0; $i < count($customerArr); $i ++)
        {
            User::firstOrCreate($customerArr[$i]);
        }
    
        return 'Jobi done or what ever';    
    }
    
      

    注意:此解决方案假设您的Laravel项目中有一个模型,并且数据库中有正确的表。

    如果你使用dd($customerArr),你会得到这个 enter image description here

答案 1 :(得分:3)

@maytham Maytham的解决方案将很好地工作。但是,如果您要处理大数据,将会遇到很大的问题。即使执行1000行,也会产生问题,因为它将单独产生1000条插入语句。我将编辑他的第三种方法并添加我自己的输入

public function importCsv()
{
    $file = public_path('file/test.csv');

$customerArr = $this->csvToArray($file);
$date = [];
for ($i = 0; $i < count($customerArr); $i ++)
{
    $data[] = [
      'column_name1' => 'value',
      'column_name2' => 'value2',
      .. so..on..and..on
    ];
    //User::firstOrCreate($customerArr[$i]);
}
DB::table('table_name')->insert($data);
return 'Jobi done or what ever';    
}

这将调用数据库一次以插入所需的任意行。可以是1000、100000或其他任何值。 但是,如果您的csv很大,这也将是一个问题,因为您将需要插入多个块。就像在PostgreSQL中一样,我注意到您可以在一条语句中最多插入65000条行。也许我对数字有误,但每个数据库都有一个限制,您需要寻找这个限制。

答案 2 :(得分:2)

store()方法中,在lists表中创建记录,然后迭代CSV文件的内容并将数据插入customers表。为此,您应该在客户和列表之间创建relation。使用PHP League’s CSV package之类的东西来阅读这些文件会更好:

public function store(AddCustomersRequest $request)
{
    // Get uploaded CSV file
    $file = $request->file('csv');

    // Create list name
    $name = time().'-'.$file->getClientOriginalName();

    // Create a list record in the database
    $list = List::create(['name' => $name]);

    // Create a CSV reader instance
    $reader = Reader::createFromFileObject($file->openFile());

    // Create a customer from each row in the CSV file
    foreach ($reader as $index => $row) {
        $list->customers()->create($row);
    }

    // Redirect back to where you need with a success message
}