Claude
Skills
Sign in
Back

php

Included with Lifetime
$97 forever

PHP language conventions, modern idioms, and type system. Invoke whenever task involves any interaction with PHP code — writing, reviewing, refactoring, debugging, or understanding PHP projects.

Productivity

What this skill does


# PHP

**Strict types, explicit contracts, no magic. If a class needs a docblock to explain what its properties do, the
properties are named wrong.**

PHP 8.5+ is the baseline. Use modern syntax unconditionally — union types, enums, readonly classes, property hooks,
named arguments, `match`, pipe operator. No backward compatibility with older PHP versions unless the project explicitly
requires it.

Every PHP file starts with `declare(strict_types=1)`.

## References

- **Type system** → `${CLAUDE_SKILL_DIR}/references/typing.md` — Union/intersection/DNF types, nullable patterns, typed
  properties and constants, coercion rules, variance
- **OOP patterns** → `${CLAUDE_SKILL_DIR}/references/oop.md` — Interfaces, traits, readonly, property hooks, enums,
  constructor promotion, lazy objects, magic methods
- **Concurrency** → `${CLAUDE_SKILL_DIR}/references/concurrency.md` — Fiber API, generator coroutines, comparison table,
  async library guidance
- **Packaging** → `${CLAUDE_SKILL_DIR}/references/packaging.md` — composer.json templates, version constraints, project
  layouts, namespace conventions

## Naming

- **Classes, interfaces, traits, enums** — PascalCase: `UserService`, `Renderable`, `Status`
- **Methods, functions** — camelCase: `findById`, `getFullName`
- **Properties, variables** — camelCase: `$userName`, `$isActive`
- **Constants (class and global)** — UPPER_SNAKE_CASE: `MAX_RETRIES`, `DEFAULT_LOCALE`
- **Namespaces** — PascalCase segments: `App\Http\Controller`
- **Enum cases** — PascalCase: `Status::Active`, `Suit::Hearts`

- **Descriptive names.** `$userCount` not `$n`. Short names (`$i`, `$k`, `$v`) only in tiny scopes (loops, array
  operations).
- **No redundant context.** `$car->make` not `$car->carMake`.
- **Boolean names:** `is`/`has`/`can`/`should` prefix: `$isValid`, `$hasAccess`.
- **Abbreviations as words.** `HttpClient` not `HTTPClient`, `JsonParser` not `JSONParser`. Treat abbreviations and
  acronyms as regular words — uppercase first letter only (PER-CS).
- **No underscore prefix** for protected/private visibility. Visibility modifiers exist for that.

## Type Declarations

PHP 8.5+ provides a complete type system. Use it everywhere.

### Core Rules

- **Type all public API boundaries** — function parameters, return types, class properties, class constants.
  Internal/private code benefits from types too.
- **`declare(strict_types=1)`** in every file. No exceptions.
- **Short type names:** `bool`, `int`, `float`, `string`. Never `boolean`, `integer`, `double`.
- **Union types with `|`:** `string|int`, `Foo|null`. Prefer `?T` for single-type nullable.
- **Intersection types with `&`:** `Countable&Traversable`. Class/interface types only.
- **DNF types:** `array|(ArrayAccess&Traversable)` — union of intersections in parentheses.
- **`void` return:** annotate on functions that return nothing.
- **`never` return:** functions that always throw or exit.
- **Avoid `mixed`** — it disables type safety. Use `object` when you mean "any object." Use `mixed` only at true interop
  boundaries with untyped code.
- **`null` last in unions:** `string|int|null`, not `null|string|int`.

### Typed Properties

- Every class property gets a type declaration.
- Typed properties must be initialized before access — use constructor promotion, default values, or constructor
  assignment.
- `callable` cannot be used as a property type. Use `Closure` instead.

### Typed Constants (8.3+)

```php
class Config
{
    public const int MAX_RETRIES = 3;
    public const string DEFAULT_LOCALE = 'en';
    protected const float TAX_RATE = 0.21;
}
```

- Type all class constants. Interface constants especially — they enforce the contract at compile time.

