前説
実際のプロジェクトにおいて、ログ出力機能は必須要件だと思います。(開発コストを削減するために、不要の場合もあるかと思いますが、ここで論外)
ログなので、日時の出力は絶対に必須となり、その中で、ミリ秒(マイクロ秒)まで出力する場合が多いと思います。
特にデッドロック発生して、調査する際に、SQLログにミリ秒までを記録するなら、エラー原因の分析&解決に役立つかと思います。
もう一つよく使われるシーンは、開始時刻から終了時刻までの差分を計算し、ある処理の実行時間を測ることです。、
誤り:date関数のミリ秒(マイクロ秒)の出力
1 2 3 4 5 6 7 8 9 10 11 |
<?php $msec = date("u"); // マイクロ秒 echo $msec; // 結果:000000 echo "<br>"; $msec = date("v"); // ミリ秒 echo $msec; // 結果:000 ?> |
落とし穴です。残念ながら、date関数を使って、のミリ秒(マイクロ秒)を出力して、その結果は常に「000000」や「000」です。
なので、date関数のミリ秒(マイクロ秒)の出力はムリです。
(お恥ずかしい話ですが、筆者は一発で落ちました。ログファイルに、6桁の0がキレ~イに並んでいました(笑))
残念な誤り:microtime関数のミリ秒(マイクロ秒)の出力
よく見かけるサンプルは下記の通りです。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?php $msec = microtime(true); // microtimeを使って、浮動小数点数(float)①を取得 $msec = explode('.', $msec); // ①の結果には、小数点がついているので、それを区切り文字として、①を配列②にする $msec = $msec[1]; // ①の小数点以下はミリ秒(マイクロ秒)なので、配列②の2番目はミリ秒(マイクロ秒)となる echo $msec; ?> |
一見正しいように見えますが、残念ながら、この方法はログ出力機能にNGです。実際のプログラムには使えないです。何故なら、この方法で実際にエラーが起こるのです。
その原因は浮動小数点数(float)のことです。浮動小数点数と言っても、小数点が付いていない場合があり、その際に、配列②のサイズが1ですので、$msec[1]をすると、「PHP Notice: Undefined offset: 1」エラーが起こります。
正解:microtime関数のミリ秒(マイクロ秒)の出力
原因は分かりましたので、$msec[1]が存在するかどうかを事前にチェックして、なければ、0を足せば済むかと思います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<?php $msec = microtime(true); $msec = explode('.', $msec); if( !isset($msec[1]) ){ $msec[1] = "0000"; // $msec[1]がセットされたかどうかをチェックし、なければ0をセット } $msec = $msec[1]; echo $msec; ?> |
いかがでしょうか。お分かりになりましたでしょうか。他人のものを実際に検証した上に、使っていただくように良いかと思います。
最後に、厳密にいうと、ここに出力したのは、ミリ秒ではなく、マイクロ秒ですが、現場のプロたちを含めて、あんまり区別しないで使うので、実際に違いますが、ミリ秒 = マイクロ秒として認識すればと思います。
おまけに、処理時間を測るサンプルを提供します。実際に検証してね。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?php $time_start = microtime(true); // いろいろ重い処理 $time_end = microtime(true); $time = $time_end - $time_start; echo $time; // 実際のプログラムは$timeをログファイルに出力する場合は多いでしょう ?> |
それでは、以上です。