キーワードを入力して検索

PHP開発 30分で読める

Claude Code PHP開発活用法|Laravel・WordPress自動化

Claude Codeは、PHPプロジェクトでも圧倒的な開発効率を発揮します。Laravel・WordPressをはじめとするPHPフレームワークでのコード生成、PHPStanによる静的解析の自動化、PHPUnitテストの一括生成まで、この記事ではPHP開発者がClaude Codeを最大限に活用するための設定方法と実践テクニックを、実際のコード例とともに徹底解説します。

1. PHPプロジェクト向けCLAUDE.mdの最適設定

Claude Codeの出力品質を大きく左右するのがCLAUDE.mdファイルです。PHPプロジェクトでは、使用するフレームワーク・PHPバージョン・コーディング規約・ディレクトリ構造を明記することで、生成コードの精度が飛躍的に向上します。

PHPプロジェクト向けCLAUDE.mdの完全テンプレート

以下は、PHP(Laravel)プロジェクト向けのCLAUDE.mdテンプレートです。プロジェクトルートに配置してください。

# プロジェクト設定 ## 技術スタック - PHP 8.3 - Laravel 11 - MySQL 8.0 - Redis 7 - Node.js 20(フロントエンド) ## ディレクトリ構造 - app/Models/ - Eloquentモデル - app/Http/Controllers/ - コントローラ - app/Services/ - ビジネスロジック - app/Repositories/ - データアクセス層 - database/migrations/ - マイグレーション - tests/Unit/ - ユニットテスト - tests/Feature/ - 機能テスト ## コーディング規約 - PSR-12 準拠 - 厳密な型宣言を使用: declare(strict_types=1) - メソッドには必ず戻り値の型を宣言する - プロパティには必ず型宣言を付ける - PHPStan レベル8で解析をパスすること - PHP CS Fixer(.php-cs-fixer.php)に従うこと ## 禁止事項 - dd()やdump()を本番コードに残さない - env()をconfig以外で直接呼ばない - SQLの直接組み立て禁止(Eloquent/QueryBuilder必須) - anyを使った型回避禁止 ## テスト規約 - テストクラス名: {対象クラス名}Test - テストメソッド名: test_{動作の説明} - 各テストにはアサーションを必ず含める - モックは Mockery を使用 - テスト実行: php artisan test ## コマンド - 構文チェック: php -l {ファイル} - 静的解析: ./vendor/bin/phpstan analyse - テスト: php artisan test - フォーマット: ./vendor/bin/php-cs-fixer fix

CLAUDE.mdは プロジェクトルートに配置します。Claude Codeは起動時にこのファイルを自動的に読み込み、記載されたルールに従ってコードを生成します。グローバル設定は~/.claude/CLAUDE.mdに配置できます。

フレームワーク別のCLAUDE.md設定ポイント

Laravel

  • Eloquentモデルのリレーション方針
  • FormRequestバリデーション必須
  • Service層の責務範囲
  • API Resource/Collectionの使い方

WordPress

  • WordPress Coding Standards準拠
  • nonce検証・エスケープ関数の使い方
  • フック(action/filter)の命名規則
  • $wpdb->prepare() 必須

Symfony

  • サービスコンテナの設定方針
  • Doctrine Entityの設計規約
  • Twig テンプレートの規約
  • Messenger/Event の活用方針

API開発(Slim/Lumen)

  • ルーティング設計のルール
  • ミドルウェアの適用方針
  • JSONレスポンス形式の統一
  • 認証方式(JWT/OAuth等)の指定

2. PHPプロジェクトでClaude Codeを始める手順

Claude Codeを既存のPHPプロジェクトで使い始めるための具体的な手順を解説します。新規プロジェクトでも既存プロジェクトでも、以下の流れで進めてください。

Step 1: Claude Codeのインストール

まだClaude Codeをインストールしていない場合は、以下のコマンドを実行します。

# Claude Codeのインストール npm install -g @anthropic-ai/claude-code # バージョン確認 claude --version

Claude Codeの詳しいインストール手順は「Claude Code入門ガイド」を参照してください。

Step 2: PHPプロジェクトで起動する

PHPプロジェクトのルートディレクトリでClaude Codeを起動します。

# プロジェクトルートに移動 cd /path/to/your-laravel-project # Claude Codeを起動 claude # Claude Codeが自動的にプロジェクト構造を認識 # - composer.json からフレームワークとパッケージを検出 # - CLAUDE.md からプロジェクトルールを読み込み # - .phpstan.neon / phpstan.neon.dist から静的解析設定を認識

