本文へ移動
cccskills
無料GitHub で公開

php-conventions

Modern PHP idioms for any PHP project (PHP 8.1+): readonly properties, enums, match expressions, constructor property promotion, typed properties, named arguments, nullsafe operator, first-class callable syntax, strict_types, PSR-12 style, and null discipline. Apply when the project is a PHP 8.1+ project. Stack-agnostic — referenced by every PHP plugin in the marketplace. Use this skill to: - Write strongly-typed, immutable-by-default value objects with readonly properties and enums. - Replace switch ladders and magic constants with match expressions and backed enums. - Cut constructor boilerplate with property promotion and express optionality with typed nullable returns. - Keep code PSR-12 compliant with declare(strict_types=1) in every file. Do NOT use this skill for: - Framework-specific idioms (Eloquent, Doctrine, Symfony services, Laravel facades — those live in framework plugin skills). - Composer / autoloading / dependency management — see php-foundation:composer-tooling. - Testing patterns — see php-foundation:php-testing.

インストール方法を見る

含まれるファイル(1)

  • SKILL.md6.8 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

PHP Conventions (stack-agnostic, PHP 8.1+)

This skill encodes idioms that reduce bugs and improve readability in any PHP codebase. Apply alongside the active framework plugin's conventions skill (e.g., laravel:laravel-conventions, symfony:symfony-conventions).

Detection

Read composer.json first to learn the target PHP version:

  • "require": { "php": "^8.1" } (or higher) → all idioms below apply.
  • "config": { "platform": { "php": "8.x" } } pins the resolver version.

Match the project's minimum version — do not use PHP 8.2+ features (e.g. readonly classes, DNF types) on an 8.1 project.

strict_types — always on

Every .php file with logic starts with:

<?php

declare(strict_types=1);

namespace App\Domain;

Strict typing turns silent coercions into TypeErrors at the boundary, catching bugs early. The declaration must be the first statement.

Constructor property promotion

Collapse the declare/assign boilerplate into the signature.

// Prefer
final class Money
{
    public function __construct(
        public readonly int $amount,
        public readonly Currency $currency,
    ) {
    }
}

// Avoid — manual field + assignment
final class Money
{
    private int $amount;
    private Currency $currency;

    public function __construct(int $amount, Currency $currency)
    {
        $this->amount = $amount;
        $this->currency = $currency;
    }
}

readonly properties — immutability by default

final class OrderLine
{
    public function __construct(
        public readonly string $sku,
        public readonly int $quantity,
    ) {
    }

    public function withQuantity(int $quantity): self
    {
        return new self($this->sku, $quantity); // return a new instance, never mutate
    }
}

readonly properties can be assigned once (from within the declaring scope) and never again. Use them for value objects and DTOs. On PHP 8.2+ a whole class may be marked readonly.

Enums — replace magic constants

Use backed enums for closed sets of values; attach behaviour with methods.

enum Status: string
{
    case Draft = 'draft';
    case Active = 'active';
    case Archived = 'archived';

    public function isPublished(): bool
    {
        return $this === self::Active;
    }

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

$status = Status::from('active');        // throws ValueError on unknown
$maybe = Status::tryFrom($input);        // null on unknown

Never model a closed set with bare string constants or class const lists when a backed enum fits.

match — exhaustive, type-safe branching

$discount = match (true) {
    $total >= 1000 => 0.15,
    $total >= 500  => 0.10,
    $total >= 100  => 0.05,
    default        => 0.0,
};

match uses strict comparison (===), has no fallthrough, and throws UnhandledMatchError if nothing matches and no default is present — far safer than switch.

Typed properties, parameters, and returns

final class UserService
{
    public function findById(int $id): ?User      // explicit nullable return
    {
        return $this->repository->find($id);
    }

    /** @return list<User> */
    public function active(): array                // PHPDoc narrows array element type
    {
        return $this->repository->whereActive();
    }
}
  • Type every parameter, property, and return value. Use ?T for nullable, union types (int|string) where genuinely needed.
  • PHP has no generics — use PHPDoc (list<T>, array<K, V>) so static analysers (PHPStan/Psalm) can check element types.

Nullsafe operator and null discipline

$country = $order?->customer?->address?->country;   // short-circuits to null

// Validate at boundaries instead of propagating null
public function charge(Customer $customer): void
{
    $card = $customer->defaultCard()
        ?? throw new NoPaymentMethodException($customer->id);
    // ...
}
  • Do not return null to signal errors from public methods — throw a domain exception or return an empty collection.
  • Use the nullsafe operator for optional read chains, not to hide missing required data.

Named arguments

$response = $client->request(
    method: 'POST',
    uri: '/orders',
    options: ['json' => $payload],
);

Use named arguments to clarify boolean/optional parameters at the call site. Do not reorder — pass them in declaration order for readability.

First-class callable syntax

$names = array_map(strtoupper(...), $words);
$ids = array_map($user->id(...), $users);

Prefer $callable(...) over string callable names or array [$obj, 'method'] forms.

Code style — PSR-12

  • 4-space indentation, no tabs. One class per file. Files use <?php (no closing ?>).
  • final by default; open for extension only when designed for it.
  • Single quotes for strings without interpolation.
  • One blank line between methods; trailing comma in multi-line arrays/arguments.
  • Run a formatter (the active framework plugin provides a Stop hook — Laravel Pint or PHP-CS-Fixer with the @PSR12 / @Symfony ruleset). Do not hand-tune whitespace the formatter owns.

Class design rules

