クリンナップのまとめ

メッセージ

PHPについてよくやりがちな修正といつかやりそうな修正について、その解説をここにまとめましょう。



ポカヨケ


'and/or' for boolean => '&&/||'

BEFORE: if ($count == 0 or $foo == 'bar') do_someting();
AFTER:  if ($count == 0 || $foo == 'bar') do_someting();

if文などで使われる論理演算( a == b, a > b など ) に演算子「and」「or」が使われている場合、容赦なく「&&」「||」に修正します (^^;

概要

OK: $dp = @opendir($dir) or die($dir . ' is not found or not readable.');

and / or 演算子は 代入文よりも後に評価されます。

'something or die()' という書き方はPerlでは普通に使われています。

実例

BUG:   $via_proxy = $use_proxy and via_proxy($arr['host']);

!boolean => ! boolean / &var => & var

BEFORE: if (!bool) do_someting();
AFTER:  if (! bool) do_someting();

今後のメンテナンスをふまえ、変数名・関数名の修正などを行う際にうっかり判定結果を反転させる事が無い様に、同様に参照渡しであるところの「&」を削ることが無い様に、極力スペースを挿入する様にしています (^^;


記述内容の整理

function_exists('gzfile') => extension_loaded('zlib')

BEFORE:  if (function_exists('gzfile')) { ... }
AFTER:   if (extension_loaded('zlib')) { ... }

特定のPHPエクステンションを要求している場合、それを明確に記述します。

このようにしておくと、コードを見た人間が「そうかウチの環境にはzlib入ってないや」などと即座に気付く事ができるようにもなります。


簡潔な記述 (兼 多少の速度向上)

正規表現が不要な文字列操作であるならば preg_ 系関数は使わない

preg_replace("/\n/", '', $string) => str_replace("\n", '', $string)
preg_replace("/[\r\n]*$/", '', $line); => rtrim($line, "\r\n");

簡潔な文字列関数で表現できる操作(意図)についてはそのように記述すべきです。正規表現を利用する関数を用いる場合、正規表現を処理するため、一般的にオーバーヘッド(メモリとCPU)が大きくなります。

一方、正規表現関数を用いることでコードを手早く構築することができるでしょう。また、時間が豊富にあるならば、後で整理する事ができます。これはバランスの問題です。

Quotation ("strings" => 'strings')

BEFORE: $str = "strings"; $array = array["cmd"];
AFTER:  $str = 'strings'; $array = array['cmd'];

(PHPの場合)単なる文字列を囲むのにダブルクォートを使っている場合、無条件でシングルクォートに直すことができます。一般的にダブルクォートは変数展開などが可能であるため、コンパイル時に無駄な処理が発生します。

BEFORE: $url = "$script?$r_page";
AFTER:  $url = $script . '?' . $r_page;

同様に、変数を不必要にダブルクォーテーションの中に入れている場合、無条件で取り出すことができます。不要な変数展開を防ぐほか、PHPコードのシンタックスカラーリングが可能なエディタやデバッガでの可読性が向上します。

count() => empty()

BEFORE: if(count($array))
AFTER:  if(! empty($array))
BEFORE: if(count($array) == 0)
AFTER:  if(empty($array))

「配列の数が0かどうか」を比較している部分に count() を使っている場合、随時 ! empty() に置き換えます。(配列の数を最後まで数えさせる必要が無いため)

ポイント

厳密には empty は必要ではありませんが、コード(行)の可読性が損なわれると判断しているため省略していません。

AFTER:  if(! empty($array))
AFTER:  if($array)

ベンチマーク

<?php
       // Code from PukiWiki
       // 現在時刻をマイクロ秒で取得
       function getmicrotime() {
               list($usec, $sec) = explode(' ', microtime());
               return ((float)$sec + (float)$usec);
       }

       // Init
       $count = array();
       for($i = 0; $i < 10; $i++)
               $count[$i] = TRUE;

       // Bench start -----------------
       define('MUTIME', getmicrotime());
       // ----

       //var_dump($count);
       for($i = 0; $i < 5000; $i++) {
               if (1) {
                       if (count($count))  echo '- ';
                       //if ($count) echo '- ';
               } else {
                       if (! empty($count)) echo '- ';
               }
       }

       // ----
       $taketime = sprintf('%01.03f', getmicrotime() - MUTIME);
       // Bench end -------------------

       echo '<br/>' . 'HTML convert time: ' . $taketime;
?>

array_key_exits() => isset()

BEFORE: $page = array_key_exists('page', $vars) ? $vars['page'] : '';
AFTER:  $page = isset($vars['page']) ? $vars['page'] : '';

多少早くなるという事以外に、「その配列の利用のされ方」を理解しやすくなるのが大きなポイントです。

ベンチマーク

※上下は省略

       for($i = 0; $i < 5000; $i++) {
               if (1) {
                       if (array_key_exists(0, $count))  echo '- ';
               } else {
                       if (isset($count[0])) echo '- ';
               }
       }

マルチバイト文字列

主に文字化けが絶対に起きないようにするためのケア

BEFORE: mb_convert_kana($str, $option);
AFTER:  mb_convert_kana($str, $option, SOURCE_ENCODING);
BEFORE: mb_strlen($word_nm);
AFTER:  mb_strlen($word_nm, SOURCE_ENCODING);
BEFORE: mb_substr($word_nm, $pos, 1);
AFTER:  mb_substr($word_nm, $pos, 1, SOURCE_ENCODING);

PukiWiki独自の部分

プラグイン

過去の整理事例


コメント


トップ   編集 凍結 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2008-05-23 (金) 02:00:15
Site admin: PukiWiki Development Team

PukiWiki 1.5.4+ © 2001-2022 PukiWiki Development Team. Powered by PHP 8.2.12. HTML convert time: 3.833 sec.

SourceForge