web-dev-qa-db-ja.com

CSVファイルをLaravelコントローラーにインポートし、2つのテーブルにデータを挿入します

だから私はLaravelに完全な初心者です。ここで何かを試してみます。CSVファイルを2つのテーブルにインポートしたいのですが、リストとテーブル名とclient_id

その後、client_idlist_idだけでなく、名前の姓の連絡先番号を取得するcustomersというテーブルがあります。

私が達成したいのは、ファイル名を取得してリストテーブルに保存する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');
    }
}
13
Devin Gray

CSVファイルを読み取り、Laravelのデータベースにインポートするには3つの手順があります。

  1. CSVファイルを読み取る
  2. 配列に変換する
  3. 最後に、データベースにレコードを作成します。

開始する前に、サンプル_test.csv_ファイルを作成し、それをファイルフォルダーの下のパブリックフォルダーに配置しました。

_name,email,password
user1,[email protected],pasxxxxxxxxxword
user2,[email protected],pasxxxxxxxxxword
user3,[email protected],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

store()メソッドで、listsテーブルにレコードを作成し、CSVファイルの内容を反復処理して、customersテーブルにデータを挿入します。この目的のために、顧客とリストの間に relation を作成する必要があります。また、 PHPリーグのCSVパッケージ のようなものを使用して、このようなファイルを読み取ることをお勧めします。

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
}
4
Martin Bean

@maytham Maythamのソリューションはうまく機能します。ただし、大きなデータを処理しようとすると、大きな問題が発生します。 1000行を実行しても、1000の挿入ステートメントを個別に作成するため、問題が発生します。彼による3番目のメソッドを編集して、独自の入力を追加します。

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

これは、データベースを1回呼び出して、必要な数の行を挿入します。 1000、100000、その他何でも。 ただし、巨大なcsvがある場合は、チャンクに挿入する必要があるため、これも問題になります。PostgreSQLのように、1つのステートメントに最大65000行を挿入できることに気付きました。私は数について間違っていますが、すべてのデータベースに制限があり、それを探す必要があります。

3
Koushik Das