Lighthouse + Laravel Sanctumのテンプレ構築手順
概要
LighthouseとLaravel 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ファイルにパスワードを設定する。
...
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のデフォルトマイグレーションは使用しないので、下記の設定をする。
...
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を使用するよう設定する。
...
'route' => [
...
'middleware' => [
+ \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
...
],
...
],
- 'guard' => 'api',
+ 'guard' => 'sanctum',
...
CORS設定ファイルにgraphqlエンドポイントを追加する。
...
- '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
...
'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
...
<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にコマンド書いておく。
...
"scripts": {
...
+ "phpcs": [
+ "./vendor/bin/phpcs --standard=phpcs.xml ./"
+ ],
+ "phpcbf": [
+ "./vendor/bin/phpcbf --standard=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にコマンド書いておく。
...
"scripts": {
...
+ "phpstan": [
+ "@php -d memory_limit=1G ./vendor/bin/phpstan analyse -c 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クラスを編集する。
<?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。
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
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の設定する。
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
- package-ecosystem: "composer"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
おわりに
テンプレート自体の構築は以上で終わり。
今後はすぐに開発に移せるよう、参考実装などもリポジトリに含める予定。
Discussion