【问题标题】:Import CSV file to Laravel controller and insert data to two tables将 CSV 文件导入 Laravel 控制器并将数据插入两个表
【发布时间】:2016-02-05 09:03:25
【问题描述】:

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

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

我想要实现的是导入一个 CSV 文件,该文件将获取文件名并将其存储在列表中,然后通过 CSV 文件创建一个数组,并将数据与列表和客户端 ID 一起导入到客户表中.

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

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');
    }
}

【问题讨论】:

  • 先看看这个stackoverflow.com/questions/21063008/…你不能像你那样直接插入数据库,如果链接没有提供帮助,请告诉我
  • 我现在正在尝试 :) 谢谢,稍后会告诉你进展如何
  • 好的,所以我尝试了上面编辑过的问题中看到的内容,但现在即使我只是在我拥有的地方返回“你好”,我也会得到空白屏幕
  • 您能帮忙解释一下我添加的区域的逻辑吗?
  • 一步一步解决问题很重要,所以如果它没有返回你好,这意味着它没有得到文件或者你的if语句返回false,试着写dd( $input) 在 if 语句之前查看您的控制器是否有生命并找出 $input 是否包含您期望的内容

标签: php laravel csv laravel-5


【解决方案1】:

在 Laravel 中读取 CSV 文件并将其导入数据库有 3 个步骤。

  1. 读取 CSV 文件
  2. 将其转换为数组
  3. 最后在我们的数据库中创建记录。

在我们开始之前,我已经创建了一个示例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),你会得到这个

【讨论】:

  • 我认为这是一个很好的方法。但是对于像 100 000 行这样的大型 CSV 呢?该数组将具有很大的大小,我可能会遇到内存 ram 的问题。
  • 这种情况下的标头取决于您在注释中提到的数据模型。在我的情况下,它是用户模型,它包含名称、电子邮件密码。你自己做,试一试。如果我误解了你,请告诉我。
  • @maytham-ɯɐɥʇʎɐɯ 你能告诉我,你在上传 csv 文件后如何加密密码?
  • @ToxifiedHashkey 我已经停止使用 laravel 几年了。但是 bcrypt 函数你可以用谷歌搜索它并找到一个 bcrypt 密码的函数。但是 $customerArr[$i] 是你导入的每个对象,你可以在概念上做一些事情,比如不测试和验证它。 $customerArr[$i]->password = bcryptFunction($customerArr[$i]->password) 这将用 bcrypted 密码覆盖文本密码。
  • @maytham-ɯɐɥʇʎɐɯ 非常感谢那个小费:D
【解决方案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
}

【讨论】:

  • 我使用了@maytham-ɯɐɥıλɐɯ 的函数来执行此操作,但我也尝试了您的答案以查看如何完成此操作,我正在编辑我的问题供您查看。
【解决方案3】:

@maytham Maytham 的解决方案效果很好。但是,如果您尝试处理大数据,它将有一个巨大的问题。即使你做了 1000 行,它也会产生问题,因为它会单独制作 1000 条插入语句。我将由他编辑第三种方法并添加我自己的输入

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

    $customerArr = $this->csvToArray($file);
    $data = [];
    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 行。也许我对这个数字有误,但每个数据库都有一个限制,你需要寻找它。

【讨论】:

  • 是的,这是一个很好的观点。如果您有一个大的 CSV 文件,在开始将数据插入数据库之前,您很可能无法将其全部存储在内存中的数组中,因此您需要在从 CSV 文件中读取数据时以块的形式插入数据.谢谢。
  • 正确。我还看到一次插入中的行数有限制。
猜你喜欢
  • 1970-01-01
  • 2019-02-21
  • 1970-01-01
  • 2015-12-06
  • 1970-01-01
  • 1970-01-01
  • 2020-03-06
  • 1970-01-01
  • 2018-03-20
相关资源
最近更新 更多