コーディングスタイル

提供:MoodleDocs
移動先:案内検索

概要

範囲

このドキュメントではMoodleコードに取り組む開発者に対する「スタイル」ガイドラインを示します。ここでは純粋にコードレイアウトの構造および私たちがMoodleのために選択にした内容に関して述べます。この仕様の目的は異なる開発者によるコードを検索する際の認知的摩擦を避けることにあります。これは共有規則一覧およびPHPコード書式の期待値により実現します。

特に他で規定がない限り、このコーディングスタイルドキュメントは PSR-12PSR-1の順で従います。

文書化されていない「デファクトMoodleスタンダード」に遭遇した場合、適切に「MDLSITE」で問題を提起した上でこのコーディングスタイルガイドの中に文書化するか、却下して代わりにPSR勧告を採用すべきです。

* 「デファクトMoodleスタンダード」は一般的にMoodleで使用されるコーディングスタイルです。

ゴール

すべての開発プロジェクト、特に多くの開発者が参加するプロジェクトにおいてコーディングスタイルの一貫性は重要なことです。標準的なスタイルでコードを簡単に読んで理解できるようになるため、結果として全体のクオリティの向上に寄与します。

私たちの努力目標要約:

  • 簡単さ
  • 読みやすさ
  • ツールの親切さ (メソッドシグナチャ、定数、IDEツールをサポートするパターン、自動作成メソッド、クラスおよびの定数名の使用)

上のゴールを考慮する場合、それぞれの局面で環境試験および様々なトレードオフのバランスが必要です。

既存の多くのMoodleコードはこれらすべてのガイドラインには従っていない可能性があります - 私たちは発見次第、引き続きコードをアップグレードします。

Moodle APIの利用に関する詳細はコーディングガイドラインをご覧ください。

便利なツール

このガイドに準拠したコードを書くため、あなたにはいくつかの異なるツールが用意されています。

コードチェッカ (eclipse/phpstormとの統合)
https://moodle.org/plugins/view.php?plugin=local_codechecker
Moodle PHPdocチェッカ
https://moodle.org/plugins/local_moodlecheck

両者とも若干チェック方法が異なるため、自分が書いているコードのチェックに両ツールを使用する価値はあります。 この2つの条件を満たすコードを作成できた場合、あなたの作業を確認する人たちと仲良くなれます。

ファイルフォーマッティング

PHPタグ

常に「長い」PHPタグを使用してください。 ただし、ホワイトスペースの問題を避けるため、ファイルの一番最後に閉じタグを含めないでください。

<?php

require('config.php');

インデント

インデントには タブ文字ではない「半角4スペース」を使用してください。ソースコードに新しいタブ文字が入るのを防ぐため、タブをスペースとして扱うようエディタを設定する必要があります。

メインのスクリプトレベルではインデントしないでください:

良い: <?php require('config.php'); $a = required_param('a', PARAM_INT); if ($a > 10) {

   call_some_error($a);

} else {

   do_something_with($a);

}

悪い: <?php

   require('config.php');
   $a = required_param('a', PARAM_INT);
   if ($a > 10) {
       call_some_error($a);
   } else {
       do_something_with($a);
   }

SQLクエリでは特別なインデントを使用しています。詳細はSQLコーディングスタイルをご覧ください。

最大行長

重要なのは読みやすさです。

便利な場合は132文字を目安にしてください。180文字以上はお勧めしません。

例外は/langディレクトリにある文字列ファイルです。$string['id'] = 'value';という行では値を任意の長さの単一の文字列として定義して引用符で囲む必要があります (連結演算子、heredoc、newdoc構文は使用できません)。これによりこれらの文字列ファイルをPHPコードとして含めることなく構文解析して処理できます。

行の折り返し

行を折り返す場合、一般的に以下のルールを適用してください:

  • デフォルトでは半角4スペースでインデントしてください。
  • 制御文の条件または関数/クラスの宣言で行を折り返した場合、それに続く制御文や関数/クラス本文と視覚的に区別するため、さらに4つの半角スペースでインデントしてください。

以下のセクションの例をご覧ください。

行の折り返しコントロール構造

while ($fileinfolevel && $params['component'] === 'user'

       && $params['filearea'] === 'private') {
   $fileinfolevel = $fileinfolevel->get_parent();
   $params = $fileinfolevel->get_params();

}

IF条件文の行の折り返し

特別なことはなく、制御構造のルールが適用されます。 if (($userenrol->timestart && $userenrol->timestart < $limit) ||

       (!$userenrol->timestart && $userenrol->timecreated < $limit)) {
   return false;

}

しかし、1つの制御構造の中にいくつかの条件がある場合、条件を評価するためのヘルパ変数を設定することで読みやすさが向上します。 $iscourseorcategoryitem = ($element['object']->is_course_item() || $element['object']->is_category_item()); $usesscaleorvalue = in_array($element['object']->gradetype, [GRADE_TYPE_SCALE, GRADE_TYPE_VALUE]);

if ($iscourseorcategoryitem && $usesscaleorvalue) {

   // これにより条件の確認および理解が容易になります。

}

次と比較してください。 // これはしないでください。 if (($element['object']->is_course_item() || $element['object']->is_category_item())

       && ($element['object']->gradetype == GRADE_TYPE_SCALE
       || $element['object']->gradetype == GRADE_TYPE_VALUE)) {
   // 複雑な条件の長すぎる行は適切にインデントされたとしても敬遠されます。

}

クラス宣言の折り返し

class foo implements bar, baz, qux, quux, quuz, corge, grault,

       garply, waldo, fred, plugh, xyzzy, thud {
   // Class body indented with 4 spaces.
   // クラス本体は半角4スペースでインデントします。

}

また、あなたが読みやすさを考慮する場合、それぞれ実装されているインターフェイスを1行にまとめてもよいでしょう:

class provider implements

       // これらの行はクラス本体と視覚的に区別するため、半角8スペースでインデントされています。
       \core_privacy\local\metadata\provider,
       \core_privacy\local\request\subsystem\provider,
       \core_privacy\local\request\core_userlist_provider {
   // クラス本文は半角4スペースでインデントします。

}

関数シグナチャの折り返し

