投稿日:2025年2月15日

普段は素のPHPJavaScript(jQuery)で書いてますが、Laravelで作ろうとしたら思いの外、苦戦したので、書き残しておこうと思います。

実際の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で書いてるので楽してましたが、Laravelrequired_ifequired_unlessなど、標準のバリデーションを使いたかったので、遠回りしてしまった次第です。
というか、私の技量不足が諸悪の根源ですが。。。^^;

今回、活用したChatGPTさまには非常に感謝しています。
「その他」をチェックボックスのグループから外し、別の項目として扱うなどの助言をいただき、まるで上級エンジニアと相談しながら進めることができました。

これからもLaravelの習得や精進に励みたいと思います。

最後までお読みいただき、ありがとうございます。

Laravel関連の記事
Pocket