付録A. コーディングスタイル

 php/CODING_STANDARDS の私訳です。このファイルは PHP5 時点から更新されていないため、必ずしも最新ではない可能性があります。


 このファイルは、プログラマーが PHP にコードを追加したり修正したりする場合に従うべき、いくつかの標準について列挙したものです。このファイルは PHP v3.0 の開発フェーズの初期に追加されたものであり、そのベースとなるコードは最新に完全に準拠したものでは(まだ)ありませんが、それでも一般的な方向性を示しています。バージョン 5 のリリースに向けて、これらのルールを使うように多くの章を記載しました。

A.1.コードの実装

  1. あなたのコードについての説明を、ソースファイルとマニュアル [tm] の両方に記載してください。
  2. リソースへのポインタを受け取る関数は、それらを free(メモリ開放)するべきではありません。

たとえば、 function int mail(char *to, char *from)to および from について free するべきでは ありません

例外

  • その関数が、それらのリソースを free するような仕様になっている場合。たとえば efree()。
  • その関数に boolean 引数を渡し、それにより引数を free するかどうかを制御するようになっている場合( true であれば関数は引数を free する必要がある。false であれば free してはならない)
  • 低レベルのパーサールーチン。メモリコピーのオーバーヘッドを最小にするために、これらはトークンキャッシュや bison のコードと密接に結びついています。
  1. その関数が同じモジュール内の別の関数と密接に結びついており、お互いの重要な振る舞いに依存する場合は、説明文書にそのように明示し、さらに static 宣言をしてください。このような関数は、作るのを避けるに越したことはありません。
  2. 定義やマクロはどこからでも使えるようにしてください。定数には意味のある名前をつけて、簡単に操作できるようにしてください。唯一の例外は 0 と 1 で、それぞれ false と true として使います。これ以外の数値定数は、固有の振る舞いや動作を指定するために、 #define を通して提供してください。
  3. 文字列を扱う関数を書く場合、PHP はそれぞれの文字列の長さを保持しており、それらの長さを strlen() で計算してはならないことに留意してください。このような方法で関数を書くことで文字列長を持つことの利点が生かされ、利用効率とバイナリセーフの両面でメリットがあります。関数の中で文字列を書き換え、それらの新しい長さを取得したら、その新しい長さを返すようにして、再度 strlen() で長さを再計算しなくてもいいようにします(例: php_addslashes() )。
  4. strncat は使わないでください。自分がやろうとしていることが確実に把握できている場合は、再度 man ページを確認し、その後で使うかどうかを再考してください。それでもやはり、これを使わないで書けないかを試してみてください。
  5. PHP ソースにある PHP_* マクロ、および Zend 配下にある ZEND_* マクロを使うようにしてください。 PHP_* マクロはそのほとんどが ZEND_* マクロの別名ですが、呼び出そうとしているマクロの種類をより明確にするような名前になっています。
  6. #if ステートメントでコードをコメントアウトする場合、0 のみを使っては なりません 。0 の代わりに <git ユーザー名>_0 を使ってください。たとえばあなたの git ユーザー名が FOO なら #if FOO_0 を使います。これにより、特にバンドルされているライブラリについて、なぜそのコードがコメントアウトされているのかを追跡するのが楽になります。
  7. 利用できない関数を定義しないでください。たとえばあるライブラリの関数が未定義の場合、その PHP 用の関数を定義しないでください。そうしないと、関数が見つからないという実行時エラーとなり、エンドユーザーは function_exists() を使って関数の存在を確認しなければならなくなります。
  8. メモリ確保/開放については、標準 C ライブラリ関数の代わりに emalloc(), efree(), estrdup() などの利用を励行してください。これらの関数では内部の セーフティネット のメカニズムを実装しており、リクエストの最後に free されていないメモリを確実に開放します。またデバッグモードにおいて、メモリアロケーションやオーバーフローに関する有用な情報を提供します。

ほとんどのケースでは、エンジンに返すメモリは emalloc() を使ってアロケートされなければなりません。

malloc() の利用は、メモリの開放を自前で制御する必要のあるサードパーティーのライブラリや、問題のメモリ領域が複数のリクエスト間において保持されなければならないようなケースに限られます。

