LaravelにCloudflare Turnstileを実装してみた2
前回は、Cloudflare Turnstile の概要と、
Laravel(カスタムパッケージ構成)で利用するための
設定ファイルやバリデーションルールの作成までを整理しました。
今回はその続きとして、
- Bladeコンポーネント化
- サービスプロバイダーへの登録
- FormRequest への組み込み
- 実際のフォームへの設置
までをまとめます。
「フォーム側のコードをできるだけ汚さずに組み込みたい」
という前提で進めています。
1. Bladeコンポーネントを作成
フォーム側では、<x-turnstile /> を置くだけで済むようにしたかったため、
Turnstile 用の Blade コンポーネントを作成します。
JavaScript の読み込みや data 属性の指定を
毎回フォーム側で書くのは避けたかった、という理由もあります。
<?php
namespace Tool\General\Application\Infrastructure\View\Components;
use Illuminate\View\Component;
class TurnstileWidget extends Component
{
public $theme;
public $size;
public function __construct($theme = 'light', $size = 'normal')
{
$this->theme = $theme;
$this->size = $size;
}
public function render()
{
return view('general::components.turnstile');
}
}theme や size は、
必要になったときに Blade 側から切り替えられるように
引数として受け取る形にしています。
この形にしておくと、
- フォーム側の記述がかなりシンプルになる
- Turnstile 固有の実装をコンポーネントに閉じ込められる
というメリットがあります。
JavaScript を直接意識せずに置けるので、
フォーム側の見通しはかなり良くなりました。
2. サービスプロバイダーに登録
次に、設定ファイルと Blade コンポーネントを
カスタムパッケージのサービスプロバイダーで登録します。
今回はTool/General/GeneralServiceProvider.php
でまとめて行っています。
useで読み込み
use Illuminate\Support\Facades\Blade;
use Tool\General\Application\Infrastructure\View\Components\TurnstileWidget;register / boot に実装
public function register()
{
$this->mergeConfigFrom(
config_path('turnstile.php'),
'turnstile'
);
}
public function boot()
{
// Turnstile Bladeコンポーネント登録
Blade::component('turnstile', TurnstileWidget::class);
// Turnstileヘルパーの読み込み
if (file_exists(__DIR__.'/Helpers/turnstile.php')) {
require_once __DIR__.'/Helpers/turnstile.php';
}
}カスタムパッケージ構成のため、mergeConfigFrom() を使って設定をマージしています。
また、turnstile_enabled() のような
ヘルパー関数を使いたかったため、
ヘルパーファイルもこのタイミングで読み込んでいます。
3. FormRequestにルールを追加
次に、既存の FormRequest に
Turnstile のバリデーションを 条件付きで追加します。
$rules = [
'name' => 'required|string|max:255',
'kana' => 'string|max:255',
'tel' => 'string|max:50',
'email' => 'required|string|email|min:5|max:255',
];
// Turnstileバリデーション追加
if (turnstile_enabled()) {
$rules['cf-turnstile-response'] = ['required', new Turnstile()];
}
return $rules;- ここで意識したポイントは以下です。
- 保存処理は通常どおり実行する
- Turnstile が失敗した場合は
コントローラに入る前に バリデーションで止める - ローカル環境やテスト環境では
turnstile_enabled()で簡単に無効化できる - Bot 対策は重要ですが、
- アプリケーションの本質的な処理とは切り離しておきたいので、
- この形に落ち着きました。
4. フォームに組み込む
最後に、フォーム側への組み込みです。
Blade 側は本当にこれだけです。
<form action="{{ url('form/submit') }}" method="POST">
@csrf
<!-- 各種フォーム項目 -->
<x-turnstile />
<button type="submit">送信</button>
</form>
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>フォームの HTML を見ても、
Turnstile の存在がほとんど主張してこないのが
個人的にはかなり好印象でした。
ユーザー側でも
「チェックさせられている感」がほぼなく、
UX の面でも reCAPTCHA より軽い印象です。
今回は、
- Blade コンポーネント化
- サービスプロバイダー登録
- FormRequest への組み込み
- フォーム設置
までを整理しました。
次回は、
- ローカル環境・CIでのテスト方法
- 成功/失敗パターンの考え方
- Feature テストでの扱い
あたりをもう少し詳しく書く予定です。
今回は以上です!