■Apache+PHP(CSVデータのダウンロード)

 データベースに登録したデータをダウンロードするPHPを作ります。
 ・ユーザーは日付の範囲を選べる
 ・ヘッダー付のカンマ区切りCSVファイルをダウンロードする
 という形にします。

 ○ソース

<?php
include("../dbconnect.php"); //共通外部ファイル
date_default_timezone_set('Asia/Tokyo');
//*** 変数定義 ********************************
$sel_list_syu_cd = array(); // 選択From用 集計
$sel_list_syu_na = array(); // 選択From用 集計
$sel_stdate='';    //開始日
$sel_endate='';    //終了日
$start_ku=true;    //初回区分
$w_message='';     //メッセージ
//*** DBへの接続 ******************************
$db_con = pg_connect(db_connect());
if(!$db_con){
    echo "接続NG";
    exit('接続できません');
}
//*** 開始日付設定。POST優先、無ければ当日 *****
if(isset($_POST["sel_stdate"])){
    $sel_stdate = $_POST["sel_stdate"];
    $start_ku=false;
    if(strtotime($sel_stdate)==false){
        $sel_stdate = date("Y-m-d");
    }
}else{
    $sel_stdate = date("Y-m-d");
}
//*** 終了日付設定。POST優先、無ければ当日 *****
if(isset($_POST["sel_endate"])){
    $sel_endate = $_POST["sel_endate"];
    if(strtotime($sel_endate)==false){
        $sel_endate = date("Y-m-d");
    }
}else{
    $sel_endate = date("Y-m-d");
}
if($start_ku==false){
    
    //*** SQL切り替え ********************
    $sql  = "SELECT sal.date AS date ,sal.code AS code , item.name AS name , item.group_code AS group_code , item.group_name AS group_name , sal.quantity AS quantity , sal.price AS price , sal.money AS money ";
    $sql .= "FROM ms_sales sal JOIN cm_item item ON sal.code = item.code ";
    $sql .= "WHERE date BETWEEN '" . $sel_stdate . "' AND '" . $sel_endate . "' ";
    $sql .= "ORDER BY sal.code ";
    //*** sql発行 ***********************************
    $result=pg_query($db_con,$sql);
    if(!$result){
        exit("{$sql}データを取得出来ません!");
    }
    
    //出力ファイル名の作成
    $csv_file = "csv_". date ( "YmdHis" ) .'.csv';
    $csv_data="";
    if(pg_num_rows($result) < 1){
        pg_free_result($result);
        $w_message="■■■■ データがありません ■■■■";
    }else{
        //ヘッダー出力
        $csv_data .= 'id';
        $csv_data .= '日付';
        $csv_data .= ',コード';
        $csv_data .= ',名前';
        $csv_data .= ',集計CD';
        $csv_data .= ',集計名';
        $csv_data .= ',数量';
        $csv_data .= ',単価';
        $csv_data .= ',金額';
        $csv_data .= "\n";
        //MIMEタイプの設定
        header("Content-Type: application/octet-stream");
        //名前を付けて保存のダイアログボックスのファイル名の初期値
        header("Content-Disposition: attachment; filename={$csv_file}");
        //文字化けを防ぐ
        $csv_data = mb_convert_encoding ( $csv_data , "sjis-win" , 'utf-8' );
        ob_end_clean(); 
        echo($csv_data);
    
        for ($i = 0 ; $i < pg_num_rows($result) ; $i++){
            $rows = pg_fetch_array($result, NULL, PGSQL_ASSOC);
            $csv_data="";
            $csv_data .= $rows['id'] . ',' ;
            $csv_data .= $rows['date'] . ',' ;
            $csv_data .= $rows['code'] . ',' ;
            $csv_data .= $rows['name'] . ',' ;
            $csv_data .= $rows['group_code'] . ',' ;
            $csv_data .= $rows['group_name'] . ',' ;
            $csv_data .= $rows['quantity'] . ',' ;
            $csv_data .= $rows['price'] . ',' ;
            $csv_data .= $rows['money'] . ',' ;
            $csv_data.= "\n" ;
            //文字化けを防ぐ
            $csv_data = mb_convert_encoding ( $csv_data , "sjis-win" , 'utf-8' );
            // データの出力
            echo($csv_data);
        }
        //クエリ開放
        pg_free_result($result);
        exit();
    }
}
?>
<!doctype html>
<html>
    <head>
        <title>明細ダウンロード</title>
        <link rel="stylesheet" type="text/css" href="result.css">
        <link rel="stylesheet" type="text/css" media="screen" href="css/overcast/jquery-ui-1.9.2.custom.min.css" />
        <script type="text/javascript" src="js/jquery-1.8.3.js"></script>
        <script type="text/javascript" src="js/jquery-ui-1.9.2.custom.min.js"></script>
        <script type="text/javascript" src="js/jquery.ui.datepicker-ja.js"></script>
        <script type="text/javascript">
            $(function() {
                $( "#datepicker" ).datepicker();
                $( "#datepicker" ).datepicker( "option", "showOn", 'both' );
                $( "#datepicker2" ).datepicker();
                $( "#datepicker2" ).datepicker( "option", "showOn", 'both' );
            });
        </script>
    </head>
    <body>
        <form action="dl_list.php" method="post">
            開始日付: <input type="text" name="sel_stdate" id="datepicker" /><br>
            終了日付: <input type="text" name="sel_endate" id="datepicker2" /><br>
            <input type="submit" name="submit" value="ダウンロード"><a href='indexトップへ戻る</a>
        </form>
        <?php 
            echo "{$w_message} <br>";
        ?>
    </body>
</html>
●ポイント

 ○検索したデータはpg_fetch_array($result, NULL, PGSQL_ASSOC);で1行づつ取得します。
  今までpg_fetch_all($result);で検索結果をまとめて取得していましたがその方法だと
  データが大量にあった場合メモリ不足になってしまいます。
  1行づつ取得し、都度出力するようにします。

 ○出力設定
  MIMEタイプ、ファイル名初期値、文字化けを防ぐ為エンコードする必要があります。

●失敗談
 恥ずかしながら上記のような事を知らなかった時はini_set('memory_limit', '-1');
 とメモリを無制限にしてやっていました。
 その結果webサーバApacheの使用メモリが増えてサーバを不安定にしてしまいました
 その時の対処はここにまとめてあります。
 正しくない対処をしてしまうと色々な所に影響が出てきますね。
 ただこれをきっかけにApacheの設定等色々学ぶ事が出来ました。

トップへ戻る