StaticPagesisCSVData

提供: GeeklogJpWiki

CSVファイルにデータを追記,書き出されたファイルをtable組みで表示する2つのプログラムを開発中です。 ただいまこのページは書きかけです。開発にご協力いただける方はGeeklog.jp SNSにご参加ください。

目次

CSVファイルにデータを追記

静的ページPHPの問合せフォームで入力された情報を1行ずつ/system/data/内の指定のファイルに書き出します。

静的ページPHP

global $_CONF;   // config.phpの変数を参照可能にする

require_once ($_CONF['path'].'system/custom/phplib_outcsv.php');
$outfile = 'formmail.csv';//出力ファイル名

// $fld_listにデータをセット

/* ファイル書き込み*/
echo phplib_outcsv( $fld_list,$outfile,1);

phplib_outcsv.php

/system/custom/phplib_outcsv.phpに以下のプログラムを記述してアップします。

現在,このプログラムでは"をエスケープしていません。渡される配列に"は含まれていないことを前提にご利用ください。このプログラムは開発中です。

<?php
/* Reminder: always indent with 4 spaces (no tabs). */
// +---------------------------------------------------------------------------+
// | 機能  csv出力処理                                                         |
// |  SJISにエンコード変換しています。先頭にタイムスタンプをいれます。         |
// | 書式 echo phplib_outcsv( $textentry ,$outfile )                           |
// | 書式 echo phplib_outcsv( $textentry ,$outfile, 2 )                        |
// +---------------------------------------------------------------------------+
// | 引数 $textAry:出力テキストの配列                                          |
// |      $outfile:出力ファイル フォルダは$_CONF['path_data']                  |
// |      $outmode:出力モード 1:ファイルに出力 2:画面にも出力                  |
// | 戻値 nomal:出力モード2の時のみ 2csvの内容(エンコードは変換前)             |
// |      err  :エラーメッセージ                                               |
// +---------------------------------------------------------------------------+
// $Id: phplib-outcsv7.php
// 2007/08/14 16:19 tsuchi AT geeklog DOT jp http://www.geeklog.jp/

function phplib_outcsv( $textAry, $outfile, $outmode = 1 ) {
    global $_CONF;
    
    $retval  = '';
    $outfile = $_CONF['path_data'] . $outfile;

    if ( !is_array( $textAry ) ) {
        $textAry = (array) $textAry;
    }

    if ( !empty( $textAry ) ) {

	// タイムスタンプをデータの先頭に追加
        $timestamp = '"' . strftime( '%Y/%m/%d %T' );
        array_unshift( $textAry, $timestamp );

	// 配列をカンマ区切りで連結
        $textentry  = implode( '","', $textAry );

	// 文字列中の改行を"<br />"に変換
	$textentry = str_replace( array ( "\r\n", "\n", "\r" ), "<br />", $textentry);

	// エンコード変換
        $textentry  = str_replace(
            array ( '<?', '?>' ), array ( '(@', '@)' ), $textentry
        );
        $encode     = mb_detect_encoding( $textentry, "EUC-JP,UTF-8,JIS,SJIS" );
        $textentry2 = mb_convert_encoding( $textentry, "UTF-8", $encode );
        $textentry2 = str_replace(
            array ( '<?', '?>' ), array( '(@', '@)' ), $textentry2
        );
        // ファイルに書込み
        $file = @fopen( $outfile, 'ab' );
        if ( $file === false ) {
            $retval .= $outfile ." is not writable!<br />" . LB;
        } else {
            if ( @flock( $file, LOCK_EX ) === true ) {
                fputs( $file, $textentry2 . "\"\r\n" );
                @flock( $file, LOCK_UN );
            }
            @fclose( $file );

            if ( $outmode == 2 ) {//画面にも出力の時
                $retval = "<pre>" . $textentry . "\"</pre><br />" . LB;
            }
        }
    }

    return $retval;
}

?>

CSVファイルを表示

静的ページPHPでファイルを表示するシステムコマンドを実行して表示します。

この静的ページは,一般ユーザが実行できないよう,管理者のみ閲覧できるようにパーミッションを設定(3,2,0,0または3,3,0,0)してください。

事例1

CSVを,サイトとおなじエンコードで保存しておけば,catコマンドでタイプするだけで簡単に表示できます。

global $_CONF;   // config.phpの変数を参照可能にする

$inputfile =$_CONF['path_data'] .  'regist.csv';//入力ファイル名

system("cat " . $inputfile);

事例2

"予"、"表"などSJISで2バイト目が"5C"の文字で終わるデータに対して、fgetcsv() の不具合は依然解消されていないようです。
例えば"予算"はOK、"予算表"はNG。fgetcsv()を使用しない関数とその使用例は "CSV アプリケーション例" をご覧ください。

事例3

data/formmail.csvをテーブル組みで表示します。

fgetcsv()をSift-JISのファイルを読み込む場合には上記のような不具合があるので,書き出し時にUTF-8で書き出して読み込むなど,使用上注意が必要のようです。

※GeeklogをMS Windows上にインストールしている場合には文字化けします。

静的ページPHP

global $_CONF;

require_once $_CONF['path_system'] . 'custom/print_csv.php';
$retval = print_csv( $_CONF['path_data'] . 'formmail.csv' );
return $retval;

プログラム

system/custom/print_csv.php:

静的ページ:

UTF-8のファイルを指定して書き出します。

global $_CONF;

require_once $_CONF['path_system'] . 'custom/phplib_printcsv.php';
$retval = print_csv( $_CONF['path_data'] . 'regist.csv', 'UTF-8' );
return $retval;


system/custom/phplib_printcsv.php:

<?php