/**

* ...
*/

protected function component_class_callback_failed(\Throwable $e, string $component, string $interface,

       string $methodname, array $params) {
   global $CFG, $DB;
   if ($this->observer) {
       // ...
   }

}

関数呼び出しパラメータの折り返し

通常、パラメータは1行に収まるようになっています。しかし、長過ぎて1行に収まらない場合、または読みやすくしたい場合、半角スペース4個でインデントしてください。

do_something($param1, $param2, null, null,

   $param5, null, true);

配列での折り返し

特別なことはなく、再度一般的なルールが適用されます。折り返し行を半角スペース4個でインデントしてください。 $plugininfo['preferences'][$plugin] = ['id' => $plugin, 'link' => $pref_url,

   'string' => $modulenamestr];

多くの場合、以下のようにぞれぞれの項目を一行にまとめたスタイルの方がコードが読みやすくなります。

$plugininfo['preferences'][$plugin] = [

   'id' => $plugin, 
   'link' => $pref_url, 
   'string' => $modulenamestr,

]; 最後の項目には末尾にカンマが残っていることに注意してください。これにより後で項目のリストを拡張して、よりきれいな差分を取れます。また、同じ理由で代入演算子は揃えない方が良いでしょう。

関数のパラメータとして渡された配列の折り返し

これは上のいくつかの例を組み合わせた例に過ぎません。 $url = new moodle_url('/course/loginas.php', [

   'id' => $course->id,
   'sesskey' => sesskey(),

]);

行の終端処理

標準的な「Unix」テキストフォーマットを使用してください。行末はラインフィード (LF) のみ使用できます。改行は序数10または16進数0x0Aで表されます。

古いマッキントッシュコンピュータのようにキャリッジリターン (CR) を使用しないでください (0x0D)。

Windowsコンピュータのようにキャリッジリターンとラインフィードの組み合わせ (CRLF) を使用しないでください (0x0D, 0x0A)。

行の最後にはスペースを入れないでください。この規則を守るため、ほとんどのエディタでは保存時等に末尾のスペースを削除するよう設定できます。

しかし、あなたが既存のMoodleファイルを編集しながら統合のために変更を適用しようとしている場合、空白の変更がパッチを汚染しないようにこの機能を無効にしてください (すべての行が空白のために編集されている場合、他の開発者はあなたの作業を確認しづらくなります)。

命名規則

ファイル名

ファイル名は:

  • すべて英語にしてください。
  • 可能な限り短くしてください。
  • 英語小文字のみ使用してください。
  • 次の拡張子で終えてください: .php, .html, .js, .css, .xml

クラス

クラス名は常に半角小文字の英語を使用してください。また、アンダースコアで区切ってください。

class some_custom_class {

   function class_method() {
       echo 'foo';
   }

}

コンストラクタがパラメータを必要としない場合でも、新しいインスタンスの作成時には必ず () を使用してください。

$instance = new some_custom_class();

例えば、$DB->insert_recordでデータベースに挿入するデータを用意する場合等、 特定のクラスを持たないプレーンなオブジェクトが必要な場合、 PHPの標準クラス「stdClass」を使用してください。例えば以下のようになります:

$row = new stdClass(); $row->id = $id; $row->field = 'something'; $DB->insert_record('table', $row);

Moodle 2.0以前ではstdClassを拡張したクラス「object」を定義してnew object()を使用していました。これは廃止されたため、代わりにstdClassを使用してください。

関数およびメソッド

関数名はシンプルな英語の小文字およびプラグイン間の衝突を避けるためフランケンスタイルの接頭辞およびプラグイン名で始めてください。単語はアンダースコアで区切ってください。

冗長の推奨: 関数名は理解を深めるために実用的な範囲の例示を推奨します。

PHPではすべての新しいコードにおいて可能な限りすべての場所でタイプヒントおよび戻り値の型の宣言の使用が必要です。ただし、既存の非準拠のコードを拡張するコード、使用できないものを実装する場合等、必要な除外事項もあります。段階的なアプローチが適用されます。

関数名とそれに続く (括弧) の間にはスペースがないことに注意してください。また、ヌル文字 (クエスチョンマーク - ?) およびパラメータまたは戻り値の型の間、関数の閉じ括弧およびコロンの間にも空白はありません。

function report_participation_get_overviews(string $action, ?int userid): ?array {

   // 実際の関数のコードをここに記述します。

}

ただし、活動モジュールのようにレガシーな理由でプラグイン名のみを接頭辞として使用しているものは除きます。

function forum_set_display_mode($mode = 0) {

   global $USER, $CFG;
        
   // 実際の関数のコードをここに記述します。

}

関数パラメータ

パラメータには常にシンプルな小文字の英単語 ($initialvalueのように複数の場合もあります) を使用してください。また、可能であれば常に適切なデフォルト値を持つべきです。

このようにデフォルト値が必要ではない場合、「false」の代わりに「null」を使用してください。 public function foo($required, $optional = null)

ただし、オプションパラメータがbooleanであり、その論理的なデフォルト値が「true」または「false」であるべき場合、「true」または「false」を使用できます。

変数

変数名は常に読みやすく、意味のある小文字の英単語にしてください。どうしても2つ以上の単語が必要な場合、それらをまとめて使用できますが、できるだけ短くしてください。オブジェクトの配列には「複数」名を使用してください。また、常に正の変数名を使用してください(使用可:「enable」、使用不可:「prevent」「disable」)。

良い: $quiz
良い: $errorstring
良い: $assignments (for an array of objects)
良い: $i (but only in little loops)
良い: $allowfilelocking = false
悪い: $Quiz
悪い: $camelCase
悪い: $aReallyLongVariableNameWithoutAGoodReason
悪い: $error_string
悪い: $preventfilelocking = true

Moodleのコアグローバル変数は英語の大文字の変数で識別されます (例 $CFG, $SESSION, $USER, $COURSE, $SITE, $PAGE, $DBおよび$THEME)。これ以上作成しないでください!

定数

定数は常に大文字およびフランケンスタイルの接頭辞およびプラグイン名で始めてください (活動の場合、レガシーな理由でモジュール名のみ)。単語はアンダースコアで区切ってください。

