← ClaudeAtlas

phplisted

Write modern, secure PHP 8.x — typed properties, enums, readonly, match, constructor promotion, PSR standards, Composer — and avoid the legacy footguns (SQL injection, XSS, unsafe deserialization, eval). Use when writing or reviewing PHP, modernizing a legacy codebase, setting up Composer/autoloading, hardening request handling, or escaping output. Targets PHP 8.3+ and PSR-12. Triggers — "PHP", "Composer", "Laravel", "WordPress plugin", "$_POST", "PDO", "this PHP is insecure", any `*.php`. Pairs with sql-authoring (parameterized queries), security-web (OWASP), wordpress (the CMS layer), api-design (the contract).
kouroshez/coding-os · ★ 6 · AI & Automation · score 77
Install: claude install-skill kouroshez/coding-os
# Modern PHP PHP earned its insecure reputation from a decade of `mysql_query("...$_GET...")`. Modern PHP (8.3+) is a typed, fast, well-tooled language — the craft is using its type system and PDO, and never trusting `$_GET`/`$_POST`/`$_REQUEST` near a query, a shell, or output. > Scan PHP for the classic dangerous patterns: > `python3 scripts/scan_php_smells.py src/**/*.php` ## Use the 8.x type system ```php // Wrong — untyped, mutable, verbose, no guarantees class Money { public $amount; public $currency; function __construct($amount, $currency) { $this->amount = $amount; $this->currency = $currency; } } // Correct — typed, readonly, promoted constructor params, enum enum Currency: string { case USD = 'USD'; case EUR = 'EUR'; } final class Money { public function __construct( public readonly int $amount, // promoted + readonly = immutable public readonly Currency $currency, ) {} } ``` `declare(strict_types=1);` at the top of every file makes type declarations enforced, not coerced. Use `readonly` for value objects, `enum` for fixed sets, `match` (exhaustive, strict `===`) over `switch`, and union/nullable types. Detail → [references/modern-php.md](references/modern-php.md). ## Never build SQL from request data ```php // Wrong — SQL injection, the canonical PHP breach $id = $_GET['id']; $db->query("SELECT * FROM users WHERE id = $id"); // Correct — PDO prepared statement; the value never touches the SQL text $stmt = $pdo->prepare('SELEC