/**
* print_csv: 与えられたCVSファイルを読み込み,HTMLに整形して返す
*
* 注意:MS Windowsでは,ロケールの関係で文字化けします。
*
* @author: mystral-kk - geeklog AT mystral-kk DOT net
*
* @param $filename       : string - CSVファイル名
* @param $input_encoding : string - CSVファイルのエンコーディング(オプション)
* @param $output_encoding: string - HTMLのエンコーディング(オプション)
* @param $header         : array of string - 行見出し(オプション)
*
* @return: mixed: string - 整形されたHTML
*                 false  - CSVファイルを開けない
*/
function print_csv( $filename, $input_encoding = 'SJIS', $output_encoding = 'UTF-8',
	$header = array () ) {
	global $_CONF;
	
	if ( !defined( 'LB' ) ) {
		define( 'LB', "\n" );
	}
	
	// スタイル
	$style_table   = '';	// <table style="foo: bar;">
	$style_caption = '';	// <caption style="foo:bar;">
	$style_tr      = '';	// <tr style="foo:bar;">
	$style_th      = ' sty;e="background-color: #507AA1;';	// <th style="foo: bar;">
	$style_row     = array ();
	$style_row[0]  = ' style="background-color: #E7E7E7;"';	// <td>偶数行
	$style_row[1]  = ' style="background-color: #F7F7F7;"';	// <td>奇数行
	
	// CSVファイルの内容を事前にエンコード変換
	$contents = file_get_contents( $filename );
	if ( $contents === false ) {
		echo "Cannot open \"{$filename}\".<br>" . LB;
		return false;
	}
	
	$tempfile = tempnam( $_CONF['path_data'], 'csv' );
	if ( $tempfile === false ) {
		echo 'Cannot create a temporary file.  Please see if Geeklog\'s data directory ($_CONF["path_data"]) is writable.<br>' . LB;
		return false;
	}
	
	$contents = mb_convert_encoding( $contents, $output_encoding, $input_encoding );
	$fh = @fopen( $tempfile, "w+b" );
	if ( $fh === false ) {
		echo "Cannot open the temporary file.<br>" . LB;
		@unlink( $tempfile );
		return false;
	} else {
		fwrite( $fh, $contents );
		rewind( $fh );
	}
	
	// 出力開始
	$display = "<table{$style_table}>" . LB;

	// <caption>を作成
	$info = pathinfo( $filename );
	$caption = "<caption{$style_caption}>[{$info['basename']}";
	if ( !empty( $info['extesion'] ) ) {
		$caption .= '.' . $info['extension'];
	}
	$caption .= ']</caption>' . LB;
	$display .= $caption;
	
	// (あれば)ヘッダ行を追加
	if ( is_array( $header ) && count( $header ) != 0 ) {
		$display .= "<tr{$style_tr}>" . LB;
		
		foreach ( $header as $h ) {
			$display .= "<th{$style_th}>" . htmlspecialchars( $h, ENT_QUOTES, $output_encoding ) . '</th>' . LB;
		}
		
		$display .= '</tr>' . LB;
	}
	
	// データ出力
	$row = 0;

	while ( ( $line = fgetcsv( $fh, 4096 ) ) !== false ) {
		$display .= "<tr{$style_tr}>" . LB;
		
		foreach ( $line as $field ) {
			if ( empty( $field ) ) {
				$field = ' ';
			} else {
				$filed = htmlspecialchars( $field, ENT_QUOTES, $output_encoding );
			}
			$display .= "<td{$style_row[$row]}>" . $field . '</td>' . LB;
		}
		
		$display .= '</tr>' . LB;
		$row = ( $row == 0 ) ? 1 : 0;
	}
	
	fclose( $fh );
	@unlink( $tempfile );
	$display .= '</table>' . LB;
	return $display;
}

?>

CSV アプリケーション例

  • 作者 shindo(Jinger James Japayuki)

アンケートフォームなどで必要な[入力][確認][完了]画面を1つのテンプレートから生成し、投稿データを(Geeklog_system)/data/ に保存。その内容を[表示]または CSV ファイルを[ダウンロード]する部分までを一連の処理として作ってあります。
動作確認は

 [開発]WinXPsp2
  +Apache2.2.2
  +PHP4.4.2-pl1
  +Zen_Cart_on_Geeklog_jp_1.4.1_20070415
 [確認]Linux
  +Apache1.3.27
  +PHP5.1.2
  +Zen_Cart_on_Geeklog_jp_1.4.1_20070415
 [確認]FedoraCore1
  +Apache2.0.47 
  +PHP4.3.3
  +geeklog_jp_1.4.1_20070312

で行いましたが、恐らくまだ多数のバグを抱えています。
各関数のスイッチなども、すべての動作を確認しているわけではありません。参考程度にお考えください。

静的ページ登録

静的ページとして以下の6つを登録してください。
[入力画面]ID:gl_csv_enter

global $_CONF;

$disp_mode = 'enter';
require_once ( $_CONF['path_html'].'staticpages/gl_csv_form.php' );

[確認画面]ID:gl_csv_confirm

global $_CONF;

$disp_mode = 'confirm';
require_once ( $_CONF['path_html'].'staticpages/gl_csv_form.php' );

[完了画面]ID:gl_csv_finish

global $_CONF;

$disp_mode = 'finish';
require_once ( $_CONF['path_html'].'staticpages/gl_csv_form.php' );

[一覧表示]ID:gl_csv_display_1

global $_CONF;

require_once ($_CONF['path'].'system/custom/phplib_gl_csv.php');

// 表組みデータ CSV ファイル
$csv_fn = $_CONF['path_data'] . 'gl_csv.csv';
// 表組みテンプレートファイル
$tpl_fn = $_CONF['path_html'] . 'staticpages/gl_csv_table.tpl';

$html_output = get_table ( $csv_fn, $tpl_fn );

print $html_output;

[一覧表示(縦組)]ID:gl_csv_display_2
[2007/08/28 追加] 今回の例のように1行の項目数が多く、横スクロールの必要が生じる場合などにはこちらの方が見やすいレイアウトになります。

global $_CONF;

require_once ($_CONF['path'].'system/custom/phplib_gl_csv.php');

// 表組みデータ CSV ファイル
$csv_fn = $_CONF['path_data'] . 'gl_csv.csv';
// 表組みテンプレートファイル
$tpl_fn = $_CONF['path_html'] . 'staticpages/gl_csv_table.tpl';

$html_output = get_table ( $csv_fn, $tpl_fn, 2 );

print $html_output;

[ダウンロード]ID:gl_csv_download
[2007/09/02 追加] エンコードを変更して CSV ファイルをダウンロード

global $_CONF;

require_once ($_CONF['path'].'system/custom/phplib_gl_csv.php');

// 表組みデータ CSV ファイル名を設定
$csv_fn = $_CONF['path_data'] . 'gl_csv.csv';
download_csv ( $csv_fn, 'SJIS' );

画面遷移と保存

上記登録内容でもお判りかと思いますが、画面遷移+保存作業の実体は gl_csv_form.php に記載されています。
これを Geeklog インストール html ディレクトリの /staticpages/ に置いてください。
[2007/08/28 追加] 確認画面を単独で呼び出すと保存データを破壊するバグを修正
gl_csv_form.php

<?php
/* copyright (c) 2007/09/01 Jinger James Japayuki ******************************/

/********************************************************************************
 ■ /staticpages/index.php から呼ばれた場合
    1.$_SESSION[ 'gl_csv_form_mode' ] = 'entry'
          入力画面を表示
    2.$_SESSION[ 'gl_csv_form_mode' ] = 'confirm'
          セッション変数からデータを読み出し
          フォーム要素に値をセットして確認画面を表示
    3.$_SESSION[ 'gl_csv_form_mode' ] = 'finish'
          セッション変数からデータを読み出し、
          値をファイルに保存して完了画面を表示
 ■ フォームからの送信先として POST データを受け取った場合
    1.$_SESSION[ 'gl_csv_form_mode' ] = 'confirm'
          セッション変数に値をセットし確認画面に移動
    2.$_SESSION[ 'gl_csv_form_mode' ] = 'finish'
          完了画面に移動
 ■ 改訂履歴
    2007/09/02 ver1.5 CSV ファイルのダウンロード機能追加
    2007/09/01 ver1.4 確認画面でフォーム要素を取り去るオプション($flg_form)を追加
             これに伴い HTML 要素解析、タグ要素解析、タグ生成関数追加
    2007/08/28 ver1.3 POST データの変換対象特殊文字に'¥'('&yen'に変換)を追加
    2007/08/28 ver1.2 完了画面を単独で呼び出した場合に保存データを破壊するバグを修正
    2007/08/28 ver1.1 静的ページ縦組み表示関数を追加
    2007/08/28 ver1.0 初版登録

********************************************************************************/
require_once ( '../lib-common.php' );
require_once ( $_CONF['path'].'system/custom/phplib_gl_csv.php' );

