投稿日:2025年2月15日
普段は素のPHPとJavaScript(jQuery)で書いてますが、Laravelで作ろうとしたら思いの外、苦戦したので、書き残しておこうと思います。
仕様
申し込みフォームで必須項目のチェックボックス(複数選択可)を作ります。
必須項目なので、未選択だとバリデーションエラーが表示されます。
複数項目の最下部に「その他」を設置。
さらに「その他」の下に「その他入力欄」を設置。
「その他」が選択されたら「その他入力欄」は必須項目にする。

▲入力画面

▲確認画面
以下ソースコードです。
index.blade.php(入力画面)
<form action="{{ route('form.confirm') }}" method="POST"">
@csrf
<table class="frmBlock">
<tr>
<th>好きな食べ物<span>必須</span></th>
<td>
<div class="inptBox">
<div>
<p class="supplement">※複数回答可</p>
<div id="favorite">
@foreach (config('favorite') as $favorite)
<label>
<input type="checkbox" name="favorite[]" value="{{$favorite}}" {{ is_array(old("favorite")) &&
in_array($favorite, old("favorite"), true)? ' checked' : '' }}>{{$favorite}}
</label>
@endforeach
<label>
<input type='hidden' value='' name='favorite02'>
<input type="checkbox" name="favorite02" value="その他" {{ old('favorite02') == 'その他' ? 'checked' : '' }}>その他
</label>
</div>
{{-- バリデーション処理 --}}
@if(!is_array(old("favorite")))
@error('favorite')
<p class="errMessege">{{$message}}</p>
@enderror
@endif
<div id="favoriteOtherWrap">
<input id="favorite_other" name="favorite_other" type="text" value="{{ old('favorite_other') }}" size="30">
{{-- バリデーション処理 --}}
@error('favorite_other')
<p class="errMessege">{{$message}}</p>
@enderror
</div>
</div>
</div>
</td>
</tr>
</table>
<div class="btnBox">
<input id="submit" type="submit" name="submitBtnVal" value="確認画面へ進む">
</div>
</form>
▲「その他」以外のチェックボックスはディレクトリconfig内のfavorite.phpに記述してあります。
ループで表示するようにしてます。
18、19行目。「その他」はfavorite.phpから外し、異なる項目として設置しました。
18行目のhidden属性は、未チェック、すなわち、空の状態でも確認画面に持っていけるようにしてあります。
23〜27行目は「その他」以外が未チェックの場合にバリデーションエラーを表示する記述です。
バリデーションに関するソースは以下です。
AppFormRequest.php(バリデーション)
public function rules(): array
{
return [
'favorite'=>['required_unless:favorite02,その他'],
'favorite_other'=>['nullable','required_if:favorite02,その他'],
];
}
▲favoriteは「その他」以外のチェックボックス。
4行目の 'favorite'=>['required_unless:favorite02,その他'],
の記述は、
favorite02が「その他」でなければfavoriteは必須という意味になります。
favorite_otherは「その他入力欄」'favorite_other'=>['nullable','required_if:favorite02,その他'],
の記述は、
nullableは空欄可。favorite02が「その他」の場合必須という意味になります。
confirm.blade.php(確認画面)
<form action="" method="POST">
@csrf
<table class="frmBlock">
<!-- 好きな食べ物 -->
<tr>
<th>好きな食べ物</th>
<td>
<div class="inptBox">
<!-- ▼「好きな食べ物」かつ「その他」のチェックが入っている場合「、」を入れる -->
@if(isset($contents['favorite']) && isset($contents['favorite02']))
{{implode('、', array_filter($contents['favorite']))}}
<input name="favorite[]" type="hidden" value="{{implode('、', array_filter($contents['favorite']))}}">、
<!-- ▼「その他」にチェックが入っていない場合「、」は不要 -->
@elseif(!isset($contents['favorite02']))
{{implode('、', array_filter($contents['favorite']))}}
<input name="favorite[]" type="hidden" value="{{implode('、', array_filter($contents['favorite']))}}">
@endif
<!-- ▼「その他」にチェックが入っている場合 -->
@if(isset($contents['favorite02'])){{$contents['favorite02']}}<input name="favorite02" type="hidden" value="{{ $contents['favorite02']}}">@endif
</div>
</td>
</tr>
<!-- 好きな食べ物 その他 -->
<tr>
<th>その他の内容</th>
<td>
<div class="inptBox">
@if(isset($contents['favorite_other']))
<div>{{ $contents['favorite_other'] }}
<input name="favorite_other" type="hidden" value="{{ $contents['favorite_other'] }}">
</div>
@endif
</div>
</td>
</tr>
</table>
<div>
<input id="backBtn" type="button" onClick="history.back()" value="戻る">
</div>
</form>
▲10〜17行目で「その他」のチェックの有無で条件分岐をしています。
「その他」がチェックされていた場合、「その他」を読点「、」で結合させます。
バリデーションのメッセージはディレクトリlang > ja > validation.phpで管理しました。
'required_if' => 'その他をチェックした場合、必須',
'required_unless' => '1つ以上チェックしてください。',
上述しましたが、ここまで辿り着くのに、なんと! 2ヶ月を要しました。
いつもは、用意されたPHPのテンプレートにjQueryで書いてるので楽してましたが、Laravelのrequired_if
やequired_unless
など、標準のバリデーションを使いたかったので、遠回りしてしまった次第です。
というか、私の技量不足が諸悪の根源ですが。。。^^;
今回、活用したChatGPTさまには非常に感謝しています。
「その他」をチェックボックスのグループから外し、別の項目として扱うなどの助言をいただき、まるで上級エンジニアと相談しながら進めることができました。
これからもLaravelの習得や精進に励みたいと思います。
最後までお読みいただき、ありがとうございます。