🦾

Lighthouse + Laravel Sanctumのテンプレ構築手順

2022/11/13に公開

概要

LighthouseとLaravel Sanctum、その他開発ツールなどを設定したテンプレ作った。

https://github.com/kkznch/template-lighthouse-with-sanctum

背景

テンプレ作っておくと便利だよねって話になったのでテンプレ作った際の手順を書いておく。

構成

  • Laravel 9.x
  • Laravel Sail
  • Laravel Sanctum
    • Cookie認証使う
  • Ligthouse
  • PHP_Codesniffer
  • Larastan
  • GitHub Actions

手順

Laravelプロジェクトの作成

Laravelのプロジェクトを作成する。

$ composer create-project laravel/laravel lighthouse-with-sanctum
$ cd lighthouse-with-sanctum

開発環境やCIでのDB起動時にDBのパスワードがないと怒られるのでenvファイルにパスワードを設定する。

.env.example
...
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
+ DB_PASSWORD=password
...

Laravel Sailの設定

Laravel Sailをインストールする。

$ composer require laravel/sail --dev

mysql, mailhogが含まれたdocker-compose.ymlを作成する。
入れたいものがあればお好みで入れると良い。

$ php artisan sail:install --with=mysql,mailhog

コンテナを起動する。

$ ./vendor/bin/sail up -d

composerインストールする。

$ docker run --rm \
    -u "$(id -u):$(id -g)" \
    -v $(pwd):/var/www/html \
    -w /var/www/html \
    laravelsail/php81-composer:latest \
    composer install --ignore-platform-reqs       