session_start();
if ( !isset ( $_SESSION['gl_csv_form_mode'] ) ) {
 $_SESSION['gl_csv_form_mode'] = 'enter';
 $_SESSION['gl_csv_form_key']  = '""';
 $_SESSION['gl_csv_form_val']  = '""';
}

// 最低限必要な要素名をセット(テンプレートとの一致必須)------------------------
$form_name   = 'gl_csv';
$keys_name   = 'h_gl_csv_keys';
$submit_name = 'b_gl_csv_01';
$html_split  = '<!-- __for_php_splitter__ -->';    // 今回は使ってません

$csv_fn      = $_CONF['path_data'] . 'gl_csv.csv'; // データ保存ファイル名
$tpl_fn      = 'gl_csv_form.tpl';                  // フォームテンプレート名
$php_fn      = 'gl_csv_form.php';                  // フォーム送信先(このファイル)
$str_cr      = '<br   />';                         // 改行コード置換文字列
$flg_form    = false;                              // 確認画面を form にしない
$page_id['enter']    = 'gl_csv_enter';             // 静的ページ入力画面 ID
$page_id['confirm']  = 'gl_csv_confirm';           // 静的ページ確認画面 ID
$page_id['finish']   = 'gl_csv_finish';            // 静的ページ完了画面 ID
$page_id['disp01']   = 'gl_csv_display_1';         // 静的ページ横組み表示 ID
$page_id['disp02']   = 'gl_csv_display_2';         // 静的ページ縦組み表示 ID
$page_id['download'] = 'gl_csv_download';          // CSV ダウンロード ID

$btn_target   = 'type="submit" name="' . $submit_name . '" ';
$btn_enter    = 'value="確認画面へ" />'."\n"
              . '<input type="reset" name="b_gl_csv_02" value="リセット"';
$btn_confirm  = 'value="送信" />'."\n"
              . '<input type="button" name="b_gl_csv_02" value="戻る"'
              . ' onclick="javascript:history.go(-1)"';
$btn_finish   = '<button name="' . $submit_name . '"' . "\n"
              . ' onclick="javascript:location.href='
              . "'index.php?page=" . $page_id['enter'] . "';"
              . '">入力画面に戻る</button>'."\n"
              . '<button name="to_display"' . "\n"
              . ' onclick="javascript:location.href='
              . "'index.php?page=" . $page_id['disp01'] . "';"
              . '">一覧表示</button>'."\n"
              . '<button name="to_display"' . "\n"
              . ' onclick="javascript:location.href='
              . "'index.php?page=" . $page_id['disp02'] . "';"
              . '">一覧縦組み表示</button>'."\n"
              . '<button name="to_display"' . "\n"
              . ' onclick="javascript:location.href='
              . "'index.php?page=" . $page_id['download'] . "';"
              . '">データ ダウンロード</button>'."\n";


// 処理振り分け *****************************************************************
if ( isset ( $_POST[ $keys_name ] ) ) {

 // POST 受取り処理 -------------------------------------------------------------
 $ary_form = get_post ( $str_cr );
 switch ( $_SESSION[ 'gl_csv_form_mode' ] ) {
  case 'enter' :
   set_formdata ( $ary_form );
   $_SESSION[ 'gl_csv_form_mode' ] = 'confirm';
   break;
  case 'confirm' :
   if ( $flg_form ) set_formdata ( $ary_form );
   $_SESSION[ 'gl_csv_form_mode' ] = 'finish';
   break;
  case 'finish' :
  default :
   $_SESSION[ 'gl_csv_form_mode' ] = 'enter';
   break;
 }
 $target_uri = 'index.php?page=' . $page_id[ $_SESSION['gl_csv_form_mode'] ];
 header ( "Location: $target_uri" );
 // ---------------------------------------------------- POST 受取り処理 ここまで

} else {
// index.php からの呼出し処理 ---------------------------------------------------
 $_SESSION[ 'gl_csv_form_mode' ] = $disp_mode;
 if ( $disp_mode ) $ary_form = get_formdata ();

// テンプレート読み込み
 $html_output = get_html ( $tpl_fn );

// フォームの送信先設定
 $str_target  = 'name="' . $form_name . '" action="';
 $str_newval  = $str_target . $php_fn;
 $html_output = str_replace ( $str_target, $str_newval, $html_output );

// $disp_mode による処理の振り分け --------------------------
 switch ( $disp_mode ) {

// 入力画面モード -------------------------------------------
  case 'enter' :

   // 送信ボタンの処理
   $html_output = str_replace ( $btn_target, $btn_target.$btn_enter, $html_output );
   break;

// 確認画面モード -------------------------------------------
  case 'confirm' :
   // 送信ボタンの処理
   $html_output = str_replace ( $btn_target, $btn_target.$btn_confirm, $html_output );
   // フォーム要素の内容を入力データに置換
   $html_output = show_data ( $ary_form, $html_output, $keys_name, $flg_form, $str_cr );
   break;
 
// 完了画面モード -------------------------------------------
  case 'finish' :
   // 保存したい要素名を配列に保存
   $ary_save_name = make_name_array ( $ary_form[ $keys_name ] );
   // データ保存
   if ( count ( $ary_save_name ) != 1 and $ary_save_name[0] != '' ) {
    append_csv ( $csv_fn, $ary_form, $ary_save_name );
   }
   // セッションデータ破棄
   unset ( $_SESSION[ 'gl_csv_form_mode' ] );
   unset ( $_SESSION[ 'gl_csv_form_key' ] );
   unset ( $_SESSION[ 'gl_csv_form_val' ] );
   // フォーム要素など削除
   $html_output = $btn_finish;
   break;

  default : break;
 }

 print $html_output;

}
// ------------------------------------------ index.php からの呼出し処理 ここまで
// ------------------------------------------------------------------------------
?>

テンプレート

投稿フォーム用と一覧表示用の2種を gl_csv_form.php と同様 /staticpages/ に置いてください。
[フォームテンプレート]gl_csv_form.tpl
※本来<body>タグ内に<style>タグを記述するのは、HTML仕様上正しくありませんが、 ie6、ff1.5、ff2.0、safari3betaで表示確認をしています。