### Variance

- **Parameters are contravariant** — child class can accept wider types.
- **Return types are covariant** — child class can return narrower types.
- `mixed` return can be narrowed to any type in a subclass.

See `${CLAUDE_SKILL_DIR}/references/typing.md` for the complete type system reference.

## Enumerations

- **Use enums for categorical constants.** Never bare strings or ints as pseudo-enums.
- **Backed enums** (`string` or `int`) when the value must interoperate with external systems (JSON, database, API).
- **`from()` throws on invalid value; `tryFrom()` returns `null`.** Choose based on whether invalid input is a caller
  error or expected.
- **Enums can implement interfaces** and define methods. Use this for behavior tied to the enum's domain.
- **Enums cannot have state** (no properties), cannot be extended, cannot be `new`'d.
- **Dynamic access:** `Status::{$name}` (8.3+) for variable-based case resolution.

```php
enum Status: string
{
    case Active = 'active';
    case Inactive = 'inactive';
    case Suspended = 'suspended';

    public function label(): string
    {
        return match ($this) {
            self::Active => 'Active',
            self::Inactive => 'Inactive',
            self::Suspended => 'Suspended',
        };
    }
}
```

## Classes

### Properties and Visibility

- **Explicit visibility on everything** — properties, methods, constants.
- **Constructor promotion** for data-carrying classes:
  ```php
  class User
  {
      public function __construct(
          public readonly string $name,
          private string $email,
          protected int $age = 0,
      ) {}
  }
  ```
- **Readonly properties** (8.1+) for immutable state. Must have a type declaration.
- **Readonly classes** (8.2+) — all properties implicitly readonly, no dynamic properties.
- **Asymmetric visibility** (8.4+) — `public protected(set)` for publicly readable, internally writable properties.
- **Property hooks** (8.4+) — `get`/`set` logic on properties. Use instead of trivial getter/setter methods.
  Incompatible with `readonly`.

### Inheritance and Composition

- **Composition over inheritance.** Use inheritance only for true "is-a" relationships.
- **Interfaces for contracts.** All interface methods are public. As of 8.4, interfaces can declare property
  requirements.
- **Abstract classes** when you need shared implementation alongside a contract.
- **Traits for horizontal reuse.** Never use traits as a substitute for interfaces. One `use` statement per trait, each
  on its own line.
- **`#[Override]`** (8.3+) on every method that overrides a parent or implements an interface method. Catches signature
  drift at compile time.
- **`super()` equivalent:** always use `parent::method()`. Never hardcode grandparent class names.

### Magic Methods

- **Avoid property overloading** (`__get`, `__set`) in new code. Typed properties with hooks are strictly better.
- **`__toString()`** — define when string conversion has meaningful semantics.
- **`__invoke()`** — for single-method objects that act as callables.
- **`__serialize()` / `__unserialize()`** — prefer over `__sleep()` / `__wakeup()`.

### Object Patterns

- **Value objects** — `readonly class` with constructor promotion. Immutable by default.
- **DTOs** — readonly classes with public properties. No behavior.
- **Service classes** — constructor injection for dependencies, no public state.
- **Lazy objects** (8.4+) — defer initialization via `ReflectionClass::newLazyGhost()`.

## Functions

- **Early return.** Guard clauses first, happy path flat. Reduce nesting.
- **One function, one job.** If the name contains "and", split it.
- **Type all parameters and return types** on public functions.
- **Named arguments** for functions with boolean flags or many optional parameters:
  `createUser(name: 'John', admin: true)`.
- **`match` over `switch`** — `match` is an expression, uses strict comparison, and does not fall through.
- **Pipe operator** (8.5+) for functional chaining:
  ```php
  $result = $input
      |> trim(...)
      |> strtolower(...)
      |> ucfirst(...);
  ```
- **First-class callables** with `...` syntax: `array_map(strlen(...), $strings)`.
- **Arrow functions** for short closures: `fn($x) => $x * 2`. Arrow functions capture by 
Files: 6
Size: 37.3 KB
Complexity: 48/100
Category: Productivity

Related in Productivity