PHP
SkillSecurityModern PHP 8.5 practices: type system, OOP, security, architecture, async, testing, tooling. Use when writing or reviewing PHP code.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the PHP skill
What this skill tells your AI
The instructions your AI receives, as published by sumonmselim/agentguard in skills/php/SKILL.md and read by ahel’s review.
Runtime and versioning
- Run PHP 8.4 (active support) or 8.5 (latest stable). Never run EOL versions — no security patches
declare(strict_types=1)at top of every file- OPcache enabled in production.
opcache.preloadfor warm startup on 8.0+ - JIT enabled for CPU-bound workloads:
opcache.jit=tracing,opcache.jit_buffer_size=128M. Not beneficial for typical I/O-bound web apps — benchmark before enabling
Type system
- Type-hint all parameters, return types, and properties. No
mixed— use union types (int|string) or generics via PHPDoc neverreturn type for functions that always throw or exitreadonlyproperties for value objects and DTOs (8.1+).readonlyclasses (8.2+) for fully immutable objects- Asymmetric visibility (8.4+):
public private(set)for properties readable everywhere but writable only within class - Property hooks (8.4+):
get/sethooks on properties — eliminates getter/setter boilerplate. Incompatible withreadonly - Intersection types (8.1+):
Countable&Iterator. DNF types (8.2+):(A&B)|null - Typed class constants (8.3+):
const string VERSION = '1.0' #[Override]attribute (8.3+) on overriding methods — compiler-checked safety net- Enums over constants for closed value sets (8.1+). Backed enums (
string/int) for serialisation - Named arguments for multi-param functions with non-obvious order. Not for all calls
matchoverswitch— exhaustive, no fall-through, returns value- First-class callable syntax (8.1+):
strlen(...)overClosure::fromCallable('strlen')
Modern syntax (8.4–8.5)
newwithout parentheses for chaining (8.4+):new Collection()->filter()->map()- Pipe operator (8.5+):
$result = $value |> trim(...) |> strtolower(...) |> htmlspecialchars(...). Prefer over nested calls clone with(8.5+):$new = clone $obj with {name: 'updated'}. Preferred over manual clone + property set- Static property asymmetric visibility (8.5+): same syntax as instance properties
- Lazy objects (8.4+): built-in lazy initialisation via
ReflectionClass::newLazyProxy(). Use for expensive dependencies in DI containers - Driver-specific PDO classes (8.4+):
Pdo\Mysql,Pdo\Pgsql,Pdo\Sqlite— type-safe, IDE-friendly alternatives to genericPDO
Error handling
- Throw exceptions, never return error codes or
false - Catch specific exception types. Never catch
\Throwableat the business layer - Custom exception classes for domain errors callers need to handle
- Log full exception context. Never swallow silently
- Fatal error backtraces (8.5+): enable via
zend.exception_ignore_args=0—error_get_last()now includes trace key
Security
- Never trust user input. Validate and sanitise at every entry point
- Parameterised queries only — PDO driver classes (8.4+) or
PDOwith prepared statements. Never string interpolation in SQL password_hash()/password_verify()withPASSWORD_BCRYPTorPASSWORD_ARGON2ID. Never MD5/SHA1- Escape all output for context: HTML →
htmlspecialchars(), shell →escapeshellarg()orproc_open()with arg array (never shell string) - Never
eval(),exec(),system(),shell_exec()with user-controlled input - Secrets in env or secret manager. Never in code or committed config
- Session cookies:
HttpOnly,Secure,SameSite=Strict. Partitioned cookie support (8.5+) viasetcookie()partitionedoption - CSP, CSRF protection, rate limiting on all forms and auth endpoints
composer auditin CI. Fail on known vulnerabilities- Keep dependencies updated.
composer outdatedas part of regular maintenance
Architecture
- PSR-12 coding standard. Enforce with PHP-CS-Fixer or Pint in CI
- PSR-4 autoloading. No manual
require/includein application code - Depend on abstractions (interfaces), not concretions. Inject dependencies
- Service classes do one thing. No business logic in controllers or views
- Value objects for domain concepts (Money, Email, UserId) — primitives leak
- Repositories only when data source swapping is a real requirement
Async and concurrency
- Fibers (8.1+): cooperative multitasking within a single thread. Foundation for async runtimes
- ReactPHP or AMPHP for event-loop-based async I/O. Swoole/OpenSwoole for coroutine-based high-concurrency servers
- Shared-nothing model is default PHP. Fibers do not add multi-threading — I/O concurrency only
- Avoid blocking calls (
file_get_contents,sleep) inside fiber/event-loop context
Composer and dependencies
- Pin major versions in
composer.json.composer.lockcommitted to git composer auditandcomposer outdatedin CIcomposer install --no-dev --optimize-autoloaderin production. Never--no-scriptsunless you understand what you're skipping- Separate
requirefromrequire-dev. Testing and analysis tools in dev only - Evaluate package maintenance health before adopting. Abandoned packages are a security risk
Testing
- Pest preferred for new projects. PHPUnit for existing codebases — don't mix
- Test behaviour, not implementation. No exposing private methods for testing
- Mock external services (HTTP, queues, storage). Never mock your own domain classes
- PHPStan at level 8+ or Psalm with strict mode. Run in CI, fail on errors
- Mutation testing with Infection for critical business logic
phpbenchfor performance-sensitive code. Benchmark before and after optimisation
Performance
- Profile first: Xdebug (development), Never optimise blind
- Generators for large dataset iteration. Never load unbounded results into memory
- Avoid N+1 queries. Eager-load relationships
SplFixedArrayfor large homogeneous datasets. Lower memory overhead than plain arrays- Fibers/async for I/O concurrency. JIT for CPU-bound computation
Signals
- GitHub stars
- 56
- Forks
- 11
- Last commit
- Jul 2026
Advanced
- Catalog kind
- skill
- Gateway key
php-sumonmselim- Source
- github.com/sumonmselim/agentguard