一般的なスタイルとシンタックス
以下のページでは CodeIgniter を開発する際に守っているコーディングルールについて記述します。
目次
- ファイルフォーマット
- PHP の囲みタグ
- クラス名、メソッド名
- 変数名
- コメント
- 定数
- TRUE、FALSE、NULL
- 論理演算子
- 返り値の比較、型のキャスト
- デバッグコード
- タブ/スペース
- 互換性
- クラス名とファイル名を共通にする
- データベーステーブル名
- 1ファイル1クラス
- タブ/スペース
- 改行コード
- インデント
- カッコの前後のスペース
- コントロールパネル内のローカライズされたテキスト
- プライベートメソッド、プライベート変数
- PHP エラー
- PHP 短縮開始タグ
- 1行1ステートメント
- 文字列
- SQL 文
- メソッド (関数) の引数のデフォルト値
ファイルフォーマット
ファイルは Unicode (UTF-8) エンコーディングで保存します。BOM なし とします。UTF-16 や UTF-32 と異なり、UTF-8 でエンコードされたファイルには BOM はありません。 そして、BOM は、ネガティブな副作用を PHP の出力にもたらし、 アプリケーションが独自のヘッダを指定するのを邪魔します。 Unix での改行コード (LF) を 使います。
有名なテキストエディタでの、これらの設定方法を以下に示します。設定方法はお使いのテキストエディタにより 異なります。お使いのテキストエディタのドキュメントを参照してください。
TextMateエディタの場合
- アプリケーションの環境設定を開きます。
- "Advanced" をクリックし、"Saving" タブをクリックします。
- "File Encoding" から "UTF-8 (recommended)" を選択します。
- "Line Endings" から "LF (recommended)" を選択します。
- オプション:ファイルを開いた際に新しい設定を反映する場合は、 "Use for existing files as well" をチェックします。
BBEdit
- アプリケーションの環境設定を開きます。
- 左のリストから "Text Encodings" を選択します。
- "Default text encoding for new documents" から "Unicode (UTF-8, no BOM)" を選択します。
- オプション: "If file's encoding can't be guessed, use" から "Unicode (UTF-8, no BOM)" を選択します。
- 左のリストから "Text Files" を選択します。
- "Default line breaks" から "Mac OS X and Unix (LF)" を選択します。
PHP の終了タグ
PHP ファイルにおける PHP の終了タグ ?> は付けなくても PHP パーサーには問題ありません。 しかしながら、開発者やユーザ、もしくは FTP ソフトによって終了タグ以降にホワイトスペースが挿入される事が考えられ、この結果、好ましくない出力や PHP エラー、もしくは後半部分が出力されなかったり、真っ白なページが表示されたりします。この理由のため、すべての PHP ファイルで終了タグを除外します。 代わりにファイルの最後には、コメントブロックを使用しアプリケーションルートからの位置を記述しています。 さらには、ファイルが途中で切れていない事が確認できます。
間違い:
<?php
echo "コードがあります!";
?>
正しい:
<?php
echo "コードがあります!";
/* End of file myfile.php */
/* Location: ./system/modules/mymodule/myfile.php */
クラス名、メソッド名
クラス名は常に最初の文字を大文字にしなければいけません。複数の単語はアンダースコアで区切ります。キャメルケースにはしないでください。クラスメソッドはすべて小文字にし、機能が分りやすい名前にします。できれば動詞が含まれる様にします。あまり長い名前や冗長な名前は避ける様にしましょう。
間違い:
class superclass
class SuperClass
正しい:
class Super_class
class Super_class {
function __construct()
{
}
}
間違ったメソッド名と正しいメソッド名:
間違い:
function fileproperties() // 表現がわかりにくく、アンダースコアが抜けている
function fileProperties() // 表現がわかりにくく、キャメルケースが使われている
function getfileproperties() // ベター! しかしながらアンダースコアが抜けている
function getFileProperties() // キャメルケースが使われている
function get_the_file_properties_from_the_file() // 長過ぎる
正しい:
function get_file_properties() // 説明的、アンダースコア、すべて小文字
変数名
変数名のガイドラインはクラス名ととても似ています。変数名は小文字だけで構成して、アンダースコアで区切り、目的や内容を表すようにします。 極端に短かったり、単語になっていない変数は for() 文のループ変数にのみ使用します。
間違い:
$j = 'foo'; // 1文字の変数は for() 文でのみ使う
$Str // 大文字が含まれている
$bufferedText // キャメルケースが使われており、意味を失う事無くもっと短縮できる
$groupid // 複数単語、アンダースコアが必要
$name_of_last_city_used // 長過ぎ
正しい:
for ($j = 0; $j < 10; $j++)
$str
$buffer
$group_id
$last_city
コメント
一般に、コードにはたくさんのコメントを入れるべきです。 経験の浅いプログラマー向けにはプログラムコードの処理フローや意図が説明されていないだけでなく、自分で書いたコードに一ヶ月後に再び戻った時、それがとても重要だという事を示すこともできません。 コメントのフォーマットは必須ではありませんが、下記の内容はおすすめします。
クラスやメソッドの宣言の前にあるDocBlock スタイルのコメントはIDEによって抽出されます。
/**
* Super Class
*
* @package パッケージ名
* @subpackage サブパッケージ名
* @category カテゴリ
* @author 作成者
* @link http://example.com
*/
class Super_class {
/**
* XML 内で使用する文字列のエンコード
*
* @access public
* @param string
* @return string
*/
function xml_encode($str)
コード中に一行コメントを使うとき、長いコメントブロックとコードの間に空行を残します。
// 改行で文字列を分割する
$parts = explode("\n", $str);
// 何が起きるのかをとても詳細に記述する必要がある場合は、
// 複数行に渡る一行コメントを使います。
// 適度な長さを維持してみてください。読みやすいのは70文字前後です。
// ためらわずに外部のリソースへのリンクを使います。
// とても詳細な情報を与えてくれるかもしれません。
//
// http://example.com/information_about_something/in_particular/
$parts = $this->foo($parts);
定数
定数は変数と同じガイドラインに従います。例外として定数には大文字のみを使用します。 CodeIgniter の定数は常にそうなっています。 SLASH, LD, RD, PATH_CACHE, etc.
間違い:
myConstant // アンダースコアが抜けており大文字でない
N // 1文字の定数はだめ
S_C_VER // 説明的でない
$str = str_replace('{foo}', 'bar', $str); // LD や RD といった定数を使うべき
正しい:
MY_CONSTANT
NEWLINE
SUPER_CLASS_VERSION
$str = str_replace(LD.'foo'.RD, 'bar', $str);
TRUE、FALSE、NULL
TRUE, FALSE, NULL は、常に大文字を使います。
間違い:
if ($foo == true)
$bar = false;
function foo($bar = null)
正しい:
if ($foo == TRUE)
$bar = FALSE;
function foo($bar = NULL)
論理演算子
|| は解像度の低いデバイスでは明瞭でない(たとえば数字の11にとらえられてしまう)。 どちらかと言うと&& が AND よりも好まれる。!の前後には空白を入れる。
間違い:
if ($foo || $bar)
if ($foo AND $bar) // これでもよいがアプリケーションのシンタックスハイライト機能にはおすすめできない。
if (!$foo)
if (! is_array($foo))
正しい:
if ($foo OR $bar)
if ($foo && $bar) // 推奨
if ( ! $foo)
if ( ! is_array($foo))
返り値の比較、型のキャスト
いくつかの PHP の関数は、失敗した場合 FALSE を返します。しかし、緩やかな比較では FALSE と評価される "" や 0 を返す場合もあります。戻り値が実際に望む値であるか、緩やかな比較で FALSE と判定される値でないか確かめるため、厳密に比較をしましょう。
戻り値や変数の値をチェックする場合は、同じ厳密な比較を使います。 === や !== を必要に応じて使います。
間違い:
// 文字列の初めが 'foo' であれば、 strpos は0を返します
// 結果として、この条件式は TRUE になります
if (strpos($str, 'foo') == FALSE)
正しい:
if (strpos($str, 'foo') === FALSE)
間違い:
function build_string($str = "")
{
if ($str == "") // おっと! FALSE や整数値の0が引数に渡されるとどうなるでしょう?
{
}
}
正しい:
function build_string($str = "")
{
if ($str === "")
{
}
}
型キャストについての情報も非常に役立ちますのでご覧ください。型キャストには、好ましい若干異なる効果があります。たとえば変数を文字列型にキャストすると、NULL やブール値の FALSE といった値は空の文字列になり、0(や他の数値)は数字を表す文字列になります。また、ブール値の TRUE は"1"になります。
$str = (string) $str; // $str を文字列型にキャストします
デバッグコード
コメントアウトしていないデバッグコードを投稿されたアドオンに含めないでください。つまり、var_dump()、print_r()、die() や exit() が、コメントアウトされずに含まれていないということです。
// print_r($foo);
タブ/スペース
PHP 開始タグの前や、終了タグの後ろに空白があってはいけません。出力はバッファリングされますので、そのような空白がファイル内にあると、CodeIgniter のバッファ出力より前に出力が開始され、エラーが発生すると CodeIgniter が適切なヘッダを送信出来ない原因になります。以下の例では、誤った空白がある事を確認するために、マウスでテキストを選択してみてください。
間違い:
<?php
// ...PHP の開始タグの上に、空白文字と改行があります
// 同様に、PHP の終了タグの後に空白文字があります
?>
正しい:
<?php
// このサンプルでは、PHP 開始タグの前にも終了タグの前にも空白文字はありません
?>
互換性
あなたのアドオンが特に言及しない限り、すべてのコードは PHP 5.1 以上との互換性を維持し、非標準のライブラリを必要とする PHP 関数を使用するのは止めてください。もし、非標準のライブラリを必要とするのであれば、その事を明記するか、非対応環境での別の手段を用意してください。
クラス名とファイル名を共通にする
あなたの作成したクラス名やファイル名がよくある名前の場合、あるいは、他の PHP スクリプトでよく見かける名前の場合、衝突を避けるためにユニークなプレフィックスを付けましょう。エンドユーザは他のアドオンや、サードパーティー製の PHP スクリプトを走らせるかもしれないことを、常に意識してください。プレフィクスには、開発者や会社としてのあなたを特定できるようなユニークなものを選択しましょう。
間違い:
class Email pi.email.php
class Xml ext.xml.php
class Import mod.import.php
正しい:
class Pre_email pi.pre_email.php
class Pre_xml ext.pre_xml.php
class Pre_import mod.pre_import.php
データベーステーブル名
あなたのアドオンが使用するテーブル名には、'exp_'というプレフィックスを必ず使用し、そのあとに開発者や会社としてのあなたを特定できる独自のプレフィックスを付け、それから短く説明的なテーブル名を続けてください。CodeIgniter のデータベースクラスは、'exp_'を自動的に実際使用されるものに変換するので、あなたはインストールの際にユーザが使用するプレフィックスについて考える必要はありません。
間違い:
email_addresses // exp_ というプレフィックスも、アドオンの開発者を特定できる独自のプレフィックスも抜けています
pre_email_addresses // exp_ というプレフィックスが抜けています
exp_email_addresses // アドオンの開発者を特定できる独自のプレフィックスが抜けています
正しい:
exp_pre_email_addresses
NOTE: MySQL はテーブル名に64文字の制限があることに注意しましょう。テーブル名でこの制限が問題になることは、不合理な名前を付けない限り滅多にありません。たとえば、以下のテーブル名はこの制限を 1文字超えています。ばかばかしいでしょ? exp_pre_email_addresses_of_registered_users_in_seattle_washington
1ファイル1クラス
アドオンで使うクラスは、クラス同士が非常に密接に関連していない限り、クラスごとに違うファイルを使いましょう。 一例として、CodeIgniter で1つのファイルに複数のクラスが入っているのは、データベースクラスのファイル( DB クラスと DB_Cache クラスが一緒に入っています)と、Magpie プラグインのファイル( Magpie クラスと Snoopy クラスが一緒に入っています)です。
タブ/スペース
コード内の空白には、スペースでなくタブを用います。これは些細な事に思えるかもしれませんが、スペースの代わりにタブを使う事で、開発者がどのようなアプリケーションを利用していても、各自が見やすくカスタマイズしたインデントレベルでコードを見る事が可能になります。さらに副次的な効果として、たとえば4つのスペースに対して1つのタブを用いる事で(わずかではありますが)ファイルがよりコンパクトになります。
改行コード
ファイルの改行コードは Unix スタイルに統一しましょう。これは Windows で開発を行う開発者にとって大きな問題ですが、どんなときでもテキストエディタのファイル保存設定が Unix スタイルの改行コードになっていることを確認してください。
インデント
Allman スタイルのインデントを利用します。クラス宣言を除いて、括弧は常に1行に単独で配置し、その制御ステートメントと同じ深さにインデントします。
間違い:
function foo($bar) {
// ...
}
foreach ($arr as $key => $val) {
// ...
}
if ($foo == $bar) {
// ...
} else {
// ...
}
for ($i = 0; $i < 10; $i++)
{
for ($j = 0; $j < 10; $j++)
{
// ...
}
}
正しい:
function foo($bar)
{
// ...
}
foreach ($arr as $key => $val)
{
// ...
}
if ($foo == $bar)
{
// ...
}
else
{
// ...
}
for ($i = 0; $i < 10; $i++)
{
for ($j = 0; $j < 10; $j++)
{
// ...
}
}
括弧の前後のスペース
一般的に、括弧の前後にはスペースを追加すべきではありません。例外として、括弧内に引数を記述する PHP 制御構造(declare, do-while, elseif, for, foreach, if, switch, while)では、関数と区別しやすくしたり可読性を高めるために、常にスペースを配置すべきです。
間違い:
$arr[ $foo ] = 'foo';
正しい:
$arr[$foo] = 'foo'; // 配列のキーの前後には空白を入れません
間違い:
function foo ( $bar )
{
}
正しい:
function foo($bar) // 関数定義の括弧の前後には空白を入れません
{
}
間違い:
foreach( $query->result() as $row )
正しい:
foreach ($query->result() as $row) // PHP の制御構造の後ろには空白を1つ入れますが、中の括弧には入れません
コントロールパネルのローカライズされたテキスト
コントロールパネルに出力するテキストはすべて、モジュールの言語ファイルを使ってローカライズできるように(生のテキストではなく)言語ファイルの変数を使いましょう。
間違い:
return "Invalid Selection";
正しい:
return $this->lang->line('invalid_selection');
プライベートメソッド、プライベート変数
ユーティリティやヘルパーのような、コードの抽象化の為に公開メソッドが使うクラス内部からのみアクセスされるメソッドや変数は、アンダースコアでプリフィクスを付けるべきです。
convert_text() // 公開メソッド
_convert_text() // プライベートメソッド
PHP エラー
コードはエラーを起こさず、潜在的な WARNING や NOTICE もなく動作するようにしましょう。たとえば、最初に isset() で確かめずに($_POST 配列のキーのような)未定義の変数を使わないようにしてください。
アドオンの開発中はすべてのユーザに対してエラーの表示を許可し、PHP の display_errors オプションが許可に設定されていることを確認してください。設定は以下のようにすれば確認できます:
if (ini_get('display_errors') == 1)
{
exit "Enabled";
}
サーバ上で display_errors が無効であり、php.ini の編集権限が無い場合、以下のようにして有効に出来ます:
ini_set('display_errors', 1);
注意: display_errors を実行時に ini_set() で設定することと、php.ini で display_errors を「許可」に設定することは全く同じではないことに注意してください。すなわち、もしコード自体が致命的なエラー(FATAL)を含んでいる場合は(display_errors を許可に設定しても)意味が無いのです(エラーは表示されません)。
PHP 短縮開始タグ
サーバーで short_open_tag が有効でないケースもあるので、常に完全な PHP 開始タグを用います。
間違い:
<? echo $foo; ?>
<?=$foo?>
正しい:
<?php echo $foo; ?>
1行1ステートメント
1行に複数のステートメントを記述してはいけません。
間違い:
$foo = 'this'; $bar = 'that'; $bat = str_replace($foo, $bar, $bag);
正しい:
$foo = 'this';
$bar = 'that';
$bat = str_replace($foo, $bar, $bag);
文字列
文字列内で変数を展開させる必要がある場合を除いて、文字列は常にシングルクォートで囲み、変数を展開させたい場合は過剰な構文解析を防ぐために括弧"{}"で囲みます。文字列内にシングルクォートが含まれる場合は、ダブルクォートを利用する事もできます。エスケープ文字を利用してはいけません。
間違い:
"My String" // 展開される変数が無いので、ダブルクォーテーションは使いません
"My string $foo" // 括弧"{}"が必要です
'SELECT foo FROM bar WHERE baz = \'bag\'' // 見にくいです
正しい:
'My String'
"My string {$foo}"
"SELECT foo FROM bar WHERE baz = 'bag'"
SQL 文
MySQL の予約語は常に大文字で記述します: SELECT, INSERT, UPDATE, WHERE, AS, JOIN, ON, IN, などです。
読みやすさを考慮して長いクエリ文は複数行に分け、それぞれの区切りで改行するのが望ましいでしょう。
間違い:
// 予約語が小文字で、クエリ文が1行に記述するには長すぎます
// (「...」は改行せずにそのまま続いている事を意味します)
$query = $this->db->query("select foo, bar, baz, foofoo, foobar as raboof, foobaz from exp_pre_email_addresses
...where foo != 'oof' and baz != 'zab' order by foobaz limit 5, 100");
正しい:
$query = $this->db->query("SELECT foo, bar, baz, foofoo, foobar AS raboof, foobaz
FROM exp_pre_email_addresses
WHERE foo != 'oof'
AND baz != 'zab'
ORDER BY foobaz
LIMIT 5, 100");
メソッド(関数)の引数のデフォルト値
その時々に適切なメソッド(関数)のデフォルト値を設定しましょう。そうすることで、間違ったメソッド(関数)呼び出しによるPHPエラーを回避することができ、コードを数行節約できるような適切な代替値を用意することができます。例:
function foo($bar = '', $baz = FALSE)