phpでcsvファイルを生成する[メモ]

前回の記事同様、最近仕事でcsvを使う場面が多かったので
自分用のメモとして書きます。よかったら参考にしてください。

集計とかする際にcsv出力は便利です。
今回は二部構成
#第一部　力技
タイトルの意味は後々わかります。
##csvを作る関数（力技ver）

```php:createCsv.php
// csvを作る関数（引数：csv用の配列、ファイル名）
function createCsv($data,$fileName){
  $dirPath = './AutoCreateCsv';
  if(!file_exists($dirPath)){
    mkdir($dirPath,0700);
  }
  $createCsvFilePath = $dirPath."/".$fileName.".csv";
  if(!file_exists($createCsvFilePath)){
    touch($createCsvFilePath);
  }
  $createCsvFile = fopen($createCsvFilePath, "w");
  if($createCsvFile){
    $csv = "";
    for($i = 0; $i < count($data); $i++){
      for($j = 0; $j < count($data[$i]); $j++){
        if($j == 0){
          $csv .= '"'.$data[$i][$j].'"';
        }else{
          $csv .= ',"'.$data[$i][$j].'"';
        }
      }
      $csv .= "\n";
    }
    fwrite($createCsvFile,$csv);
    fclose($createCsvFile);
  }
  // win用
  $createCsvFilePath .="for_win.csv";
  if(!file_exists($createCsvFilePath)){
    touch($createCsvFilePath);
  }
  $createCsvFileForWin = fopen($createCsvFilePath, "w");
  if($createCsvFileForWin){
    $csv = mb_convert_encoding($csv, "SJIS-win","UTF-8");
    fwrite($createCsvFileForWin,$csv);
    fclose($createCsvFileForWin);
  }
}
```
"**phpでcsvファイルを作る**"って検索したことある方ならみなさん思ってますよね
「いや、fputcsv使えよ」

自分はこう思ってました
『ダブルクォーテーションないの!?　ダメじゃね？』
結論だけいうと大丈夫みたいですね(笑)。

それと障害がもう一つ、みなさんおなじみのExcel
あれでひらくと日本語が入っていた場合文字化けしちゃうんですよね
なのでwindows用にもcsvを用意ということで
win用の記述がしてあります。
普通のものと違う点は、文字コード（正式には文字エンコーディングというらしいです）を変換する
`$csv = mb_convert_encoding($csv, "SJIS-win","UTF-8");`
です。初期値はUTF-8になっているみたいなので
windows用の **SJIS-win** に変換します
~~windows用に作るのか。なんて面倒くさいんだ...~~
みんなお世話になってますからこのくらいの手間は惜しんじゃダメですね。
##使い方
csvファイルにしたい連想配列とファイル名を引数で渡してください。
（普通の配列でも一応使えます）

```php:main.php
$data = array(
  array("area", "name", "opening_day"),
  array("トゥモローランド", "スペース・マウンテン", "1983-4-15"),
  array("ウエスタンランド", "ビッグサンダー・マウンテン", "1987-07-04"),
  array("クリッターカントリー", "スプラッシュ・マウンテン", "1992-10-1")
);

createCsv($data,'test');
```
##出力結果
```csv:test.csv
"area","name","opening_day"
"トゥモローランド","スペース・マウンテン","1983-4-15"
"ウエスタンランド","ビッグサンダー・マウンテン","1987-07-04"
"クリッターカントリー","スプラッシュ・マウンテン","1992-10-1"
```

```csv:test.csvfor_win.csv
"area","name","opening_day"
"�g�D�����[�����h","�X�y�[�X�E�}�E���e��","1983-4-15"
"�E�G�X�^�������h","�r�b�O�T���_�[�E�}�E���e��","1987-07-04"
"�N���b�^�[�J���g���[","�X�v���b�V���E�}�E���e��","1992-10-1"
```
※Excelで開けば大丈夫な感じに変換されました。

##createCsv関数(力技)の説明（興味ない人は読まなくて大丈夫です）
コメントアウトで行ごとに説明してます

```php:createCsv.php
// csvを作る関数（引数：csv用の配列、ファイル名）
function createCsv($data,$fileName){
  $dirPath = './AutoCreateCsv';                           //ディレクトリの設定
  if(!file_exists($dirPath)){                             //ディレクトリが存在しなければ
    mkdir($dirPath,0700);                                 //ディレクトリを作る（所有者だけフル権限）
  }
  $createCsvFilePath = $dirPath."/".$fileName.".csv";     //ファイル名と組み合わせてファイルパス 
  if(!file_exists($createCsvFilePath)){                   //ファイルが存在しなければ
    touch($createCsvFilePath);                            //ファイルを作る
  }
  $createCsvFile = fopen($createCsvFilePath, "w");        //ファイルをひらく（w:書き込みモード）
  if($createCsvFile){                                     //ちゃんと開けているかチェック
    $csv = "";                                            //最後に書き込むcsv用のテキスト
    for($i = 0; $i < count($data); $i++){                 //配列の個数ループ
      for($j = 0; $j < count($data[$i]); $j++){           //連想配列の個数ループ
        if($j == 0){                                      //連想配列:0番目の要素のとき
          $csv .= '"'.$data[$i][$j].'"';                  //「"」で括って追記
        }else{                                            //連想配列:0番目以外の要素のとき
          $csv .= ',"'.$data[$i][$j].'"';                 //「,」をつけ「"」で括って追記
        }
      }
      $csv .= "\n";                                       //1行終えたら改行コード
    }
    fwrite($createCsvFile,$csv);                          //作ったcsv用のテキストを書き込み
    fclose($createCsvFile);                               //ファイルを閉じる
  }
  // win用
  $createCsvFilePath .="for_win.csv";                     //さっき作ったファイルパスにfor_win.csvを追加
  if(!file_exists($createCsvFilePath)){                   //ファイルが存在しなければ
    touch($createCsvFilePath);                            //ファイルを作る
  }
  $createCsvFileForWin = fopen($createCsvFilePath, "w");  //ファイルをひらく（w:書き込みモード）
  if($createCsvFileForWin){                               //ちゃんと開けているかチェック
    $csv = mb_convert_encoding($csv, "SJIS-win","UTF-8"); //さっき作ったcsv用のテキストの文字コードを変換
    fwrite($createCsvFileForWin,$csv);                    //win用に変換したcsv用のテキストを書き込み
    fclose($createCsvFileForWin);                         //ファイルを閉じる
  }
}
```


