— y2sunlight 2020-04-28
本章は、若干の補足を加筆してはいるものの単にPSRのサイトを日本語に翻訳したものに過ぎません。英語が堪能な方は原文をご参照下さい。翻訳に当たっては、基本的に機械翻訳を使い、理解できない部分は独断で意訳しております。拙い訳では御座いますが恥を忍んで投稿しておりますので、ご指摘など御座いましたらコメントを頂ければ幸いです。
関連記事
PSR-5: PHPDoc の中で使用されている用語「タグカタログPSR(Tag Catalog PSR)」はPSR-19: PHPDoc tags を指します。この2つのPSRは元々1つだったものが分割したものです。
— 原文より翻訳 PSR-5: PHPDoc 2020-04-28 現在
このPSRの主な目的は、PHPDoc規約の完全かつ正式な定義を提供することです。このPSRは、その前身である https://www.phpdoc.org/phpDocumentor 1.x に関連付けられた事実上のPHPDoc規約からは逸れており、PHP言語の新しい機能のサポートを提供し、その前身のいくつかの欠点に対処しています。
SHALL NOT
)。 しかし、現在の慣行に基づいて後続のPSRを作成できる汎用性を提供します。このトピックの詳細については、5.3章を参照してください。SHALL NOT
)。このドキュメントは、構文と目的に関する正式な仕様に限定されています。
このドキュメントのキーワード MUST
, MUST NOT
, REQUIRED
, SHALL
, SHALL NOT
, SHOULD
, SHOULD NOT
, RECOMMENDED
, MAY
及び OPTIONAL
は、 RFC 2119で説明されているように解釈して下さい。
RFC 2119の説明
MUST
,REQUIRED
,SHALL
— 絶対必要
MUST NOT
,SHALL NOT
— 絶対禁止
SHOULD
,RECOMMENDED
— 推奨(但し、無視できる特定の正当な理由が存在するかもしれない)
SHOULD NOT
— 推奨できない(但し、許可できる特定の正当な理由が存在するかもしれない)
MAY
,OPTIONAL
— オプション
PHPDoc
は 構造的要素
に関しての情報提供を行うドキュメントセクションです。 構造的要素
は、プログラミング構成物のコレクションで、DocBlock を前に付けることができます (MAY
)。このコレクションには、次の構成物が含まれます。
構造的要素
の前に、DocBlock を付けることをお勧めします (RECOMMENDED
)。DocBlock を構造的要素の直ぐ前に置くことは一般的な方法ですが、いくつかの空行で区切られる場合もあります (MAY
)。
例:
/** @var int $int This is a counter. */ /** @var int $int これはカウンターです */ $int = 0; // there should be no docblock here // ここには docblock があってはなりません $int++;
または
/** * This class acts as an example on where to position a DocBlock. * このクラスは、DocBlockを配置する場所の例として機能します。 */ class Foo { /** @var string|null $title contains a title for the Foo */ /** @var string|null $title Fooのタイトルが含まれています */ protected $title = null; /** * Sets a single-line title. * 単一行のタイトルを設定します。 * * @param string $title A text for the title. * @param string $title タイトルのテキスト * * @return void */ public function setTitle($title) { // there should be no docblock here // ここには docblock があってはなりません $this->title = $title; } }
本規約の範囲を超える使用例は、明示的にforeach内の変数をドキュメント化することです。いくつかのIDEではこの情報を使用して、オートコンプリート機能を支援します。
本規約ではこの特定の例をカバーしていません。なぜならforeachステートメントは 構造的要素
ではなく 制御フロー
ステートメントと見なされるからです。
/** @var \Sqlite3 $sqlite */ foreach ($connections as $sqlite) { // there should be no docblock here // ここには docblock があってはなりません $sqlite->open('/my/database/path'); <...> }
DocComment
は特別なタイプのコメントです。それは以下に従います (MUST
)。:/**
で始まり、その後に空白文字が続き*/
で終わり
DocComment が複数の行にまたがる場合、すべての行はアスタリスク(*)で始まる必要があり(MUST
)、これは開始行の最初のアスタリスクの位置に合わせる必要があります (SHOULD
)。
単一行の例:
/** <...> */
複数行の例:
/** * <...> */
DocBlock
は、単一の PHPDoc
構造を含んでいる DocComment で、基本的なソース内の表現です。タグ
は、構造的要素
またはそのコンポーネントに関する単一のメタ情報です。タイプ
は、要素に関連付けられているデータがどんなの型なのかを決定する為のものです。これは、引数、定数、プロパティなどの正確な値を決定するときに一般的に使用されます。FQSEN
は Fully Qualified Structural Element Name ( 完全修飾構造要素名 ) の略です。この表記は、FQCN(完全修飾クラス名)を拡張し、クラス/インターフェイス/トレイトの各メンバーを識別する表記を追加し、FQCN の原則をインターフェース、トレイト、関数、およびグローバル定数に再適用します。
構造的要素
のタイプごとに次の表記法が使用できます。
\My\Space
\My\Space\myFunction()
\My\Space\MyClass
\My\Space\MyInterface
\My\Space\MyTrait
\My\Space\MyClass::myMethod()
\My\Space\MyClass::$my_property
\My\Space\MyClass::MY_CONSTANT
FQSEN には次の ABNF定義があります。
FQSEN = fqnn / fqcn / constant / method / property / function fqnn = "\" [name] *("\" [name]) fqcn = fqnn "\" name constant = (fqnn "\" / fqcn "::") name method = fqcn "::" name "()" property = fqcn "::$" name function = fqnn "\" name "()" name = (ALPHA / "_") *(ALPHA / DIGIT / "_")
DocComment
に含まれている必要があります (MUST
)。これら2つの組み合わせを DocBlock
と呼びます。構造的要素
の直前に配置する必要があります (MUST
)。
PHPDoc 形式には、次の ABNF定義があります。
PHPDoc = [summary] [description] [tags] summary = *CHAR (2*CRLF) description = 1*(CHAR / inline-tag) 1*CRLF ; any amount of characters ; with inline tags inside tags = *(tag 1*CRLF) inline-tag = "{" tag "}" tag = "@" tag-name [":" tag-specialization] [tag-details] tag-name = (ALPHA / "\") *(ALPHA / DIGIT / "\" / "-" / "_") tag-specialization = 1*(ALPHA / DIGIT / "-") tag-details = *SP (SP tag-description / tag-signature ) tag-description = 1*(CHAR / CRLF) tag-signature = "(" *tag-argument ")" tag-argument = *SP 1*CHAR [","] *SP
使用例は5.4章に含まれています。
Summary には、構造的要素
の目的を定義する概要を含める必要があります (MUST
)。概要は、1行または多くても2行でそれを超えないようにすることをお勧めします (RECOMMENDED
)。
Summary は、PHPDoc の唯一のコンテンツでない限り、連続した2つの改行で終了する必要があります (MUST
)。
Description が提供されている場合は、その前に Summary を付ける必要があります (MUST
)。そうでないと、Description は最後に到達するまで、Summary と見なされるでしょう。
Summary は章のタイトルに相当するので、できるだけ少ないフォーマットを使用することは有益です。そのため、Description(次の章を参照)とは異なり、マークアップ言語をサポートするような推奨事項はありません。これをサポートするかどうかは、実装アプリケーションに明示的に委ねられます。
Description はオプションです (OPTIONAL
) が、このDocBlockに続く 構造的要素
が、Summary のみで説明できるよりも多くの操作 または より複雑な操作をが含んでいる場合は Description を含めるべきです (SHOULD
)。
Description を解析するアプリケーションは、このフィールドの為の Markdown(マークアップ言語) をサポートすることが推奨されます (RECOMMENDED
)。これにより、作成者にコード例を表現する形式と明確な方法を提供できるようになります。
Description の一般的な用途はとりわけ次のとおりです:
構造的要素
を適用できる一般的な使用例またはシナリオのセットを提供する
タグは、後続の 構造的要素
に関する簡潔なメタデータを作成者が提供する方法を与えます。各タグは新しい行で始まり、その後にアットマーク(@)とタグ名が続き、その後に空白とメタデータ(説明を含む)が続きます。
メタデータが提供されている場合、それは複数行にまたがる場合があります(MAY
)。そして、厳密な形式に従うことができ(COULD
)、タグのタイプによって指定されるパラメーターを提供します。タグのタイプは、その名前から得ることができます。
例えば:
@param string $argument1 これはパラメータです。上記のタグは、名前('param') と メタデータ('string $ argument1 これはパラメーターです。') で構成されています。メタデータは
Type
('string')、変数名('$argument') と 説明('これはパラメータです。')に分割されます。
タグの説明には、フォーマット言語として Markdown をサポートする必要があります(MUST
)。Markdown の性質上、同じ行または後続の行でタグの説明を開始し、同じように解釈することができます。
従って、次のタグは意味的に同一です。
/**
* @var string これは説明です。
* @var string これは
* 説明です。
* @var string
* これは説明です。
*/
このバリエーションとしては、説明の代わりに、タグのシグニチャが使用されます。ほとんどの場合、タグは実際には アノテーション
になります。タグ・シグネチャは、その操作に関するパラメータをアノテーションに与えることができます。
タグ・シグネチャが存在する場合、同じタグ内に説明が存在してはいけません (MUST NOT
)。
タグによって提供されるメタデータにより、後続の 構造的要素
の実際の実行時の動作が変化する可能性があります。その場合、タグ
の代わりに アノテーション
という用語が一般的に使用されます。
タグ名は、このタグによって表される情報のタイプを示します。また、それがアノテーションの場合は、後続の 構造的要素
に注入すべてき動作を示しています。
アノテーションをサポートするために、個々のアプリケーションまたはアプリケーションのサブセット用に特別に設計されたタグのセットを導入することができます(これらのタグは本仕様ではカバーされていません)。
これらのタグまたはアノテーションは、次のいずれかによって名前空間を提供する必要があります (MUST
)。
phpスタイルの名前空間がプレフィックスとして付いたタグ名の例:
(プレフィックスのスラッシュはオプションです)
上記の原文
Example of a tag name prefixed with a php-style namespace (the prefixing slash is OPTIONAL):
— 曖昧な翻訳 —
the prefixing slashとは何か?
@\Doctrine\Orm\Mapping\Entity()
注:PHPDoc規約は、このドキュメントまたはその後の追加や拡張で指定されていない限り、タグの意味を想定していません。
つまり、プレフィックスの名前空間要素が提供されている限り、名前空間のエイリアスを使用することができます(CAN
)。従って、以下も同様に合法です。
@Mapping\Entity()独自のライブラリまたはアプリケーションが名前空間のエイリアスをチェックし、これからFQCN(完全修飾クラス名)を作成することがあるかもしれませんが、これはこの規約に影響を与えません。
重要:PHPDoc規約を使用するツールは、そのアプリケーションに登録されている名前空間を解釈して、カスタム動作を適用する場合があります(MAY
)。
ベンダー名とハイフンが前に付いたタグ名の例:
@phpdoc-event transformer.transform.pre
ベンダーまたは名前空間のプレフィックスが付いていないタグ名は、タグカタログPSRや公式の付録に記載する必要があります (MUST
)。
この規約で定義されたタグにニュアンスを与える方法を提供するために(ただし基本セットを拡張せずに)、タグ名の後にコロンを追加し、その後に、よりニュアンスのある説明を与える文字列を追加することにより、タグの特殊化を提供できます(MAY
)。サポートされているタグ特殊化のリストは、時間の経過とともに変更される可能性があるため、タグカタログPSRではメンテナンスされません。タグカタログPSRのメタドキュメントには、タグ名ごとに一連の推奨事項が含まれている場合がありますが、プロジェクトは、該当する場合、独自のタグの特殊化を自由に選択できます。
重要:PHPDoc規約を使用するツールは、そのアプリケーションに登録/理解されているタグの特殊化を解釈してカスタム動作を適用することができますが(MAY
)、タグカタログPSRで定義されている前述のタグ名を実装することを期待されているだけです。
例えば:
@see:unit-test \Mapping\EntityTest::testGetId上記のタグは、名前('see')とタグの特殊化('unit-test')で構成されています。このように、これは開発が進行しているメソッドのユニットテストとの関係を定義します。
タグ・シグネチャは、現在のタグに固有の追加メタデータを提供するアノテーションためのに一般的に使用されます。
この提供されるメタデータは、所有するアノテーションの振る舞いに影響を与えるため、後続の 構造的要素
の振る舞いに影響を与える可能性があります。
シグネチャの内容は(タグ名で述べたように)タグタイプによって決定され、本仕様の範囲を超えます。ただし、タグ・シグネチャの後には、説明やその他の形式のメタデータを続けてはなりません(MUST NOT
)。
The following examples serve to illustrate the basic use of DocBlocks; it is advised to read through the list of tags in the Tag Catalog PSR.
次の例は、DocBlock
の基本的な使用法を示しています。タグカタログPSRのタグのリストを一読することをお勧めします。
完全な例は次のようになります:
/** * This is a Summary. * * This is a Description. It may span multiple lines * or contain 'code' examples using the _Markdown_ markup language. * これは説明です。複数行にわたることができ、 * _Markdown_マークアップ言語を使用した「コード」の例が含まれる場合があります。 * * @see Markdown * * @param int $parameter1 A parameter description. * @param \Exception $e Another parameter description. * * @\Doctrine\Orm\Mapper\Entity() * * @return string */ function test($parameter1, $e) { ... }
説明を省略することもできます:
/** * This is a Summary. * * @see Markdown * * @param int $parameter1 A parameter description. * @param \Exception $parameter2 Another parameter description. * * @\Doctrine\Orm\Mapper\Entity() * * @return string */ function test($parameter1, $parameter2) { }
また、タグセクションさえも省略できます(ただし、パラメーターと戻り値に関する情報が不足しているためお勧めしません)。
/** * This is a Summary. */ function test($parameter1, $parameter2) { }
DocBlock
は1行の場合もあります:
/** @var \ArrayObject $array */ public $array = null;
タイプには次のABNF定義があります。
type-expression = type *("|" type) *("&" type) type = class-name / keyword / array array = (type / array-expression) "[]" array-expression = "(" type-expression ")" class-name = ["\"] label *("\" label) label = (ALPHA / %x7F-FF) *(ALPHA / DIGIT / %x7F-FF) keyword = "array" / "bool" / "callable" / "false" / "float" / "int" / "iterable" / "mixed" / "null" / "object" / keyword = "resource" / "self" / "static" / "string" / "true" / "void" / "$this"
タイプ
が使用される場合、ユーザーは以下に詳述するように、値または値のセットを期待します。
タイプ
が複数のタイプで構成されている場合、これらは共用体タイプ(union)の縦棒記号(|)または交差タイプ(intersection)のアンパサンド(&)のいずれかで区切る必要があります (MUST
)。本仕様をサポートするインタープリターは、これを認識し、評価の前に タイプ
を分割する必要があります (MUST
)。
共用体タイプの例:
@return int|null
交差タイプの例:
@var \MyClass&\PHPUnit\Framework\MockObject\MockObject $myMockObject
タイプ
で表される値は配列にすることができます。このタイプは、次のオプションのいずれかの形式に従って定義する必要があります (MUST
)。
@return int []
mixed も単一のタイプであり、このキーワードを使用して、各配列の値に可能なタイプが含まれていることを示すことができる点に注意してください。
:@return(int | string)[]
有効なクラス名は、タイプが言及しているコンテキストに基づいて参照されます。従って、これは完全修飾クラス名(FQCN)であるか。または名前空間内に存在ローカル名であるかのいずれかになります。
このタイプが適用される要素は、このクラスのインスタンス、または指定されたクラスの子(や子の子)であるクラスのインスタンスのいずれかです。
上記の性質により、この情報を収集して形成するアプリケーションでは、クラスの各表現とともに子クラスのリストを表示することをお勧めします (RECOMMENDED
)。 これにより、どのクラスがタイプとして受け入れられるかがユーザーに明らかになります。
上記の原文
Due to the above nature, it is RECOMMENDED for applications that collect and shape this information to show a list of child classes with each representation of the class. This would make it obvious for the user which classes are acceptable as type.
— 曖昧な翻訳 —
'applications that collect and shape this information' とはどんなアプリケーションなのか、PHPDocのツールと言う解釈でよいのか?
キーワードは、タイプの目的を定義します。すべての要素がクラスによって決められているわけではなく、開発者が DocBlock
の対象となるコードの理解に役立つ分類には価値があります。
これらのキーワードのほとんどは、PHPでクラス名として使用でき、実際のクラスと区別するのが難しい場合があります。そのため、ほとんどのクラス名は大文字の最初の文字で始まるため、キーワードは小文字にする必要があります (MUST
)。コード内でこれらの名前のクラスを使用すべきではありません (SHOULD NOT
)。
これらのキーワードの名前でクラスに名前を付けない理由は他にもありますが、それは本仕様の範囲を超えています。
このPSRによって認識されるキーワードは次の通りです:
Traversable
オブジェクトです。/** * @return void */ function outputHello() { echo 'Hello world'; }
上記の例では、returnステートメントが指定されていないため、戻り値は決定されません。
例2:
/** * @param bool $quiet when true 'Hello world' is echo-ed. * * @return void */ function outputHello($quiet) { if ($quiet) { return; } echo 'Hello world'; }
この例では、関数には特定の値のないreturnステートメントが含まれています。実際の値が指定されていないため、これも void タイプと見なされます。
/** * @return null */ function foo() { echo 'Hello world'; return null; }
このタイプは通常、何も返されない可能性があることを示しますために、他のタイプと組み合わせて使用されます。
例2:
/** * @param bool $create_new When true returns a new stdClass. * * @return stdClass|null */ function foo($create_new) { if ($create_new) { return new stdClass(); } return null; }
callable
)な任意のタイプです。メソッド c はクラス A に含まれています。DocBlock は、戻り値の型が self であることを示しています。そのため、メソッド c はクラス A のインスタンスを返します。
これは、継承が関与しているときに混乱する状況につながる可能性があります。
クラス B はクラス A を拡張し、メソッドcを再定義しません。そのため、クラス B からメソッド c を呼び出すことができます。
この状況では、self がクラス A または B のいづれかとして解釈されるため、あいまいさが生じる可能性があります。これらの場合、self は、self タイプを含む DocBlock が記述されているクラスのインスタンスであると解釈しなければなりません (MUST
)。
上記の例で、self はクラス A のメソッド c で定義されているため、常にクラスAを参照する必要があります(self
)。
上記の性質により、この情報を収集し形成化するアプリケーションでは、クラスの各表現とともに子クラスのリストを表示することをお勧めします (RECOMMENDED
)。 これにより、どのクラスが型として受け入れられるかがユーザーに明らかになります。