define('BLOCK_COURSE_OVERVIEW_SHOWCATEGORIES_NONE', '0'); define('FORUM_MODE_FLATOLDEST', 1);

ブール値およびヌル値

truefalsenullには小文字を使用してください。

ネームスペース

Moodleのすべての新しいクラスには正式なネームスペースが必要です。以下の例外があります:

  1. 既存の非ネームスペースクラスをネームスペースに移行する必要はありません。
  2. クラスを読み込むための既存のメカニズムが存在、そして、そのメカニズムが名前付きクラスの使用をサポートしていない場合、クラス名に既存のフランケンスタイル接頭辞の付加が許可されます。

クラス名でのクラス名のフランケンスタイル接頭辞の使用は非推奨であり、前述の例外にのみ使用すべきです。

良い: namespace mod_forum; class example { }

namespace mod_forum\external; class example { }

namespace core_user; class example {}

悪い (廃止): class mod_forum_example { }

class mod_forum_external_example { }

class core_user_example { }

ネームスペースの使用は、以下のルールに準拠する必要があります:

  1. ネームスペースに属するクラスはプラグイン内のclassesディレクトリ (mod/forum/classes等) またはコアコードの場合はlib/classesまたはsubsystemdir/classesに作成する必要があります。
  2. すべてのネームスペースクラスのクラス名およびファイル名は自動クラス読み込みのルールに従う必要があります。すべての新しいコードではPHPの正式なネームスペースクラスの使用が必要です。
  3. ファイルごとに最大1つのネームスペース宣言を使用してください。

良い: <? // This is a file mod/porridge/classes/local/equipment/spoon.php

namespace mod_porridge\local\equipment;

class spoon {

   // あなたのコードをここに記述します。

}

// End of file.

悪い: namespace mod_porridge\local\equipment;

class spoon {

   // あなたのコードをここに記述します。

}

namespace mod_porridge\local\procedures; // 私たちはここでネームスペースを変更します。これはやめてください。

class eat {

   // 別のコードをここに記載します。

}

// End of file.

ネームスペース宣言の前にはdocブロックを付加できます。

クラスネーミングルールはそれぞれのレベルのネームスペースにも適用されます。

ネームスペース宣言はファイルの先頭の非コメント行に記述してください。その後、1行の空行、(任意の) 「use」ステートメントが続きます。 「use 」ステートメントは1行に1つずつ記述して、その後に空行を1行記述してください。

コードの中で長いネームスペースが繰り返されないように「use」ステートメントを使用する必要があります。

「use」ステートメントでネームスペース全体をインポートするのではなく、個々のクラスのみをインポートしてください。

衝突を回避するため、絶対に必要な場合を除き名前付きインポート (「XXXXをYYYとして使用」) を使用しないでください。

良い:

use mod_porridge\local\equipment\spoon; // 1行あたり1クラス use mod_porridge\local\equipment\bowl; // 1行あたり1クラス

悪い:

use mod_porridge\local\equipment\spoon, mod_porridge\local\equipment\bowl; // 1行あたり複数クラス use mod_porridge\local; // ネームスペース全体をインポートする use core; // ネームスペース全体をインポートする use mod_breakfast; // ネームスペース全体をインポートする use mod_porridge\local\equipment\spoon as silverspoon; // 理由のない名前付きインポート

the __NAMESPACE__ magic定数は使用しないでください。

「namespace」キーワードはネームスペース宣言以外では使用しないでください。

悪い: $obj = new namespace\Another();

括弧付きの「namespace」ブロックは使用しないでください。

悪い: namespace {

   // Global scope.

}

ネームスペースは「classes」のサブフォルダに存在するクラスにのみ使用する必要があります。

新しいクラスの場合 - ネームスペースの決定時に最大レベルの詳細を使用する必要があります。

良い: namespace xxxx\yyyy; // 「xxxx」はコンポーネント、「yyyy」はapiです。

class zzzz { }

「namespace」および「use」の記述では先頭にバックスラッシュ (/) を使用しないでください。

ネームスペースのコードから呼び出されるグローバル関数には先頭にバックスラッシュ (\) を使用しないでください。

現在のスコープの外にあるクラスは先頭のバックスラッシュを使用してください。そうでない場合、「use」キーワードでインポートされます。詳細はPHPマニュアルを参照してください。

良い: namespace mod_breakfast\local;

use moodle_url;

echo get_string('goodmorning', 'mod_breakfast'); // グローバル関数の先頭にはバックスラッシュを付けないでください。 $url = new moodle_url(...); //「use」でネームスペースにインポートしたため、ここでは先頭のバックスラッシュは必要ではありません。 $tasks = \core\task\manager::get_all_scheduled_tasks(); // ここでは先頭のバックスラッシュが必要です。 $a = new \stdClass(); // ここでは先頭のバックスラッシュが必要です。

悪い: namespace \mod_breakfast; // ここでは先頭のバックスラッシュは不要です。

use \core\task\manager; // ここでは先頭のバックスラッシュは不要です。

\get_string('xxxx', 'yyyy'); // ここでは先頭のバックスラッシュは不要です。

ネームスペースのパーツ

以下のようなクラスの完全修飾名が与えられます:

"\<level1>\<level2>\<level3>\...\<classname>"

ネームスペースの各レベルで何が許されるのか、明確なルールがあります。第一階層のみ必須です。入れ子になったネームスペースはクラスが何らかのコアAPIを実装している場合やプラグインのメンテナがプラグイン内でクラスを別のネームスペースに整理したい場合に使用されます。詳細はレベル2に関するルールをご覧ください。

レベル1のルール

最初のレベルは以下のいずれかでなければなりません:

  • 完全なコンポーネント名 (例: \mod_forum)。プラグインでネームスペースを使用するすべてのクラスはこのレベル1のネームスペースに含まれなければなりません。

または

  • すべてのコアAPIのための"\core"

レベル2のルール

2番目のレベルは以下のいずれかでなければなりません:

または

  • "\local"はメインテナがさらに整理したい場合のクラスコンポーネント内の他のすべてのクラス用です (恐らく、ほとんどのコンポーネントではルートレベル1のネームスペースのみの自クラスで十分です)。

レベル3のルール

