MKYS
@MKYS

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

laravel:問い合わせフォーム実装でのエラー

Q&A

Closed

解決したいこと

HTTPメソッド:post
ルートパス:/thanks
コントローラ:ContactController
アクション:store

上記におけるデータ保存・完了ページ表示を実現したいです。
3日ほどここでつまずいており、大変困っています...。

発生している問題・エラー

The GET method is not supported for this route. Supported methods: POST.

該当するソースコード

.web.php
<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ContactController;

Route::get('/',[ContactController::class, 'index']);
Route::post('/confirm',[ContactController::class, 'confirm']);
Route::post('/thanks',[ContactController::class, 'store']);
.ContactController
<?php

namespace App\Http\Controllers;

use App\Http\Requests\ContactRequest;
use App\Models\Contact;
use App\Models\Category;

class ContactController extends Controller
{
    public function index()
    {
        $categories = Category::all();
        return view('index',compact('categories'));
    }

    public function confirm(ContactRequest $request)
    {
        $contact = $request->only(['first_name', 'last_name','gender','email', 'tell1','tell2','tell3', 'address','building','category_id','detail']);
        $category = Category::find($contact['category_id']);
        return view('confirm', compact('contact','category'));
    }

    public function store(ContactRequest $request)
    {
        $contact = $request->only(['first_name', 'last_name','gender','email', 'tell1','tell2','tell3', 'address','building','category_id','detail']);
        Contact::create($contact);
        return view('thanks');
    }
}
.confirm.blade.php
// 中略

@section('content')
    <div class="confirm__content">
      <div class="confirm__heading">
        <h2>Confirm</h2>
      </div>
      <form class="form" action="/thanks" method="post">
      @csrf
        <div class="confirm-table">
          <table class="confirm-table__inner">
            <tr class="confirm-table__row">
              <th class="confirm-table__header">お名前</th>
              <td class="confirm-table__text">
                <p>{{ $contact['first_name'] }}</p>
                <input type="hidden" name="first_name" value="{{ $contact['first_name'] }}"/>
                <p>{{ $contact['last_name'] }}</p>
                <input type="hidden" name="last_name" value="{{ $contact['last_name'] }}"/>
              </td>
            </tr>
            <tr class="confirm-table__row">
              <th class="confirm-table__header">性別</th>
              <td class="confirm-table__text">
                <p>
                  @php
                  switch($contact['gender']){
                      case "1":
                      echo "男性";
                      break;
                      case "2":
                      echo "女性";
                      break;
                      case "3":
                      echo "その他";
                      break;
                  }
                  @endphp
                </p>
                  <input type="hidden" name="gender" value="{{ $contact['gender'] }}"/>
              </td>
            </tr>
            <tr class="confirm-table__row">
              <th class="confirm-table__header">メールアドレス</th>
              <td class="confirm-table__text">
                <p>{{ $contact['email'] }}</p>
                <input type="hidden" name="email" value="{{ $contact['email'] }}"/>
              </td>
            </tr>
            <tr class="confirm-table__row">
              <th class="confirm-table__header">電話番号</th>
              <td class="confirm-table__text">
                <p>{{ $contact['tell1'] }}{{ $contact['tell2'] }}{{ $contact['tell3'] }}</p>
                <input type="hidden" name="tell" value="{{ $contact['tell1'] }}{{ $contact['tell2'] }}{{ $contact['tell3'] }}"/>
              </td>
            </tr>
            <tr class="confirm-table__row">
              <th class="confirm-table__header">住所</th>
              <td class="confirm-table__text">
                <p>{{ $contact['address'] }}</p>
                <input type="hidden" name="address" value="{{ $contact['address'] }}"/>
              </td>
            </tr>
            <tr class="confirm-table__row">
              <th class="confirm-table__header">建物名</th>
              <td class="confirm-table__text">
                <p>{{ $contact['building'] }}</p>
                <input type="hidden" name="building" value="{{ $contact['building'] }}"/>
              </td>
            </tr>
            <tr class="confirm-table__row">
              <th class="confirm-table__header">お問い合わせの種類</th>
              <td class="confirm-table__text">
                <p>{{ $category['content'] }}</p>
                <input type="hidden" name="category_id" value="{{ $contact['category_id'] }}">
              </td>
            </tr>
            <tr class="confirm-table__row">
              <th class="confirm-table__header">お問い合わせ内容</th>
              <td class="confirm-table__text">
                <p>{!! nl2br(e($contact['detail'])) !!}</p>
              <input type="hidden" name="detail" value="{{ $contact['detail'] }}"/>
              </td>
            </tr>
          </table>
        </div>
        <div class="form__button">
          <button class="form__button-submit" type="submit">送信</button>
          <a class="form__button-correction" href="#" onclick="event.preventDefault(); history.back();">修正</a>
        </div>
      </form>
    </div>