// copyright (c) 2007/08/24 Jinger James Japayuki *******************************
//[使用法]---------------------------------------------------------------------
// 1. テンプレート内の PHPコメント行 '//' は HTML に出力されません。
// 2. フォームの各要素は、その種類で name 属性の接頭辞に下記を使ってください。
//      text     : t_
//      password : p_
//      radio    : r_
//      checkbox : c_
//      select   : s_
//      textarea : a_
//      hidden   : h_
//      button   : b_
// 3. 下記要素については1行で表記してください。
//      <input type="radio" ....>
//      <input type="checkbox" ....>
//      <option>....</option>
// 4. 各要素にデフォルト値を持たせることはできません。
// 5. '<input type="submit" name="b_gl_csv_01" />' を送信等のボタンに置換します。
//[使用法]ここまで ------------------------------------------------------------
//
// この3行は変更しないでください
<!-- gl_csv_form.tpl { -->
<form id="gl_csv" name="gl_csv" action="" method="post">
<input type="hidden" name="h_gl_csv_mode" />
//
// この要素は必要に応じて value を変えてください(消してもOK)。
<input type="hidden" name="h_gl_csv_encoding" value="utf-8" />
//
// この要素には定型保存したい要素名をカンマ区切りで列挙してください。
// 同じ name 属性のチェックボックスは配列の個数-1の値を入れてください。
<input type="hidden" name="h_gl_csv_keys"
 value="t_gl_csv_01, p_gl_csv_01, r_gl_csv_01, c_gl_csv_s01[2], c_gl_csv_d01,
        c_gl_csv_d02, c_gl_csv_d03, s_gl_csv_01, s_gl_csv_02,a_gl_csv_01" />
//
// 以下自由に編集してください ---------------------------------------------------
<style>
td {
 border:1px solid #cccccc;
}
.noborder {
 border:0px solid #cccccc;
}
</style>
<table>
 <tr>
  <td>テキスト入力</td>
  <td>
<input type="text" name="t_gl_csv_01" size="60" />
  </td>
 </tr>
 <tr>
  <td>パスワード</td>
  <td>
<input type="password" name="p_gl_csv_01" size="60" />
  </td>
 </tr>
 <tr>
  <td>ラジオボタン</td>
  <td>
<input type="radio" id="r01" name="r_gl_csv_01" value="1" />
 <label for="r01">ラジオボタン1</label><br />
<input type="radio" id="r02" name="r_gl_csv_01" value="2" />
 <label for="r02">ラジオボタン2</label><br />
<input type="radio" id="r03" name="r_gl_csv_01" value="3" />
 <label for="r03">ラジオボタン3</label><br />
  </td>
 </tr>
 <tr>
  <td>チェックボックス<br />(同じ name 属性)</td>
  <td>
<input type="checkbox" id="cs01" name="c_gl_csv_s01[]" value="1" />
 <label for="cs01">チェックボックス1</label><br />
<input type="checkbox" id="cs02" name="c_gl_csv_s01[]" value="2" />
 <label for="cs02">チェックボックス2</label><br />
<input type="checkbox" id="cs03" name="c_gl_csv_s01[]" value="3" />
 <label for="cs03">チェックボックス3</label><br />
  </td>
 </tr>
 <tr>
  <td>チェックボックス<br />(違う name 属性)</td>
  <td>
<input type="checkbox" id="cd01" name="c_gl_csv_d01" value="1" />
 <label for="cd01">チェックボックス1</label><br />
<input type="checkbox" id="cd02" name="c_gl_csv_d02" value="2" />
 <label for="cd02">チェックボックス2</label><br />
<input type="checkbox" id="cd03" name="c_gl_csv_d03" value="3" />
 <label for="cd03">チェックボックス3</label><br />
  </td>
 </tr>
 <tr>
  <td>プルダウンリスト<br />( value 属性なし)</td>
  </td>
  <td>
<select name="s_gl_csv_01">
 <option>-- 選択してください --</option>
 <option>選択肢 1</option>
 <option>選択肢 2</option>
 <option>選択肢 3</option>
 <option>選択肢 4</option>
 <option>選択肢 5</option>
</select>
  </td>
 </tr>
 <tr>
  <td>プルダウンリスト<br />( value 属性あり)</td>
  </td>
  <td>
<select name="s_gl_csv_02">
 <option value="0">-- 選択してください --</option>
 <option value="1">選択肢 1</option>
 <option value="2">選択肢 2</option>
 <option value="3">選択肢 3</option>
 <option value="4">選択肢 4</option>
 <option value="5">選択肢 5</option>
</select>
  </td>
 </tr>
 <tr>
  <td>複数行テキスト入力</td>
  <td>
<textarea name="a_gl_csv_01" cols="60" rows="5"></textarea>
  </td>
 </tr>
 <tr>
// この要素は基本的に消さないで!
  <td colspan="2"><input type="submit" name="b_gl_csv_01" /></td>
 </tr>
</table>
// 自由編集領域 ここまで -------------------------------------------------------
</form>
<!-- } gl_csv_form.tpl -->

[表示テンプレート]gl_csv_table.tpl
※本来<body>タグ内に<style>タグを記述するのは、HTML仕様上正しくありませんが、 ie6、ff1.5、ff2.0、safari3betaで表示確認をしています。

// copyright (c) 2007/08/24 Jinger James Japayuki *******************************
// 1. テンプレート内の PHPコメント行 '//' は出力されません
// 2. 要素の開始タグ
//     '<table>','<tr>','<th>','<td>'
//    は1行あたり1つだけ表記してください。
// 3. 各 class 名を変更すると、不具合が生じるかもしれません。
<!-- gl_csv_table.tpl { -->
<style type="text/css">
.gl_csv_table_01 {
 background     : #ffcccc;
 border         : solid 1px #990000;
}
.gl_csv_tr_th_01 {
 vertical-align : middle;
}
.gl_csv_th_01 {
 background     : #eeffee;
 border         : solid 1px #009900;
}
.gl_csv_tr_td_01 {
 vertical-align:top;
}
.gl_csv_td_01 {
 background     : #eeeeff;
 border         : solid 1px #000099;
}
</style>
<table class="gl_csv_table_01">
 <tr class="gl_csv_tr_01">
  <th class="gl_csv_th_01"></th>
 </tr>
 <tr class="gl_csv_tr_02">
  <td class="gl_csv_td_01"></td>
 </tr>
</table>
<!-- } gl_csv_table.tpl -->

関数ライブラリ

Geeklog システムディレクトリ /system/custom/ に置いてください。
[2007/08/28 追加] POST データの変換対象特殊文字に'¥'('&yen;'に変換)を追加
[2007/09/01 追加] 確認画面でフォーム要素を取り去るオプション($flg_form)を追加。HTML 要素解析、タグ要素解析、タグ生成関数追加
[2007/09/02 追加] csv ファイルのダウンロード関数追加
phplib_gl_csv.php

<?php
/* copyright (c) 2007/09/02 Jinger James Japayuki ******************************/

// テンポラリファイルに対する入出力 *********************************************