レベル3のネームスペースとして使用できるものを制限する規則はありません。ここではプラグインまたはアドオンが他のプラグインまたはAPIと衝突することなく、ネームスペースを広範囲に使用できます。今後も同様に使用できます。

**/testsディレクトリ内のネームスペース

(agreed @ MDLSITE-4800)

  • テストの際にはネームスペースの使用が推奨されます。そして、テスト済み/カバー済みコードのネームスペースと一致させるのが刺激的な方法です。
  • 第1レベルのネームスペースは属するコンポーネントと100%一致します。
  • サブネームスペースは許可されていますが、前述のレベル2および3の一般的なネームスペースのルールに厳密に従っています。

良い: namespace mod_breakfast; // ネストしたネームスペース を使用していない場合のプラグイン独自のネームスペース (典型的なもの) namespace mod_breakfast\local; // ネストしたネームスペース を使用する際のプラグイン自身のネームスペース namespace mod_breakfast\local\utils; // ネストしたネームスペース をさらに整理して使用する場合のプラグインの独自のネームスペース namespace mod_breakfast\event; // コアAPIを実装するためのプラグインのネームスペース

悪い: namespace mymodule; // レベル1のルールに違反 - 無効なコンポーネント名 namespace mod_breakfast\myutilities; // レベル2のルールに違反 - 無効なコアAPI名 namespace mod_forum\test; // 技術的には正しいのですが (「test」は有効なAPIです)、OKではありません。

                                       // なぜなら、テストの名前空間は対象となるコードの名前空間と一致しなければならないため、
                                       // 通常コンポーネントには対象となる「テスト」レベル2は存在しないからです。
                                       // このような場合にのみ使用できます。

ストリング Strings

現在のバージョンのPHPでは文字列のパフォーマンスは問題にならないため、文字列の主な基準は可読性です。

一重引用符 Single quotes

文字列がリテラルである場合や二重引用符を多く含む場合 (HTML等)、常に一重引用符を使用してください:

$a = 'ストリング例'; echo ''; $html = '<a href="http://something" title="something">リンク</a>';

二重引用符

これらはMoodleではあまり役に立たないものです。プレーンな変数や多くの一重引用符を含める必要がある場合、二重引用符 を使用してください。

echo "$string"; $statement = "本気じゃないでしょ!";

複雑なSQLクエリは常に二重引用符で囲む必要があります。

$sql = "SELECT e.*, ue.userid

         FROM {user_enrolments} ue
         JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'self' AND e.customint2 > 0)
         JOIN {user} u ON u.id = ue.userid
        WHERE :now - u.lastaccess > e.customint2";

変数の置換

変数の置換には以下のような形式があります:

$greeting = "$name さん、おかえりなさい!";

$greeting = "{$name} さん、おかえりなさい!";

文字列の連結

文字列は「.」演算子を使って連結する必要があります。

$longstring = $several.$short.'ストリング';

行が長い場合、複数行に分けて文を読みやすくしてください。このような場合、各行の最後に「ドット (.)」を入れてください。

$string = 'これは非常に長く愚かなストリングです。なぜなら、'.$editorname.
          ' が良い例文を思いつかなかったからです。';

ドット演算子は上の例のように左右にスペースを入れずに使用できます。また、左右にスペースを入れても使用できます。どちらにしても、開発者の好みに合わせて使用できます。

言語ストリング

大文字

言語ストリングは常に次のように記述してください: "Always look like this" そして、次のようには記述しないでください: "Never Like This Example".


大文字は以下の場合のみ使用してください:

  1. 文の始め、または
  2. 「Moodle」のような固有名詞の始め

構造

他の言語で問題が発生する可能性があるため、文字列はUIの連結のために設計されるべきではありません。また、各文字列は独立していなければなりません。

悪い:

$string['overduehandling'] = '受験期限が終了した場合';
$string['overduehandlingautosubmit'] = '受験は自動的に送信されます。';
$string['overduehandlinggraceperiod'] = '受験提出の猶予期間はありますが、それ以上の問題には';
$string['overduehandlingautoabandon'] = '答えられません。時間切れになる前に送信しない場合、カウントされません。';

良い:

$string['overduehandling'] = '時間制限の挙動';
$string['overduehandlingautosubmit'] = '未完了の受験は直ちに送信されます。';
$string['overduehandlinggraceperiod'] = '未完了の受験には評定のための送信猶予期間があります。';
$string['overduehandlingautoabandon'] = '未完了の受験は直ちに破棄されます。';

配列

数値インデックス付き配列

配列を宣言する場合、読みやすさを向上させるため、各コンマ区切りの後にスペースを追加する必要があります:

$myarray = [1, 2, 3, 'Stuff', 'Here'];

複数行のインデックス付き配列でも問題ありませんが、前述のように連続する各行に半角4スペースのインデントを入れてください:

$myarray = [1, 2, 3, 'Stuff', 'Here',

   $a, $b, $c, 56.44, $d, 500];

上の例は以下のようにも記述できることに留意してください:
(注意を引く目的で行末にカンマを付加することにより、後でリスト項目を追加しやすくなります)

$myarray = [

   1, 2, 3, 'Stuff', 'Here',
   $a, $b, $c, 56.44, $d, 500,

];

いずれにしても、1行のアイテム数に関わらず括弧および改行のバランスを取る必要があります。

連想配列

読みやすさを考慮して複数行にも記述できます。例えば以下のようになります:

$myarray = [

   'firstkey' => '最初の値',
   'secondkey' => '2番目の値',

];

クラス宣言

  • クラスはMoodleの命名規則に従って命名する必要があります。
  • 自動読み込みやネームスペーシングの利点を得るため、クラスはそれぞれ「component/classes」ディレクトリ配下に置く必要があります。そこから外に出した場合、そのような贅沢はできません。
  • それぞれのphpファイルには1つのクラス (またはインターフェイスまたはトレイト ...) のみ含みます。ただし、複数のアーティファクトファイルが許可されている古いAPIの一部である場合を除きます。
  • ブレースは常にクラス名の横の行に記述する必要があります。
  • すべてのクラスはPHPDocumentor規格に準拠したドキュメンテーションブロックを持つ必要があります。
  • クラス内のすべてのコードは4つの半角スペースでインデントされる必要があります。
  • クラスファイルでの追加コード ("side-effects") の配置はオートローディングで提供されないアーティファクト (Moodleのブートストラップで読み込まれない「classes」ディレクトリの古いクラスまたはlib) を必要とする場合のみ許可されます。 この場合、MOODLE_INTERNAL checkの使用が必要となります。