A.2.ユーザー関数/メソッドの命名規則

  1. ユーザーレベルの関数名は PHP_FUNCTION() マクロで括る必要があります。関数名は小文字、単語の区切りはアンダースコアで、文字数をなるべく少なくしてください。可読性が著しく悪化するので関数名に略語を使うべきではありません。
良い例
  • mcrypt_enc_self_test
  • mysql_list_fields
利用可能
  • mcrypt_module_get_algo_supported_key_sizesmcrypt_mod_get_algo_sup_key_sizes でも可)
  • get_html_translation_tablehtml_get_trans_table でも可)
悪い例
  • hw_GetObjectByQueryCollObj
  • pg_setclientencoding
  • jf_n_s_i
  1. 関数群が、その「親となるセット」の一部である場合、親の名前はユーザー関数名に含まれ、親となるプログラムや関数ファミリーに関連していなければなりません。これは 親_* という書式で記載します。

たとえば 'foo' という関数ファミリーであれば、

良い例
  • foo_select_bar
  • foo_insert_baz
  • foo_delete_baz
悪い例
  • fooselect_bar
  • fooinsertbaz
  • delete_foo_baz
  1. ユーザー関数によって使われる(下請け)関数の名前としては、接頭辞として _php_ を付け、その後に関数の内容を表す1個の単語、または複数の単語をアンダースコアで繋いだものをすべて小文字で指定します。可能であれば、それらは static で宣言してください。
  2. 変数名は意味のあるものにしてください。その変数が特別な意味を持たない場合(たとえば for (i=0; i<100; i++) ... などのカウンター変数)を除き、1文字だけの変数名は避けるべきです。
  3. 変数名は小文字にしてください。単語の間はアンダースコアで繋ぎます。
  4. メソッド名は studlyCapsbumpy caseキャメルケース とも呼ばれます)に従い、文字数がなるべく最小になるように心がけましょう。名前の最初の文字は小文字に、それぞれの 単語 の先頭は大文字にします。
良い例
  • connect()
  • getData()
  • buildSomeWidget()
悪い例
  • get_Data()
  • buildsomewidget
  • getI()
  1. クラス名には説明的な名前を付けます。可能なところでは略語を使わないようにしましょう。クラス名の中の個々の単語は大文字で始め、アンダースコアは付けません(大文字で始まる CamelCaps )。クラス名は「親となるのセット(すなわち拡張モジュールの名前)」を頭に付けるようにします。
良い例
  • Curl
  • FooBar
悪い例
  • foobar
  • foo_bar

A.3.内部関数の命名規則

  1. 外部 API の一分となる関数群は php_modulename_function() のような名前にしてシンボルの衝突を防ぎます。これらは小文字でアンダースコアで区切ります。公開する API は php_modulename.h に定義しなければなりません。:

    PHPAPI char *php_session_create_id(PS_CREATE_SID_ARGS);
    

公開しないモジュール関数は static とし、 php_modulename.h で定義してはなりません。:

static int php_session_destroy()
  1. メインのモジュールソース名は モジュール名.c でなければなりません。
  2. 他のソースから使われるヘッダーファイルは php_モジュール名.h でなければなりません。