ここまで実行すると、画面(http://localhost)にアクセスした際にLaravelが動作していることが確認できる。

Laravel Sanctumの設定

Laravel SanctumはLaravelプロジェクト作成時にデフォルトでインストールされているので、不要なものを取り除きつつ設定していく。

Sanctumのデフォルトマイグレーションは使用しないので、下記の設定をする。

app/Providers/AppServiceProvider.php
...
use Illuminate\Support\ServiceProvider;
+ use Laravel\Sanctum\Sanctum;

...
    public function register()
    {
+        Sanctum::ignoreMigrations();
    }
...

今回はCookie認証を使用するため、不要なマイグレーションファイルを削除する。

$ rm database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php

Lighthouseの設定

Lighthouseをインストールする。

$ ./vendor/bin/sail composer require nuwave/lighthouse
$ ./vendor/bin/sail artisan vendor:publish --tag=lighthouse-schema
$ ./vendor/bin/sail artisan lighthouse:ide-helper
$ echo -e "schema-directives.graphql\nprogrammatic-types.graphql\n_lighthouse_ide_helper.php" >> .gitignore

Lighthouseの設定ファイルを設置する。

$ ./vendor/bin/sail artisan vendor:publish --tag=lighthouse-config

Lighthouseの設定ファイルにミドルウェアとしてLaravel Sanctumを使用するよう設定する。

config/lighthouse.php
...
    'route' => [
        ...
        'middleware' => [
+            \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
            ...
        ],
        ...
    ],

-    'guard' => 'api',
+    'guard' => 'sanctum',
...

CORS設定ファイルにgraphqlエンドポイントを追加する。

config/cors.php
...
-    'paths' => ['api/*', 'sanctum/csrf-cookie'],
+    'paths' => [
+        'api/*',
+        'graphql',
+        'sanctum/csrf-cookie',
+    ],
...

GraphQL DevToolsの設定

GraphQL開発ツールとしてgraphql-playgroundをインストールする。

$ ./vendor/bin/sail composer require mll-lab/laravel-graphql-playground

graphql-playgroundの設定をする。

$ ./vendor/bin/sail artisan vendor:publish --tag=graphql-playground-config
config/graphql-playground.php
...
    'route' => [
        'uri' => '/graphql-playground',
        'name' => 'graphql-playground',
-        // 'middleware' => ['web']
+        'middleware' => ['web'],
...

Cookie認証を用いるので、graphql-playground画面からのリクエスト時にCSRFトークンを付与する設定を追加する。

$ ./vendor/bin/sail artisan vendor:publish --tag=graphql-playground-view

resources/views/vendor/graphiql/index.blade.php

resources/views/vendor/graphiql/index.blade.php
...
<head>
    <meta charset=utf-8 />
    <meta name="viewport" content="user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, minimal-ui">
+    <meta name="csrf-token" content="{{ csrf_token() }}">
    <title>GraphQL Playground</title>
...
        GraphQLPlayground.init(root, {
            endpoint: "{{url(config('graphql-playground.endpoint'))}}",
            subscriptionEndpoint: "{{config('graphql-playground.subscriptionEndpoint')}}",
+            settings: {
+            'request.credentials': 'same-origin',
+            'request.globalHeaders': {
+                'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
+                }
+            }
        }) 
...  

PHP_Codesnifferの設定

PHP_Codesnifferをインストールする。

$ ./vendor/bin/sail composer require squizlabs/php_codesniffer --dev

composer.jsonのscriptsにコマンド書いておく。

composer.json
...
    "scripts": {
        ...
+        "phpcs": [
+            "./vendor/bin/phpcs --standard=phpcs.xml ./"
+        ],
+        "phpcbf": [
+            "./vendor/bin/phpcbf --standard=phpcs.xml ./"
+        ]
    },

phpcs.xmlを作成する。ルールの定義はお好みでどうぞ。

phpcs.xml
<?xml version="1.0"?>
<ruleset name="PSR12">
    <description>PSR12 compliant rules and settings for Laravel</description>
    <!-- 拡張子が php のものにだけ適用 -->
    <arg name="extensions" value="php" />
    <!-- PSR12 コーディング規約の指定 -->
    <rule ref="PSR12" />
    <!-- 出力に色を適用 -->
    <arg name="colors" />
    <!-- オプション p:進捗表示  s:エラー表示時にルールを表示 -->
    <arg value="ps" />

    <!-- テストではメソッド名に日本語を使用することがあるので除外 -->
    <rule ref="PSR1.Methods.CamelCapsMethodName.NotCamelCaps">
        <exclude-pattern>*/tests/*</exclude-pattern>
    </rule>

    <!-- 除外ディレクトリ・ファイル-->
    <exclude-pattern>/bootstrap/</exclude-pattern>
    <exclude-pattern>/public/</exclude-pattern>
    <exclude-pattern>/resources/</exclude-pattern>
    <exclude-pattern>/storage/</exclude-pattern>
    <exclude-pattern>/vendor/</exclude-pattern>
    <exclude-pattern>/app/Console/Kernel.php</exclude-pattern>
    <exclude-pattern>/tests/CreatesApplication.php</exclude-pattern>
    <exclude-pattern>/_lighthouse_ide_helper.php</exclude-pattern>	
</ruleset>

Larastanの設定

Larastanをインストールする。

$ ./vendor/bin/sail composer require nunomaduro/larastan --dev

composer.jsonのscriptsにコマンド書いておく。

composer.json
...
    "scripts": {
        ...
+        "phpstan": [
+            "@php -d memory_limit=1G ./vendor/bin/phpstan analyse -c phpstan.neon"
+        ]
    },

phpstan.neonを作成する。ルールの定義はお好みでどうぞ。

phpstan.neon
includes:
    - ./vendor/nunomaduro/larastan/extension.neon
parameters:
    level: 6
    paths:
        - ./app
        - ./tests
    # タイプヒントでクラスのジェネリクス型チェックをしないよう設定
    checkGenericClassInNonGenericObjectType: false

PHPUnitの設定

phpunitを並列で実行できるようパッケージをインストールする。

$ ./vendor/bin/sail composer require brianium/paratest --dev

Lighthouseのテストが実行できるよう、TestCaseクラスを編集する。

tests/TestCase.php
<?php

namespace Tests;

use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
+ use Nuwave\Lighthouse\Testing\MakesGraphQLRequests;
+ use Nuwave\Lighthouse\Testing\RefreshesSchemaCache;

abstract class TestCase extends BaseTestCase
{
    use CreatesApplication;
+    use MakesGraphQLRequests;
+    use RefreshesSchemaCache;

+    protected function setUp(): void
+    {
+        parent::setUp();
+        $this->bootRefreshesSchemaCache();
+    }
}

GitHub Actionsの設定

GitHub Actionsの設定ファイルを作成する。
以下はphpcs, phpstan, phpunitを実行するテスト用action。

.github/actions/test/action.yml
name: Testing
description: Test with phpcs, phpstan and phpunit
runs:
  using: composite
  steps:
    - uses: shivammathur/setup-php@v2
      with:
        php-version: 8.1
        extensions: mbstring, dom, fileinfo, mysql
        tools: composer
        coverage: xdebug
    - name: Cache composer dependencies
      id: composer-cache
      uses: actions/cache@v3
      with:
        path: ./vendor
        key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
        restore-keys: |
          ${{ runner.os }}-composer-
    - name: Install composer dependencies
      if: steps.composer-cache.outputs.cache-hit != 'true'
      run: composer install --ignore-platform-reqs
      shell: bash
    - name: Prepare the application
      run: |
        php -r "file_exists('.env') || copy('.env.example', '.env');"
        php artisan key:generate
      shell: bash
    - name: Test with phpcs
      run: composer phpcs
      shell: bash
    - name: Test with phpstan
      run: composer phpstan
      shell: bash      
    - name: Test with phpunit
      run: php artisan test --parallel
      shell: bash
.github/workflows/ci.yml
name: CI

on:
  push:
    branches:
      - '*'

jobs:
  test:
    runs-on: ubuntu-latest
    timeout-minutes: 5
    env:
      DB_HOST: 127.0.0.1
      REDIS_HOST: 127.0.0.1
    services:
      mysql:
        image: mysql/mysql-server:8.0
        ports:
          - 3306:3306
        env:
          MYSQL_ROOT_PASSWORD: password
          MYSQL_ROOT_HOST: "%"
          MYSQL_DATABASE: testing
        options: --health-cmd "mysqladmin ping -h localhost" --health-interval 5s --health-timeout 5s --health-retries 10
      redis:
        image: redis:alpine
        ports:
          - 6379:6379
        options: --health-cmd="redis-cli ping" --health-interval 5s --health-timeout 5s --health-retries 10
    steps:
      - uses: actions/checkout@v3
      - uses: ./.github/actions/test

Dependabotの設定する。

.github/dependabot.yaml
version: 2
updates:
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"
      day: "monday"
  - package-ecosystem: "composer"
    directory: "/"
    schedule:
      interval: "weekly"
      day: "monday"

おわりに

テンプレート自体の構築は以上で終わり。
今後はすぐに開発に移せるよう、参考実装などもリポジトリに含める予定。

参考

Discussion