例:

/**

* クラスの短い説明です。
*
* クラスの長い説明です (もしあれば) ... 
*
* @package    mod_mymodule
* @copyright  2008 Kim Bloggs
* @license    https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

class sample_class {

   // コンテンツ内のすべてのクラスは
   // 4つの半角スペースでインデントされる必要があります。

} PHPDocスタイルのクラスはこのドキュメントのドキュメンテーションおよびコメント/クラスセクションでより詳細に定義されています。

関数およびメソッド

関数およびメソッド宣言

関数はMoodleの関数命名規則に従って命名する必要があります。

クラス内のメソッドは必ずprivate、protected、publicのいずれかの修飾子を使用して可視性を宣言する必要があります。

クラスと同様にブレスは常に関数名と同じ行に記述する必要があります。

関数名と引数の開始括弧の間にスペースを入れないでください。

戻り値を括弧で囲まないでください。これは可読性を損なうだけでなく、後にメソッドが参照を返すように変更された場合にコードが壊れる可能性があるからです。

Returnは1つのデータタイプのみとします。複数のリターンタイプを持つことは推奨されません。

/**

* ここにドキュメンテーションブロックを置きます。
*/

class sample_class {

   /**
    * ここにドキュメンテーションブロックを置きます。
    */
   public function sample_function() {
       // すべての関数のコンテンツは
       // 半角4スペースでインデントしてください。
       return true;
   }

}

関数およびメソッドの使い方

関数の引数はカンマ区切りの後に半角スペース1つを入れて区切ってください。

three_arguments(1, 2, 3);

マジックメソッド

マジックメソッドは極力避けて、使用する場合は正当な理由が必要となります。注意: 怠慢は有効な議論になりません。

(根拠に関する議論は MDL-52634 をご覧ください)

制御文

一般的に自由に行間のホワイトスペース使用して分かりやすくします。

If / else

括弧内の制御文の前後にスペースを入れて括弧内の半角スペースで演算子を区切ってください。 論理的なグループ化の改善に役立つ場合、内側のブラケットを使用してください。

半角4スペースでインデントしてください。

elseifは使用しないでください!

常に波括弧を使用してください (ブロックが1行でPHPが中括弧を必要としない場合でも)。ブロックの開始波括弧は常に対応する文または宣言と同じ行に置いてください。

if ($x == $y) {

   $a = $b;

} else if ($x == $z) {

   $a = $c;

} else {

   $a = $d;

}

スイッチ

括弧内の制御文の前後にスペースを入れて半角括弧内のスペースで演算子を区切ってください。 論理的なグループ化の改善に役立つ場合、内側のブラケットを使用してください。

常に半角4スペースでインデントしてください。 各ケース制限文の下のコンテンツはさらに4つの半角スペースでインデントする必要があります。

switch ($something) {

   ケース1:
       break;
   ケース2:
       break;
   default:
       break;

}

Foreach

前述のように以下のような形で半角スペースを使用してください:

foreach ($objects as $key => $thing) {

   process($thing);

}

三項演算子

三項演算子は「短く」「わかりやすい」文にのみでの使用が許可されています。一文で理解できない場合、代わりにif文を使用してください。

演算子の周りには空白を設けて、どこで演算しているか明確にする必要があります。

良い例: $username = isset($user->username) ? $user->username : ; ** $users = is_array($users) ? $users : [$users];

悪い例: $toload = (empty($CFG->navshowallcourses))?self::LOAD_ROOT_CATEGORIES:self::LOAD_ALL_CATEGORIES; $coefstring = ($coefstring== or $coefstring=='aggregationcoefextrasum') ? 'aggregationcoefextrasum' : 'aggregationcoef';

** PHP 7.0以降、「isset()」の多くの3値は新しい省略形 null coalescing operator を使用するように変更することができるため、前述の例は以下と同であることに留意してください:

$username = $user->username ?? ;

Require / include

ブラウザからアクセスされる各ファイルに関して、最初にメインのconfig.phpファイルを含むようにしてください。

require(__DIR__ . '/../../config.php');

その他のinclude/requireでは__DIR__え始まるパス、または$CFG->dirrootまたは$CFG->libdirで始まる絶対パスを使用してください。

「../」で始まる相対的なインクルードはPHPで変な動作をすることがあるため使用しないでください。私たちのCLIスクリプトでは「../」で始まる相対的なconfig.phpのパスを使用すべきではありません。

通常の用途で使用するライブラリファイルではrequire_onceを使用してください (これは前述のように常に「require」を使用すべきconfig.phpとは異なります)。例: require_once(__DIR__ . '/locallib.php'); require_once($CFG->libdir . '/filelib.php');

includeは一般的にファイルの先頭またはそれを必要とする関数/メソッド内部でのみ実行されるべきです。グローバルスコープのファイルの途中でinclude/requireを使用した場合、コードのセキュリティ監査が非常に困難になります。

インポートされたサードパーティのライブラリおよび「副作用」のないファイル (単一のクラス定義、インターフェイスまたはトレイト等) を除く他のすべてのスクリプトでは一番上に以下のコードを使用して、間違って設定された本番サーバでエラーメッセージが表示される可能性のある直接実行を防ぐ必要があります。

defined('MOODLE_INTERNAL') || die();

*副作用: グローバルスコープのコードで a)ネームスペースおよびuse文、b)ネームスペースの定数、c)strict_types宣言 (一般的な宣言) ではないもの。

ファイル内の副作用の有無は上で説明したようにコードレベルでのみ影響することに注意してください。特に言及されていない限り、その他のコーディングスタイルにおいては考慮すべきではありません。

ドキュメンテーションおよびコメント

コードドキュメンテーションではコードの流れ、関数および変数の目的を説明します。 実際のコーディングの際は必ず使用してください。