Step 3: PHPStan・PHP CS Fixerを導入する

コード品質を担保するために、静的解析ツールとコードフォーマッターを導入します。これらがあるとClaude Codeが生成後に自動チェックできます。

# PHPStan(静的解析)のインストール composer require --dev phpstan/phpstan composer require --dev phpstan/phpstan-strict-rules # Laravel用の拡張 composer require --dev larastan/larastan # PHP CS Fixer(フォーマッター)のインストール composer require --dev friendsofphp/php-cs-fixer # PHPUnit(テスト)は通常Laravelに同梱済み # Laravelでない場合: composer require --dev phpunit/phpunit

Step 4: PHPStan設定ファイルを作成する

プロジェクトルートにphpstan.neonを配置します。Claude Codeはこの設定を自動認識します。

# phpstan.neon(Laravelプロジェクト向け) includes: - vendor/larastan/larastan/extension.neon parameters: paths: - app/ level: 8 ignoreErrors: # 必要に応じてエラーを除外 excludePaths: - app/Http/Middleware/ checkMissingIterableValueType: false

Step 5: 最初のタスクを実行する

準備が整ったら、Claude Codeに最初のタスクを指示してみましょう。

# Claude Codeへの指示例 > app/Models/User.php を確認して、 プロフィール更新機能を追加してください。 Service層・FormRequest・テストも作成してください。

Claude Codeは以下の順序で作業を進めます。

  1. 既存のコードを読み取り、プロジェクトの構造やコーディングスタイルを理解する
  2. CLAUDE.mdのルールに従い、必要なファイルを生成する
  3. php -lで構文チェックを実行する
  4. PHPStanで静的解析を実行し、エラーがあれば自動修正する
  5. テストを実行して動作を確認する

3. Laravel開発でClaude Codeを使う実践チュートリアル

Laravelは日本のPHP開発者に最も人気のあるフレームワークです。Claude Codeとの相性は非常に良く、Eloquent・マイグレーション・テスト・APIリソースなどの生成を高い精度で行えます。ここでは実際のユースケースに沿って解説します。

3-1. CRUD機能の一括生成

Claude Codeに以下のように指示するだけで、Model・Migration・Controller・FormRequest・Resource・テストを一括生成できます。

# Claude Codeへの指示 > 「商品管理」機能を作成してください。 - Productモデル(name, price, description, stock, status) - マイグレーション - ProductController(CRUD) - StoreProductRequest / UpdateProductRequest - ProductResource / ProductCollection - Unit/Featureテスト - Laravel 11のルーティング形式で

Claude Codeが生成するコードの例を見てみましょう。

<?php // app/Models/Product.php declare(strict_types=1); namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; /** * @property int $id * @property string $name * @property int $price * @property string|null $description * @property int $stock * @property string $status */ class Product extends Model { use HasFactory; use SoftDeletes; protected $fillable = [ 'name', 'price', 'description', 'stock', 'status', ]; protected $casts = [ 'price' => 'integer', 'stock' => 'integer', ]; public function scopeActive( \Illuminate\Database\Eloquent\Builder $query ): \Illuminate\Database\Eloquent\Builder { return $query->where('status', 'active'); } }
<?php // app/Http/Requests/StoreProductRequest.php declare(strict_types=1); namespace App\Http\Requests; use Illuminate\Foundation\Http\FormRequest; class StoreProductRequest extends FormRequest { public function authorize(): bool { return true; } /** * @return array<string, array<int, string>> */ public function rules(): array { return [ 'name' => ['required', 'string', 'max:255'], 'price' => ['required', 'integer', 'min:0'], 'description' => ['nullable', 'string', 'max:5000'], 'stock' => ['required', 'integer', 'min:0'], 'status' => ['required', 'in:active,inactive,draft'], ]; } /** * @return array<string, string> */ public function messages(): array { return [ 'name.required' => '商品名は必須です。', 'price.required' => '価格は必須です。', 'price.min' => '価格は0以上で入力してください。', ]; } }

3-2. Eloquentリレーションの構築

複雑なリレーションもClaude Codeに自然言語で指示できます。

# Claude Codeへの指示 > User hasMany Order、Order belongsTo User、 Order hasMany OrderItem、OrderItem belongsTo Product のリレーションを構築してください。 Eager Loading用のスコープも作成してください。
<?php // 生成されるリレーション例(app/Models/Order.php) declare(strict_types=1); namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Builder; class Order extends Model { protected $fillable = ['user_id', 'total', 'status']; public function user(): BelongsTo { return $this->belongsTo(User::class); } public function items(): HasMany { return $this->hasMany(OrderItem::class); } /** * Eager Loading用スコープ */ public function scopeWithDetails(Builder $query): Builder { return $query->with([ 'user:id,name,email', 'items.product:id,name,price', ]); } }