A.4.文法とインデント

  1. C++ スタイルのコメント(すなわち // コメント)は使用しないでください。常に C スタイルのコメントを使うようにします。PHP は C で書かれており、ANSI-C に準拠したコンパイラでコンパイルすることを想定しています。多くのコンパイラでは C のソース中で C++ スタイルのコメントをサポートしていますが、それら以外のコンパイラでもコンパイルできることを保証しなければなりません。このルールの唯一の例外が、Win32 固有のコードです。これは、Win32 への移植は MS Visual C++ 向けとなっており、このコンパイラは C のコードに C++ スタイルのコメントを書けることがよく知られているからです。
  2. K&R スタイルを使ってください。もちろんすべての人に、自分が使わないスタイルのコーディングを強制することはできませんし、やりたくもありません。しかしながら、あなたは PHP コアやその標準的なモジュールの中で使われるコードを書いているのです。お願いですから K&R スタイルを維持してください。このことは、インデントやコメントのスタイルから関数宣言の書式まで、おおよそすべてに渡って言えることです。
  1. ホワイトスペースとカッコについて寛大な対処をお願いします。ブロックの中では、論理的な実行文のグループ間だけではなく、変数宣言部と実行文の間にも1行空行を空けてください。また関数と関数の間には少なくとも1行、できれば2行の空白行を入れます。また常に:

    if(foo)bar;
    

ではなく:

if (foo) {
    bar;
}

としてください。

  1. インデントの際は、タブ文字を使ってください。1個のタブは4個のスペースを表現することとします。インデントの一貫性を保つことで、定義、コメントおよび制御構文が正しい位置となります。
  2. プリプロセッサのステートメント( #if など)は1カラム目から書いてください。プリプロセッサのディレクティブをインデントしたい場合、 # を1カラム目に置き、その後に任意のホワイトスペースを置くようにします。

A.5.テスト

  1. Extension は *.phpt を使って十分にテストされていなければなりません。これについては README.TESTING をごらんください。

A.6.文書化と折りたたみのフック

 オンラインドキュメントをコードごとに一列に並べて参照できるように、それぞれのユーザーレベル関数には関数のコードの前にユーザーレベルの関数プロトタイプを置き、その下にその関数が行う処理を1行で簡潔に記載してください。たとえば以下のようにします。:

/* {{{ proto int abs(int number)
   number の絶対値を返します */
PHP_FUNCTION(abs)
{
   ...
}
/* }}} */

 {{{ は Emacs や vim (set fdm=marker) の折りたたみモードにおいて、デフォルトの折りたたみ用シンボルです。大きなファイルを編集する際、折りたたみ機能はとても有用です。ファイルを素早くスクロールし、見たいところだけ折りたたみを開いて中身を確認すればよいからです。それぞれの関数の最後には }}} を置いて折りたたみの最後を指示しますが、この行は独立した1行にしてください。

  proto キーワードは、完全な関数サマリーを生成する doc/genfuncsummary スクリプトのヘルパーに過ぎません。この単語を関数プロトタイプの先頭に置いておけば、コードの他の部分は折りたたみの中に隠れるので、関数のサマリーで混乱しなくて済みます。

 オプション引数は以下のように記載します。:

/* {{{ proto object imap_header(int stream_id, int msg_no [, int from_length [, int subject_length [, string default_host]]])
   定義済みパラメーターを含むヘッダーオブジェクトを返します */

 さらにプロトタイプは、たとえそれが長くなっても1行に収めるようにしてください。

A.7. 新しい、実験的な関数

 新しい関数のセットを一般公開する際に生じやすい問題をなるべく少なくするため、関数のディレクトリの中に EXPERIMENTAL という名前のファイルを用意するようにしてください。さらに、その関数群の最初の実装の間は、標準的なプリフィックスの規則に従ってください。

EXPERIMENTAL というファイルには以下の情報を書くようにします。

  • 作者からの情報(既知のバグ、モジュールの将来的な方向性)
  • Git のコメントに入れるにはふさわしくない、現時点の状況

 新しい機能については、一般的に、それをコア配布物に直接追加しなければならない特別な事情がない限り、PECL や実験的なブランチに置くべきです。

A.8. エイリアスと古いドキュメント

 あなたが作成した拡張モジュールの中に、たとえば somedb_select_resultsomedb_selectresult のようにほぼ重複するような名前を持つ、廃止予定のエイリアスがあるとします。文書化にあたっては一番最新の名前だけを記載し、そこに親関数のためのエイリアスを併記するようにします。参照しやすくするために、ユーザー関数は完全に違った名前にしておき、同名の関数へのエイリアス(たとえば highlight_file と show_source)は別々に文書化するようにします。proto は相変わらず include されなければなりませんが、そこにはどの関数がエイリアスされているのかという情報を記載します。

 互換性のための関数や名前は、そのコードがコードベースの一部として存続している間は維持されなければなりません。ドキュメント作成に関する詳細は /phpdoc/README をごらんください。