はじめに
・PHPで、CSVでダウンロードを実装したい方
・MySQLiを使用して、DB操作を実装したい方。
・オブジェクト指向でコードを実装した方
CSVダウンロードの実装をしよう
CSVとは、**Comma Separated Value
の略称で、直訳するとカンマで区切った値という意味になります。なお、PHPでCSVを実装するには、header関数
**を使用します。
######基本形(サンプルコード)
<?php
// 出力情報の設定
header("Content-Dispositionntent-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=GRAYCODE.csv");
header("Content-Transfer-Encoding: binary");
// 変数の初期化
$member = array();
$csv = null;
// 出力したいデータのサンプル
$member = array(
array(
'id' => 1,
'name' => '山田太郎',
'furigana' => 'やまだたろう',
'email' => 'taroyamada@sample.com'
),
array(
'id' => 3,
'name' => '加藤明美',
'furigana' => 'かとうあけみ',
'email' => 'akemikato@sample.com'
),
array(
'id' => 5,
'name' => '佐藤健夫',
'furigana' => 'さとうたけお',
'email' => 'takeosato@sample.com'
)
);
// 1行目のラベルを作成
$csv = '"ID","氏名","ふりがな","メールアドレス"' . "\n";
// 出力データを生成
foreach( $member as $value ) {
$csv .= '"' . $value['id'] . '","' . $value['name'] . '", "' . $value['furigana'] . '","' . $value['email'] . '"' . "\n";
}
// CSVファイル出力
echo $csv;
return;
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<link rel="stylesheet" href="">
</head>
<body>
<h1>CSV Download</h1>
<form method="get" action="./csv.php">
<input type="submit" name="btn_download" value="ダウンロード">
</form>
</body>
</html>
コード抜き出し解説①
header("Content-Dispositionntent-Type: application/octet-stream");
**header関数
で、HTTPヘッダの情報を送信します。ContentDispositionntentType
では、クライアントに返されたコンテンツがどのようなものかを伝え、application/octet-stream
**はファイルの種類が分からないときなどに使用する、MIMEタイプを指定しています。
コード抜き出し解説②
header("Content-Disposition: attachment; filename=GRAYCODE.csv");
**Content-Disposition: attachment
で、ダウンロードファイルとして表示させ、filename=GRAYCODE.csv
でファイル名を指定しています。
※今回のファイル名は、GRAYCODE.csv
**になります。
コード抜き出し解説③
header("Content-TransferEncoding:binary");
**Content-Transfer-Encoding:
で、エンコーディング形式を伝え、binary
**でバイナリーデータを指定します。
MySQLiを使ってDB操作を実装しよう
MySQLiとは、**MySQL improved extension
**の略称です。MySQLと、MariaDBを操作するためのPHPの拡張機能で、オブジェクト指向で記述が可能です。
MySQLiのインスタンスを作成
$mysqli = new mysqli('host_name', 'user_name', 'password','database_name');
インスタスの引数の説明
引数名 | 詳細 |
---|---|
host_name | ホスト名(localhost、127.0.0.1など) |
user_name | 使用するDBのユーザー名 |
password | DBにログイン際のパスワード |
database_name | 使用するDBの名前 |
※引数は、各自の環境に合わして変更してください。 |
MySQLiでSQLクエリの実行
$mysqli->query(`SELECT * FROM test_table`);
今回の場合**SELECT * FROM test_table
で、test_table
**のレコードを全て取得するSQL文を実行しています。
※他のSQL文でも可能。
DBに接続(オブジェクト指向での書き方)
// データベースへ接続
$mysqli = new mysqli('host_name', 'user_name', 'password', 'database_name');
// 接続エラーの確認
if ($mysqli->connect_errno) {
echo $mysqli->connect_errno .':' .$mysqli->connect_error;
}
// 接続解除
$mysqli->close();
MySQLiのインスタンスを作成でDBに接続し、MySQLiプロパティを実装することでエラー処理などを記述。
※empty関数を使用し、**if (!empty ($mysqli->connect_errno))
**でも可能。
プロパティ | 詳細 |
---|---|
connect_errno | 接続エラーの番号を返す |
connect_error | 接続エラーのメッセージを返す |
オブジェクト指向で、実装しよう
全体のサンプルコード
<?php
// DB操作に必要な変数をゲッター、セッターで実装したクラス
class DbData {
private static $sql_result = null;
private static $message_array = array();
public static function getSqlResult() {
return self::$sql_result;
}
public static function getMessageArray() {
return self::$message_array;
}
public static function setSqlResult($sql_result) {
self::$sql_result = $sql_result;
}
public static function setMessageArray($message_array) {
self::$message_array = $message_array;
}
}
// 条件分岐で必要なSELECT文を実装するクラス
class DbSlect {
private static $sql_select = null;
private static $limt = "LIMIT";
public static function getSqlSelect() {
if (self::$sql_select == null) {
self::$limt = null;
}
return "SELECT * FROM message ORDER BY post_date ASC"." ".self::$limt." ".self::$sql_select;
}
public static function setSqlSelect($sql_select) {
if (!is_null($sql_select) && !is_numeric($sql_select)){
throw new Exception('Error: Please enter a number or a string');
}
self::$sql_select = $sql_select;
}
}
?>
<?php
// csvの操作を実装するクラス
class csvDownlod {
private static $csv = null;
public static function csvOpretion() {
self::$csv = '"ID","表示名","メッセージ","投稿日時"'."\n";
foreach (DbData::getMessageArray() as $value) {
self::$csv .= '"' . $value['id'] . '","' . $value['view_name'] . '","' . $value['message'] . '","' . $value['post_date'] . "\"\n";
}
echo self::$csv;
}
}return;
?>
<?php
// 外部ファイルの呼び出し
require_once('db.php');
require_once('csv.php');
// DB情報を定数で実装
define('DB_HOST', '127.0.0.1');
define('DB_USER', 'root');
define('DB_PASS', '各自のpass');
define('DB_NAME', 'board');
// mysqliクラスを使用し、GETパラメータの値で条件分岐
$mysqli = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
if (!empty ($mysqli->connect_errno)) {
echo $mysqli->connect_errno .':' .$mysqli->connect_error;
}
$get_data = $_GET['download_number'];
if (!empty($get_data)) {
if ($get_data === '10') {
DbSlect::setSqlSelect(10);
}elseif ($get_data === '30') {
DbSlect::setSqlSelect(30);
}else{
DbSlect::setSqlSelect(null);
}
}
DbData::setSqlResult($mysqli->query(DbSlect::getSqlSelect()));
DbData::setMessageArray(DbData::getSqlResult());
DbData::getMessageArray()->fetch_all(MYSQLI_ASSOC);
$mysqli->close();
// ヘッター関数を使用し、出力情報の設定
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=メッセージデータ.csv");
header("Content-Transfer-Encoding: binary");
csvDownlod::csvOpretion();
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<link rel="stylesheet" href="">
</head>
<body>
<form action="test_download.php" method="get">
<select name="download_number">
<option value="">全て</option>
<option value="10">10件</option>
<option value="30">30件</option>
</select>
<button type="submit" name="btn-submit" value="btn-submit">ダウンロード</button>
</form>
</body>
</html>
DB情報について
今回使用する、DB情報は以下になります↓
DB名 | ユーザー名 | テーブル名 | カラム名① | カラム名② | カラム名③ |
---|---|---|---|---|---|
message | root | id(int) | view_name(varchar(100)) | message(text) | post_date(datetime) |
コード抜き出し解説①
class DbData {
private static $sql_result = null;
private static $message_array = array();
// 中略
ここでは、**DbDataクラス
を定義しています。private static 〜 変数名
とすることでクラスの外部からアクセス、変更不可の静的なプロパティ
**を定義できます。
コード抜き出し②
// 中略
public static function getSqlResult() {
return self::$sql_result;
}
public static function getMessageArray() {
return self::$message_array;
}
// 中略
public static function get~() { ...
とすることで、静的なメソッド
を定義できまふす。このメソッドはGetter
と呼ばれ、private
でクラス外部からからアクセス変更不可な、プロパティの値だけを返すメソッドの総称
のことを指します。クラス内で静的なプロパティにアクセスする際には、self::$プロパティ名
になります。
※動的なメソッド
の場合はstatic
をつけず、public function メソッド名() { ...
になり、動的なプロパティにアクセスする際には、**this->プロパティ名
**となります。
コード抜き出し③
// 中略
public static function setSqlResult($sql_result) {
self::$sql_result = $sql_result;
}
public static function setMessageArray($message_array) {
self::$message_array = $message_array;
}
// 中略
**public static function set~() { ...
とすることで、コード抜き出し②
と同様に、静的なメソッド
を定義することができる。このメソッドはSetter
と呼ばれ、private
でクラス外部からからアクセス変更不可な、プロパティの値を変更するメソッドの総称
のことを指します。
※Setter
を使用しないと、privateのプロパティ
**を変更できない仕組みになっています。
コード抜き出し④
class DbSlect {
// 中略
public static function getSqlSelect() {
if (self::$sql_select == null) {
self::$limt = null;
}
return "SELECT * FROM message ORDER BY post_date ASC"." ".self::$limt." ".self::$sql_select;
}
// 中略
ここでは、**DbSlectクラス
**を定義しています。
if (self::$sql_select == null) { self::$limt = null; }
のコードで、ダウンロード件数を指定しない場合はプロパティの**$limt
の値をnull
**にしている。これにより、ダウンロード件数を指定しない場合は、DBから全てのデータを取得する条件分分岐が可能になる。
また、**return "SELECT * FROM message ORDER BY post_date ASC"." ".self::$limt." ".self::$sql_select;
で、SELECT文
**に当たる文字列を実装しています。
コード抜き出し⑤
class csvDownlod {
private static $csv = null;
public static function csvOpretion() {
self::$csv = '"ID","表示名","メッセージ","投稿日時"'."\n";
foreach (DbData::getMessageArray() as $value) {
self::$csv .= '"' . $value['id'] . '","' . $value['view_name'] . '","' . $value['message'] . '","' . $value['post_date'] . "\"\n";
}
echo self::$csv;
}
}return
ここでは、**csvDownlodクラス
**を定義しています。
self::$csv = '"ID","表示名","メッセージ","投稿日時"'."\n"; foreach (DbData::getMessageArray() as $value) { self::$csv .= '"' . $value['id'] . '","' . $value['view_name'] . '","' . $value['message'] . '","' . $value['post_date'] . "\"\n"; } echo self::$csv; } }return
で、DBから取得したデータをcsvに実装するために、**カンマ区切り
で、$value
**に値を格納し、DBのデータも同様に配列として格納することで、カンマ区切りになっています。
コード抜き出し⑥
// 中略
public static function setSqlSelect($sql_select) {
if (!is_null($sql_select) && !is_numeric($sql_select)){
throw new Exception('Error: Please enter a number or a string');
}
self::$sql_select = $sql_select;
}
}return
?>
**if (!is_null($sql_select) && !is_numeric($sql_select)){ throw new Exception('Error: Please enter a number or a string'); }
では、Setter
**でプロパティの値をセットしたり変更する際に、値の検査を行なっている。
コード抜き出し⑦
// 中略
DbData::setSqlResult($mysqli->query(DbSlect::getSqlSelect()));
DbData::setMessageArray(DbData::getSqlResult());
DbData::getMessageArray()->fetch_all(MYSQLI_ASSOC);
// 中略
csvDownlod::csvOpretion();
ここでは、DbDataクラスとDbSlectクラスの静的メソッドを呼び出しています。静的メソッドは、インスタンスを作成せずに呼び出すことが可能で、**クラス名::静的メソッド名
**と記述します。
まとめ
・ヘッター関数を使用して、CSVの出力の設定をする。
・MySQLiクラスのインスタスを作成し、引数にDB情報を設定する。
・**private static プロパティ名;
**で、クラスの外部からアクセスや変更できない、静的なプロパティを定義。
・**private プロパティ名;
**で、クラスの外部からアクセスや変更できない、動的なプロパティを定義。
・**public static function メソッド名(){ ...
**で、クラス外部からアクセス可能な静的なメソッドを定義。
・**public function メソッド名(){ ...
**で、クラス外部からアクセス可能な動的なメソッドを定義。
・静的なプロパティにアクセスするには、**self:: $プロパティ名
**で、アクセス可能。
・動的なプロパティにアクセスするには、**this->プロパティ名
**で、アクセス可能。