Skip to content
Development
Skill

/php-rules

PHP coding rules: style, patterns, security, testing. Triggers: .php, composer.json, Laravel, Symfony, PHPUnit, PSR-12, Composer.

From plugin
ai-toolkit
161111 skills44 agents
Install
$ npx -y skills add softspark/ai-toolkit --skill php-rules --agent claude-code

How 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.md
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
Read more
Ships withai-toolkit

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,

Get the whole plugin