Invoke BEFORE writing phpDoc.
Never duplicate signature information without adding value. If the class name, method name, parameter names, and PHP types already tell the full story, skip the docblock entirely.
Skip documentation when:
$width, $height, $name)Write documentation when:
@return string[])Use consistent phrasing for recurring situations:
| Situation | Phrase |
|---|---|
| Returns a value | "Returns..." |
| Returns null on failure | "Returns X, or null if..." |
| Checks a condition | "Checks whether..." |
| Creates an object | "Creates..." |
| Converts format | "Converts X to Y." |
| Sets a value | "Sets..." |
| Finds/searches | "Finds...", "Searches for..." |
| Removes | "Removes..." |
| Validates | "Validates..." |
| Parses | "Parses..." |
Describe the condition the method tests, not when it returns true. The return type already says it is a yes/no answer, so naming the truthy branch ("Returns true for...", "Returns true if...") just restates the signature.
true case ("Returns true when...", "Returns true for...").For example, a validator method is documented as "Checks whether the address is a syntactically valid IPv4 or IPv6 address, including IPv4-mapped IPv6." - the focus is the condition, and the special case rides along in the same clause.
Across the whole codebase keep documentation uniform:
Use single-line format for simple @var annotations:
/** @var string[] */
private array $name;
Short comments for non-obvious properties:
/** for back compatibility */
protected Explorer $context;
?Type over Type|null for nullable types/**
* @return string primary column sequence name
* @param mixed $var description here
*/
Include parameter docs only when explaining:
array<T> = array<int|string, T> - any keys (omitting key type means int|string)array<int, T> - int keys only (not necessarily sequential)array<string, T> - string keys onlylist<T> - sequential int keys starting from 0 (0, 1, 2...)list<T> is accurate if the function always returns sequential keyslist<T> can be too restrictive - may reject valid inputs with non-sequential keyslist<T> for inputAnalyze the implementation:
foreach ($arr as $v) - doesn't use keys → array<T> is sufficient$arr[0], $arr[1] - accesses by index → requires list<T>For return types dependent on parameters:
/**
* @return ($flag is true ? list<array{string, int}> : list<string>)
*/
Examples:
Clear purpose, adding array contents info:
/**
* Returns list of supported languages.
* @return string[] Array of language codes
*/
public function getSupportedLanguages(): array
Describing unusual behavior:
/**
* Creates new transaction. Returns null if user has exceeded daily limit.
*/
public function createTransaction(float $amount): ?Transaction
// Signature says it all - no docblock needed
protected readonly string $name;
public function getWidth(): int
public function setName(string $name): void
Self-explanatory parameters - document only the method purpose:
/**
* Calculates dimensions of image cutout.
*/
public function calculateCutout(int $left, int $top, int $width, int $height): array