// POST データを整形して戻す ----------------------------------------------------
// 2段目のループは同名チェックボックスと multpul プルダウン対策
function get_post ( $str_cr ) {

 foreach ( $_POST as $key=>$val ) {
  $loop_max_val = count ( $val );
  if ( !is_array ( $val ) ) {
   $ary_data[ $key ] = $val;
  } else {
   for ( $i=0; $i<$loop_max_val; $i++ ) {
    $str_key = $key . "[$i]";
    $ary_data[ $str_key ]= $val[$i];
   }
  }
 }
 $ary_data = escape_data ( $ary_data, $str_cr );

 return $ary_data;

}


// $ary_data の key と val を $tmp_fn に保存 ------------------------------------
function set_formdata ( $ary_data ) {

 $str_key = '"';
 $str_val = '"';
 foreach ( $ary_data as $key=>$val ) {
  $str_key .= $key . '","';
  $str_val .= $val . '","';
 }
 $str_key = ereg_replace ( ',"$', '', $str_key );
 $str_val = ereg_replace ( ',"$', '', $str_val );

 $_SESSION[ 'gl_csv_form_key' ] = $str_key;
 $_SESSION[ 'gl_csv_form_val' ] = $str_val;

 return true;

}


// $tmp_fn から key と val を取り出し連想配列を戻す -----------------------------
function get_formdata () {

 if ( $_SESSION[ 'gl_csv_form_key' ] == '' ) return $ary_form;

 $key = ereg_replace ( '^"', '', $_SESSION[ 'gl_csv_form_key' ] );
 $key = mb_substr ( $key , 0, mb_strlen ( $key ) - 1 );
 $ary_key = explode ( '","', $key );

 $val = ereg_replace ( '^"', '', $_SESSION[ 'gl_csv_form_val' ] );
 $val = mb_substr ( $val , 0, mb_strlen ( $val ) - 1 );
 $ary_val = explode ( '","', $val );

 $i = 0;
 foreach ( $ary_key as $val ) {
  $ary_data[ $val ] = $ary_val[$i];
  $i++;
 }

 return $ary_data;

}


// フォーム要素置換関数群 *******************************************************

// 送信データを HTML に埋め込み -------------------------------------------------
function show_data ( $ary_form, $html_output, $keys_name,
                     $flg_form = false, $str_cr = '<br />' ) {

 foreach ( $ary_form as $key=>$val ) {
  $type_element = substr ( $key, 0, 2 );
  switch ( $type_element ) {
   case 't_' : // テキスト
   case 'p_' : // パスワード
   case 'h_' : // ヒドゥン
    if ( $key == $keys_name ) break;
    $html_output = form_t_replace ( $key, $val, $html_output, $flg_form );
    break;
   case 'r_' : // ラジオボタン
   case 'c_' : // チェックボックス
    $html_output = form_r_replace ( $key, $val, $html_output, $flg_form );
    break;
   case 's_' : // プルダウン ※ multipul 非対応
    $html_output = form_s_replace ( $key, $val, $html_output, $flg_form );
    break;
   case 'a_' : // テキストエリア( $str_cr は省略可能)
    $html_output = form_a_replace ( $key, $val, $html_output, $flg_form, $str_cr );
    break;
   default : break;
  }
 }

 if ( !$flg_form ) {
  $html_output = delete_radios_checks_labels( $html_output );
 }

 return $html_output;
}


// テキスト・パスワード・ヒドゥン -----------------------------------------------
function form_t_replace ( $key, $val, $html_output, $flg_form ) {
 if ( $flg_form ) {
  $ary_target['name']  = $key;
  $ary_newval['value'] = $val;
  $html_output = html_replace ( $ary_target, $ary_newval, $html_output );
 } else {
  if ( $val == '' ) $val = ' ';
  $html_output = mb_ereg_replace (
   '<input[^>]* name="'.$key.'.*?>', $val, $html_output );
 }

 return $html_output;
}

// チェックボックス・ラジオボタン -----------------------------------------------

function form_r_replace ( $key, $val, $html_output, $flg_form ) {
 if ( $flg_form ) {
  // 同一 name 属性を持つチェックボックス用処理
  $key = mb_ereg_replace ( '\[[[:digit:]]+\]', '[]', $key );

  $ary_target  = array ( 'name'=>$key, 'value'=>$val );
  $ary_newval['checked'] = 'checked';
  $html_output = html_replace ( $ary_target, $ary_newval, $html_output );
 } else {

  // 同一 name 属性を持つチェックボックス用処理
  $key = mb_ereg_replace ( '\[[[:digit:]]+\]', '', $key );

  $int_pos = 0;
  while ( $int_pos = mb_strpos ( $html_output, 'name="'.$key, $int_pos ) ) {
   mb_ereg ( '<input[^>]*? name="'.$key.'.*?>', $html_output, $ary_tag );
   if ( mb_strpos ( $ary_tag[0], $val ) ) {
    $html_output = str_replace ( $ary_tag[0], $val.'<br />', $html_output );
   } else {
    $html_output = str_replace ( $ary_tag[0], '', $html_output );
   }
   $int_pos ++;
  }
 }

 return $html_output;
}

// プルダウンメニュー -----------------------------------------------------------
function form_s_replace ( $key, $val, $html_output, $flg_form ) {
 if ( $flg_form ) {
  $ary_target  = array ( 'name'=>$key, 'value'=>$val );
  $ary_newval['selected'] = 'selected';
  $html_output = html_replace ( $ary_target, $ary_newval, $html_output );
 } else {
  $html_output = mb_ereg_replace (
   '<select[^>]* name="'.$key.'.*?/select>', $val, $html_output );
 }

 return $html_output;
}

// テキストエリア ---------------------------------------------------------------
function form_a_replace ( $key, $val, $html_output, $flg_form, $str_cr ) {
 if ( $flg_form ) {
  $ary_target['name']  = $key;
  $ary_newval['value'] = str_replace ( $str_cr, "\n", $val );
  $html_output = html_replace ( $ary_target, $ary_newval, $html_output );
 } else {
  if ( $val == '' ) $val = ' ';
  $html_output = mb_ereg_replace (
   '<textarea[^>]* name="'.$key.'.*?>.*?</textarea>',
   $val, $html_output );
 }

 return $html_output;
}

// 不必要な radio, checkbox, label を削除 ---------------------------------------
function delete_radios_checks_labels ( $html_output ) {

 // 'type=radio' を含むタグの削除
 $html_output = mb_ereg_replace (
  '[[:space:]]*<[^>]*type="radio"[^>]*>',
  ' ', $html_output );

 // 'type=checkbox' を含むタグの削除
 $html_output = mb_ereg_replace (
  '[[:space:]]*<[^>]*type="checkbox"[^>]*>',
  ' ', $html_output );

 // <label>タグの削除
 $html_output = mb_ereg_replace (
  '[[:space:]]*<label[^>]*'.$ary_id[1].'.*?/label>[^<,^>]*(<br[^>]*>)*',
  '', $html_output );

 return $html_output;
}

