XAMPPを用いた動作環境でPHP言語によるMySQLへのアクセスと実行動作のログ機能を実装します。すでに「環境データ保存用データベースの作成」でMySQLへのアクセスを実装していますが、この処理を見直してログ機能を追加します。
データベースの準備
MySQLのデータ管理アプリ「phpMyAdmin」を使用して、データベースにテーブルを作成します。phpMyadminのSQLの画面を使用して、SQL「show create table power;」を入力すると作成されているテーブルの構造が表示されます。
また、次のSQL文をphpMyadminのSQLの画面で実行して、テーブルを作成します。
CREATE TABLE IF NOT EXISTS `power` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, `datetime` datetime NOT NULL, `value1` float(11) NOT NULL , ・・・ PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=0 ;
PHPログ機能について
PHPログ機能は、別ファイルに関数化し、require関数により呼び出します。ディレクトリ「log」にログを保存し、ログサイス「 1024 * 1024」で3世代管理します。SetLogFile関数によりログファイル名を設定し、WriteLog関数のパラメータで保存するログを指定します。
logoutput.php
<?php
const LOG_DIRECTORY = './log/'; // ログディレクトリ
const MAX_LOTATES = 3; // ログファイルを残す世代数
const MAX_LOGSIZE = 1024 * 1024; // 1ファイルの最大ログサイズ(バイト)
$LOG_FILEPATH = "";
function SetLogFile($filename) {
global $LOG_FILEPATH;
$LOG_FILEPATH = LOG_DIRECTORY . $filename;
}
function WriteLog($strlog) {
global $LOG_FILEPATH;
// 保存先ディレクトリを作成
if (!file_exists(LOG_DIRECTORY)) {
mkdir(LOG_DIRECTORY);
}
// ログのローテート
if (file_exists($LOG_FILEPATH)) {
if (filesize($LOG_FILEPATH) > MAX_LOGSIZE) {
// 最古のログを削除
@unlink(LOG_FILEPATH . strval(MAX_LOTATES));
// ログをリネーム .log → .log_01
for ($i = MAX_LOTATES - 1; $i >= 0; $i--) {
$bufilename = ($i == 0) ? $LOG_FILEPATH : $LOG_FILEPATH . strval($i);
rename($bufilename, $LOG_FILEPATH . strval($i + 1));
}
}
}
// ログ出力
$strlog = mb_convert_encoding($strlog, "UTF-8", "SJIS");
file_put_contents($LOG_FILEPATH, date('y-m/d-H:i:s ') . $strlog . "\n", FILE_APPEND | LOCK_EX);
}
データベース書込みスクリプトの作成
データベース書込みスクリプト「wdatabase.php」を次に示します。
- 2行目でログスクリプト「logoutput.php」をrequireで読み込み、8行目でSetLogFile関数を使ってログファイル名「dbwrite.log」を設定します。14行目でWriteLog関数を使って取得したヘッダの内容をログ保存します。
- 18行目でデータベースのアクセスを設定し、20行目で例外の発生を許可します。「’SET NAMES utf8’」は日本語のテーブル項目のアクセスを可能とします。データベースの例外は39行目から記述される「PDOException」でキャッチされます。
- 53行目のgetfloat関数は浮動小数点型文字列のエラーチェックを行う関数で、空文字もしくは浮動小数点型の文字列化をチェックし、エラーの場合は例外を発生します。
- 64行目のgettime関数はdatetime型文字列のエラーチェックを行う関数で、空文字もしくはdatetime型の文字列化をチェックし、エラーの場合は例外を発生します。
wdatabase.php
<?php
require("logoutput.php");
$DB_DSN = "mysql:host=localhost; dbname=xxxx";
$DB_USER = "xxx";
$DB_PASSWD = "xxx";
SetLogFile("dbwrite.log");
try {
$headers = getallheaders();
$post_body = file_get_contents('php://input');
foreach ($headers as $name => $value) {
WriteLog("$name: $value");
}
WriteLog("$post_body");
$pdo = new PDO($DB_DSN, $DB_USER, $DB_PASSWD,
array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// SQL作成
$csvdata = explode(',', $post_body);
$datetime = gettime($csvdata[0]);
$value1 = getfloat($csvdata[1]);
$sql = "INSERT INTO xxx (
datetime,value1
) VALUES (
'$datetime',$value1
)";
// SQL実行
$res = $pdo->query($sql);
header("HTTP/1.1 200 OK");
header("Status: 200");
header("Content-Type: text/plain");
echo "OK";
} catch (PDOException $e) {
WriteLog($e->getMessage());
header("HTTP/1.1 500 NG");
header("Status: 500");
header("Content-Type: text/plain");
echo "Internal Server Error";
} catch (Exception $e) {
WriteLog($e->getMessage());
header("HTTP/1.1 501 NG");
header("Status: 501");
header("Content-Type: text/plain");
echo "Internal Server Error";
}
function getfloat($floatdata) {
if (empty($floatdata)) {
throw new Exception("getfloat1 null data");
}
if (!is_numeric(trim($floatdata))) {
throw new Exception("getfloat2 " . $floatdata);
}
$value = floatval(trim($floatdata));
return $value;
}
function gettime($timedata) {
if (empty($timedata)) {
throw new Exception("gettime1 null data");
}
if ($timedata === date('Y/m/d H:i', strtotime($timedata))) {
return trim($timedata);
} else {
throw new Exception("gettime2 " . $timedata . ':' . date('Y/m/d H:i', strtotime($timedata)));
}
}
データベース書込みスクリプトの実行
作成したサーバスクリプトの動作を確認するために、ブラウザからPOSTメソッドを送信できるChrome拡張「Advanced REST client」を使用します。インストールは、「Advanced REST client」に移動し、「CHROMEに追加」をクリックすると、アプリの一覧に「Advanced REST client」が追加されます。「Advanced REST client」をクリックして、次のように設定してHTTPリクエストのPOSTデータでテキストデータを送信します。
次のログが「dbwrite.log」に保存されます。。
20-01/02-21:09:15 HOST: 192.168.10.6 20-01/02-21:09:15 content-type: text/plain 20-01/02-21:09:15 content-length: 24 20-01/02-21:09:15 2019/01/06 02:40,11.23
データベース読込みスクリプトの作成
データベース読込みスクリプト「rdatabase.php」を次に示します。
- 2行目でログスクリプト「logoutput.php」をrequireで読み込み、8行目でSetLogFile関数を使ってログファイル名「dbread.log」を設定します。21行目でWriteLog関数を使ってMySQLから取得したデータをログ保存します。
- 118行目でデータベースのアクセスを設定し、13行目で例外の発生を許可します。「’SET NAMES utf8’」は日本語のテーブル項目のアクセスを可能とします。データベースの例外は23行目から記述される「PDOException」でキャッチされます。
rdatabase.php
<?php
require("logoutput.php");
$DB_DSN = "mysql:host=localhost; dbname=xxx";
$DB_USER = "xxx";
$DB_PASSWD = "xxx";
SetLogFile("dbread.log");
WriteLog("start");
try {
$pdo = new PDO($DB_DSN, $DB_USER, $DB_PASSWD,
array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT datetime, value1 FROM xxx";
$stmt = $pdo->query($sql);
while ($row = $stmt->fetch()) {
$datetime = $row['datetime'];
$value1 = $row['value1'];
WriteLog($datetime . ',' . $value1);
}
} catch (PDOException $e) {
WriteLog($e->getMessage());
} catch (Exception $e) {
WriteLog($e->getMessage());
}
データベース読込みスクリプトの実行
作成したデータベース読込みスクリプトのURL「http://192.168.10.6/datadisplay/rdatabase.php」にアクセスすると、次のログが「dbread.log」に保存されます。
20-01/02-21:12:51 start 20-01/02-21:12:51 2019-01-06 02:40:00,11.23