PHPDoc

Moodleはファイル、クラスおよび関数をドキュメント化するため、「標準」PHPDocフォーマットにできるだけ近付けています。 これにより (NetbeansまたはEclipseのような) IDEはMoodle開発者のために適切に動作します。また、私たちがウェブドキュメントを自動生成できます。

PHPDocには様々な場所 (ファイル、クラス、関数) で使用できる多くのタグがあります。 Moodleでそれらのタグを使用する場合、私たちが従う必要のある個別のルールがあります。

タイプ

以下のいくつかのタグ (@param, @return...) は有効なPHP型および説明の指定を必要とします。以下、これらすべてが許可されています:

  • PHPプリミティブ型: int, bool, string...
  • PHP複合型: 配列, stdClass (非配列、オブジェクト)
  • PHPクラス:フルまたは (現在のネームスペースに対して) 相対クラス名
  • true, false, null (常に半角英小文字)
  • static: 子/呼び出し元クラスの新しいインスタンスを返すメソッドのため
  • self: 親/呼び出し元クラスの新しいインスタンスを返すメソッドのため
  • $this:クラスの現在のインスタンスを返すメソッドのため
  • void: 明示的に空の「return」ステートメントを持つメソッドのための

また、これらの型の使い方には基本的なルールがあります。

  • 私たちは短い型名を使用します (booleanの代わりにbool、integerの代わりにintを使用します)。
  • ある「型」が複数使用されている場合、単純で情報量の少ない「配列」ではなく、type[]としての文書化を強く推奨します。
  • 複数の異なるタイプが可能な場合は、縦棒 (パイプ) で区切る必要があります。
  • すべてのプリミティブおよびキーワードは半角英小文字にする必要があります。複合型およびクラスのケースはオリジナルと一致する必要があります。

タグ

@copyright

ここではオリジナルファイルの年号や著作権者 (作成者) が含まれます。 既存のファイルで内容を変更しないでください!

 @copyright 2008 Kim Bloggs
@license

これはGPL v3+であり、このフォーマットを使用してください:

 @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
@param

変数名の後にはハイフン等を入れずにスペースのみを入れてください。

 @param type $name Description.
@return

@eturnタグは関数にreturn文がある場合は必須ですが、ない場合は省略できます。

説明部分は任意です。何が返されるかがすでに説明されている場合、説明部分を省略できます。

 @return タイプ 説明
@var

@varタグはクラス属性を記述するために使用されます。

 @return タイプ 説明

例外的に、利用可能なのどれもが戻り値を定義していない場合、型のヒントを提供するインライン@var phpdocs (メソッドのボディ内) が戻り値の型に対して許可されます。悪用厳禁です!

@uses

関数でdieまたはexitを使用している場合、この関数によるページ終了の可能性を開発者に知らせるため、このタグをdocblockに追加してください:

 @uses exit
@access

accessは要素のアクセス制御を指定するため使用できます。

  1. メソッド定義でまだアクセスコントロールが指定されていない場合にのみ使用する必要があります。
  2. 関数の場合、パブリックアクセスの指定が冗長であるため、避けるべきです。
 @access private
@package

package タグはphpファイルに正しい フランケンスタイル コンポーネント名を付けるために常に使用されるべきです。 完全なルールはそのページで説明されていますが、要約すると以下のようになります:

  1. ファイルがコンポーネントプラグインの一部である場合、プラグインコンポーネント名を使用してください (例:「mod_quiz」または「gradereport_xls」)。
  2. ファイルがコアサブシステムの一部である場合、core_xxxxとなります。xxxxはget_core_subsystems()で定義された名称です (例:「'core_enrol」または「'core_group」等)。
  3. ファイルがサブシステムに属していないコアの少数のファイルの1つである場合 (lib/moodlelib.php等)、「'core」パッケージとして扱われます。
  4. それぞれファイルは1つのパッケージにのみ含めます。

(私たちには@subpackageの規格は一切ありません。 自分の@package内で好きなように使用してください)

 @package gradereport_xls
@category

私たちはコアAPIの一部であるパブリッククラス、関数、ファイル、またはCore APIの実装例を示すものをハイライトするためにのみカテゴリを使用しています。 値はコアAPIページにあるもののうちの1つである必要があります。

 @category preferences 
@since

Moodleコアライブラリに新しいクラスまたは関数を追加 (または、既存のクラスに新しいメソッドを追加) する場合、どのバージョンのMoodleで追加されたか記録するため、@sinceタグを使用してください。例えば以下のようになります:

 @since Moodle 2.1
@see

あなたがユーザにURLではなく別の関連要素 (include、class、function、define、method、variable) を参照させたい場合、@seeを使用してください。

 @see some_other_function()

このタグはphpdocコメント内でインラインでも使用できます。

  /**
   * この関数は通貨名の取得に {@see get_string()} を使用します ...
   * .....
@link

あなたがユーザに外部URLを参照させたい場合、同時に関連する要素を参照させたくない場合、@linkを使用してください。

 @link https://docs.moodle.org/dev/Core_APIs

このタグはphpdocコメント内でインラインでも使用できます。

  /**
   * 以下の実装の詳細に関して {@link https://docs.moodle.org/dev/Core_APIs} を参照して ...
   * .....
@deprecated (and @todo)

古いAPIを廃止する場合、@deprecatedタグを使用してどのバージョンのMoodleで廃止されたか記録してください。可能であれば@todoおよび@seeを追加してください。 また、関連するMDLバグ報告を必ず言及してください。 例えば以下のようになります: /**

* ...
* @deprecated since Moodle 2.0 MDL-12345 - 今後、この関数は使用しないでください。 
* @todo MDL-22334 この関数はMoodle 2.2で削除されます。
* @see class_name::new_function()
*/

開発者によるコード更新が重要な場合、廃止されたメッセージを繰り返す debugging('...', DEBUG_DEVELOPER); コールの追加も検討してください。古い関数が全くサポートされなくなった場合、coding_exceptionを投げなければならないかもしれません。lib/deprecatedlib.php内に様々なオプションの例があります。

@throws

このタグは有効であり、メソッドや関数が例外を投げることを示すために任意で使用できます。これは開発者がこのような関数からの例外を処理しなければならない可能性があることを知るためのものです。

