デバッグし易くしよう! 1: 処理を表示する
はじめに
プログラムにデバッグ向けのコードを入れておくと、開発時はもちろん、運用開始後も、何か問題が発生した場合に、それが、コーディングの問題なのか、データの問題なのか、あるいはTwitter側の問題なのかを切り分ける作業と判断に必要な時間を大幅に短縮できます。
しかし、案外PHPの入門書にも、ネットを見渡してみてもまとまった説明が見当たらないようでしたので、いくつか簡単なものをご紹介してみることにしました。
なお、自分の環境が PHP5であるため前提が PHP5となってしまう点はご了承ください。
サンプル・コード
デバッグ・コードを追加していくサンプルとして、今回は以下のfopenを利用してTwitterのステータスを更新するコードを利用してみます。
<pre> <?php //ユーザー名、パスワード $username='Twitterユーザ‐名'; $password='Twitterパスワード'; $message='テストメッセージ!!'; $ret= tweet_fop($message, $username, $password); exit(); //プログラム終了 //fopenを利用したtweet function function tweet_fop($message, $username, $password) { $url = "http://twitter.com/statuses/update.json?"; $params = "status=". rawurlencode($message); $st = stream_context_create(array( "http" => array( "method" => "POST", "header" => "Authorization: Basic ". base64_encode($username. ":". $password) ) )); if(($fp = fopen($url.$params, 'r', false, $st)) == false){ return(false); } $contents=stream_get_contents($fp); fclose($fp); return ($contents); } ?> </pre>
しかし、上のプログラムを実行しても、画面上には何も表示されず、Twitter側を確認して、初めて上手くステータスの更新が出来たのか否かが分かります。
Step1 : どの処理が行われたか表示
例えば、Web経由でツイッターにアクセスした場合でも、手動で”投稿”ボタンを押してもなかなか反映されずに終わってしまう経験をされた方も多いのではないでしょうか?
サンプル・プログラムも特に問題がなければ、すぐにexit()処理に辿りつきますが、もし何か問題が生じていると中々処理が終わらない場合もあるかもしれません。
もし、現在どの処理が実行中かを表示できれば、処理が順調に進んでいるのか、どこかで引っかかってしまっているのか簡単に分かりますね!
・・・という訳でいくつか echo 文を追加してみます。
<?php echo "プログラム開始<br>"; //ユーザー名、パスワード $username='Twitterユーザ‐名'; $password='Twitterパスワード'; echo " ユーザー名、パスワードセット完了<br>"; $message='投稿テストメッセージ!!'; echo " 投稿メッセージのをセット完了<br>"; $ret= tweet_fop($message, $username, $password); echo "プログラム終了<br>"; exit(); //fopenを利用したtweet function function tweet_fop($message, $username, $password) { echo " 関数tweet_fop:START<br>"; $url = "http://twitter.com/statuses/update.json?"; $params = "status=". rawurlencode($message); $st = stream_context_create(array( "http" => array( "method" => "POST", "header" => "Authorization: Basic ". base64_encode($username. ":". $password) ) )); echo " fopen実行<br>"; if(($fp = fopen($url.$params, 'r', false, $st)) == false){ echo " fopen 失敗のため 関数tweet_fopから戻る<br>"; return(false); } echo " fopen成功<br>"; $contents=stream_get_contents($fp); echo " fclose実行<br>"; fclose($fp); echo " 関数tweet_fop:END<br>"; return ($contents); } ?>
これを実行すると、正常に処理が進んだ場合は下のように画面にメッセージが表示され、処理が最後まで正常に進んだことが確認できます。
プログラム開始 ユーザー名、パスワードセット完了 投稿メッセージのをセット完了 関数tweet_fop:START fopen実行 fopen成功 fclose実行 関数tweet_fop:END プログラム終了
以降こんな感じで少しづつ デバッグのためにプログラムに追加してみると良さそうなことをまとめて見たいと思います。
デバッグし易くしよう! 2: PHPのエラー表示レベルを変更 error_reporting を使う
Step2 PHPのエラー表示レベルをerror_reporting($level)で変更
PHPでは、error_reporting($level) という関数を利用すると、引数である$levelに設定する値により、どのレベルのエラー、警告までを表示するかを制御することができます。
詳しくはPHPマニュアルをご覧頂けるとよいのですが、
level | 表示対象 | 補足説明 |
---|---|---|
E_ALL ^ E_NOTICE | 変数、変数名のスペルミスなど以外の全てのエラーを表示 | 通常php.iniのデフォルト設定 |
E_ALL | 全てのPHPエラーを表示 | |
0 | 全てのPHPエラーを表示しない |
例えば、デフォルトの状態で、プログラムの8行目の最後の”;”をわざとはずすと
致命的エラー(Parseエラー)となるので下のようにエラーが表示され実行がそこで終了します。
Parse error: syntax error, unexpected T_VARIABLE in C:\(中略)\test_update_fopen.php on line 8
開発段階では、”E_ALL”に設定しておくと色々教えてくれるので便利だと思います。
<?php error_reporting(E_ALL); ?>
(余談)ちなみに自分が利用しているさくらインターネットではerror_reporting(E_ALL);を設定しても何も表示されません少なくともPHP5の場合。php.iniを編集すれば表示できるようですが、本番環境で色々表示されるのも厄介なのでローカルでデバッグできれば、まあ、いいやと自分は、放置しています
自分のローカル・テスト環境で、PHPのエラーは取り去っておきたいものです。
デバッグし易くしよう! 3: デバッグ時と本番運用時の処理を簡単に切り替える
Step1で、デバッグ用にかなり沢山のecho文を追加しましたが、本番時には無用の長物。しかしながらプログラムの変更を行ったりする場合には、やはり表示できた方が便利。ここでは、定数の値を変更することで、デバッグ用の処理を実行するかどうかを簡単に切り替える方法を説明します。
Step3 デバッグ/運用モードの簡単切り替え
ここではdefine関数(マニュアル)を利用する方法をご紹介します。
まず、define関数で、デバッグモードであるか否かを識別するための定数を定義します。
define('DEBUG', TRUE);
デバッグ時にのみ行いたい処理が 定数DEBUG=TRUEの場合にのみ実行されるようにコードを書きなおします。
if (DEBUG) { デバッグ処理 };
運用時には、最初のdefineの部分を書き変えて定数DEBUG=FALSEとしれば、デバッグ用のコードは実行されません。
define('DEBUG', FALSE);
参考までに、サンプルコードをこれを利用して書き直すと次の通りになります。
デバッグし易くしよう! 4: 変数、配列の中身確認 var_dump関数等
プログラムの処理が進んでいる中で、必要な値が正しく変数、配列にセットできているかどうかは大切なことです。これもデバッグ処理時は表示するなり何なりして確認したいものです。
Step4 変数、配列の中身を確認
恐らく、これは良く紹介されている関数だと思いますが、変数に関する情報をダンプする関数 var_dump関数(マニュアル)を利用します。これを利用すると引数として指定した変数の値をデータの型と値を返してくれます。配列にも利用することが可能です。
例を見ていただく方が良いと思いますが、下の例のように文字列、数字(INT,float)、bool値を代入した変数と、配列をvar_dump関数を使って表示させると
<?php $hensu1="文字をいれました"; $hensu2=125; $hensu3=123456789012345; $hensu4=FALSE; $arr1=array("たま"=>array("syurui"=>"猫","age"=>1,"かわいいよ"), "ぽち"=>array("syurui"=>"犬","age"=>3,"食いしん坊だよ") ); var_dump($hensu1); var_dump($hensu2); var_dump($hensu3); var_dump($hensu4); var_dump($arr1); ?>
以下のようにデータ型(桁数)値 の形で処理結果が表示ます。
string(24) "文字をいれました" int(125) float(1.2345678901234E+14) bool(false) array(2) { ["たま"]=> array(3) { ["syurui"]=> string(3) "猫" ["age"]=> int(1) [0]=> string(15) "かわいいよ" } ["ぽち"]=> array(3) { ["syurui"]=> string(3) "犬" ["age"]=> int(3) [0]=> string(21) "食いしん坊だよ" } }
変数の値だけを取得したい場合には、var_export関数(マニュアル)があります。先ほどのコードの後半をvar_exportで下のように書き変えて実行すると
<?php $hensu1="文字をいれました"; $hensu2=125; $hensu3=123456789012345; $hensu4=FALSE; $arr1=array("たま"=>array("syurui"=>"猫","age"=>1,"かわいいよ"), "ぽち"=>array("syurui"=>"犬","age"=>3,"食いしん坊だよ") ); var_export($hensu1); var_export($hensu2); var_export($hensu3); var_export($hensu4); var_export($arr1); ?>
次のように、データ型などの情報は含まず、変数、配列の値だけが戻されます。
'文字をいれました'1251.2345678901234E+14falsearray ( 'たま' => array ( 'syurui' => '猫', 'age' => 1, 0 => 'かわいいよ', ), 'ぽち' => array ( 'syurui' => '犬', 'age' => 3, 0 => '食いしん坊だよ', ), )
試しに以前から利用しているサンプルコードで、var_dumpを利用してみると