#第二部　fputcsv
いよいよ本命のfputcsvです。
##csvを作る関数（fputcsv ver）

```php:createCsv.php
// csvを作る関数（引数：csv用の配列、ファイル名）
function createCsv($data,$fileName){
  $dirPath = './AutoCreateCsv';
  if(!file_exists($dirPath)){
    mkdir($dirPath,0700);
  }
  $createCsvFilePath = $dirPath."/".$fileName.".csv";
  if(!file_exists($createCsvFilePath)){
    touch($createCsvFilePath);
  }
  $createCsvFile = fopen($createCsvFilePath, "w");
  if ($createCsvFile) {
    foreach($data as $line){
      fputcsv($createCsvFile, $line);
    }
  }
  fclose($createCsvFile);

  // win用
  $createCsvFilePathForWin = $dirPath."/".$fileName."_for_win.csv";
  if(!file_exists($createCsvFilePathForWin)){
    touch($createCsvFilePathForWin);
  }
  $createCsvFileForWin = fopen($createCsvFilePathForWin, "w");
  if ($createCsvFileForWin) {
    foreach($data as $line){
      $lineForWin = mb_convert_encoding($line, "SJIS-win","UTF-8");
      fputcsv($createCsvFileForWin, $lineForWin);
    }
  }
  fclose($createCsvFile);
}
```

行数も少ないしこっちのほうが良さそうですよね
##使い方
csvファイルにしたい連想配列とファイル名を引数で渡してください。
（普通の配列でも一応使えます）

```php:main.php
$data = array(
  array("area", "name", "opening_day"),
  array("トゥモローランド", "スペース・マウンテン", "1983-4-15"),
  array("ウエスタンランド", "ビッグサンダー・マウンテン", "1987-07-04"),
  array("クリッターカントリー", "スプラッシュ・マウンテン", "1992-10-1")
);

createCsv($data,'test');
```
##出力結果
```csv:test.csv
area,name,opening_day
トゥモローランド,スペース・マウンテン,1983-4-15
ウエスタンランド,ビッグサンダー・マウンテン,1987-07-04
クリッターカントリー,スプラッシュ・マウンテン,1992-10-1
```

```csv:test_for_win.csv
area,name,opening_day
�g�D�����[�����h,�X�y�[�X�E�}�E���e��,1983-4-15
�E�G�X�^�������h,�r�b�O�T���_�[�E�}�E���e��,1987-07-04
�N���b�^�[�J���g���[,�X�v���b�V���E�}�E���e��,1992-10-1
```
力技のほうとの違いは "ダブルクォーテーション" の有無だけですね。
##createCsv関数(fputcsv)の説明（興味ない人は読まなくて大丈夫です）
コメントアウトで行ごとに説明してます

```php:createCsv.php
// csvを作る関数（引数：csv用の配列、ファイル名）
function createCsv($data,$fileName){
  $dirPath = './AutoCreateCsv';                                     //ディレクトリの設定
  if(!file_exists($dirPath)){                                       //ディレクトリが存在しなければ
    mkdir($dirPath,0700);                                           //ディレクトリを作る（所有者だけフル権限）
  }
  $createCsvFilePath = $dirPath."/".$fileName.".csv";               //ファイル名と組み合わせてファイルパス 
  if(!file_exists($createCsvFilePath)){                             //ファイルが存在しなければ
    touch($createCsvFilePath);                                      //ファイルを作る
  }
  $createCsvFile = fopen($createCsvFilePath, "w");                  //ファイルをひらく（w:書き込みモード）
  if($createCsvFile){                                               //ちゃんと開けているかチェック
    foreach($data as $line){                                        //配列を1つずつ取得
      fputcsv($createCsvFile, $line);                               //開いたファイルにいれていく
    }
  }
  fclose($createCsvFile);                                           //ファイルを閉じる

  // win用
  $createCsvFilePathForWin = $dirPath."/".$fileName."_for_win.csv"; //win用のファイルパスを設定
  if(!file_exists($createCsvFilePathForWin)){                       //ファイルが存在しなければ
    touch($createCsvFilePathForWin);                                //ファイルを作る
  }
  $createCsvFileForWin = fopen($createCsvFilePathForWin, "w");      //ファイルをひらく（w:書き込みモード）
  if ($createCsvFileForWin) {                                       //ちゃんと開けているかチェック
    foreach($data as $line){                                        //配列を1つずつ取得
      $lineForWin = mb_convert_encoding($line, "SJIS-win","UTF-8"); //文字コードを変換
      fputcsv($createCsvFileForWin, $lineForWin);                   //開いたファイルにいれていく
    }
  }
  fclose($createCsvFile);                                           //ファイルを閉じる
}
```

#感想
『ダブルクォーテーションないしwin用に変換しなきゃならんのかー』
→自分で作ったろ
=無駄骨だった気がしますね。

結論：fputcsv は便利