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