CodeIgniterの学習 27 - CSVファイルをクエリから出力してみる。ついでにDB_utility.php内の出力形態の微調整

今日はCodeIgniterからCSVファイルの出力をしてみる。連携ファイルの出力とかで必要だよね。

昨日のエントリのsqlite3が結構重かったので今日は簡単なネタ。

マニュアルの通りにやれば一応CSV出力できるのだが、気に入らない箇所を微修正した(後述)。

出力の基本

出力自体は簡単なので、実験コード部分だけ貼る。ビューは省く。

詳しくはマニュアルとか見るべし。
コントローラ内:

<?php
//上略
//CSVファイルダウンロードのテスト
function downloadcsv(){

  //本当はここでも権限チェックを入れる

  //データベースユーティリティクラスのロード
  $this->load->dbutil();

  //ダウンロードヘルパのロード
  $this->load->helper('download');

  // データ取得
  //列名がヘッダになる
  $query = $this->db->query("SELECT id , title as 'タスク名' , note as '内容' , target_date as '完了予定日' , limit_date as '期限'  FROM tasklist");

  //csv形式に変換
  $csv =  $this->dbutil->csv_from_result($query); 

  //受け付けてくれるの普通はShift-JISだもんね
  $csv = mb_convert_encoding($csv,'Shift-JIS','UTF-8');

  //ファイル名
  $fname = 'hoge_'.date("ymdhi",time()).'.csv';
  
  //ファイルをダウンロードさせる
  force_download( $fname , $csv); 
}
//下略
 ?>

てな感じ、
$this->load->dbutil();と$this->load->helper('download');
を使って、
クエリをcsv_from_result()に渡してあげた後でforce_download()させればよい。


微修正前出力結果

ビュー側で、

<a href="/tasklist/downloadcsv/">CSVファイルのダウンロードテスト</a>

みたいにリンクを作ってダウンロードした結果はこんな感じ。

うむ、気に入らない。

ダブルクォートはちゃんと""ってエスケープしてくれてるけど、
行末のカンマはいらないでしょ。あとEOFのみの最終行もいらないよね。

↓のようになって欲しいのだ。


system/database/DB_utility.phpを微修正する

というわけで、微修正した。
(database以下はオーバーライドできないとか書いていた気がするので直接ファイルを修正した。)

system/database/DB_utility.php
元ソース(function csv_from_result部分):

<?php
//上略
function csv_from_result($query, $delim = ",", $newline = "\n", $enclosure = '"')
{
  //if ( ! is_object($query) OR ! method_exists($query, 'field_names'))
  if ( ! is_object($query) OR ! method_exists($query, 'list_fields'))  //Version 1.7.0で動くように変更
  {
    show_error('You must submit a valid result object');
  } 

  $out = '';
  
  // First generate the headings from the table column names
  foreach ($query->list_fields() as $name)
  {
    $out .= $enclosure.str_replace($enclosure, $enclosure.$enclosure, $name).$enclosure.$delim;
  }
  
  $out = rtrim($out);
  $out .= $newline;
  
  // Next blast through the result array and build out the rows
  foreach ($query->result_array() as $row)
  {
    foreach ($row as $item)
    {
      $out .= $enclosure.str_replace($enclosure, $enclosure.$enclosure, $item).$enclosure.$delim;
    }
    $out = rtrim($out);
    $out .= $newline;
  }
  return $out;
}
//下略
 ?>




修正ソース(function csv_from_result部分):

<?php
//上略
function csv_from_result($query, $delim = ",", $newline = "\n", $enclosure = '"')
{
  //if ( ! is_object($query) OR ! method_exists($query, 'field_names'))
  if ( ! is_object($query) OR ! method_exists($query, 'list_fields')) //Version 1.7.0で動くように変更
  {
    show_error('You must submit a valid result object');
  } 

  $out = '';
  
  // First generate the headings from the table column names
  foreach ($query->list_fields() as $name)
  {
    $out .= $enclosure.str_replace($enclosure, $enclosure.$enclosure, $name).$enclosure.$delim;
  }
  
  $out = rtrim($out);
  $out = rtrim($out,$delim);//改行直前のデリミタは不要なので除去する
  $out .= $newline;
  
  // Next blast through the result array and build out the rows
  foreach ($query->result_array() as $row)
  {
    foreach ($row as $item)
    {
      $out .= $enclosure.str_replace($enclosure, $enclosure.$enclosure, $item).$enclosure.$delim;
    }
    $out = rtrim($out);
    $out = rtrim($out,$delim);//改行直前のデリミタは不要なので除去する
    $out .= $newline;
  }
  $out = rtrim($out,$newline);//ファイル末尾の改行は不要なので除去する
  return $out;
}
//下略
 ?>




以上本日の修正おわり。

全然サンプルアプリがすすまないな。まあいいや。着実に飛び道具は揃いつつある。


(08/11/14変更 ソース内 field_names → list_fields と置換して、Version 1.7.0で動くようにした)