質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.60%

Laravel postで送信しているのにgetエラー

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 13K+

Chandler_Bing

score -56

お疲れ様です。先日のエラーですがミニプログラムを作成したので、添付します。

オリジナルのバリデートを作成しているクラス

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Validator;

class Test_ValidationServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {

        //特殊文字は許さない
        /*以下の条件に一致しない(特殊文字が含まれている)ときにエラー処理を行う*/
        Validator::extend('invalid', function ($attribute, $value, $parameters, $validator) {
            $pattern = '-._~%:/?#[]@!$&\'()*+,;=';
            $pattern = preg_quote($pattern, '/');
            $pattern = "/[^" . $pattern . "]/";
            return preg_match($pattern, $value);
        });

        //IDとパスワードはパスワードは英数字を含んだ16文字以下
        Validator::extend('passid', function ($attribute, $value, $parameters, $validator) {
            return preg_match("/\A(?=.*?[a-z])(?=.*?\d)[a-z\d]{5,16}+\z/i", $value);
        });
    }
}


ルートです

//テンプレであるコメントアウトは提示していません。
Route::get('/', 'TestController@basic1');
Route::post('/basic1', 'TestController@basic1Check');
Route::post('/basic2', 'TestController@basic2');


オリジナルのバリデートをルールに追加しています

<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;

class TestRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'name' => 'required|invalid|',
            'id' => 'passid',
            'pass' => 'passid|different:id',
        ];
    }

    public function messages()
    {
        return [
            //名前のバリデーション
            'name.required' => '名前の入力は必須です',
            'name.invalid' => '名前に使用できない文字が含まれています',
            //idのバリデーション
            'id.passid' => 'ログインIDは英数字を含んだ16文字以下で入力してください',
            //passのバリデーション
            'pass.passid' => 'パスワードは英数字を含んだ16文字以下で入力してください',
            'pass.different' => 'IDと同じパスワードは設定できません',
        ];
    }
}


コントローラーです

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Requests\TestRequest;

class TestController extends Controller
{
   //一番初めに呼ばれます
    public function basic1()
    {
        $hash = array(
        'name'  => null,
        'id'  => null,
        'pass'  => null,
      );
        return view('tests.test_basic1')->with($hash);
    }
  //test_basic1から送信された値がバリデートを通過したあとの処理です
    public function basic1Check(TestRequest $request)
    {
        $name = $request->name;
        $id = $request->id;
        $pass = $request->pass;
        //値を配列に格納し、分解します
        $basic1 = ['name' => $name, 'id' => $id, 'pass' => $pass];
        //この値がtest_basic2のbuttonタグのvalueに入ります
        $basic1Str =  implode(',', $basic1);
        return view('tests.test_basic2', ['basic1Str' => $basic1Str]);
    }

    public function basic2(Request $request)
    {
//このifでbackボタンが押されたかどうか判断していま
        if (isset($request->basic1Str)) {
            $basic1 = explode(',', $request->basic1Str);
            $name = $basic1[0];
            $id = $basic1[1];
            $pass = $basic1[2];

            $hash = array(
                'name'  => $name,
                'id'  => $id,
                'pass'  => $pass,
              );
            return view('tests.test_basic1')->with($hash);
        }
        return view('tests.test_basic2');
    }
}


以下bladeです

{{--一部抜粋です(test_basic1.php)--}}
    <form method="post" action="/basic1">
        {{ csrf_field() }}
        <p>ナマエ</p>
        <input type="text" name="name" value="{{ old('name', $name) }}">
        @if ($errors->has('name'))
        <span class="errormsg">{{ $errors->first('name') }}</span>
        @endif


        <p>ログインID</p>
        <input type="text" name="id" value="{{ old('id', $id) }}">
        @if ($errors->has('id'))
        <span class="errormsg">{{ $errors->first('id') }}</span>
        @endif


        <p>パスワード</p>
        <input type="text" name="pass" value="{{ old('pass', $pass) }}">
        @if ($errors->has('pass'))
        <span class="errormsg">{{ $errors->first('pass') }}</span>
        @endif

        <button type="submit" class="btn btn-primary mb-5">Next</button>
    </form>
{{--一部抜粋です(test_basic2.php)--}}
  <form method="post" action="/basic2">
        {{ csrf_field() }}

        <select id="inputReason" class="custom-select">
            <option selected>Open this select menu</option>
            <option value="1">One</option>
            <option value="2">Two</option>
            <option value="3">Three</option>
        </select>
        <button type="submit">Next</button>
        <button type="submit" name="basic1Str" value="{{ $basic1Str }}">back</button>
    </form>


問題
①一番初めにurlに'/'のurlを打つ

②test_basic1.blade.php表示


test_basic1.balde.phpでバリデートを通過する値を入力(通過しない値でもきちんと画面に設定したエラーメッセージがでる。)