その他の特定タグ

タグの中には特定のコンテクストでのみ許可されて、グローバルでは許可されないものがあります。より正確には:

  • @Given, @When, @Then (behatステップ定義内)
  • @covers, @coversDefaultClass, @coversNothing (単体テスト内の範囲をコントロールしやすくするため)
  • @dataProvider (単体テスト内)
  • @expectedException[コード|メッセージ|MessageRegExp] (例外的な期待値を定義するため、単体テスト内)
  • @group (単体テストをまとめやすくするため、PHPUnit MoodleDocsのガイドラインに従う)
  • @codingStandardsIgnoreLine (次の行がCodechecker (phpcs)にスキップされるようにするため)

*) 現在のベストプラクティスではアノテーションシンタックスの代わりに$this->expectException()を使用することに留意してください。

ファイル

PHPコードを含むすべてのファイルはphp openタグの後に空行を入れずに上部に完全なGPLの著作権声明を記載してください。また、そのすぐ下に以下の内容を含む分離したdocblockを入れるべきです:

  1. ファイルの短い一行の説明
  2. 長いファイルの説明
  3. @package タグ (必須)
  4. @category タグ (ファイル内のすべてがコアAPIのいずれかに関連している場合のみ)
  5. @copyright (必須)
  6. @license (必須)

アーティファクトを1つだけ含むファイルの場合、アーティファクト (クラス、インターフェイス、trait...) がドキュメント化されていればファイルのphpdcブロックは省略可能です。その場合、次の「クラス」のセクションをご覧ください。

<?php // This file is part of Moodle - https://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <https://www.gnu.org/licenses/>.

/**

* This is a one-line short description of the file.
*
* You can have a rather longer description of the file as well,
* if you like, and it can span multiple lines.
*
* @package    mod_mymodule
* @category   backup
* @copyright  2008 Kim Bloggs
* @license    https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

クラス

すべてのクラスには以下のような完全なdocblockが必要です:

/**

* Short description for class.
*
* Long description for class (if any)...
*
* @package    mod_mymodule
* @category   backup
* @copyright  2008 Kim Bloggs
* @license    https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

class policy_issue {

1つのアーティファクトのみを含むファイル (class, interface, trait...)、 特にclassesディレクトリ内のすべてのファイルおよびそれ以外の場所で条件を満たすファイルすべてにはclass phpdocブロックで十分です。ファイルphpdocブロックはすべての効果においてオプションとみなされた上でクラスに1つの優先権が与えられます。

上の例で示されているように@package@copyright@licenseタグ (およびオプションの@categoryタグ) はファイル内(どのdocblockでも良いですが、すべて同時)に常に存在しなければなりません。

プロパティ

すべてのプロパティには以下のような最低限の情報を記載したdocblockが必要です:

class example {

   /** @var string This variable does something */
   protected $something;

} or class example {

   /** 
    * This variable does something and has a very long description which can
    * wrap on multiple lines
    * @var string 
    */
   protected $something;

} 複数のプロパティに共通点がある場合でもDocBlockテンプレートは使用しないでください。代わりに次の例のようにすべてのプロパティを明示的に文書化してください:

class zebra {

   /** @var int 白いストライプの数 */
   protected $whitestripes = 0;
   /** @var int 黒いストライプの数 */
   protected $blackstripes = 0;
   /** @var int 赤いストライプの数 */
   protected $redstripes = 0;

}

定数

クラス定数は以下のように文書化する必要があります:

class sam {

  /**
   * これはサムの機嫌がいいときに使われます。
   */
  const MOOD_GOOD = 0;

}


関数

すべての関数およびメソッドには以下ような完全なdocblockが必要です:

/**

* The description should be first, with asterisks laid out exactly
* like this example. If you want to refer to a another function,
* use @see as below.   If it's useful to link to Moodle
* documentation on the web, you can use a @link below or also 
* inline like this {@link https://docs.moodle.org/dev/something}
* Then, add descriptions for each parameter and the return value as follows.
*
* @see clean_param()
* @param int   $postid The PHP type is followed by the variable name
* @param array $scale The PHP type is followed by the variable name
* @param array $ratings The PHP type is followed by the variable name
* @return bool A status indicating success or failure
*/

たとえ@paramおよび@returnの行から明らかになっていたとしても、あなたは説明を含める必要があります。

ただし、親メソッドの意味を変更せず、引数や戻り値が同じであるオーバーライドされたメソッドは例外です。この場合、コメントを完全に省略する必要があります。@inheritdocまたは@seeタグの使用は完全なdocblockの代わりとして明確に禁止されています。

定義

すべての定義は以下の方法で文書化してください:

/**

* PARAM_INT - integers only, use when expecting only numbers.
*/

define('PARAM_INT', 'int');

/**

* PARAM_ALPHANUM - expected numbers and letters only.
*/

define('PARAM_ALPHANUM', 'alphanum');

インラインコメント

インラインコメントは「//」(スラッシュ2個+空白) スタイルを使用してコードの中に収まるようにきれいにレイアウトした上でコードと一緒に並べる必要があります。コメントの最初の行は大文字 (または数字、'...') で始めてコメントは適切な句読点で終わる必要があります。許される最後の文字は次のとおりです: 「.」「?」「!」