// 保存対象要素名を配列に保存 ---------------------------------------------------
function make_name_array ( $str_key_name ) {
 if ( $str_key_name == '' ) return '';
 // trim () がうまくいかないので str_replace () で代用
 $str_key_name = str_replace ( ' ', '', $str_key_name );
 $str_key_name = str_replace ( array ( "\r\n", "\r", "\n" ), '', $str_key_name );
 $ary_key_name = explode ( ',', $str_key_name );
 $i = 0;
 foreach ( $ary_key_name as $val ) {
  if ( $int_start = strpos ( $val, '[' ) ) {
   if ( $int_stop = strpos ( $val, ']' ) ) {
    $loop_max = substr ( $val, $int_start + 1, $int_stop - $int_start - 1 ) + 1;
    for ( $j=0; $j<$loop_max; $j++ ) {
     $ary_save_name[$i] = substr ( $val, 0, $int_start + 1 ) . $j . ']';
     $i++;
    }
   }
  } else {
   $ary_save_name[$i] = $val;
   $i++;
  }
 }

 return $ary_save_name;

}


// テーブル表示関数 *************************************************************


// 配列を表組み出力 -------------------------------------------------------------
// $csv_fn     : 表組みデータ CSV ファイル フルパス
// $tbl_fn     : 表組みテンプレートファイル フルパス
// $flg_header : ヘッダ行出力(デフォルト:出力する)
// $row_max    : 表示する表の最大行数(デフォルト:100行)
function get_table ( $csv_fn, $tbl_fn, $tbl_type = 1, $flg_header = true, $row_max = 100 ) {

 $ary_data = get_csv ( $csv_fn );
 $ary_html = file ( $tbl_fn ) or
  die ( "function get_html エラー:$str_html_fn が開けません。" );

 $html_output = '';
 // 'bcc' means 'block comment close'
 $tag = array ( 'table'=>'', 'trh'=>'', 'trd'=>'', 'td'=>'', 'bcc'=>'' );

 // テンプレートから <table><tr><th><td> 要素を抜き出す
 foreach ( $ary_html as $val ) {
  $val  = mb_ereg_replace ( '^ +<', '<', $val );
  $cap2 = substr ( $val, 0, 2 );
  if ( $cap2 != '//' ) {
   $cap3 = substr ( $val, 0, 3 );
   switch ( $cap3 ) {
    case '<ta' :
     $tag['table'] = get_html_tag ( $val );
     break;
    case '<tr' :
     if ( $tag['trh'] == '' ) {
      $tag['trh'] = get_html_tag ( $val );
     } else {
      $tag['trd'] = get_html_tag ( $val );
     }
     break;
    case '<th' :
     $tag['th'] = get_html_tag ( $val );
    case '<td' :
     $tag['td'] = get_html_tag ( $val );
    case '</t' :
     break;
    default :
     $cap6 = substr ( $val, 0, 6 );
     if ( $cap6 == '<!-- }' ) {
      $tag['bcc'] = $val;
     } else {
      $html_output .= $val;
     }
     break;
   }
  }
 }

 $int_row_max = count ( $ary_data );
 if ( $int_row_max == 0 ) return '';
 if ( $int_row_max >= $row_max ) $int_row_max = $row_max;

 switch ( $tbl_type ) {
  // 通常 ---------------------------------------------------
  case 1 :
   $html_output .= $tag['table'] . "\n";
   for ( $i=0; $i<$int_row_max; $i++ ) {
    if ( $flg_header ) {
     $tag_key = 'h';
     $flg_header = false;
    } else {
     $tag_key = 'd';
    }
    $html_output .= $tag[ 'tr'.$tag_key ] . "\n";
    foreach ( $ary_data[$i] as $val ) {
     if ( $val == '' ) $val = ' ';
     $html_output .= $tag[ 't'.$tag_key ] . $val . '</td>' . "\n";
    }
    $html_output .= '</tr>' . "\n";
   }
   $html_output .= '</table>' . "\n";
   $html_output .= $tag['bcc'] . "\n";
   break;

  // コラム数が多いときなど ---------------------------------
  case 2 :
   $rowspan = count ( $ary_data[0] ) - 1;
   $html_output .= $tag['table'] . "\n";
   if ( $flg_header ) {
     $loop_start = 1;
     $str_add[0] = $ary_data[0][0] . '<br />';
     $str_add[1] = $tag['th'] . $ary_data[0][1] . '</th>'."\n";
   }
   for ( $i=$loop_start; $i<$int_row_max; $i++ ) {
    // 1・2個目のセル
    $html_output .= $tag['trd'] . "\n";
    $td_span = str_replace ( '<th', '<th rowspan="' . $rowspan . '"', $tag['th'] );
    $html_output .= $td_span;
    $html_output .= $str_add[0] . array_shift ( $ary_data[$i] ) . '</th>'."\n";
    $html_output .= $str_add[1]
                  . $tag['td'] . array_shift ( $ary_data[$i] ) . '</td>'."\n";
    $html_output .= '</tr>'."\n";
    if ( $rowspan > 2 ) {
     // 3個目のセル以降
     $int_header = 2;
     foreach ( $ary_data[$i] as $val ) {
      $html_output .= $tag['trd'] . "\n";
      if ( $flg_header ) {
       $html_output .= $tag['th'] . $ary_data[0][$int_header] . '</th>'."\n";
      }
      if ( $val == '' ) $val = ' ';
      $html_output .= $tag['td'] . $val . '</td>'."\n";
      $html_output .= '</tr>'."\n";
      $int_header ++;
     }
    }
   }
   $html_output .= '</table>'."\n";
   $html_output .= $tag['bcc'] . "\n";
   break;

  default : break;
 }

 return $html_output;

}


// HTML 置換関数群 **************************************************************


// HTML 文字列内の特定タグを新しい値で書き換える --------------------------------
function html_replace ( $ary_target, $ary_newval, $str_html ) {

 // HTML 文字列をパースし、バラされた要素ごとに処理
 $ary_html = parse_html ( $str_html );
 $loop_max = count ( $ary_html );
 for ( $i=0; $i<$loop_max; $i++ ) {
  $flg_match = true;
  if ( mb_substr ( $ary_html[$i], 0, 1 ) == '<' ) {
   $ary_info = info_tag ( $ary_html[$i] );
   if ( $ary_info['name'] == $ary_target['name'] ) {
    switch ( $ary_info['tag'] ) {
     case 'select' :
      // select は別処理
      while ( mb_substr ( $ary_html[$i+1], 0, 8 ) != '</select' ) {
       $ary_info = info_tag ( $ary_html[$i+1] );
       if ( $ary_info['value'] == $ary_target['value'] ) {     // value があれば
        $ary_html[$i+1] = make_tag ( $ary_info, $ary_newval );
       } else if ( $ary_html[$i+2] == $ary_target['value'] ) { // value がなければ
        $ary_html[$i+1] = make_tag ( $ary_info, $ary_newval );
       }
       $i++;
      }
      break;
     case 'textarea' :
      // textarea は別処理
      $ary_html[$i] .= $ary_newval['value'];
      while ( mb_substr ( $ary_html[$i+1], 0, 10 ) != '</textarea' ) {
       $ary_html[$i+1] = '';
       $i++;
      }
      break;
     default :
      // select, textarea 以外のタグ
      foreach ( $ary_target as $key=>$val ) {
       if ( $ary_info[$key] != $val ) {
        $flg_match = false;
       }
      }
      if ( $flg_match ) {
       $ary_html[$i] = make_tag ( $ary_info, $ary_newval );
      }
      break;
    }
   }
  }
 }

 $html_output = '';
 foreach ( $ary_html as $val ) $html_output .= $val;

 return $html_output;

}

