/php-rules
PHP coding rules: style, patterns, security, testing. Triggers: .php, composer.json, Laravel, Symfony, PHPUnit, PSR-12, Composer.
$ npx -y skills add softspark/ai-toolkit --skill php-rules --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/php-rules
Context preview
The summary Claude sees to decide when to auto-load this skill.
PHP coding rules: style, patterns, security, testing. Triggers: .php, composer.json, Laravel, Symfony, PHPUnit, PSR-12, Composer.
SKILL.md
php-rules.SKILL.mdname: php-rules
description: "PHP coding rules: style, patterns, security, testing. Triggers: .php, composer.json, Laravel, Symfony, PHPUnit, PSR-12, Composer."
effort: medium
user-invocable: false
allowed-tools: Read
PHP Rules
These rules come from `app/rules/php/` in ai-toolkit. They cover the project's standards for coding style, frameworks, patterns, security, and testing in PHP. Apply them when writing or reviewing PHP code.
PHP Coding Style
Standards
- Follow PSR-12 extended coding style.
- Use `declare(strict_types=1)` at the top of every file.
- Use PHP 8.1+ features: enums, fibers, readonly properties, intersection types.
- Use PHP CS Fixer or Pint for automated formatting.
Naming
- PascalCase: classes, interfaces, traits, enums.
- camelCase: methods, functions, variables.
- UPPER_SNAKE: class constants (`public const MAX_RETRIES = 3`).
- snake_case: not used for methods. PSR convention is camelCase.
- Suffix interfaces with `Interface` or prefix with contract name (project convention).
Type System
- Use typed properties: `private readonly string $name;`.
- Use union types: `string|int`. Use intersection types: `Countable&Iterator`.
- Use `enum` (PHP 8.1) for fixed sets of values. Use backed enums for persistence.
- Use `readonly` classes (PHP 8.2) for immutable DTOs.
- Use constructor promotion: `public function __construct(private string $name)`.
- Use `never` return type for functions that throw or exit.
Functions
- Use typed parameters and return types on all functions/methods.
- Use named arguments for readability: `new User(name: 'Ada', age: 36)`.
- Use null-safe operator: `$user?->address?->city`.
- Use match expression over switch for value mapping.
- Use first-class callable syntax: `array_map($this->transform(...), $items)`.
Imports and Namespaces
- Use PSR-4 autoloading via Composer.
- Group `use` statements: classes, functions, constants.
- Never use `require`/`include` for class loading. Use Composer autoloader.
- Use one class per file. File name matches class name.
Error Handling
- Use exceptions for error conditions. Never return error codes.
- Create domain exception hierarchies extending `RuntimeException` or `LogicException`.
- Use `match` with `throw` for exhaustive error mapping.
- Log exceptions with context using PSR-3 logger.
Configuration
- Use PHPStan at level 8+ for static analysis.
- Use Rector for automated code upgrades and refactoring.
- Use `.php-cs-fixer.dist.php` for formatting rules.
- Run `composer analyse` (PHPStan) and `composer format` (Pint) in CI.
PHP Frameworks
Laravel
- Use route model binding: `Route::get('/users/{user}', ...)`.
- Use Form Requests for validation: `class StoreUserRequest extends FormRequest`.
- Use Eloquent scopes for reusable query constraints: `scopeActive()`.
- Use API Resources for response transformation: `UserResource::collection($users)`.
- Use `config()` helper for configuration. Never access `env()` outside config files.
- Use middleware groups for auth, throttling, and CORS.
Eloquent ORM
- Use relationships: `hasMany`, `belongsTo`, `belongsToMany`, `morphMany`.
- Use eager loading: `User::with('posts.comments')->get()` to prevent N+1.
- Use `$fillable` or `$guarded` on models. Prefer `$fillable` (explicit whitelist).
- Use model events or observers for lifecycle hooks.
- Use `upsert()` for bulk insert-or-update operations.
- Use `cursor()` for memory-efficient iteration over large result sets.
Symfony
- Use attributes for route definitions: `#[Route('/api/users', methods: ['GET'])]`.
- Use autowiring for dependency injection. Register services in `services.yaml`.
- Use Symfony Forms for complex validation and data mapping.
- Use Messenger component for async message handling (commands, events).
- Use Doctrine ORM with repository pattern and query builders.
Doctrine ORM
- Use entity classes with annotations or attributes for mapping.
- Use repositories for data access: `$em->getRepository(User::class)`.
- Use DQL for type-safe queries. Use QueryBuilder for dynamic queries.
- Use migrations: `bin/console doctrine:migrations:diff` and `migrate`.
- Use lifecycle callbacks (`@PrePersist`, `@PostUpdate`) for entity events.
Symfony Serializer
- Default behavior uses property names as-is. Combined with PSR-12 `camelCase` property names, JSON output is `camelCase` with zero configuration.
- Avoid adding `api_platform.name_converter: CamelCaseToSnakeCaseNameConverter` globally. Known side-effect ([api-platform/core #6101](https://github.com/api-platform/core/issues/6101)): overrides the project-wide `MetadataAwareNameConverter`, affecting Messenger serializers, custom normalizers, and CLI JSON output — not just the HTTP API.
- Use `#[SerializedName]` only when justified: legacy field alias during rename, external contract mapping, ObjectNormalizer cross-version stabilization. Community practice ([Symfony docs](https://symfony.com/doc/current/serializer.html), Sylius, SymfonyCasts): prefer clean property/getter naming over aliases. When using, document the reason next to the attribute.
- Symfony 7.3.5+ `ObjectNormalizer` produces `isActive` natively for a `isActive(): bool` getter ([symfony/symfony #62353](https://github.com/symfony/symfony/issues/62353)). Older `#[SerializedName('isActive')]` aliases added for pre-7.3.5 `ObjectNormalizer` (which produced `active`) are redundant after upgrade — remove them.
- Avoid duplicate getters like `isActive()` + `getIsActive()` on the same property — `ObjectNormalizer` treats them as two fields and serializes ambiguously. Keep one (`isXxx()` for booleans, `getXxx()` otherwise).
API Platform
- Use API Platform for rapid REST/GraphQL API generation from entities.
- Use `#[ApiResource]` attribute for automatic CRUD endpoint generation.
- Use custom state providers and processors for business logic.
- Use serialization groups for controlling response shape.
- Use filters for query parameter support: pagination, sea
Read more
name: php-rules description: "PHP coding rules: style, patterns, security, testing. Triggers: .php, composer.json, Laravel, Symfony, PHPUnit, PSR-12, Composer." effort: medium user-invocable: false allowed-tools: Read
PHP Rules
These rules come from `app/rules/php/` in ai-toolkit. They cover the project's standards for coding style, frameworks, patterns, security, and testing in PHP. Apply them when writing or reviewing PHP code.
PHP Coding Style
Standards
- Follow PSR-12 extended coding style.
- Use `declare(strict_types=1)` at the top of every file.
- Use PHP 8.1+ features: enums, fibers, readonly properties, intersection types.
- Use PHP CS Fixer or Pint for automated formatting.
Naming
- PascalCase: classes, interfaces, traits, enums.
- camelCase: methods, functions, variables.
- UPPER_SNAKE: class constants (`public const MAX_RETRIES = 3`).
- snake_case: not used for methods. PSR convention is camelCase.
- Suffix interfaces with `Interface` or prefix with contract name (project convention).
Type System
- Use typed properties: `private readonly string $name;`.
- Use union types: `string|int`. Use intersection types: `Countable&Iterator`.
- Use `enum` (PHP 8.1) for fixed sets of values. Use backed enums for persistence.
- Use `readonly` classes (PHP 8.2) for immutable DTOs.
- Use constructor promotion: `public function __construct(private string $name)`.
- Use `never` return type for functions that throw or exit.
Functions
- Use typed parameters and return types on all functions/methods.
- Use named arguments for readability: `new User(name: 'Ada', age: 36)`.
- Use null-safe operator: `$user?->address?->city`.
- Use match expression over switch for value mapping.
- Use first-class callable syntax: `array_map($this->transform(...), $items)`.
Imports and Namespaces
- Use PSR-4 autoloading via Composer.
- Group `use` statements: classes, functions, constants.
- Never use `require`/`include` for class loading. Use Composer autoloader.
- Use one class per file. File name matches class name.
Error Handling
- Use exceptions for error conditions. Never return error codes.
- Create domain exception hierarchies extending `RuntimeException` or `LogicException`.
- Use `match` with `throw` for exhaustive error mapping.
- Log exceptions with context using PSR-3 logger.
Configuration
- Use PHPStan at level 8+ for static analysis.
- Use Rector for automated code upgrades and refactoring.
- Use `.php-cs-fixer.dist.php` for formatting rules.
- Run `composer analyse` (PHPStan) and `composer format` (Pint) in CI.
PHP Frameworks
Laravel
- Use route model binding: `Route::get('/users/{user}', ...)`.
- Use Form Requests for validation: `class StoreUserRequest extends FormRequest`.
- Use Eloquent scopes for reusable query constraints: `scopeActive()`.
- Use API Resources for response transformation: `UserResource::collection($users)`.
- Use `config()` helper for configuration. Never access `env()` outside config files.
- Use middleware groups for auth, throttling, and CORS.
Eloquent ORM
- Use relationships: `hasMany`, `belongsTo`, `belongsToMany`, `morphMany`.
- Use eager loading: `User::with('posts.comments')->get()` to prevent N+1.
- Use `$fillable` or `$guarded` on models. Prefer `$fillable` (explicit whitelist).
- Use model events or observers for lifecycle hooks.
- Use `upsert()` for bulk insert-or-update operations.
- Use `cursor()` for memory-efficient iteration over large result sets.
Symfony
- Use attributes for route definitions: `#[Route('/api/users', methods: ['GET'])]`.
- Use autowiring for dependency injection. Register services in `services.yaml`.
- Use Symfony Forms for complex validation and data mapping.
- Use Messenger component for async message handling (commands, events).
- Use Doctrine ORM with repository pattern and query builders.
Doctrine ORM
- Use entity classes with annotations or attributes for mapping.
- Use repositories for data access: `$em->getRepository(User::class)`.
- Use DQL for type-safe queries. Use QueryBuilder for dynamic queries.
- Use migrations: `bin/console doctrine:migrations:diff` and `migrate`.
- Use lifecycle callbacks (`@PrePersist`, `@PostUpdate`) for entity events.
Symfony Serializer
- Default behavior uses property names as-is. Combined with PSR-12 `camelCase` property names, JSON output is `camelCase` with zero configuration.
- Avoid adding `api_platform.name_converter: CamelCaseToSnakeCaseNameConverter` globally. Known side-effect ([api-platform/core #6101](https://github.com/api-platform/core/issues/6101)): overrides the project-wide `MetadataAwareNameConverter`, affecting Messenger serializers, custom normalizers, and CLI JSON output — not just the HTTP API.
- Use `#[SerializedName]` only when justified: legacy field alias during rename, external contract mapping, ObjectNormalizer cross-version stabilization. Community practice ([Symfony docs](https://symfony.com/doc/current/serializer.html), Sylius, SymfonyCasts): prefer clean property/getter naming over aliases. When using, document the reason next to the attribute.
- Symfony 7.3.5+ `ObjectNormalizer` produces `isActive` natively for a `isActive(): bool` getter ([symfony/symfony #62353](https://github.com/symfony/symfony/issues/62353)). Older `#[SerializedName('isActive')]` aliases added for pre-7.3.5 `ObjectNormalizer` (which produced `active`) are redundant after upgrade — remove them.
- Avoid duplicate getters like `isActive()` + `getIsActive()` on the same property — `ObjectNormalizer` treats them as two fields and serializes ambiguously. Keep one (`isXxx()` for booleans, `getXxx()` otherwise).
API Platform
- Use API Platform for rapid REST/GraphQL API generation from entities.
- Use `#[ApiResource]` attribute for automatic CRUD endpoint generation.
- Use custom state providers and processors for business logic.
- Use serialization groups for controlling response shape.
- Use filters for query parameter support: pagination, sea
Professional-grade AI coding toolkit with multi-platform support. Machine-enforced safety, 109 skills, 44 agents, expanded lifecycle hooks, persona presets, experimental opt-in plugin packs, and benchmark tooling — works with Claude Code, Claude Chat/Cowork,
Repo: softspark/ai-toolkit
Other skills on ai-toolkit.
- /ai-toolkit-rules
Mandatory engineering, security, testing, git, performance, quality, and response rules. Claude MUST load this skill for every technical, coding, debugging, review, architecture, DevOps, data, or file-editing task in Chat or Cowork.
Open skill - /mem-search
Search past coding sessions using natural language. Finds relevant observations, decisions, and context from previous work.
Open skill - /a11y-validate
Accessibility validator: WCAG 2.1 AA, EN 301 549, EAA. Triggers: a11y, accessibility, WCAG, EAA, ARIA, contrast, keyboard, screen reader.
Open skill - /agent-creator
Creates new specialized agents with frontmatter, tools, delegation. Triggers: new agent, create agent, agent scaffold, specialized agent.
Open skill - /analyze
Analyzes code quality, complexity, patterns across codebase. Triggers: quality report, hotspot scan, code analysis, architecture signal.
Open skill - /api-patterns
REST/GraphQL API design: naming, versioning, pagination, idempotency, OpenAPI. Triggers: API design, REST, GraphQL, OpenAPI, Swagger, idempotency, rate limit.
Open skill