@endsection

自分で試したこと

○Route::get('/confirm',[ContactController::class, 'confirm']); を追記
→リダイレクトが繰り返し行われ、エラー

○バリデーションの確認
→バリデーションに失敗し、前の画面へリダイレクト(get)していた為ルーティングが見つからずエラーした可能性を考え、index.blade.phpファイル(入力フォーム用のviewファイル)におけるバリデーション記述箇所をコメントアウトするも同エラー

○デベロッパーツールで動作確認
→リクエストURL:http://localhost/confirm
リクエストメソッド:GET
ステータスコード:405 Method Not Allowed

0

4Answer

POSTのときはreturn view('thanks');で表示することはできないようです。
thanks用のGETルーティングを別に作って、redirectで表示するようにしましょう。

参考

1Like

Comments

  1. 挙げていただいている記事は誤りです。
    POSTルートではview()が使えないなどといったことはありません。
    view()redirect()は明確に役割が異なります。
    その名の通り、ビューファイルの内容をレンダーしたいときはview()を、リダイレクトを行いたいときはredirect()を使用します。

画面が3つあるようですが、どのような手順で操作したときのエラーでしょうか?
問題が起きているのが/thanksなのか/confirmなのか判断できないので、状況を詳しく教えてほしいです。

デベロッパーツールのネットワーク(Network)タブから、実際にどのようなリクエストが送らているか確認することはできますか?

今のところの予想ですが、storeでもバリデーションが行われ、バリデーションエラーによってGETで/confirmへリダイレクトされてるような気がしています。(/confirmはPOSTなのでエラーになる)

1Like

Comments

  1. 横槍すみません、

    今のところの予想ですが、storeでもバリデーションが行われ、バリデーションエラーによってGETで/confirmへリダイレクトされてるような気がしています。(/confirmはPOSTなのでエラーになる)

    これビンゴな気がします。。
    index -> confirm は tel1, tel2, tel3と3つに分かれて送信されていますが、confirm -> thanks へは tel という名前でまとめて値が送信されてしまっています。
    バリデーションルールで tel1, tel2, tel3 が必須などに指定されていたとしたら、確かにthanksでエラーになりconfirmにリダイレクトされる、という挙動になりますね。。

  2. @MKYS

    Questioner

    ご回答頂きありがとうございます。

    HTTPメソッド | ルートパス | コントローラ   | アクション
    get      | /      | ContactController | index
    →入力フォーム(index.blade.php)の表示
    post      | /confirm   | ContactController | confirm
    →入力内容確認画面(confirm.blade.php)の表示
    post      | /thanks   | ContactController | store
    →データ保存完了ページ(thanks.blade.php)表示

    3つの画面はそれぞれ上図のような手順で操作するイメージです。
    (汚い図ですみません)

    入力内容確認画面から、postメソッドでデータ保存完了ページにアクセスを試みると、エラーメッセージが表示されました。

    また、デベロッパーツールで動作確認を行うと以下のリクエストが送られている事が確認できましたので、記載いたします。

    名前:thanks
    リクエスト URL:http://localhost/thanks
    リクエスト メソッド:POST
    ステータス コード:302 Found

    名前:confirm
    リクエストURL:http://localhost/confirm
    リクエストメソッド:GET
    ステータスコード:405 Method Not Allowed

  3. 確認いただきありがとうございます。

    入力内容確認画面から、postメソッドでデータ保存完了ページにアクセスを試みると、エラーメッセージが表示されました。

    /confirmからフォームの送信ボタンを押した、ということですね。

    リクエストを見ると/thanksへリクエストしたあとに、/confirmへリダイレクトしているようですから、バリデーションエラーで戻っていることが考えられます。
    送信しているデータやバリデーションについて確認するのがよいと思います。

    確認画面を使う場合に値を引き継ぐ方法として、バリデーションを通過した値をセッションに保存する方法があります。
    hiddenを使って引き継いだ値は検証しなければいけませんが、セッションを使えば安全に引き継ぐことができます。

    参考