3-3. APIエンドポイントの作成

RESTful APIの実装もClaude Codeの得意分野です。

# Claude Codeへの指示 > 商品APIを作成してください。 - GET /api/products(一覧・ページネーション・検索・ソート) - GET /api/products/{id}(詳細) - POST /api/products(作成・認証必須) - PUT /api/products/{id}(更新・認証必須) - DELETE /api/products/{id}(削除・認証必須) - API Resourceを使ったレスポンス統一 - Sanctum認証
<?php // app/Http/Controllers/Api/ProductController.php declare(strict_types=1); namespace App\Http\Controllers\Api; use App\Http\Controllers\Controller; use App\Http\Requests\StoreProductRequest; use App\Http\Requests\UpdateProductRequest; use App\Http\Resources\ProductCollection; use App\Http\Resources\ProductResource; use App\Models\Product; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; class ProductController extends Controller { public function index(Request $request): ProductCollection { $query = Product::query(); // 検索 if ($search = $request->input('search')) { $query->where('name', 'like', "%{$search}%"); } // ステータスフィルタ if ($status = $request->input('status')) { $query->where('status', $status); } // ソート $sortBy = $request->input('sort_by', 'created_at'); $sortDir = $request->input('sort_dir', 'desc'); $query->orderBy($sortBy, $sortDir); return new ProductCollection( $query->paginate($request->input('per_page', 15)) ); } public function store( StoreProductRequest $request ): JsonResponse { $product = Product::create($request->validated()); return (new ProductResource($product)) ->response() ->setStatusCode(201); } public function show(Product $product): ProductResource { return new ProductResource($product); } public function update( UpdateProductRequest $request, Product $product ): ProductResource { $product->update($request->validated()); return new ProductResource($product); } public function destroy(Product $product): JsonResponse { $product->delete(); return response()->json(null, 204); } }

3-4. マイグレーション・Seederの生成

データベース関連のコードも自然言語で指示できます。

# Claude Codeへの指示 > productsテーブルにcategory_idカラムを追加する マイグレーションを作成してください。 categoriesテーブルへの外部キー制約付きで、 既存データにはデフォルトカテゴリを設定してください。
<?php // database/migrations/2026_03_17_add_category_id_to_products.php declare(strict_types=1); use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\DB; return new class extends Migration { public function up(): void { Schema::table('products', function (Blueprint $table) { $table->foreignId('category_id') ->nullable() ->after('name') ->constrained() ->nullOnDelete(); }); // 既存データにデフォルトカテゴリを設定 $defaultCategory = DB::table('categories') ->where('slug', 'uncategorized') ->first(); if ($defaultCategory) { DB::table('products') ->whereNull('category_id') ->update(['category_id' => $defaultCategory->id]); } } public function down(): void { Schema::table('products', function (Blueprint $table) { $table->dropForeign(['category_id']); $table->dropColumn('category_id'); }); } };

4. WordPress開発でのAI活用パターン

WordPress開発にもClaude Codeは強力なパートナーです。プラグイン開発・テーマカスタマイズ・カスタムブロック作成・REST API拡張など、WordPressの複雑なエコシステムをClaude Codeが理解した上でコードを生成します。

4-1. WordPress向けCLAUDE.mdの設定

# WordPress プラグイン開発 - CLAUDE.md ## 技術スタック - WordPress 6.7 - PHP 8.2 - MySQL 8.0 ## コーディング規約 - WordPress Coding Standards(WPCS)準拠 - プラグインプレフィックス: myplugin_ - テキストドメイン: my-plugin - すべてのユーザー入力をサニタイズする - 出力は必ずエスケープする(esc_html, esc_attr, wp_kses) ## セキュリティルール - nonce検証: wp_verify_nonce() / check_admin_referer() - 権限チェック: current_user_can() を必ず使用 - DB操作: $wpdb->prepare() 必須 - ファイルアップロード: wp_handle_upload() 使用 ## 禁止事項 - extract() の使用禁止 - eval() の使用禁止 - 直接的なSQL文の組み立て禁止 - $_GET/$_POST の直接echo禁止

4-2. カスタム投稿タイプとメタボックスの作成

Claude Codeにカスタム投稿タイプの作成を指示する例です。

