コーディング規約

注:Drupalのコーディング規約はDrupal内のコードと寄贈モジュールに適用されます。本書は PEARコーディング規格に基づいています。

コメントや名称については、アメリカ英語のスペルで記述するようにしましょう。(例、「colour」ではなく「color」)

Drupalのコーディング規約はDrupalのバージョンには関係なく「常に最新のものを使う」という考え方に則っています。新しいコードは コアのバージョンに関わらず、最新の規約に則って記述すべきです。ただし、既存の古いバージョンのコーsドについては、更新する方が良いですが、それは必須ではありません。特に(Drupalのコアなどのように)コードベースが大きい場合には、以前のバージョンのコードを現在の規約に合わせて更新するのは非常に大変な作業となります。しかし、現在のバージョンのコードは現在の規約に従って記述するべきです。

メモ:コーディング規約の更新やクリーンアップを、関係のないパッチに入れるのは避けてください。関連するコード行だけを変更してください。また、既存のコードを最新の規約に合わせて更新する際は常に別々のパッチを用意してください。
コーディング規約の問題(あるいは問題を修正すること)に関連したコードレビューが可能なモジュール情報については、このページの最下部のヘルパーモジュールセクションを参照してください。

コーディング規約への変更点の提案については、まずCoding Standards issue queueで議論されます。
Drupalのコーディング規約の詳細・重要性・使い方については、Drupal コーディング規約を理解するを参照してください。

インデントとホワイトスペース

インデントはタブではなく空白2つを使ってください。

行末には空白は置かないでください。

ファイルの改行は \n (Unixの改行)を使い、 \r\n (Windowsの改行)は使わないでください。

テキストファイルはすべて改行ひとつで終わらせてください。そうすることで、「No newline at end of file」というパッチ警告が出なくなり、ファイルの末尾に行が追加されたときのパッチが読みやすくなります。

演算子

+ - = != == > などの二項演算子(ふたつの値の間に入る演算子)は、読みやすさのためその前後に空白を置いてください。たとえば代入は $foo=$bar; ではなく $foo = $bar; としてください。 ++ などの単項演算子(ひとつの値だけの演算に使うもの)は演算子と値や数値との間に空白ははさまないでください。

キャスト

(型名) と $変数名 との間に空白をおいてください。たとえば(int) $mynumber など。

制御構造

制御構造とは if for while switch などです。このうち最も複雑なのが if文なので、そのサンプルを見てみましょう。

if (condition1 || condition2) {
  action1;
}
elseif (condition3 && condition4) {
  action2;
}
else {
  defaultaction;
}

注: 「else if」は使わないこと。必ず elseif を使ってください。

制御文は制御キーワードと丸括弧との間に空白を入れてください。これは関数呼び出しと区別するためです。

中括弧は、技術的にはオプションである場合でも必ず使うようにしましょう。それらがある方が読みやすさが向上しますし、新しい行が追加されたときにロジックエラーが起こる可能性を軽減できます。

switch 文の場合:

switch (condition) {
  case 1:
    action1;
    break;

  case 2:
    action2;
    break;

  default:
    defaultaction;
}

do-while 文の場合:

do {
  actions;
} while ($condition);

テンプレートのための別の制御文シンタックス

<?php if (!empty($item)): ?>
  <p><?php print $item; ?></p>
<?php endif; ?>

<?php foreach ($items as $item): ?>
  <p><?php print $item; ?></p>
?php endforeach; ?>

行の長さ・折り返し

以下のルールを適用しましょう。コメントについてはDoxygenとコメントの書き方の規約に目を通しましょう

一般的に、行はすべて 80 文字以下の長さにしてください。

それよりも長い名前、関数、クラスの定義や変数宣言などを含む行の場合は 80 文字を超えてもかまいません。

制御構造は、読みやすくわかりやすいシンプルなものであれば、 80 文字を超えてもかまいません。以下が例です。

  if ($something['with']['something']['else']['in']['here'] == mymodule_check_something($whatever['else'])) {
    ...
  }
  if (isset($something['what']['ever']) && $something['what']['ever'] > $infinite && user_access('galaxy')) {
    ...
  }
  // Non-obvious conditions of low complexity are also acceptable, but should
  // always be documented, explaining WHY a particular check is done.
  if (preg_match('@(/|\\)(\.\.|~)@', $target) && strpos($target_dir, $repository) !== 0) {
    return FALSE;
  }

条件は複数行にわたって書かないでください。

制御構造の条件では、「Most Compact Condition In Least Lines Of Code Award」を獲得しようとしてはいけません。以下が例です。

  // DON'T DO THIS!
  if ((isset($key) && !empty($user->uid) && $key == $user->uid) || (isset($user->cache) ? $user->cache : '') == ip_address() || isset($value) && $value >= time())) {
    ...
  }