@blue32a
@myr
お二人から頂いたご助言をもとに、confirm.blade.phpファイルを以下のように修正したところ、解決しました!!

.confirm.blade.php(修正前)
<input type="hidden" name="tell" value="{{ $contact['tell1'] }}{{ $contact['tell2'] }}{{ $contact['tell3'] }}"/>
.confirm.blade.php(修正後)
<input type="hidden" name="tell1" value="{{ $contact['tell1'] }}"/>
<input type="hidden" name="tell2" value="{{ $contact['tell2'] }}"/>
<input type="hidden" name="tell3" value="{{ $contact['tell3'] }}"/>

index.blade.phpファイルからconfirm.blade.phpファイルへは tel1, tel2, tel3と3つに分けて送信していたところ、confirm.blade.phpファイルからthanks.blade.phpファイルへはtel という名前でまとめて値が送信していた事が原因でした。
(バリデーションルールで tel1, tel2, tel3 を必須と指定していました)

本当にありがとうございました。

1Like

エラーメッセージの通り、POSTを想定しているルートに対しGETでアクセスしてしまっています。

○デベロッパーツールで動作確認
→リクエストURL:http://localhost/confirm
リクエストメソッド:GET
ステータスコード:405 Method Not Allowed

恐らくですが、最初の問い合わせフォームの入力ページ( index.blade.php )内の<form>タグが以下のようになっていないでしょうか?

<form class="form" action="/confirm">

action属性でpostを指定してあげれば想定通りに動くかと思います。

<form class="form" action="/confirm" action="post">
0Like