// 既存のタグ要素を新しい値で置き換えたHTMLタグを生成 ---------------------------
function make_tag ( $ary_orgval, $ary_newval ) {
 $ary_newtag = array_merge ( $ary_orgval, $ary_newval );
 // 属性名="値" の形でなくてもよいタグ
 $ary_attr = array ( 'checked', 'compact', 'declare', 'defer', 'disabled',
                     'ismap', 'multiple', 'noresize', 'noshade', 'nowrap',
                     'readonly', 'selected');
 // 閉じタグの必要がないタグ
 $ary_slash = array ( 'area', 'base', 'basefont', 'br', 'col', 'frame', 'hr',
                      'img', 'input', 'isindex', 'link', 'meta', 'param');

 $str_tag = '<';

 foreach ( $ary_newtag as $key=>$val ) {
  if ( $key == 'tag' ) {
   $str_tag .= $val . ' ';
  } else {
   $flg_attr = true;
   if ( $val == '' ) {
    foreach ( $ary_attr as $attr_key=>$attr_val ) {
     if ( $key == $attr_key ) $flg_attr = false;
    }
   }
   if ( $flg_attr ) $str_tag .= $key . '="' . $val . '" ';
  }
 }

 // 単独で使われるタグは閉じる前に '/' を追加
 $flg_slash = false;
  foreach ( $ary_slash as $val ) {
   if ( $ary_newtag['tag'] == $val ) $flg_slash = true;
  }
 if ( $flg_slash ) $str_tag .= '/';

 $str_tag .= '>';

 return $str_tag;

}

// HTML 文字列をパースして配列を戻す --------------------------------------------
// コンテンツに'<'を使うと誤動作します
function parse_html ( $str_html ) {
 $pos = 0;
 $i   = 0;
 $loop_max = mb_strlen ( $str_html );
 $ary_element[0] = '';
 $flg_tag = false;

 for ( $j=0; $j<$loop_max; $j++ ) {
  $char = mb_substr ( $str_html, $pos, 1 );
  switch ( $char ) {
   case '<' :
    if ( $flg_tag ) break;
    if ( mb_substr ( $str_html, $pos-1, 1 ) != '>' ) $i++;
    $ary_element[$i] = $char;
    if ( mb_substr ( $str_html, $pos, 4 ) == '<!--' ) break;
    $flg_tag = true;
    break;
   case '>' :
    $ary_element[$i] .= $char;
    if ( mb_substr ( $str_html, $pos-2, 3 ) == '-->' ) break;
    $i++;
    break;
   default :
    $ary_element[$i] .= $char;
    $flg_tag = false;
  }
  $pos++;
 }

 return $ary_element;
}

// HTML タグの属性名を key にした配列を戻す -------------------------------------
function info_tag ( $str_tag ) {
 $str_tag = trim ( $str_tag );
 if ( mb_substr ( $str_tag, 0, 1 ) != '<' or
      mb_strpos ( $str_tag, '<', 1 ) or
      mb_substr ( strrev ( $str_tag ), 0, 1 ) != '>' or
      mb_strpos ( strrev ( $str_tag ), '>', 1 )
 ) return false;

 // checked, selected など、属性名なしの属性を処理
 $ary_attr = array ( 'checked', 'compact', 'declare', 'defer', 'disabled',
                     'ismap', 'multiple', 'noresize', 'noshade', 'nowrap',
                     'readonly', 'selected');
 foreach ( $ary_attr as $val ) {
  $str_tag = mb_eregi_replace ( '[^=,^\"]'.$val, $val.'='.$val, $str_tag );
 }

 // 属性名・属性値以外の文字を削除
 $str_tag = mb_ereg_replace ( '[ ,\t,\r,\n,>,/,\",\']+', ' ', $str_tag );
 $str_tag = mb_ereg_replace ( ' *= *', '=', $str_tag );
 $str_tag = trim ( $str_tag );

 $ary_tag = explode ( ' ', $str_tag );
 foreach ( $ary_tag as $val ) {
  if ( mb_substr ( $val, 0, 1 ) == '<' ) {
   $attr_name = 'tag';
   $attr_val  = mb_strtolower ( ltrim ( $val, '<' ) );
  } else {
   $ary_attr  = explode ( '=', $val );
   $attr_name = mb_strtolower ( $ary_attr[0] );
   $attr_val  = $ary_attr[1];
  }
  $ary_info[ $attr_name ] = $attr_val;
 }

 return $ary_info;

}

// HTML ファイルを文字列として読み込み ------------------------------------------
// file_get_contents() が使えない環境(PHP4.3未満)対策
function get_html ( $str_html_fn ) {

 $ary_html = file ( $str_html_fn ) or
  die ( "function get_html エラー:$str_html_fn が開けません。" );
 $str_html = '';
 foreach( $ary_html as $val ) {
  if ( mb_substr ( ltrim ( $val ), 0, 2 ) != '//' ) $str_html .= $val;
 }

 return $str_html;

}

// 与えられた文字列からタグ部分を抜き出して返す ---------------------------------
function get_html_tag ( $str_html, $start_pos = 0 ) {
 if ( !is_bool ( $int_open_pos = strpos ( $str_html, '<', $start_pos ) ) ) {
  if ( $int_close_pos = strpos ( $str_html, '>', $int_open_pos ) ) {
   return substr ( $str_html, $int_open_pos, $int_close_pos - $int_open_pos +1 );
  }
 }

 return false;

}


// ファイル操作等汎用関数群 *****************************************************


// CSV ファイルのダウンロード ---------------------------------------------------
function download_csv ( $str_fn, $coding = 'SJS' ) {
 $ary_data = file ( $str_fn ) or 
  die ( "function download_csv エラー:$str_fn が開けません。" );
 if ( mb_strtoupper ( $coding ) != mb_internal_encoding () ) {
  foreach ( $ary_data as $i=>$val ) {
   $ary_data[$i] = mb_convert_encoding ( $val, $coding, mb_internal_encoding () );
  }
 }
 $str_fn = basename ( $str_fn );
 header ( 'Content-type: application/octet-stream;' );
 header ( 'Content-disposition: attachment; filename=' . $str_fn );
 foreach ( $ary_data as $val ) {
  print $val;
 }

 exit;

}