  • Single Responsibility: one reason to change per class.
  • Prefer composition over inheritance; keep inheritance trees shallow.
  • Keep the public API minimal — private/protected by default, public only when needed.
  • Define contracts with interface; depend on abstractions, not concretions.
  • Avoid static state. Pure static helpers for stateless functions are acceptable.

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Angular 18-21 project structure, standalone components vs NgModule, control flow (@if/@for/@switch + *ngIf/*ngFor legacy), decorators, dependency injection (inject() function), lifecycle hooks, pipes, Angular Universal SSR pointer. Use this skill to: - Detect project style (standalone vs NgModule) and apply matching patterns. - Pick correct decorators and DI approach. - Use modern control flow (@if/@for/@switch) in Angular 17+ projects. - Apply `inject()` function over constructor injection where appropriate. - Wire bootstrap correctly (bootstrapApplication for standalone, AppModule for legacy). Do NOT use this skill for: - State management (see angular-state-and-rx). - Routing (see angular-routing). - Forms (see angular-forms). - Testing (see angular-testing).

日本語の概要は準備中です。原文の説明を表示しています。

AratKruglik/claude-sdlc362026年9月21日 更新

Angular forms: Reactive Forms (preferred — typed FormGroup/FormControl since Angular 14, FormBuilder, custom + async validators, FormArray, multi-step) and Template-driven (`[(ngModel)]` + FormsModule). Validation strategies, server error mapping, accessibility. Use this skill to: - Build Reactive Forms with typed FormGroup/FormControl. - Use FormBuilder для concise syntax. - Implement custom synchronous and async validators. - Wire FormArray for dynamic field lists. - Map server errors back to form fields. - Pick Reactive vs Template-driven (prefer Reactive). Do NOT use this skill for: - General conventions (see angular-conventions). - State management beyond forms (see angular-state-and-rx). - Routing (see angular-routing). - Testing forms (see angular-testing).

日本語の概要は準備中です。原文の説明を表示しています。

AratKruglik/claude-sdlc362026年9月21日 更新

Angular Router (built-in `@angular/router`) — route configuration for standalone and NgModule projects, functional guards (Angular 14.1+), lazy loading, route resolvers, typed params via signals/observables, programmatic navigation, route data and meta. Use this skill to: - Configure routes (standalone-style or NgModule-style). - Use functional guards (canActivate as function, preferred over class-based in 17+). - Lazy-load components or feature modules. - Implement auth guards via route meta + functional guards. - Read params/queries via `inject(ActivatedRoute)` + signals or RxJS. Do NOT use this skill for: - General conventions (see angular-conventions). - State management (see angular-state-and-rx). - Forms (see angular-forms). - Testing routes (see angular-testing).

日本語の概要は準備中です。原文の説明を表示しています。

AratKruglik/claude-sdlc362026年9月21日 更新

State management for Angular 18-21: signals (signal/computed/effect), services-as-state, NgRx Store + Effects + Selectors, NgRx Component Store, NgRx Signals (newer signal-based store). RxJS essentials — operators, async pipe, takeUntilDestroyed, signal/observable interop. Use this skill to: - Pick the right state tool (signals / services / NgRx variant / vue-query equivalent). - Use signals correctly (signal/computed/effect — when each). - Build a Pinia-style service-as-state singleton. - Set up NgRx Store + Effects + Selectors. - Use RxJS without leaking subscriptions (async pipe, takeUntilDestroyed, Subject patterns). - Bridge signals ↔ observables via toSignal / toObservable. Do NOT use this skill for: - General Angular conventions (see angular-conventions). - Routing state (see angular-routing). - Form state (see angular-forms). - Testing state (see angular-testing).

日本語の概要は準備中です。原文の説明を表示しています。

AratKruglik/claude-sdlc362026年9月21日 更新

Testing Angular 18-21: TestBed, component harnesses (@angular/cdk/testing), Karma+Jasmine (default historical) vs Jest (jest-preset-angular, modern), Angular Testing Library (RTL-style). HttpClient mocking via HttpTestingController. NgRx Effects testing. Cypress / Playwright e2e. Use this skill to: - Detect runner (Karma+Jasmine vs Jest) and configure correctly. - Write component tests with TestBed. - Use component harnesses for Material / custom UI components. - Mock HttpClient via provideHttpClientTesting + HttpTestingController. - Test signal-based inputs with componentRef.setInput(). - Test NgRx Effects with provideMockActions. Do NOT use this skill for: - General Angular conventions (see angular-conventions). - Routing patterns broadly (see angular-routing — covers testing routes briefly). - Form patterns broadly (see angular-forms).

日本語の概要は準備中です。原文の説明を表示しています。

AratKruglik/claude-sdlc362026年9月21日 更新

Shared conventions for every SDLC development-phase architect agent: hard rules, code quality bar, workflow steps (superpowers invocation, spec reading, codebase exploration, verification), and the report/compact-summary contract. Architects load this skill first, then apply their stack-specific instructions on top.

日本語の概要は準備中です。原文の説明を表示しています。

AratKruglik/claude-sdlc362026年9月21日 更新

AratKruglik のスキルをすべて見る

このスキルの問題を報告する