FrontPage >

PHP5ベストプラクティス

※以下のプラクティスでは、できる限り妥当な理由づけをしていますが、プログラミング感覚に左右される部分も少なくありません。もし、あなたにとってベストもしくはベターなプラクティスが見つかれば幸いです。

ビルドの自動化

  • phing(PHP版Ant)により、ユニットテスト(PHPUnit)、パッケージング(PEARパッケージ)、ドキュメンテーション(PhpDocumentor)などが自動化できます。

ドキュメンテーション

  • PhpDocumentor で、APIドキュメントを最新に保ちます。

ディレクトリ構成とファイル名

  • クラスが定義されているファイルの場所が分かるように、ファイルへのパスはクラス名に反映させるようにします(PEARの規約と同様)。したがって、ディレクトリ階層は適当な深さ(2〜4階層ほど)で、各ディレクトリ名は大文字で始め、コンパクトな長さにします。
  • クラス名は、ファイルへのパスの区切り文字('/'や'\')をアンダースコア('_')に置換し、拡張子を除いたものになります。
    1ファイルパスCommons/Lang/Builder/ToStringBuilder.php
    定義されているクラスCommons_Lang_Builder_ToStringBuilder
    2ファイルパスCommons/Lang/Time/StopWatch?.php
    定義されているクラスCommons_Lang_Time_StopWatch?
  • ファイル名は、クラスを定義している場合には(クラス名に反映させるので)大文字で始め、実行スクリプトの場合には小文字で始めます。拡張子は、.php のみを用います。.class.php は冗長ですし、定数定義に define は使用しない(代わりに const を使う)ので、.inc を使う場面もないでしょう。

命名規約

  • クラス名は、上記の通りファイルへのパスを反映させます。
  • 他のものについては、PEARの規約に準じます。

コーディング

PHP5の既知の問題

オブジェクト指向言語ではないPHP5の特徴

マルチバイト文字列対応

定数

  • 定数は define せずに、抽象クラスまたはインタフェイスの中の const 変数で定義します。迂闊な二重定義を防ぐことができ、定義されている場所を見失うこともありません。

プロパティ

比較

  • 基本的に、同じ型同士で比較するようにします。
  • 非オブジェクト型の比較(同値性比較)の場合には、常に型を考慮する比較演算子(===、!==)を用います。
  • オブジェクト型の比較の場合には、同値性比較には各クラスに equals() メソッドを用意し、それを用い、同一性比較には同じクラスの同じインスタンスを参照する場合を比較する演算子(===!==)を用います。
  • 比較演算子 == と != は型を考慮しないので(オブジェクトの場合にはクラスを考慮しますが紛らわしいので)、使用を控えます。

正規表現

  • 正規表現は強力ですが、網羅的なテストが難しく、バグが潜在しやすいものです。本当に必要な場合やごくシンプルで確実な場合にのみ使います。
  • 機能的にそしてパフォーマンス的にも優位な場合が多いので、主にpreg*関数を使います。
  • PHPの場合、正規表現はすべて文字列で与えることになりますので、ダブルクォーテーションではなく、メタキャラクタの少ない(' と \ のみ)シングルクォーテーションで常に記述します。紛らわしさを避けるため、正規表現における \ は常に '\\' と記述し、\ 自身へのマッチは '\\\\' と統一的に記述します。

__toString()メソッドのオーバーライド

  • クラスでは、__toString()メソッドをオーバーライドし、有益な文字列情報を出力するようにします。オブジェクト状態のロギングが容易になります。
  • 以下の例にある ToStringBuilder は、array の内容を展開し文字列化しますが、array の要素に自己参照や参照ループがある場合、無限ループを回避することができませんので、ご注意ください(自己参照を持つ array の同一性比較自体が要素比較の走査によりエラーになるので)。
      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
    
    <?php
    require_once 'Commons/Lang/Builder/ToStringBuilder.php';
    // ...
        public function __toString() {
            $builder = new Commons_Lang_Builder_ToStringBuilder($this);
            return $builder
                ->append('_startTime', $this->_startTime)
                ->append('_stopTime', $this->_stopTime)
                ->__toString();
        }
    ?>

プログラムの計測

  • パフォーマンスに注意が必要な処理には、時間計測のコードを入れるようにします。
      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
    
    <?php
    require_once 'Commons/Lang/Time/StopWatch.php';
    // ...
    $stopWatch = new Commons_Lang_Time_StopWatch();
    $stopWatch->reset();
    $stopWatch->start();
    // ...    // 処理
    $stopWatch->stop();
    $elapsedTime = $stopWatch->getTime();          // 156(ミリ秒)
    $elapsedTimeStr = $stopWatch->__toString();    // '0:00:00.156'
    ?>

デバッグセッションの活用

ロギング

  • log4php のようなカテゴリとレベル機構のあるフレームワークを利用します。
    • カテゴリ名には、(ディレクトリ階層を反映した)クラス名のアンダースコア('_')をドット('.')に置換したものを指定します。これにより、各ディレクトリ階層でログ出力を制御することができるようになります。
      クラス名Commons_Lang_Time_StopWatch?
      カテゴリ名Commons.Lang.Time.StopWatch?

PHP Commons Logging を利用したログ出力

  • PHP Commons Logging を利用することにより、ログ出力コードを変更せずに実際にログ出力するロギングフレームワークを切替えることが可能になります。
  • 詳細はこちら

ユニットテスト

ツール

DI


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2008-10-04 (土) 14:37:27 (4377d)