// フォームデータ内の改行や [ ", <, >, \ ] を変換 -------------------------------
// ただし 要素名が 'h_' で始まるものは半角スペースと改行のみ削除
//
// この関数内では文字'&gt;','&lt;','&amp;','&yen;'等を使っているため、投稿時に
// 手作業で'&'を'&amp;' に書き換えていますが、修正モレがあるかもしれません。
// コピペの際にはご注意ください。
function escape_data ( $ary_data, $str_cr ) {

 if ( !is_array ( $ary_data ) ) return $ary_data;

 $loop_max = count ( $ary_data );
 $ary_keys = array_keys ( $ary_data );
 for ( $i=0; $i<$loop_max; $i++ ) {
  if ( substr ( $ary_keys[$i], 0, 2 ) != 'h_' ) {
   $ary_data[ $ary_keys[$i] ] = str_replace ( '\"', '&quot;', $ary_data[ $ary_keys[$i] ] );
   $ary_data[ $ary_keys[$i] ] = str_replace ( '"',  '&quot;', $ary_data[ $ary_keys[$i] ] );
   $ary_data[ $ary_keys[$i] ] = str_replace ( "\\\\", '&yen;', $ary_data[ $ary_keys[$i] ] );
   $ary_data[ $ary_keys[$i] ] = preg_replace ( '/\x5c/', '&yen;', $ary_data[ $ary_keys[$i] ] );
   $ary_data[ $ary_keys[$i] ] = str_replace ( '<', '&lt;', $ary_data[ $ary_keys[$i] ] );
   $ary_data[ $ary_keys[$i] ] = str_replace ( '>', '&gt;', $ary_data[ $ary_keys[$i] ] );
   $ary_data[ $ary_keys[$i] ] = str_replace ( array ( "\r\n","\r","\n" ),
                                              $str_cr, $ary_data[ $ary_keys[$i] ] );
  } else {
   $ary_data[ $ary_keys[$i] ] = str_replace ( ' ', '', $ary_data[ $ary_keys[$i] ] );
   $ary_data[ $ary_keys[$i] ] = str_replace ( array ( "\r\n","\r","\n" ),
                                              '', $ary_data[ $ary_keys[$i] ] );
  }
 }

return $ary_data;

}

// 1次元配列を CSV 形式ファイルに追加保存 --------------------------------------
// モードの指定は
//  'p' :末尾に保存(デフォルト)         'np' :先頭に保存
//  'd' :タイムスタンプあり(デフォルト) 'nd' :タイムスタンプなし
//  'h' :ヘッダあり(デフォルト)         'nh' :ヘッダなし
function append_csv ( $str_fn, $ary_data, $ary_save_name, $mode = '-t-d-h' ) {

 // 第4引数によるモード設定
 $push_mode = true;
 $date_mode = true;
 $head_mode = true;
 if ( strpos ( $mode, '-np' ) ) $push_mode = false;
 if ( strpos ( $mode, '-nd' ) ) $date_mode = false;
 if ( strpos ( $mode, '-nh' ) ) $head_mode = false;

 // 第3引数が配列でない場合は $ary_data の $key で代用
 if ( !is_array ( $ary_save_name ) ) {
  $i = 0;
  foreach ( $ary_data as $key=>$val ) {
   $ary_save_name[$i] = $key;
  }
 }
 $loop_max = count ( $ary_save_name );

 // タイムスタンプ
 if ( $date_mode ) {
  $ary_datetime = getdate();
  $str_date  = $ary_datetime[year] . '/';
  $str_date .= sprintf( '%02d', $ary_datetime[mon] ) . '/';
  $str_date .= sprintf( '%02d', $ary_datetime[mday] ) . ' ';
  $str_date .= sprintf( '%02d', $ary_datetime[hours] ) . ':';
  $str_date .= sprintf( '%02d', $ary_datetime[minutes] ) . ':';
  $str_date .= sprintf( '%02d', $ary_datetime[seconds] );
 } else {
  $str_date = '';
 }

 // ヘッダ文字列
 if ( $head_mode ) {
  if ( $date_mode ) {
   $str_head = '"datetime","';
  } else {
   $str_head = '"';
  }
  for ( $i=0; $i<$loop_max; $i++ ) {
   $str_head .= $ary_save_name[$i] . '","';
  }
  $str_head = ereg_replace ( ',"$', '', $str_head );
 }

 // 書き込むデータ配列を文字列に変換
 if ( $date_mode ) {
  $str_data = '"' . $str_date . '","';
 } else {
  $str_data = '"';
 }

 for ( $i=0; $i<$loop_max; $i++ ) {
  $flg_match = false;

  foreach ( $ary_data as $key=>$val ) {
   if ( !is_array ( $val ) ) {
    //通常(配列でない)データの処理
    if ( $ary_save_name[$i] == $key ) {
     $str_data .= $val . '","';
     $flg_match = true;
    }
   } else {
    // 配列用処理
    $loop_max_val = count ( $val );
    for ( $j=0; $j<$loop_max_val; $j++ ) {
     if ( $ary_save_name[$i] == $key . "[$j]" ) {
      $str_data .= $val[$j] . '","';
      $flg_match = true;
     }
    }
   }
  }

  if ( !$flg_match ) $str_data .= '","';
 }
 $str_data = ereg_replace ( ',"$', '', $str_data );

 // CSV ファイル読み込み、ヘッダがあれば削除してから新データを付加
 if ( file_exists ( $str_fn ) ) {
  if ( filesize ( $str_fn ) > 2 ) {
   $ary_org_data = file ( $str_fn ) or
    die ( "function append_csv エラー:$str_fn が読み込み時に開けません。" );
   if ( $head_mode ) array_shift ( $ary_org_data );
  } else {
   $ary_org_data = array ();
  }
 } else {
  $ary_org_data[0] = '';
 }
 if ( $push_mode ) {
  array_push ( $ary_org_data, $str_data . "\n" );
 } else {
  array_unshift  ( $ary_org_data, $str_data . "\n" );
 }
 if ( $head_mode ) array_unshift ( $ary_org_data, $str_head . "\n" );

 // ファイルに保存
 $fh = fopen ( $str_fn, 'w' ) or
  die ( "function append_csv エラー:$str_fn が書き込み時に開けません。" );
 flock ( $fh , LOCK_EX );
  foreach ( $ary_org_data as $val ) {
   fwrite ( $fh, $val );
  }
 flock ( $fh , LOCK_UN );
 fclose ( $fh );
 return true;
}


// CSV ファイルを読み込み2次元配列として戻す -----------------------------------
// fgetcsv 関数はバグがあるので修正版
function get_csv ( $str_fn ) {

 if ( !file_exists ( $str_fn  ) ) touch ( $str_fn );
 $ary_data = file ( $str_fn ) or $ary_data = array ();


 foreach ( $ary_data as $row => $val ) {
  $val = ereg_replace ( '^"', '', $val );
  $val = ereg_replace ( '",*'."\r\n", '', $val );
  $val = ereg_replace ( '",*'."\n", '', $val );
  $val = str_replace ( array ( "\r\n", "\r", "\n" ), '', $val );
  $ary_data[$row] = explode ( '","', $val );
 }

 return $ary_data;

}


// ------------------------------------------------------------------------------
?>
個人用ツール