Comments

  1. @MKYS

    Questioner

    ご回答ありがとうございます!

    最初の問い合わせフォームの入力ページ( index.blade.php )は以下のようになっております。

    .index.blade.php
    //中略
    
    @section('content')
      <div class="contact-form__content">
          <div class="contact-form__heading">
            <h2>Contact</h2>
          </div>
          <form class="form" action="/confirm" method="post">
          @csrf
            <div class="form__group">
              <div class="form__group-title">
                <span class="form__label--item">お名前</span>
                <span class="form__label--required">※</span>
              </div>
              <div class="form__group-content">
                <div class="form__input--name">
                  <input type="text" name="first_name" value="{{ old('first_name') }}" placeholder="例:山田" />
                  <input type="text" name="last_name" value="{{ old('last_name') }}" placeholder="例:太郎" />
                </div>
                <div class="form__error">
                  @error('first_name')
                  {{ $message }}
                  @enderror
                  @error('last_name')
                  {{ $message }}
                  @enderror
                </div>
              </div>
            </div>
            <div class="form__group">
              <div class="form__group-title">
                <span class="form__label--item">性別</span>
                <span class="form__label--required">※</span>
              </div>
              <div class="form__group-content">
                <div class="form__input--gender">
                  <label><input type="radio" name="gender" value="1" checked />男性</label>
                  <label><input type="radio" name="gender" value="2"/>女性</label>
                  <label><input type="radio" name="gender" value="3"/>その他</label>
                </div>
                <div class="form__error">
                  @error('gender')
                  {{ $message }}
                  @enderror
                </div>
              </div>
            </div>
            <div class="form__group">
              <div class="form__group-title">
                <span class="form__label--item">メールアドレス</span>
                <span class="form__label--required">※</span>
              </div>
              <div class="form__group-content">
                <div class="form__input--text">
                  <input type="email" name="email" value="{{ old('email') }}" placeholder="例:test@example.com" />
                </div>
                <div class="form__error">
                  @error('email')
                  {{ $message }}
                  @enderror
                </div>
              </div>
            </div>
            <div class="form__group">
              <div class="form__group-title">
                <span class="form__label--item">電話番号</span>
                <span class="form__label--required">※</span>
              </div>
              <div class="form__group-content">
                <div class="form__input--tell">
                  <input type="tel" name="tell1" value="{{ old('tell1') }}" placeholder="080" />-
                  <input type="tel" name="tell2" value="{{ old('tell2') }}" placeholder="1234" />-
                  <input type="tel" name="tell3" value="{{ old('tell3') }}" placeholder="5678" />
                </div>
                <div class="form__error">
                  @error('tell1')
                  {{ $message }}
                  @enderror
                  @error('tell2')
                  {{ $message }}
                  @enderror
                  @error('tell3')
                  {{ $message }}
                  @enderror
                </div>
              </div>
            </div>
            <div class="form__group">
              <div class="form__group-title">
                <span class="form__label--item">住所</span>
                <span class="form__label--required">※</span>
              </div>
              <div class="form__group-content">
                <div class="form__input--text">
                  <input type="text" name="address" value="{{ old('address') }}" placeholder="例:東京都渋谷区千駄ヶ谷1-2-3" />
                </div>
                <div class="form__error">
                  @error('address')
                  {{ $message }}
                  @enderror
                </div>
              </div>
            </div>
            <div class="form__group">
              <div class="form__group-title">
                <span class="form__label--item">建物名</span>
              </div>
              <div class="form__group-content">
                <div class="form__input--text">
                  <input type="text" name="building" value="{{ old('building') }}" placeholder="例:千駄ヶ谷マンション101" />
                </div>
              </div>
            </div>
            <div class="form__group">
              <div class="form__group-title">
                <span class="form__label--item">お問い合わせの種類</span>
                <span class="form__label--required">※</span>
              </div>
              <div class="form__group-content">
                <div class="form__input--category">
                  <select name="category_id">
                    <option selected>選択してください</option>
                    @foreach($categories as $category)
                    <option value="{{ $category->id }}">{{ $category->content }}</option>
                    @endforeach
                  </select>
                </div>
                <div class="form__error">
                  @error('category_id')
                  {{ $message }}
                  @enderror
                </div>
              </div>
            </div>
            <div class="form__group">
              <div class="form__group-title">
                <span class="form__label--item">お問い合わせ内容</span>
              </div>
              <div class="form__group-content">
                <div class="form__input--textarea">
                  <textarea name="detail" value="{{ old('detail') }}" placeholder="お問い合わせ内容をご記載ください"></textarea>
                </div>
                <div class="form__error">
                  @error('detail')
                  {{ $message }}
                  @enderror
                </div>
              </div>
            </div>
            <div class="form__button">
              <button class="form__button-submit" type="submit">確認画面</button>
            </div>
          </form>
      </div>
    @endsection
    

    index.blade.phpファイル・confirm.blade.phpファイル共にmethod属性でpostを指定しているので、どこがエラーの原因がわからず途方に暮れています...。

  2. (失礼しました、先ほどの回答内、action属性ではなくmethod属性でしたね。。)

    The GET method is not supported for this route. Supported methods: POST.

    このエラーが発生しているのはどの画面(どのURL)の場合でしょうか?
    また、

    ○デベロッパーツールで動作確認
    →リクエストURL:http://localhost/confirm
    リクエストメソッド:GET
    ステータスコード:405 Method Not Allowed

    これは具体的にどのような操作を行って確認したのでしょうか?

    それと念の為ですが、web.php内の記述順を以下のようにしてみてください。

    Route::get('/',[ContactController::class, 'index']);
    Route::post('/confirm',[ContactController::class, 'confirm']);
    Route::post('/thanks',[ContactController::class, 'store']);
    

    Route::post('/confirm',[ContactController::class, 'confirm']);
    Route::post('/thanks',[ContactController::class, 'store']);
    Route::get('/',[ContactController::class, 'index']);
    
  3. @MKYS

    Questioner

    お返事ありがとうございます。
    質問内容の情報が不足しておりすみません💦

    ==================================
    HTTPメソッド | ルートパス | コントローラ   | アクション
    get      | /      | ContactController | index
    →入力フォーム(index.blade.php)の表示
    post      | /confirm   | ContactController | confirm
    →入力内容確認画面(confirm.blade.php)の表示
    post      | /thanks   | ContactController | store
    →データ保存完了ページ(thanks.blade.php)表示
    ==================================

    「入力内容確認画面(confirm.blade.php)」から、postメソッドで「データ保存完了ページ(thanks.blade.php)」にアクセスを試みると、エラーメッセージが表示されました。

    デベロッパーツールでの動作確認は
    ①入力内容確認画面(confirm.blade.php)を開く
    ②デベロッパーツールの「Network」タブを選択
    ③「Network」タブを開いたまま入力内容確認画面(confirm.blade.php)の送信ボタンを押す
    という手順で確認しました。

    また、web.php内の記述順をご助言頂いた通りに修正し実行してみましたが、同エラーが表示されました...。

Your answer might help someone💌