LoginSignup
3
3

More than 5 years have passed since last update.

PHPでのCSVファイル読み込みおよび配列化

Posted at

基盤系の開発などをしていると、売上データや顧客データなどが書かれたExcelファイルや、CSVファイルを読み込んで、DBに格納するというシーンがボチボチあるため、対応しやすいようQiitaにまとめておく。

環境

PHP 7.1.7
Laravel 5.6.33(pureでも問題ない、使うのはpure標準の関数だか開発した環境がたまたまLaravelだっただけ)
MySQL 5.7.22

使う主な関数

fopen()

第一引数に指定したファイルを第二引数で指定したファイルモードで開く。
今回の場合はCSVファイルを開くのに使用する。
ファイルモードに関してはドキュメントを参照するのが一番良いと思う。とりあえず今回使うのは、読み込み専用でファイルがなかった場合falseを返す、'r'となる。

ex.)
fopen('指定したファイル', 'ファイルモード');

fgetcsv()

引数に指定したfopen()関数を通過した後のCSVファイルを行ごとに配列化する。
fopen()関数を通したあとでないと使えないので注意

ex.)
fgetcsv(引数);

fclose()

引数に指定したファイルを閉じる。
今回はCSVファイルを閉じるのに使用する。

ex.)
fclose(引数);

手順

流れとしては、
①fopen()関数でCSVファイルを開く。
②CSVファイルをfgetcsv()関数で行ごとに抽出(行ごと抽出なので回数回してあげないと抽出できない)
③fclose()関数でCSVファイルを閉じる。
となる。

View側Formの内容に関しては詳しい話は省略するが、

ex.)
{!! Form::open(['route' => 'hoge.hoge', 'files' => true]) !!}
    {{Form::file('csvfile')}}
    {{Form::submit('送信')}}
{!! Form::close() !!}

こんな感じでしょう。type属性は'csvfile'としている。
またForm::open()メソッドの'files'キーを'true'にしておかないとファイルアップロードの対応をしてくれないので忘れずに:sweat_drops:
まずはCSVファイルを開いてあげる。

ex.)

public function hoge(Request $request)
{
    $input = $request->all(); 
    $csvfile = $input['csvfile']; 
    $importfile = fopen($csvfile, "r"); 
}

fopen()関数の第一引数にはformから送られてきたCSVファイルが代入されている'$csvfile'が,第二引数には読み込み専用のファイルモードが記述されている。
ちなみに今回はForm経由のCSVファイルを使っているわけだが、fopen()関数の第一引数に直接Pathを記述して指定することもできるので、もし挙動チェックなどをしたい場合などに使うと良いだろう。:relaxed:

続いて、fgetcsv()関数を用いてCSVファイルの行ごと取得を行っていく。

ex.)
while($line = fgetcsv($importfile)) {
    //headerのスキップ処理
    if($line[0] == 'id') {
      continue;
    }
    $importline = [
                      'hoge' => $line[1],
                      'fuga' => $line[2]                               
                  ];
    $array[] = $importline;
}

今回はwhile文で処理してみた。
注意点はCSVファイルだと大概「ヘッダー」(id,名前,年齢,性別的なやつ)が記述されているとおもうが、それも読み込んでしまうので条件式でスキップさせる必要がある。(上記ではfgetcsvで$lineに行の内容を配列として取得した際に、$line[0]がidという文字列だった場合、処理を飛ばしてあるが、ここは自分がクールだと思う方法で飛ばしてあげて良いと思う。。)
あとは$lineの内容を連想配列化し、その連想配列をさらに配列に入れ多次元配列化してあげる。この処理は$lineがfalseを返すまで繰り返される。

つづいてDBに格納する。:grin:

ex.)
    while() {
    ...
    }
    DB::insert($array);
    fclose($importfile);
}

DBへ格納する方法はいくつかあるとは思うが、今回注意なのはsave()メソッドを使うと最後尾の行しか反映されないので、insertメソッドで処理すると全行をDBへ保存できる。(DBの部分はDBファサードで置き換え、DBファサードはuseしておく必要があるので忘れずに)
最後にfclose()関数でCSVファイルを閉じてあげる。
あとはトップページなどにリダイレクトしてあげれば処理としては終了:sunny:
割と急ぎだったけどまとめとしてはこんな感じでしょうか:hugging:

まとめコード

全部まとめるとこんな感じ

ex.)
public function hoge(Request $request)
{
    $input = $request->all(); 
    $csvfile = $input['csvfile']; 
    $importfile = fopen($csvfile, "r"); 

    while($line = fgetcsv($importfile)) {
        //headerのスキップ処理
        if($line[0] == 'id') {
          continue;
        }
        $importline = [
                        'hoge' => $line[1],
                        'fuga' => $line[2]                               
                      ];
        $array[] = $importline;
    }
    DB::insert($array);
    fclose($importfile);
    return redirect()->to('遷移したいページ');
}
3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3