CakePHP の開発者はコーディング規約として下記のルールに加え、 PSR-2 coding style guide にも従って頂くことになります。
その他の CakePHP プラグイン等 (訳注:原文 CakeIngredients 、ケーキの材料のこと) の開発でも同じ規約に従うことが推奨されます。
CakePHP Code Sniffer を使って、 コードが規約に沿っているかどうかをチェックすることができます。
新しい機能は、そのテストが無い限り、追加してはいけません。 このテストはリポジトリーにコミットされる前にパスする必要があります。
IDE が空白の "trim right" の設定がされているかどうかを確かめてください。 その設定で、行の空白は残りません。
最新の IDE は、 .editorconfig
ファイルをサポートします。CakePHP アプリの
スケルトンは、デフォルトで提供しています。すでにデフォルトでベストプラクティスが入っています。
IDE との互換性を最大限にしたい場合、 IdeHelper プラグインの使用をお勧めします。 アノテーションを最新の状態に保ち、IDE がすべてのクラスの仕組みを完全に理解し、 より良いタイプヒントと自動補完を提供するのを支援します。
インデントには4つの空白を用います。
従って、インデントはこのようになります。
// 基本レベル
// レベル1
// レベル2
// レベル1
// 基本レベル
または:
$booleanVariable = true;
$stringVariable = '大鹿';
if ($booleanVariable) {
echo '真偽値は true です';
if ($stringVariable === '大鹿') {
echo '大鹿に遭遇しました';
}
}
あなたが、複数行にわたる関数呼び出しを使用している場合、以下のガイドラインに従ってください。
複数行にわたる関数呼び出しのカッコを開く時には、行末になければなりません。
複数行にわたる関数呼び出しの中の1行ごとに1引数のみ許可します。
複数行にわたる関数呼び出しの閉じカッコは、1行にしなければなりません。
例として、以下の形式が使用されていた場合、
$matches = array_intersect_key($this->_listeners,
array_flip(preg_grep($matchPattern,
array_keys($this->_listeners), 0)));
代わりに以下を使用してください。
$matches = array_intersect_key(
$this->_listeners,
array_flip(
preg_grep($matchPattern, array_keys($this->_listeners), 0)
)
);
コードを読みやすくするために、だいたい 100 文字程度の長さで改行することを推奨します。 80 文字や 120 文字に制限することで、複雑なロジックや式を関数によって分割するだけでなく、 関数やオブジェクトに、短く、より表現的な名前をつけることが必要になります。 行を 120 文字より長くしてはいけません。
要約すると:
100 文字がソフトな制限
120 文字がハードな制限
制御構造は例えば "if
"、"for
"、"foreach
"、"while
"、"switch
"などです。
下記に、 "if
" の例を示します。
if ((expr_1) || (expr_2)) {
// action_1;
} elseif (!(expr_3) && (expr_4)) {
// action_2;
} else {
// default_action;
}
制御構造では1個の空白が最初の丸括弧の前に、1個の空白が最後の丸括弧と開き中括弧の間にある必要があります。
制御構造では、必要でなくとも常に中括弧を使います。 これはコードの可読性を高め、論理エラーが発生しにくくなります。
開き中括弧は制御構造と同じ行に置かれる必要があります。閉じ中括弧は新しい行に置かれ、 制御構造と同じレベルのインデントがされている必要があります。中括弧内に含まれているステートメントは 新しい行で始まり、その中に含まれるコードは、新しいレベルのインデントが付けられる必要があります。
インラインの代入は、制御構造の中で使用するべきではありません。
// 間違い=中括弧が無い、ステートメントの場所が悪い
if (expr) statement;
// 間違い=中括弧が無い
if (expr)
statement;
// よろしい
if (expr) {
statement;
}
// 間違い=インラインの代入
if ($variable = Class::function()) {
statement;
}
// よろしい
$variable = Class::function();
if ($variable) {
statement;
}
三項演算子は、三項演算子全体が1行に収まる場合に許容されます。
長い三項演算子は if else
ステートメントに分割するべきです。
どのような場合でも、三項演算子はネストしてはいけません。
見やすさのために、丸括弧を三項の条件チェックの周りに使ってもかまいません。
//良い。シンプルで読みやすい
$variable = isset($options['variable']) ? $options['variable'] : true;
//ネストされた三項はダメ
$variable = isset($options['variable']) ? isset($options['othervar']) ? true : false : false;
テンプレートファイル (拡張子が .ctp のファイル) 内では、開発者は、キーワードの制御構造を使用する 必要があります。キーワードの制御構造を使うと、複雑なテンプレートファイルが読みやすくなります。 制御構造は、大きい PHP ブロック内、または別々の PHP タグに含めることができます。
<?php
if ($isAdmin):
echo '<p>You are the admin user.</p>';
endif;
?>
<p>The following is also acceptable:</p>
<?php if ($isAdmin): ?>
<p>You are the admin user.</p>
<?php endif; ?>
値の比較は、常に可能な限り厳密に行うようにしてください。もし厳格でないテストが意図的なものであれば、 混乱を避けるためにコメントを残しておいたほうがいいかもしれません。
変数が null かどうかのテストの場合は、厳密なチェックを使用することを推奨します。
if ($value === null) {
// ...
}
チェック対象の値は右側に配置してください。
// 非推奨
if (null === $this->foo()) {
// ...
}
// 推奨
if ($this->foo() === null) {
// ...
}
関数は、関数の名前と開き括弧の間に空白を入れて呼び出してはいけません。 関数呼び出しの引数各々に対して単一の空白がある必要があります。
$var = foo($bar, $bar2, $bar3);
上記をご覧の通り、イコール記号 (=) の両サイドには単一の空白がある必要があります。
メソッドの定義の例:
public function someFunction($arg1, $arg2 = '')
{
if (expr) {
statement;
}
return $var;
}
デフォルトを用いた引数は、関数の定義の最後に置く必要があります。関数は何かを、少なくとも true か false を、関数呼び出しが成功したかどうかを判定できるように、返すように作ってみてください。
public function connection($dns, $persistent = false)
{
if (is_array($dns)) {
$dnsInfo = $dns;
} else {
$dnsInfo = BD::parseDNS($dns);
}
if (!($dnsInfo) || !($dnsInfo['phpType'])) {
return $this->addError();
}
return true;
}
イコール記号の両サイドには空白を置きます。
早期退出により不必要なネストを避けるようにしてください。
public function run(array $data)
{
...
if (!$success) {
return false;
}
...
}
public function check(array $data)
{
...
if (!$success) {
throw new RuntimeException(...);
}
...
}
これは、コードの流れをシンプルかつ容易に保つのに役立ちます。
オブジェクトや配列を期待する引数はタイプヒンティングを指定することができます。 しかしながらタイプヒンティングはコストフリーではないので、public メソッドにだけ指定します。
/**
* メソッドの説明。
*
* @param \Cake\ORM\Table $table 使用するテーブルクラス
* @param array $array 配列。
* @param callable $callback コールバック。
* @param bool $boolean 真偽値。
*/
public function foo(Table $table, array $array, callable $callback, $boolean)
{
}
ここで $table
は \Cake\ORM\Table
のインスタンスで、また $array
は array
でなければならず、 $callback
は callback
(有効なコールバック) 型でなければなりません。
ちなみに、もし $array
が \ArrayObject
のインスタンスでも受け付けるようにしたい場合は、
array
のタイプヒントを指定してプリミティブ型だけを受け入れるようにするべきではありません。
/**
* メソッドの説明。
*
* @param array|\ArrayObject $array 配列。
*/
public function foo($array)
{
}
メソッドチェーンは複数の行にまたがる複数のメソッドとなり、空白4つでインデントする必要があります。
$email->from('[email protected]')
->to('[email protected]')
->subject('A great message')
->send();
全てのコメントは英語で書かれ、コードのコメントブロックを明確な方法で記述する必要があります。
コメントは以下の phpDocumentor タグを含めることができます。
@deprecated
@version <vector> <description>
形式を使用して、 version
と description
は必須です。バージョンは非推奨のバージョンを示します。
PhpDoc タグは Java の JavaDoc タグによく似ています。 タグはドキュメントブロックの行の最初のもののみ処理されます。 例:
/**
* タグの例。
*
* @author このタグは解析されますが、この @version は無視されます
* @version 1.0 このタグも解析されます
*/
/**
* インライン phpDoc タグの例。
*
* この関数は世界征服のために foo() を使って身を粉にして働きます。
*
* @return void
*/
function bar()
{
}
/**
* Foo function.
*
* @return void
*/
function foo()
{
}
ファイルの最初のブロック以外のコメントブロックは、常に新しい行を先に置く必要があります。
ドキュメントブロックで使う変数の型:
説明
型が定義されていない(もしくは複数定義されている)変数。
Integer 型の変数 (整数)。
Float 型 (小数点のある数値)。
論理型 (true または false)。
String 型 (" " や ' ' で囲まれるすべての値)。
Null 型。通常は他の型と一緒に使われる。
配列型。
オブジェクト型。可能なら特定のクラス名を指定するべきです。
リソース型 (例えば mysql_connect() の戻り値)。型を mixed に指定する場合、 不明 (unknown) なのか、取りうる型が何なのかを指し示すべきということを覚えていてください。
呼び出し可能な関数。
パイプ文字を使って型を組合せます。
int|bool
3つ以上の型の場合は mixed
を使うほうが最良です。
チェーンのように自分自身のオブジェクトを返すような場合は代わりに $this
を使ってください。
/**
* Foo function.
*
* @return $this
*/
public function foo()
{
return $this;
}
include
、 require
、 include_once
そして require_once
は括弧を付けません。
// 間違い = 括弧あり
require_once('ClassFileName.php');
require_once ($class);
// よろしい = 括弧なし
require_once 'ClassFileName.php';
require_once $class;
クラスまたはライブラリーを伴うファイルを読み込む場合、 require_once 関数のみを常に使用してください。
常にショートタグ (<? ?>
) の代わりに、ロングタグ (<?php ?>
) を使ってください。
テンプレートファイル (.ctp) の中では適宜、ショート Echo を使ってください。
ショート Echo はテンプレートファイルの中で <?php echo
の代わりに使ってください。開きタグ、
空白1つ、 変数もしくは echo
とその引数、半角1つ、閉じタグのように記述してください。
// ダメ = セミコロンがあり、空白もない
<td><?=$name;?></td>
// OK = 空白があり、セミコロンもない
<td><?= $name ?></td>
PHP 5.4 以降、ショート Echo タグ (<?=
) はもはや 'ショートタグ' とは見なされず、
ini ディレクティブの short_open_tag
にかかわらず有効となります。
変数名はできる限り説明的に、しかしできる限り短くもしてください。すべての変数は小文字で始まり、 複数の単語の場合はキャメルバックで書く必要があります。オブジェクトを参照する変数は、 何らかの方法で変数がオブジェクトとなっているクラスに関連したものになるべきです。例:
$user = 'John';
$users = ['John', 'Hans', 'Arne'];
$dispatcher = new Dispatcher();
メソッドと変数には、PHP の public
, protected
そして private
キーワードを指定してください。
全ての URL とメールアドレスの例には、「example.com」、「example.org」、 「example.net」を使用してください。例を挙げます。
Eメール: someone@example.com
"example.com" ドメインはこの (RFC 2606 を見てください) 為に予約されており、 ドキュメント内の説明や例として使うことが推奨されています。
次のキャストを使用します。
説明
boolean にキャスト。
integer にキャスト。
float にキャスト。
string にキャスト。
array にキャスト。
object にキャスト。
できるなら intval($var)
よりも (int)$var
を、
floatval($var)
よりも (float)$var
を使ってください。
定数は大文字で定義する必要があります。
define('CONSTANT', 1);
もし定数の名前が複数の単語でできている場合は、アンダースコアー文字によって分割する必要があります。 例:
define('LONG_NAMED_CONSTANT', 2);
empty()
は、使いやすい関数ですが、エラーの隠蔽と '0'
や 0
が与えられた際に
意図しない効果を引き起こします。変数やプロパティーがすでに定義されていた場合、 empty()
の利用は推奨されません。変数を操作する際、empty()
の代わりに boolean 型への
強制変換に頼る方が良いです。
function manipulate($var)
{
// 推奨しません。 $var はすでにスコープ内で定義されています。
if (empty($var)) {
// ...
}
// boolean 型への強制変換を使用。
if (!$var) {
// ...
}
if ($var) {
// ...
}
}
定義されたプロパティーを扱っている際、 empty()
/isset()
チェックよりも
null
チェックを優先してください。
class Thing
{
private $property; // 定義済み
public function readProperty()
{
// プロパティーは、クラスで定義されているので、推奨しません。
if (!isset($this->property)) {
// ...
}
// 推奨します。
if ($this->property === null) {
}
}
}
配列を操作する際、 empty
チェックを使うよりも、デフォルト値をマージする方が良いです。
デフォルト値をマージすることによって、必要なキーが定義されることを保証できます。
function doWork(array $array)
{
// empty チェックを避けるためにデフォルト値をマージ
$array += [
'key' => null,
];
// 推奨しません。キーはすでにセットされています。
if (isset($array['key'])) {
// ...
}
// 推奨します。
if ($array['key'] !== null) {
// ...
}
}