代わりに、複数の条件を切り分けて個別の条件として準備する形がお薦めの方法です。そうするとそれぞれの条件に対するコメントを書くこともできるようになります。

  // Key is only valid if it matches the current user's ID, as otherwise other
  // users could access any user's things.
  $is_valid_user = (isset($key) && !empty($user->uid) && $key == $user->uid);

  // IP must match the cache to prevent session spoofing.
  $is_valid_cache = (isset($user->cache) ? $user->cache == ip_address() : FALSE);

  // Alternatively, if the request query parameter is in the future, then it
  // is always valid, because the galaxy will implode and collapse anyway.
  $is_valid_query = $is_valid_cache || (isset($value) && $value >= time());

  if ($is_valid_user || $is_valid_query) {
    ...
  }

注: このコード例はまだ少し難解です。コードを知らない人たちが、そのロジックを理解することができるか、いつも自分なりに考え決断するようにしましょう。

関数呼び出し

関数は、関数名と開き括弧、開き括弧と最初の引数との間には空白を入れずに呼び出してください。各”,”とパラメータの間には空白を入れ、最後のパラメータと閉じ括弧、閉じ括弧とセミコロン(;)の間には空白を入れないでください。以下が例です。

$var = foo($bar, $baz, $quux);

上記のとおり、関数の戻り値を変数に代入する際の等号(=)については、その前後に空白を1ついれるようにしてください。関係のある代入式ブロックがある場合には、読みやすさを上げるためもっとたくさんの空白を入れてもかまいません。

$short         = foo($bar);
$long_variable = foo($0baz);

関数宣言

function funstuff_system($field) {
  $system["description"] = t("This module inserts funny text into posts randomly.");
  return $system[$field];
}

デフォルト値を持った引数は引数リストの末尾に置くようにしてください。関数はそれが適切な値であれば必ず意味のある数値を返すように心がけましょう。

クラスコンストラクタ呼び出し

引数なしでクラスコンストラクタを呼び出すときには、常に括弧をつけましょう。

$foo = new MyClassName();

これは引数を持つコンストラクタとの間で一貫性を持たせるためです。

$foo = new MyClassName($arg1, $arg2);

クラス名が変数の場合は、まず変数がクラス名を取得するために評価され、それからコンストラクタが呼び出されます。共通のシンタックスを使いましょう。

$bar = 'MyClassName';
$foo = new $bar();
$foo = new $bar($arg1, $arg2);

配列

配列は各要素を分けるために(コンマのあとに)空白を入れ、また、”=>” の前後には空白を入れるようにしてください。

$some_array = array('hello', 'world', 'foo' => 'bar');

配列を宣言する行が 80文字を越える場合は(フォームやメニューの宣言など)、各要素をインデントした形で1行ずつに分けて配置してください。

$form['title'] = array(
  '#type' => 'textfield',
  '#title' => t('Title'),
  '#size' => 60,
  '#maxlength' => 128,
  '#description' => t('The title of your node.'),
);

注:配列最後の要素の末尾にあるカンマは記述誤りではありません。
リストの最後に要素が追加された場合、解析エラーの発生を防ぐことができます。

PHP5.4以降の配列の短縮構文の使用についてDrupal8においては議論されており、すでに幾つかのパッチでは使用されています。使用する場合は、少なくともメソッドもしくは関数全体で一貫して使用するようにしてください。配列の短文構造は、Drupal7やDrupal6の、コアや寄贈モジュールでは使用しないでください

引用符

Drupalにはシングルクォートとダブルクォートの使用に関して厳しい基準はありません。可能であれば、各モジュール内で一貫性を保ち、開発者の個人的なスタイルを尊重しましょう。

このことを考慮した上で、シングルクォートの文字列をデフォルトで使用します。シングルクォートは以下の2つの場合は、推奨されません。

  1. 「<h2>$header</h2>」 などの意図的なインライン変数の挿入。
  2. 翻訳用の文字列などで、ダブルクォートで囲うことにより、シングルクォートをエスケープするのを避ける場合。例えば、“He's a good person.”は、シングルクォートを使うと 'He\'s a good person.' となる。このようなエスケープは、言語翻訳のための .pot ファイルジェネレータでは適切に処理されない可能性があります。また、少し読みづらいです。

文字列連結

読みやすいように、ドットと連結される文字列の間には必ず空白を入れましょう。

<?php 
  $string = 'Foo' . $bar;
  $string = $bar . 'foo';
  $string = bar() . 'foo';
  $string = 'foo' . 'bar';
?>

簡単な変数を連結する時は、ダブルクォートを使用し、内部に変数を追加することが出来ます。それ以外では、シングルクォートを使用します。

<?php
  $string = "Foo $bar";
?>

結合代入演算子(.=)を使う際は、演算子の前後にスペースを置きましょう。

<?php
$string .= 'Foo';
$string .= $bar;
$string .= baz();
?>

コメント

コメントの規約は、別途、Doxygenとコメントスタイルの規約の議論ページで議論されています。

コードの読み込み

無条件にクラスファイルを読み込む場所ではrequire_once() を使いましょう。条件付きでクラスファイルを読み込む場所(たとえばファクトリメソッドなど)では include_once() を使いましょう。どちらの場合もクラスファイルは一度だけ読み込まれます。同一のファイルリストが共有されるので、混在して使っても問題ありません。require_once() で読み込まれたファイルが再び include_once() で読み込まれることはありません。