④通過するとtest_basic2.blade.phpを表示(backボタンのvalueにはtest_basic1で入力した値がきちんと入っていることは確認済みです)

⑤backボタンを押す

⑥test_basic1.blade.phpが表示され、先ほど入力した値がすでに入力済み(期待値)

⑦-1
バリデート通過する値を入力すると問題なくtest_basic2.blade.phpが表示される
⑦-2
バリデート通過しない値を入力すると以下のエラーが表示される

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

一番初めにtest_basic1.blade.phpでバリデートエラーを出してもtest_basic2.blade.phpからtest_basic1.blade.phpに戻ってきてバリデートエラーを出しても動きは同じだと思うのですが、何が問題でしょうか。

またバリデートクラスの作成は以下のサイトの方法と全く同じです。
Laravelのカスタムバリデーション

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • Chandler_Bing

    2019/06/13 17:45

    ミニプログラムを作成しコード再記載します。
    諸事情により、かなり後になるか明日になるかのどちらがですが、その際はまたよろしくお願いします。

    キャンセル

  • zushi0905

    2019/06/13 17:52

    戻るの意味がよく分かってないですけど、下のbladeでNextもbackも両方/basic2にpostしているのはなんででしょう?

    キャンセル

  • m.ts10806

    2019/06/13 17:53

    たぶん埋もれるので、なかったことにして放置します。
    これまでの経緯から本当にそのまま再現確認できるコードが提示されるか怪しいので。
    (できるなら最初から提示している。これだけの質問書く時間が勿体ない)

    キャンセル

回答 2

checkベストアンサー

+2

一番初めにtest_basic1.blade.phpでバリデートエラーを出しても
test_basic2.blade.phpからtest_basic1.blade.phpに戻ってきてバリデートエラーを出しても
動きは同じ

「動きは同じ」様に見えますが、実際には同じではありません。

bladeファイルを中心にお話されていますが、論点が違います。。。

バリデーションエラー時の処理は、「ひとつ前のURLにGETでリダイレクト」です。
画面表示に使っているbladeファイルは、バリデーションエラーの戻り先には影響しません。

単純にひとつ前の「画面」に戻る・・・と考えると、「同じbladeファイルを使っている」ので同じ画面のような気がしてしまうのかもしれませんが、
【一番初めにtest_basic1.blade.php】の画面と、
【test_basic2.blade.phpからtest_basic1.blade.phpに戻って】の画面は、URLが違うので別の画面です。

一番初めにtest_basic1.blade.phpでバリデートエラー

スタート時点の入力画面のURLは「/」なので、エラー時の戻り先は「/」です。

実際の画面遷移は、/から、/basic1にpostしたけど、バリデーションエラーだから/にGETで戻るよ
となり、最後に戻ってきた/は、ルートがGET設定なので、ここでは問題は起きません。

一方、

test_basic2.blade.phpからtest_basic1.blade.phpに戻ってきてバリデートエラー

こちらの場合、入力画面のURLは「/basic2」なので、エラ-時の戻り先も「/basic2」です。

実際の画面遷移は、/basic2から、/basic1にpostしたけど、バリデーションエラーだから/basic2にGETで戻るよ
となるわけですが、こちらは最後に戻ってきた/basic2のルートはPOSTで設定されていますので、バリデーションエラー時にGETでリダイレクトされてきたアクセスはエラーになります。

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


が発生しているのはココなので、POST送信したかどうかではなく、バリデーションエラー発生時の戻り先URLがGETアクセスできないことが原因です。


解決には、「戻る機能」の仕組みを変更するとか、バリデーションエラー時のリダイレクト先を/に共通化するとか・・・何かしらの工夫が必要かなと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/07/01 15:23

    全く知りませんでした。解決しました。ありがとうございます。

    キャンセル

-2

2ページ目のこの部分がbackもポストになっていますね。

 <div class="form-group mb-5">
        <button type="submit" class="btn btn-primary mr-5">Next</button>
        <button type="submit" class="btn btn-secondary" id="" name="basic1Str" value="{{ $basic1Str }}">back</button>
    </div>

type="submit"は指定されたポストのアクションを起こすということなので。
type="submit"は本来ポストしたい項目のみ適用してください。

では、GETでどうするのかというと

<button onclick="location.href='{{ url()->previous() }}'">
back
</button>

これでGETとして送信できるはずです。

しかし、他にも問題点がありそうですね。
仕様がよく理解できていないのでこれで意図した挙動になるかは不透明です。

P.S.
推奨はいたしませんが、GETでもPOSTでも通す方法はあります

Route::match(['get', 'post'], 'foo','HomeController@index');

参考:https://qiita.com/fagai/items/a1bf55b6249aee03a624

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/06/14 16:37

    試してみます。同じエラーを出すミニプログラムを作成したのでそちらも目を通していただけたら嬉しいです。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.60%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る