# Claude Codeへの指示 > 「イベント」カスタム投稿タイプを作成してください。 - カスタムフィールド: 開催日、場所、定員、参加費 - メタボックス付き - 管理画面カラムにカスタムフィールドを表示 - アーカイブページ対応 - WordPressコーディング規約準拠
<?php /** * Plugin Name: Event Manager * Description: イベント管理プラグイン * Version: 1.0.0 * Text Domain: event-manager */ declare(strict_types=1); defined('ABSPATH') || exit; /** * カスタム投稿タイプ「イベント」を登録 */ function em_register_event_post_type(): void { $labels = array( 'name' => __('イベント', 'event-manager'), 'singular_name' => __('イベント', 'event-manager'), 'add_new' => __('新規追加', 'event-manager'), 'add_new_item' => __('新規イベントを追加', 'event-manager'), 'edit_item' => __('イベントを編集', 'event-manager'), 'view_item' => __('イベントを表示', 'event-manager'), 'all_items' => __('すべてのイベント', 'event-manager'), 'search_items' => __('イベントを検索', 'event-manager'), ); $args = array( 'labels' => $labels, 'public' => true, 'has_archive' => true, 'rewrite' => array('slug' => 'events'), 'supports' => array('title', 'editor', 'thumbnail'), 'menu_icon' => 'dashicons-calendar-alt', 'show_in_rest' => true, ); register_post_type('event', $args); } add_action('init', 'em_register_event_post_type'); /** * イベント詳細メタボックスを追加 */ function em_add_event_meta_boxes(): void { add_meta_box( 'em_event_details', __('イベント詳細', 'event-manager'), 'em_render_event_meta_box', 'event', 'normal', 'high' ); } add_action('add_meta_boxes', 'em_add_event_meta_boxes'); /** * メタボックスのHTML出力 */ function em_render_event_meta_box(\WP_Post $post): void { wp_nonce_field('em_save_event', 'em_event_nonce'); $event_date = get_post_meta($post->ID, '_em_event_date', true); $location = get_post_meta($post->ID, '_em_location', true); $capacity = get_post_meta($post->ID, '_em_capacity', true); $fee = get_post_meta($post->ID, '_em_fee', true); ?> <table class="form-table"> <tr> <th><label for="em_event_date"> <?php esc_html_e('開催日', 'event-manager'); ?> </label></th> <td><input type="date" id="em_event_date" name="em_event_date" value="<?php echo esc_attr($event_date); ?>"></td> </tr> <tr> <th><label for="em_location"> <?php esc_html_e('場所', 'event-manager'); ?> </label></th> <td><input type="text" id="em_location" name="em_location" class="regular-text" value="<?php echo esc_attr($location); ?>"></td> </tr> <tr> <th><label for="em_capacity"> <?php esc_html_e('定員', 'event-manager'); ?> </label></th> <td><input type="number" id="em_capacity" name="em_capacity" min="0" value="<?php echo esc_attr($capacity); ?>"></td> </tr> <tr> <th><label for="em_fee"> <?php esc_html_e('参加費', 'event-manager'); ?> </label></th> <td><input type="number" id="em_fee" name="em_fee" min="0" value="<?php echo esc_attr($fee); ?>"></td> </tr> </table> <?php } /** * メタデータの保存 */ function em_save_event_meta(int $post_id): void { // nonce検証 if ( ! isset($_POST['em_event_nonce']) || ! wp_verify_nonce( sanitize_text_field( wp_unslash($_POST['em_event_nonce']) ), 'em_save_event' ) ) { return; } // 自動保存をスキップ if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return; } // 権限チェック if (! current_user_can('edit_post', $post_id)) { return; } $fields = array( '_em_event_date' => 'sanitize_text_field', '_em_location' => 'sanitize_text_field', '_em_capacity' => 'absint', '_em_fee' => 'absint', ); foreach ($fields as $key => $sanitize_fn) { $field_name = str_replace('_em_', 'em_', $key); if (isset($_POST[$field_name])) { $value = wp_unslash($_POST[$field_name]); update_post_meta( $post_id, $key, $sanitize_fn($value) ); } } } add_action('save_post_event', 'em_save_event_meta');

Claude Codeが生成したWordPressコードは、nonce検証・権限チェック・サニタイズ・エスケープなどのセキュリティベストプラクティスを自動的に含みます。CLAUDE.mdでセキュリティルールを明記しておくことで、さらに確実になります。

4-3. REST API拡張

WordPress REST APIのカスタムエンドポイント追加もClaude Codeで簡単です。

# Claude Codeへの指示 > WordPressのREST APIに /wp-json/em/v1/events エンドポイントを追加してください。 - 一覧取得(ページネーション対応) - 日付範囲フィルタ - 認証必須のPOSTエンドポイント
<?php /** * REST APIエンドポイント登録 */ function em_register_rest_routes(): void { register_rest_route('em/v1', '/events', array( array( 'methods' => 'GET', 'callback' => 'em_get_events', 'permission_callback' => '__return_true', 'args' => array( 'page' => array( 'default' => 1, 'sanitize_callback' => 'absint', ), 'per_page' => array( 'default' => 10, 'sanitize_callback' => 'absint', ), 'from' => array( 'sanitize_callback' => 'sanitize_text_field', ), 'to' => array( 'sanitize_callback' => 'sanitize_text_field', ), ), ), array( 'methods' => 'POST', 'callback' => 'em_create_event', 'permission_callback' => function () { return current_user_can('publish_posts'); }, ), )); } add_action('rest_api_init', 'em_register_rest_routes'); /** * イベント一覧を取得 */ function em_get_events(\WP_REST_Request $request): \WP_REST_Response { $args = array( 'post_type' => 'event', 'posts_per_page' => $request->get_param('per_page'), 'paged' => $request->get_param('page'), 'orderby' => 'meta_value', 'meta_key' => '_em_event_date', 'order' => 'ASC', ); // 日付範囲フィルタ $meta_query = array(); $from = $request->get_param('from'); $to = $request->get_param('to'); if ($from) { $meta_query[] = array( 'key' => '_em_event_date', 'value' => sanitize_text_field($from), 'compare' => '>=', 'type' => 'DATE', ); } if ($to) { $meta_query[] = array( 'key' => '_em_event_date', 'value' => sanitize_text_field($to), 'compare' => '<=', 'type' => 'DATE', ); } if (! empty($meta_query)) { $args['meta_query'] = $meta_query; } $query = new \WP_Query($args); $events = array(); foreach ($query->posts as $post) { $events[] = array( 'id' => $post->ID, 'title' => $post->post_title, 'date' => get_post_meta( $post->ID, '_em_event_date', true ), 'location' => get_post_meta( $post->ID, '_em_location', true ), 'capacity' => (int) get_post_meta( $post->ID, '_em_capacity', true ), 'fee' => (int) get_post_meta( $post->ID, '_em_fee', true ), ); } return new \WP_REST_Response(array( 'events' => $events, 'total' => $query->found_posts, 'pages' => $query->max_num_pages, ), 200); }

4-4. 既存テーマのカスタマイズ

子テーマの作成やfunctions.phpのカスタマイズもClaude Codeで効率化できます。

# Claude Codeへの指示 > Twenty Twenty-Fourの子テーマを作成してください。 - カスタムヘッダー・フッター - OGP自動出力機能 - パンくずリスト機能 - 構造化データ(JSON-LD)自動出力

5. PHPStanとClaude Codeで型安全性を向上させる

PHPStanは静的解析ツールで、実行前にコードのバグを検出できます。Claude CodeとPHPStanを組み合わせることで、型安全なPHPコードを効率的に書けるようになります。

5-1. PHPStanレベルの解説

レベル チェック内容 推奨
0 基本的なチェック(未定義変数など) 入門
1-3 型の不一致、不要なキャスト、未定義メソッド レガシー
4-5 戻り値の型、dead code検出 標準
6-7 union型の厳密チェック、引数の型安全 推奨
8-9 nullable型、mixed型の制限、完全な型安全 厳密

5-2. Claude CodeでPHPStanエラーを自動修正する

Claude Codeに「PHPStanのエラーを修正して」と指示するだけで、エラーの解析から修正まで自動で行われます。

# Claude Codeへの指示 > ./vendor/bin/phpstan analyse を実行して、 報告されたエラーをすべて修正してください。

Claude Codeは以下のように動作します。

# Claude Codeの作業フロー $ ./vendor/bin/phpstan analyse ------ ------------------------------------------------- Line app/Services/OrderService.php ------ ------------------------------------------------- 45 Parameter #1 $price of method calculateTax() expects int, string given. 78 Method getTotal() should return int but returns int|null. ------ ------------------------------------------------- # Claude Codeが自動修正 # 1. $price の型をintにキャスト # 2. getTotal() の戻り値型を int|null に変更、 # またはnullチェックを追加 # 修正後に再度PHPStanを実行して確認 $ ./vendor/bin/phpstan analyse # [OK] No errors

5-3. レガシーコードの型安全化

型宣言のないレガシーPHPコードをClaude Codeで段階的に型安全にする戦略です。

# Claude Codeへの指示(段階的アプローチ) > app/Services/PaymentService.php に対して、 以下の順序で型安全化を行ってください。 1. declare(strict_types=1) を追加 2. メソッド引数に型宣言を追加 3. 戻り値の型宣言を追加 4. プロパティの型宣言を追加 5. PHPDocの @var/@param/@return を更新 6. phpstan analyse --level 8 でエラーがないこと
<?php // Before: 型宣言なしのレガシーコード class PaymentService { private $gateway; private $logger; public function __construct($gateway, $logger) { $this->gateway = $gateway; $this->logger = $logger; } public function charge($amount, $currency, $token) { $result = $this->gateway->charge($amount, $currency, $token); $this->logger->info('Payment charged', $result); return $result; } } // After: Claude Codeによる型安全化 declare(strict_types=1); class PaymentService { public function __construct( private readonly PaymentGatewayInterface $gateway, private readonly LoggerInterface $logger, ) { } /** * @throws PaymentFailedException */ public function charge( int $amount, string $currency, string $token ): PaymentResult { $result = $this->gateway->charge( $amount, $currency, $token ); $this->logger->info('Payment charged', [ 'amount' => $amount, 'currency' => $currency, 'transaction_id' => $result->getTransactionId(), ]); return $result; } }

5-4. PHPDoc生成の自動化

既存コードにPHPDocを一括追加することもClaude Codeで可能です。

# Claude Codeへの指示 > app/Services/ 配下のすべてのクラスに PHPDocを追加してください。 - クラスの概要説明 - @param, @return, @throws - PHPStan用の @template, @extends 等 - 配列の型は array<string, mixed> 形式で記載

6. PHPUnitテスト自動生成の実践例

テスト作成は開発者にとって時間のかかる作業ですが、Claude Codeを使えばテストコードを高速に生成できます。ユニットテスト・機能テスト・統合テストのいずれにも対応します。

6-1. 基本的なユニットテストの自動生成

# Claude Codeへの指示 > app/Services/PriceCalculator.php のユニットテストを 作成してください。 - 正常系・異常系・境界値をカバー - データプロバイダを活用 - カバレッジ100%を目指す
<?php // tests/Unit/Services/PriceCalculatorTest.php declare(strict_types=1); namespace Tests\Unit\Services; use App\Services\PriceCalculator; use InvalidArgumentException; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; class PriceCalculatorTest extends TestCase { private PriceCalculator $calculator; protected function setUp(): void { parent::setUp(); $this->calculator = new PriceCalculator(); } #[Test] public function test_calculate_tax_with_standard_rate(): void { $result = $this->calculator->calculateTax(1000, 0.10); $this->assertSame(100, $result); } #[Test] public function test_calculate_tax_with_reduced_rate(): void { $result = $this->calculator->calculateTax(1000, 0.08); $this->assertSame(80, $result); } #[Test] #[DataProvider('priceWithDiscountProvider')] public function test_apply_discount( int $price, int $discountPercent, int $expected ): void { $result = $this->calculator->applyDiscount( $price, $discountPercent ); $this->assertSame($expected, $result); } /** * @return array<string, array{int, int, int}> */ public static function priceWithDiscountProvider(): array { return [ '10%割引' => [1000, 10, 900], '20%割引' => [1000, 20, 800], '50%割引' => [1000, 50, 500], '割引なし' => [1000, 0, 1000], '100%割引' => [1000, 100, 0], ]; } #[Test] public function test_throws_exception_for_negative_price(): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Price must be non-negative'); $this->calculator->calculateTax(-100, 0.10); } #[Test] public function test_throws_exception_for_invalid_discount(): void { $this->expectException(InvalidArgumentException::class); $this->calculator->applyDiscount(1000, 150); } // 境界値テスト #[Test] public function test_zero_price(): void { $this->assertSame( 0, $this->calculator->calculateTax(0, 0.10) ); } #[Test] public function test_large_price(): void { $result = $this->calculator->calculateTax( PHP_INT_MAX, 0.10 ); $this->assertIsInt($result); } }

6-2. Laravelの機能テスト(Feature Test)

# Claude Codeへの指示 > ProductControllerのFeatureテストを作成してください。 - 認証済み/未認証ユーザーの動作確認 - バリデーションエラーのテスト - データベースへの保存確認 - JSONレスポンスの構造確認
<?php // tests/Feature/Api/ProductControllerTest.php declare(strict_types=1); namespace Tests\Feature\Api; use App\Models\Product; use App\Models\User; use Illuminate\Foundation\Testing\RefreshDatabase; use PHPUnit\Framework\Attributes\Test; use Tests\TestCase; class ProductControllerTest extends TestCase { use RefreshDatabase; private User $user; protected function setUp(): void { parent::setUp(); $this->user = User::factory()->create(); } #[Test] public function test_can_list_products(): void { Product::factory()->count(5)->create(); $response = $this->getJson('/api/products'); $response->assertOk() ->assertJsonCount(5, 'data') ->assertJsonStructure([ 'data' => [ '*' => ['id', 'name', 'price', 'status'], ], 'meta' => ['current_page', 'total'], ]); } #[Test] public function test_authenticated_user_can_create(): void { $payload = [ 'name' => 'テスト商品', 'price' => 3000, 'description' => '説明文', 'stock' => 10, 'status' => 'active', ]; $response = $this->actingAs($this->user) ->postJson('/api/products', $payload); $response->assertCreated() ->assertJsonPath('data.name', 'テスト商品'); $this->assertDatabaseHas('products', [ 'name' => 'テスト商品', 'price' => 3000, ]); } #[Test] public function test_unauthenticated_user_cannot_create(): void { $response = $this->postJson('/api/products', [ 'name' => 'テスト商品', ]); $response->assertUnauthorized(); } #[Test] public function test_validation_error_on_invalid_data(): void { $response = $this->actingAs($this->user) ->postJson('/api/products', [ 'name' => '', 'price' => -100, ]); $response->assertUnprocessable() ->assertJsonValidationErrors([ 'name', 'price', 'stock', 'status', ]); } #[Test] public function test_can_search_products(): void { Product::factory()->create(['name' => 'Laravel本']); Product::factory()->create(['name' => 'PHP入門']); $response = $this->getJson( '/api/products?search=Laravel' ); $response->assertOk() ->assertJsonCount(1, 'data') ->assertJsonPath('data.0.name', 'Laravel本'); } #[Test] public function test_can_delete_product(): void { $product = Product::factory()->create(); $response = $this->actingAs($this->user) ->deleteJson("/api/products/{$product->id}"); $response->assertNoContent(); $this->assertSoftDeleted('products', [ 'id' => $product->id, ]); } }

6-3. テストカバレッジの向上

Claude Codeにカバレッジレポートを渡して、不足しているテストを追加させることもできます。

# カバレッジレポート生成 php artisan test --coverage-html=coverage/ # Claude Codeへの指示 > coverage/ のHTMLレポートを確認して、 カバレッジが80%未満のクラスに対して テストを追加してください。 特にapp/Services/ のカバレッジを重点的に改善してください。

7. Composer連携と依存管理の自動化

Claude CodeはComposerと連携して、パッケージの追加・更新・設定を自動化できます。必要なライブラリを自然言語で伝えるだけで、インストールからコードへの組み込みまで一貫して行います。

7-1. パッケージ追加とコード実装の一括実行

# Claude Codeへの指示 > Stripe決済機能を追加してください。 - stripe/stripe-php パッケージをインストール - 設定ファイルにStripeキーを追加 - PaymentServiceを作成 - 決済・返金・Webhook処理を実装 - テストも作成

Claude Codeは以下の順序で処理を進めます。

  1. composer require stripe/stripe-php を実行
  2. config/services.php にStripe設定を追加
  3. app/Services/StripePaymentService.php を作成
  4. Webhookコントローラを作成
  5. ルーティングを追加
  6. テストを作成・実行

7-2. セキュリティアップデート

# Claude Codeへの指示 > composer audit を実行して、 脆弱性のあるパッケージをアップデートしてください。 後方互換性に問題がある場合は報告してください。
# Claude Codeの実行例 $ composer audit Found 2 security vulnerability advisories: - guzzlehttp/guzzle (7.5.0) - CVE-2023-XXXX - symfony/http-kernel (6.3.0) - CVE-2024-XXXX $ composer update guzzlehttp/guzzle symfony/http-kernel # アップデート後にテスト実行 $ php artisan test # Tests: 156 passed

7-3. Composerスクリプトの設定

CLAUDE.mdにComposerスクリプトを定義しておくと、Claude Codeが品質チェックに活用します。

// composer.json の scripts セクション { "scripts": { "lint": "php -l app/ tests/", "analyse": "./vendor/bin/phpstan analyse", "format": "./vendor/bin/php-cs-fixer fix", "test": "php artisan test", "check": [ "@lint", "@analyse", "@test" ] } }

CLAUDE.mdに「コード変更後は composer check を実行すること」と記載しておけば、Claude Codeがコード変更のたびに自動で品質チェックを実行します。

8. PHP開発で使えるClaude Codeの実践Tips

ここまでの基本を踏まえた上で、日常のPHP開発で活用できる実践的なTipsを紹介します。

Tip 1: デバッグの効率化

エラーが発生した際、エラーメッセージとスタックトレースをClaude Codeに渡すだけで原因特定と修正を一気に行えます。

# Claude Codeへの指示 > 以下のエラーが発生しています。原因を特定して修正してください。 TypeError: App\Services\OrderService::calculateTotal(): Return value must be of type int, null returned in /app/Services/OrderService.php:45

Tip 2: データベースマイグレーションの安全な作成

マイグレーションの作成時に「ダウン方法も含めて」と指示すると、ロールバック可能なマイグレーションを確実に作成します。

# Claude Codeへの指示 > usersテーブルにphone_numberカラムを追加する マイグレーションを作成してください。 - nullable、unique制約付き - down()メソッドも必ず実装 - 既存データへの影響を考慮

Tip 3: コードリファクタリング

Fat Controllerやロングメソッドの分割もClaude Codeが得意とするタスクです。

# Claude Codeへの指示 > app/Http/Controllers/OrderController.php の storeメソッドが150行あります。 以下の方針でリファクタリングしてください。 - バリデーション → FormRequest - ビジネスロジック → Service層 - DB操作 → Repository層 - コントローラは薄く保つ - 既存テストが壊れないこと

Tip 4: MCP Serverを活用したPHP開発

Claude CodeのMCP(Model Context Protocol)Server機能を使えば、データベースへの直接接続やAPI連携も可能になります。

# MCP Serverの設定例(~/.claude/settings.json) { "mcpServers": { "mysql": { "command": "npx", "args": [ "-y", "@anthropic-ai/claude-code-mysql-mcp", "--host", "localhost", "--database", "my_app", "--user", "root" ] } } }

MCPサーバーの詳しい構築方法は「Claude Code MCP Server構築ガイド」を参照してください。

Tip 5: .claude/rulesで品質ルールを自動適用

プロジェクトの.claude/rules/ディレクトリにルールファイルを配置すると、Claude Codeが自動的に従います。

# .claude/rules/php-quality.md ## PHPコーディングルール ### 必須 - declare(strict_types=1) をすべてのPHPファイルに追加 - メソッドには戻り値の型宣言を必ず付ける - SQLインジェクション対策: PDOプリペアドステートメント使用 ### 禁止 - var_dump(), print_r() の使用禁止 - @(エラー抑制演算子)の使用禁止 - グローバル変数の使用禁止 ### テスト - コード変更時は関連テストも更新すること - テストカバレッジ80%以上を維持

Tip 6: Git連携による安全な開発フロー

Claude Codeはgitコマンドを理解しているため、ブランチ作成からコミットまでを一連のフローで行えます。

# Claude Codeへの指示 > feature/payment ブランチを作成して、 Stripe決済機能を実装してください。 実装が完了したら、変更内容を要約した コミットメッセージ付きでコミットしてください。

9. よくある質問(FAQ)

まとめ

Claude CodeはPHP開発の全工程を強力にサポートします。この記事のポイントをまとめます。

  1. CLAUDE.mdが鍵 - PHPバージョン、フレームワーク、コーディング規約を明記することで生成コードの精度が飛躍的に向上
  2. PHPStan連携で型安全 - レベル6以上のPHPStanとClaude Codeを組み合わせることで、型安全なコードを自動生成
  3. テスト自動生成 - PHPUnitテストをClaude Codeに任せることで、テストカバレッジを効率的に向上
  4. Laravel・WordPress対応 - フレームワーク固有の規約を理解した高品質なコード生成
  5. Composer連携 - パッケージ管理からセキュリティアップデートまで自動化

まずはCLAUDE.mdの作成から始めて、PHPStanとPHPUnitを導入してみてください。Claude Codeがあなたの開発パートナーとして、日々のPHP開発を劇的に変えてくれるはずです。

関連記事

Claude Codeをもっと活用したい方へ

ClaudeCodeNaviでは、Claude Codeの使い方や活用事例を日々発信しています。記事の投稿やQ&Aへの参加もお待ちしています。

または

8文字以上で入力してください

または

パスワードをリセット

登録したメールアドレスを入力してください。パスワードリセット用のリンクをお送りします。