solid-php について
solid-php は、Laravel 13 と PHP 8.3 以降のプロジェクト向けにコーディング指針を示すスキルです。Laravel と FuseCore のモジュール構成を判別し、配置ルールやアンチパターン検出、SOLID と DRY に基づくリファクタリングを案内します。
主な機能
- 01Laravel と FuseCore の構成を判別
- 02責務に応じたファイル配置の案内
- 03行数と PHPDoc の規約
- 04重複や一般的なアンチパターンの検出
- 05SOLID に基づくリファクタリング指針
活用シーン
- 01Laravel 13 の機能に適した構成の選択
- 02FuseCore モジュール内のインターフェースやサービスの配置
- 03大きなクラスやモデル内の業務ロジックの整理
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ fusengine/ agents --skill solid-phpインストール後、Claude Code で/solid-phpを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/anti-patterns.mddecision-guide.mddependency-inversion.mdfusecore-structure.mdinterface-segregation.mdlaravel12-structure.mdliskov-substitution.mdopen-closed.mdphp85-features.mdsingle-responsibility.mdsolid-principles.mdreferences/templates/code-templates.mdcontroller-templates.mdrefactoring-guide.md詳細
Laravel 13 + PHP 8.3+ のコードに SOLID 原則と DRY を適用します。ファイルは
100 行未満(90 行で分割)、インターフェースは
FuseCore/[Module]/App/Contracts/(共有のものは FuseCore/Core/App/Contracts/)に分離し、
すべての public メソッドに PHPDoc を必須とします。Laravel か
FuseCore モジュラーアーキテクチャかを自動検出し、それに応じてコードの配置を振り分けます
(Controllers/Requests/Actions/Services/Repositories/DTOs/Contracts/Events/
Policies)。アンチパターン検出(肥大化したクラス、モデル内のビジネスロジック、具象依存、
strict_types の欠落)と、SOLID 原則(SRP/OCP/LSP/ISP/DIP)ごとのリファクタリング
ガイダンスも提供します。
SOLID PHP - Laravel 13 + PHP 8.3
エージェントワークフロー(必須)
いかなる実装の前にも、3 つのエージェントを並列で起動してください。それぞれ name を指定した Agent 呼び出し 1 回ずつです。
- fuse-ai-pilot:explore-codebase - 既存のアーキテクチャを分析
- fuse-ai-pilot:research-expert - Context7 経由で Laravel/PHP のドキュメントを検証
- mcp__context7__query-docs - SOLID パターンを確認
実装後は、検証のために fuse-ai-pilot:sniper を実行してください。
DRY - 作成する前に再利用(必須)
新しいコードを書く前に:
- 類似するクラス名、メソッド、ロジックがないかコードベースを grep する
- 共有の場所を確認する:
FuseCore/Core/App/Services/、FuseCore/Core/App/Traits/、FuseCore/[Module]/App/Contracts/ - 類似のコードが存在する場合 → 重複させずに拡張/再利用する
- 2 つ以上の機能で使われるコードの場合 → 共有の Services または Traits に作成する
- 繰り返されるロジック(3 回以上の出現)を共有ヘルパーまたは Traits に抽出する
- 記述後に重複が発生していないことを確認する
自動検出(モジュラー必須)
| 検出されるファイル | アーキテクチャ | インターフェースの場所 |
|---|---|---|
FuseCore/ ディレクトリ | FuseCore モジュラー | FuseCore/[Module]/App/Contracts/ |
モジュール内の module.json | FuseCore モジュラー | FuseCore/[Module]/App/Contracts/ |
確認: php artisan --version → Laravel 13.x
構造: 常に FuseCore モジュラー。共有は FuseCore/Core/App/ に配置します。
決定木: コードをどこに置くか?(FuseCore モジュラー)
New code needed?
├── HTTP validation → FuseCore/[Module]/App/Http/Requests/
├── Single action → FuseCore/[Module]/App/Actions/
├── Business logic → FuseCore/[Module]/App/Services/
├── Data access → FuseCore/[Module]/App/Repositories/
├── Data transfer → FuseCore/[Module]/App/DTOs/
├── Interface → FuseCore/[Module]/App/Contracts/
├── Event → FuseCore/[Module]/App/Events/
└── Authorization → FuseCore/[Module]/App/Policies/
決定木: どのパターンを使うか?
| 必要性 | パターン | 場所 | 最大行数 |
|---|---|---|---|
| HTTP 処理 | Controller | Controllers/ | 50 |
| バリデーション | FormRequest | Requests/ | 50 |
| 単一の操作 | Action | Actions/ | 50 |
| 複雑なロジック | Service | Services/ | 100 |
| データアクセス | Repository | Repositories/ | 100 |
| データ構造 | DTO | DTOs/ | 50 |
| 抽象化 | Interface | Contracts/ | 30 |
重要なルール(必須)
1. ファイルは 100 行未満
- 90 行で分割 - 100 行を超えないこと
- Controllers は 50 行未満
- Models は 80 行未満(リレーションを除く)
- Services は 100 行未満
2. インターフェースの分離(FuseCore モジュラー必須)
FuseCore/[Module]/App/Contracts/ # Module interfaces ONLY
├── UserRepositoryInterface.php
└── PaymentGatewayInterface.php
FuseCore/Core/App/Contracts/ # Shared interfaces
3. PHPDoc 必須
/**
* Create a new user from DTO.
*
* @param CreateUserDTO $dto User data transfer object
* @return User Created user model
* @throws ValidationException If email already exists
*/
public function create(CreateUserDTO $dto): User
リファレンスガイド
概念
| トピック | リファレンス | 参照すべきタイミング |
|---|---|---|
| SOLID の概要 | solid-principles.md | すべての原則のクイックリファレンス |
| SRP | single-responsibility.md | ファイルが長すぎる、ファットなコントローラー/モデル |
| OCP | open-closed.md | 支払い方法やチャネルの追加 |
| LSP | liskov-substitution.md | インターフェースの契約、プロバイダーの差し替え |
| ISP | interface-segregation.md | ファットなインターフェース、未使用のメソッド |
| DIP | dependency-inversion.md | 密結合、テスト、モック |
| アンチパターン | anti-patterns.md | コードスメルの検出 |
| 意思決定 | decision-guide.md | パターンの選択 |
| PHP 8.5 | php85-features.md | モダンな PHP の機能 |
| 構造 | laravel12-structure.md | 標準的な Laravel |
| FuseCore | fusecore-structure.md | モジュラーアーキテクチャ |
テンプレート
| テンプレート | 使用するタイミング |
|---|---|
| code-templates.md | Service、DTO、Repository、Interface |
| controller-templates.md | Controller、Action、FormRequest、Policy |
| refactoring-guide.md | レガシーコードからの段階的な移行 |
禁止事項
| アンチパターン | 検出方法 | 修正方法 |
|---|---|---|
| 100 行を超えるファイル | 行数 | より小さなファイルに分割する |
| 50 行を超えるコントローラー | 行数 | Service に抽出する |
| 実装ファイル内のインターフェース | 配置場所 | FuseCore/[Module]/App/Contracts/ に移動する |
| モデル内のビジネスロジック | モデル内のコード | Service に抽出する |
| 具象依存 | new Class() | ModuleServiceProvider 経由で注入する |
| PHPDoc の欠如 | doc ブロックがない | ドキュメントを追加する |
| strict_types の欠如 | declare がない | すべてのファイルに追加する |
| ファットなクラス | public メソッドが 5 つを超える | 責務を分割する |
| 重複したロジック | 2 つ以上のファイルに同じコード | Service/Trait に抽出する |
| コーディング前の Grep 不足 | 検索せずに作成 | まずコードベースを Grep する |
ベストプラクティス
| すべきこと | すべきでないこと |
|---|---|
| コンストラクタプロパティプロモーションを使用する | プロパティ代入を使用する |
| インターフェースに依存する | 具象クラスに依存する |
final readonly class を使用する | 可変クラスを使用する |
declare(strict_types=1) を使用する | 型宣言を省略する |
| 90 行で分割する | 100 行になるまで待つ |
| データ転送に DTO を使用する | 配列を使用する |
Laravel 13 の注意事項
PHP 8.3 以上が必須
Laravel 13 には PHP 8.3 が必要です(L12 では 8.2 でした)。SOLID に適した機能:
readonlyクラス:final readonly class UserDto(完全な不変性)- 型付きクラス定数:
const int MAX_RETRIES = 3; #[\Override]属性: 親メソッドのオーバーライドを明示的に宣言します(タイポを検出)- ネイティブの
json_validate()(json_decode+ try/catch より高速) - 動的クラス定数フェッチ:
$class::{$name}
use Override;
final readonly class PaymentService implements PaymentContract
{
public const int DEFAULT_TIMEOUT = 30;
public function __construct(
private StripeClient $stripe,
private LoggerInterface $logger,
) {}
#[Override]
public function process(PaymentDto $payment): PaymentResult
{
// ...
}
}
L13 向けのより厳格な SOLID ルール
- すべての DTO/値オブジェクトには
final readonly classを優先する - すべての継承メソッドに
#[\Override]を使用する(CI で検出) - 定数に型を付ける(
const string ROLE = 'admin';)
コメント
Markdown 対応