function forum_get_ratings_mean($postid, $scale, $ratings = null) {

   if (!$ratings) {
       $ratings = [];     // Initialize the empty array.
       $rates = $DB->get_records('forum_ratings', ['post' => $postid)];
       // ... then process each rating in
       // turn.
       foreach ($rates as $rate) {
           do_something_with($rate);
       }
       // Do we need to tidy up?
       if (!empty($rates))
           // 42 more things happen here!
           finsh_up();
       }

良い例: // Comment explaining this piece of code. 悪い例: /* Comment explaining this piece of code. */

  1. Comment explaining this piece of code.

// comment explaining this piece of code (without capital letter and punctuation)

もし、あなたのコメントが何らかのMDL問題によるものである場合、遠慮なく正しいMDL-12345をコメントに加えてください。 これにより、問題に関する決定および議論の追跡が容易になります。

TODOの使用

これはコードにまだ問題が残っていて、あなたが後で対処すべきだと分かっている場合には特に重要です。 MDLコードと一緒にTODOを使用してこれをマークしてください。 例えば以下のようになります: // TODO MDL-12345 This works but is a bit of a hack and should be revised in future.

もし、あなたがいくつかのTODOを除いて大きなタスクがほぼ完了している場合、そして、その大きなタスクを本当に完了したものとしてマークしたい場合、それぞれのTODOに対して新しいトラッカータスクを報告した上でTODOのコメントが新しい問題番号を指すように変更する必要があります。

ウェブ@ lib/tests/other/todochecker.phpから利用可能な管理者限定の素晴らしい「Todoチェッカ」レポートツールがあります。

最後に、あなたのTODOで使用されているMDL-l2345 (および@todosも、非推奨プロセスの一部でない限り、それらは別に扱われます) の「Review TODOs Epic」への追加を忘れないでください: MDL-47779 (問題を確認するにはログインが必要です)

CVSキーワード

私たちはMoodle 2.0で$Id$のようなCVSキーワードの使用を完全に停止しました。

例外

例外を使用して特にライブラリコードでのエラーを報告します。

例外の発生にはprint_error()を呼び出した場合とほぼ同じ効果がありますが、より柔軟性があります。例えば呼び出し側が例外をキャッチして何らかの処理をできます。また、単体テストの作成も容易になります。

2021年以降、print_error()の廃止に関する同意のため、代わりにthrow moodle_exception()が正しい処理方法であることに留意してください。

キャッチされなかった例外はprint_errorが適切に呼び出され、ユーザに報告されます。例外の「エラーコード」は最終的にユーザへの表示が意図される場合のみ翻訳されます。

通常のコードフローに例外を乱用しないでください。例外は誤った状況でのみ使用してください。

例外クラス

私たちにはカスタム例外クラスのセットがあります。ベースクラスはmoodle_exceptionです。あなたはnew moodle_exception(...)に渡す引数がprint_errorに渡すものと非常に似ていると理解できると思います。特定のタイプのエラーのためのより特別なサブクラスがあります。

例外タイプの完全なリストを取得するには、正規表現「class +w+_exception +extends」を検索するか、あなたのIDEでmoodle_exceptionのすべてのサブクラスをリストアップしてください。

必要に応じて、あなたのコードで使用するためにmoodle_exceptionの新しいサブクラスを作成してください。

いくつかの注目すべき例外タイプです:

moodle_exception
Moodleでの例外の基本クラスです。より具体的なタイプが適切ではない場合に使用してください。
coding_exception
開発者のミスによって問題が発生したと思われる場合にスローされます。プラグインと相互作用するコアコードで良くスローされます。このタイプの例外をスローする場合、プラグインの作者がコードを修正する方法を知ることができるようにエラーメッセージが役立つようにしてください。
dml_exception (およびsubclasses)
データベースクエリが失敗したときにスローされます。
file_exception
ファイルAPIによってスローされます。

危険な関数およびコンストラクタ

PHPには複数の疑わしい機能が含まれています。それらは深刻なセキュリティ問題の原因となる場合が多いため、極めてお勧めできません。

  1. eval()関数を使用しないでください - 言語パックは例外です (将来的に解決される予定です)。
  2. preg_replace()' を /e モディファイアで使用しないでください - 意図しないPHPの実行を防ぐためにコールバックを使用してください。。
  3. シェルコマンドの実行にはバックティック (バッククオート) を使用しないでください。
  4. 演算子およびラベルに「goto」を使用しないでください - 実行フローを制御するには他のプログラミング技術を使用してください。

コーディングスタイルのみの修正に関する方針

このコーディングスタイルガイドが定義および合意される前、すでに多くのコードが書かれていました。そのようなコードは明らかにコードスタイルに全く従っていません。私たちは新しいコードに対して適合性を強制しますが、以前のコードの状態についてはあまり気にしていません。

いずれにしても、(漸進的で非クリティカルな) 移行を正常化するためにポリシー問題(MDL-43233)が作成されて合意されました。そして、これがコーディングスタイルのみの変更に適用するルールです。

  1. 実際の問題の中で関連するコーディングスタイルの変更 (同一行、メソッド/関数内の変数、隣接するコメント ...)は認められます。
  2. 実際の問題の中で関連性のないコーディングスタイルの変更 (他のメソッド、コードブロック、コメント..) はマスターおよび別のコミットでのみ受け付けられます。
  3. コーディングスタイルのみの問題は各サイクルの最初の2ヶ月間のみ、マスターに受け付けられます。

Gitコミット

明確で情報量の多いコミットの実行はオープンソースのコード作成上、重要なことであり、コミットの履歴は開発者間のコミュニケーションの重要な一部となります。コミットを適切に作成して、それを達成するためにgitツールの使用に時間を費やすべきです。 Gitコミットは:

  • 歴史をクリーンアップして完璧に伝える。まるで最初に完璧に書かれたコードのように。
  • 変更に関するMDL-xxxx問題番号を含む。
  • 適切な場合、CODE AREAを含めてください。(コードエリアとはこの変更が影響するMoodleのエリアの短い名前です。意味があればコンポーネント名にできますが、そうする必要はありません。あなたの読者はコンピュータではなく人間であることを覚えておいてください。コンポーネント名の短縮版がより読みやすく特徴的である場合、代わりにそれを使用してください)
  • 以下のようにフォーマットしてください:
MDL-xxxx CODE AREA: short summary (72 chars soft limit)

Blank line on line 2, followed by an unlimited length detailed explanation
following if necessary. This section might include the motivation for the change
and contrast it with the previous behaviour.

Gitコミットは以下のようにしないでください:

  • 統合前に発見および修正されたバグの変更を含む
  • 1つの問題に対して同じコードラインに多くの別々のリビジョンを含める
  • 論理的変更の詳細セットの一部である場合、任意に分割する

詳細なガイダンスはコミットチートシートをご覧ください。

謝辞

この資料は以下のソースから作成されました:

  1. オリジナル Coding guidelines ページ
  2. Zendガイドライン および
  3. すべてのコアMoodle開発者からのフィードバック

関連情報