claude-skills/engineering-team/skills/code-reviewer/languages/php.md
fouad 19f74425bf
feat(code-reviewer): add C, C++, Rust, Ruby, PHP, and Dart/Flutter language support (#769)
Adds 6 new language files to the code-reviewer skill, expanding coverage from 7 to 13 languages. Each file follows the established hybrid structure — language-specific rules inline, universal rules in rules/universal.md.

Files added:
- languages/c.md — memory safety, banned functions, pointer ownership, buffer bounds, UB
- languages/cpp.md — smart pointers, RAII, reinterpret_cast, virtual destructors, C++17/20
- languages/rust.md — unsafe blocks, .unwrap() in production, Tokio pitfalls, clippy
- languages/ruby.md — Rails-aware N+1, strong_parameters, YAML.safe_load, Marshal.load
- languages/php.md — SQLi, unserialize, eval, file inclusion, CSRF, XSS, PHP 8.x
- languages/dart.md — Dart + Flutter: dispose(), BuildContext across async, const widgets

SKILL.md dispatch table and --language valid values updated accordingly.
2026-05-28 08:26:14 +02:00

4.9 KiB

language extensions
php
.php
.phtml
.php3
.php4
.php5
.phps

PHP — Language-Specific Review Notes

Load this file alongside rules/universal.md. Universal rules are not repeated here — only PHP-specific rules and idioms.


PR Analyzer — PHP Risk Signals

  • var_dump / print_r / echo debug statements left in production code
  • @ error suppression operator — masks real errors; verify it is justified
  • // phpcs:ignore / // phpstan-ignore comments — verify they are justified
  • Hardcoded credentials, database passwords, or API keys in source
  • eval() anywhere — almost always a security issue
  • $_GET / $_POST / $_REQUEST / $_COOKIE used without sanitization

Code Quality — PHP Checks

  • Missing type declarations on function parameters and return types
  • mixed return type used broadly — tighten to specific types
  • Global variables (global $var) — pass dependencies explicitly
  • Long functions (>50 lines) — PHP functions tend to accumulate logic
  • isset() / empty() used to mask type errors instead of fixing the root cause
  • Missing strict_types=1 declaration at the top of the file

Security

  • Flag $_GET / $_POST / $_REQUEST used directly in SQL queries — require PDO prepared statements
  • Flag mysqli_query($conn, "SELECT ... WHERE id = " . $_GET['id']) — SQL injection
  • Flag echo $_GET['name'] or any unescaped output — XSS; use htmlspecialchars() with ENT_QUOTES
  • Flag include / require with user-controlled paths — local/remote file inclusion
  • Flag eval() — remote code execution risk; no legitimate use in application code
  • Flag shell_exec / exec / system / passthru with user-controlled input — command injection
  • Flag unserialize() on untrusted data — arbitrary object instantiation and code execution
  • Flag move_uploaded_file without MIME type validation and extension whitelist — file upload attack
  • Flag header("Location: " . $_GET['url']) without validation — open redirect
  • Flag missing CSRF token validation on state-changing form endpoints

Async / Concurrency

  • Flag long-running synchronous operations in a request cycle — offload to a queue (Laravel Queue, RabbitMQ)
  • Flag sleep() used inside a request handler — blocks the PHP-FPM worker
  • Flag shared mutable state in static properties accessed across requests in long-running processes (Swoole, RoadRunner)
  • Flag missing idempotency in queued jobs — jobs can be retried on failure

Resource Management

  • Flag database connections not closed or returned to the pool ($pdo = null or $conn->close())
  • Flag fopen / fwrite without a matching fclose on all paths
  • Flag curl_init without curl_close — leaks the curl handle
  • Flag unbounded file uploads with no size or type restriction
  • Flag sessions not explicitly closed (session_write_close()) before long operations — session locking blocks other requests

Exception Handling

  • Flag empty catch blocks — swallowed exceptions
  • Flag catch (Exception $e) {} without logging — silent failure
  • Flag die() / exit() used for error handling in library code — use exceptions
  • Flag @ operator used to suppress errors from functions that can fail — check return values instead
  • Flag trigger_error used in new code — prefer exceptions

Performance

  • Flag N+1 Eloquent / Doctrine queries — use eager loading (with(), load(), join)
  • Flag count($array) called repeatedly in a loop condition — cache the result
  • Flag array_push($arr, $val) — use $arr[] = $val which is faster
  • Flag in_array on large arrays without the strict third argument — use isset on a flipped array for O(1) lookup
  • Flag file_get_contents on remote URLs in a request cycle — use an HTTP client with timeout and async where possible
  • Flag Eloquent all() without pagination — loads entire table into memory

Idioms and Best Practices

Type Safety

  • Always declare declare(strict_types=1) at the top of every file
  • Use union types (int|string) and nullable types (?string) rather than mixed
  • Use typed properties on classes — avoid untyped public $foo
  • Use constructor promotion for simple value objects

Modern PHP (8.x)

  • Prefer match expressions over switch — strict comparison, no fall-through
  • Use named arguments for functions with many optional parameters
  • Use enum for fixed sets of values instead of class constants
  • Use readonly properties for immutable data
  • Use nullsafe operator (?->) instead of nested isset checks
  • Use first-class callable syntax (strlen(...)) instead of string references

Laravel / Symfony Specific

  • Keep controllers thin — logic belongs in service classes or action classes
  • Use form requests for validation — never validate in the controller directly
  • Prefer Eloquent relationships over manual joins for readability
  • Flag raw queries where the ORM can express the same intent safely