Missing DocBlock Analyzer
| Analyzer ID | Category | Severity | Time To Fix |
|---|---|---|---|
missing-docblock | ✅ Code Quality | Low | 15 minutes |
What This Checks
- Detects public methods missing PHPDoc comments
- Requires
@paramtags for parameters with generic types (array, iterable, object, mixed, callable) or no type hints - Requires
@returntag for generic return types or class names (not needed for scalar types like void, string, int, bool, float) - Requires
@throwstags for exceptions (when applicable) - Excludes simple getter/setter methods (get*, set*, is*, has*)
- Reports exact file location and line number of each issue
Follows PSR-2 conventions: @param and @return tags are redundant for non-generic native types but required for generic types to specify their structure.
Why It Matters
- Code documentation: DocBlocks explain what methods do and how to use them
- IDE support: IDEs use DocBlocks for autocomplete and type hints
- API documentation: DocBlocks generate API documentation automatically
- Team collaboration: New team members understand code faster
- Type safety: DocBlocks help catch type mismatches
- Maintenance: Well-documented code is easier to modify
- Best practices: PSR-5 standardizes DocBlock format
- Code quality: Documentation is a sign of professional code
How to Fix
Quick Fix (5 minutes)
Add basic DocBlock to public methods:
// ❌ Before: Missing DocBlock
public function calculateTotal($items)
{
return array_sum(array_column($items, 'price'));
}
// ✅ After: DocBlock with generic type documentation
/**
* Calculate the total price of items.
*
* @param array<int, array{price: float}> $items Array of items with price field
*/
public function calculateTotal(array $items): float
{
return array_sum(array_column($items, 'price'));
}Note: The @return float tag is omitted because float is a scalar type (self-documenting). The @param tag is required because array is a generic type that needs structure specification.
Proper Fix (15 minutes)
1: Complete DocBlock with Parameters
// ❌ Before: Missing or incomplete DocBlock
public function processOrder(Order $order, User $user, bool $sendEmail)
{
// Implementation
}
// ✅ After: Complete DocBlock (class types documented, scalar types omitted)
/**
* Process an order for a user.
*
* @param \App\Models\Order $order The order to process
* @param \App\Models\User $user The user placing the order
* @return \App\Models\Order
* @throws \App\Exceptions\InvalidOrderException
* @throws \App\Exceptions\PaymentFailedException
*/
public function processOrder(Order $order, User $user, bool $sendEmail): Order
{
// Implementation
}Note: The bool $sendEmail parameter doesn't need a @param tag because bool is a scalar type (self-documenting). If you want to document what it does, you can optionally include it, but it's not required by this analyzer.
2: Document Generic Return Types
// ❌ Before: Missing return documentation for Collection (generic type)
public function getUserOrders(int $userId)
{
return User::find($userId)->orders;
}
// ✅ After: Document generic collection return type
/**
* Get all orders for a user.
*
* @return \Illuminate\Database\Eloquent\Collection<\App\Models\Order>
*/
public function getUserOrders(int $userId)
{
return User::find($userId)->orders;
}Note: The int $userId parameter doesn't need a @param tag because int is a scalar type (self-documenting). The @return tag IS required because Collection is a generic type that needs to specify what it contains.
3: Document Exceptions
// ❌ Before: Missing exception documentation
public function chargePayment(Order $order, float $amount)
{
if ($amount <= 0) {
throw new InvalidAmountException();
}
if (!$order->canBeCharged()) {
throw new PaymentFailedException();
}
// Charge payment
}
// ✅ After: Document all exceptions (class param and exceptions only)
/**
* Charge a payment for an order.
*
* @param \App\Models\Order $order The order to charge
* @throws \App\Exceptions\InvalidAmountException When amount is invalid
* @throws \App\Exceptions\PaymentFailedException When payment cannot be processed
*/
public function chargePayment(Order $order, float $amount): void
{
if ($amount <= 0) {
throw new InvalidAmountException();
}
if (!$order->canBeCharged()) {
throw new PaymentFailedException();
}
// Charge payment
}Note: Both float $amount and : void don't need documentation because they're scalar types (self-documenting).
4: Document Complex Parameters
// ❌ Before: Missing documentation for array parameter (generic type)
public function searchUsers(array $filters, int $limit = 10)
{
// Implementation
}
// ✅ After: Document array structure and generic return type
/**
* Search users with filters.
*
* @param array<string, mixed> $filters Search filters (e.g., ['name' => 'John', 'status' => 'active'])
* @return \Illuminate\Database\Eloquent\Collection<\App\Models\User>
*/
public function searchUsers(array $filters, int $limit = 10)
{
// Implementation
}Note: The int $limit parameter doesn't need a @param tag because int is a scalar type. The array $filters parameter DOES need documentation because array is a generic type that needs structure specification.
5: Document Nullable Class Returns
// ❌ Before: Missing documentation for nullable class return
public function findUserByEmail(string $email)
{
return User::where('email', $email)->first();
}
// ✅ After: Document nullable class return type
/**
* Find a user by email address.
*
* @return \App\Models\User|null
*/
public function findUserByEmail(string $email): ?User
{
return User::where('email', $email)->first();
}Note: The string $email parameter doesn't need a @param tag because string is a scalar type. The @return tag IS required because User is a class name (even when nullable).
6: Document Array Shapes
// ❌ Before: Missing documentation for array return (generic type)
public function getUserStats(int $userId): array
{
return [
'total_orders' => 10,
'total_spent' => 1000.00,
'last_order_date' => '2024-01-15',
];
}
// ✅ After: Document array shape with precise structure
/**
* Get user statistics.
*
* @return array{total_orders: int, total_spent: float, last_order_date: string|null}
*/
public function getUserStats(int $userId): array
{
return [
'total_orders' => 10,
'total_spent' => 1000.00,
'last_order_date' => '2024-01-15',
];
}Note: The int $userId parameter doesn't need a @param tag because int is a scalar type. The @return tag IS required because array is a generic type that needs its shape documented.
References
- PSR-2 Coding Style Guide - Laravel follows PSR-2 conventions
- PSR-5 PHPDoc Standard - PHPDoc documentation standard
- PHP DocBlock Documentation - Complete DocBlock guide
- PHPDoc Types - Type annotation reference
Related Analyzers
- Naming Convention Analyzer - Validates naming standards
- Method Length Analyzer - Detects methods that are too long
- Commented Code Analyzer - Detects commented-out code