Missing Function Comments
debt(d3/e1/b3/t5)
Closest to 'default linter catches the common case' (d3). The detection_hints list phpcs, phpstan, and phpmd — all standard PHP toolchain tools that catch missing docblocks and undocumented @throws by default or with minimal configuration. The pattern is detectable automatically, matching d3.
Closest to 'one-line patch or single-call swap' (e1). The quick_fix is to add a PHPDoc comment above the method — a localised, minimal change that doesn't require refactoring logic or touching other files. Even adding multiple @throws lines is still a contained, single-location fix.
Closest to 'localised tax' (b3). Missing documentation affects the component or class where it appears; it doesn't impose a cross-cutting architectural burden. Applies across web/cli/queue contexts but each instance is isolated — the debt is a local productivity tax on maintainers reading or calling undocumented methods, not a system-shaping choice.
Closest to 'notable trap — a documented gotcha most devs eventually learn' (t5). The misconception field states that developers believe PHP 8 native type declarations make PHPDoc obsolete, but @throws, complex generics like array<string, User>, and explanatory summaries cannot be expressed with native types alone. This is a well-known but commonly encountered mistake, fitting t5.
Also Known As
TL;DR
Explanation
In PHP 8 with full native type declarations, @param and @return are often redundant — the types speak for themselves. What is never redundant: a one-line summary of what the function does, @throws documentation for every exception that can propagate out, @deprecated for functions being phased out, and explanatory notes for any non-obvious preconditions or side effects. PHPStan and Psalm use PHPDoc for complex generics and templates that native types cannot express.
Common Misconception
Why It Matters
Common Mistakes
- Omitting @throws for every exception that can escape the function.
- Repeating the method name as the docblock: /** getUserById */ — adds nothing.
- Not documenting preconditions: the caller must ensure X before calling this.
- Outdated docblocks after parameter types changed — wrong documentation is worse than none.
Code Examples
// No docblock — what does it throw? What are the constraints?
public function transfer(int $fromId, int $toId, float $amount)
{
if ($amount <= 0) throw new InvalidArgumentException('Amount must be positive');
// Can throw DatabaseException, InsufficientFundsException...
$this->db->beginTransaction();
// ...
}
/**
* Transfers funds between two accounts atomically.
*
* @param int $fromId Source account ID
* @param int $toId Destination account ID
* @param float $amount Positive amount in account currency
*
* @throws InvalidArgumentException If amount is not positive
* @throws InsufficientFundsException If source balance is insufficient
* @throws DatabaseException On transaction failure (rolled back)
*/
public function transfer(int $fromId, int $toId, float $amount): void