注: include_once() や require_once() は宣言文であり、関数ではありません。読み込むファイル名の前後に括弧をおく必要ありません。

同じディレクトリやサブディレクトリからコードを読み込むときは、ファイルパスを "." で始めましょう。

include_once ./includes/mymodule_formatting.inc

Drupal7.Xとそれ以降のバージョンでは、 DRUPAL_ROOTを使いましょう。

require_once DRUPAL_ROOT . '/' . variable_get('cache_inc', 'includes/cache.inc');

モジュールでインクルードする場合は以下となります。

module_load_include('inc', 'node', 'node.admin');

PHP コードタグ

PHP コードを区切る場合は必ず を使い、省略形のは使わないようにしましょう。これは Drupal準拠のためには欠かせないもので、異なる OS や環境で PHP コードを読み込むうえで最も移植性の高い方法です。

Drupal4.7以降、コード・ファイルの末尾の ?> は意図的に省略することに注意してください。これはモジュールとインクルードファイルにもあてはまります。この理由は以下のとおりです。

  • ?> を削除することで 「header already sent」 エラーや XHTML/XML バリデーションの問題、その他の問題の原因となりうるファイル末尾の空白が生じることはなくなります。
  • ファイル末尾の?>は任意です。
  • PHP.net 自体、ファイル末尾の ?> は省かれています(例:prepend.inc)。したがって、?>を省略するのが「ベストプラクティス」でしょう。

セミコロン

PHP 言語では、ほとんどの行末尾にセミコロンが必要ですが、コードブロックの末尾では省略することも可能です。ただし、Drupalのコーディング規約では、コードブロックの末尾においてもセミコロンは必須です。特に、一行の PHP ブロックの場合には注意が必要です。

<?php print $tax; ?> -- YES
<?php print $tax ?> -- NO

URLsの例

RFC 2606に基づき、全てのURLの用例には、必ず「example.com」を使いましょう。

命名規約

関数・変数
関数と変数名には小文字を使い、単語は ‘_’ で繋げてください。さらに関数については、モジュール間の名前の重複を防ぐため、モジュール名を頭につけてください。
永続変数
永続変数(Drupalのvariable_get()/variable_set() 関数を使って定義された変数や設定のこと)は、すべて小文字で記述し、単語は ‘_’ で繋げてください。モジュール間の名前の重複を防ぐため、モジュール名を頭につけて使用してください。
定数
  • 定数は必ずすべて大文字にし、単語を分けるために ‘_’ を使用してください。(TRUE FALSE NULL のような定義済みの PHP 定数も含まれます。)
  • モジュールで定義された定数の名前には、大文字モジュール名を先頭に置いてください。
  • Drupal8 および以降では、パフォーマンスが良くなるので、定数には(define() のかわりに) PHPのconstキーワードを使うようにしてください。
/**
 * Indicates that the item should be removed at the next general cache wipe.
 */
 const CACHE_TEMPORARY = -1;

注: constは PHPコードでは使えないことに注意が必要です。条件付きで定数を定義する時やリテラル以外の値を使って定義するときにはdefine() を使いましょう。

if (!defined('MAINTENANCE_MODE')) {
  define('MA
		INTENANCE_MODE', 'error');
}
グローバル変数
グローバル変数を定義する必要がある場合、変数名は‘_’で始めて、そのあとにモジュール・テーマ名などを ‘_’ で繋げてください。
クラス
命名規約を含むクラスとインタフェース関連の規約はすべて、http://drupal.org/node/608152に記載されています。
ファイル名
ドキュメントファイルはすべて、Windows システムで簡単に閲覧できるようにファイル名拡張子を「.txt」にしてください。また、ドキュメントファイル名はすべて大文字とし( readme.txt ではなく README.txt )、拡張子はすべて小文字と( TXT ではなく txt )してください。
例: README.txt INSTALL.txt TODO.txt CHANGELOG.txt など。

ヘルパー・モジュール

コーディング規約に準拠しているかどうかのレビューを支援する寄贈モジュールやプロジェクトがいくつかあります。

Coder モジュール。Coder Review(レビュー)とCoder Upgrade(コードの更新)の両方の機能があります。利用するには:
  1. (他のモジュールと同じように)モジュールをインストールしてください。
  2. ナビゲーション・メニューの「Code Review」のリンクをクリックしてください。
  3. 「Select Specific Modules」のところまでスクロールしてください。
  4. レビューしたいモジュールを選択し「Submit」ボタンをクリックしてください。
ナビゲーションメニューの「Code Review」からではなく、モジュール管理画面でレビューを行いたいモジュールのリンクをクリックしても同様の処理が行えます。
Dreditor(パッチなどをレビューするためのブラウザプラグイン)
PAReview(コーディングテストを実行してプロジェクトのアプリケーションをレビューするためのスクリプト)
Coder Sniffer(Drupalをロードすることなくコーディング規約のバリデーションを実行するもの)
Grammar Parser モジュールはコーディング規約に準拠した形でコード・ファイルを自動的に書き換える機能を提供します。さらに、Grammar Parser UIモジュールがあると便利です。

翻訳元URL:https://www.drupal.org/coding-standards