【问题标题】:Laravel PATCH works on update but validation in controller failsLaravel PATCH 适用于更新,但控制器中的验证失败
【发布时间】:2020-09-24 14:50:00
【问题描述】:

我正在关注 Laracast 实验室、Tweety 提要,一切都很顺利,直到我碰壁。

我有一个补丁来更新用户配置文件,它可以工作并更新记录,但验证没有。如果完全完成并且记录很好,则表单提交,但如果表单验证在我的控制器中的服务器端失败,我得到如下:

Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException 此路由不支持 GET 方法。支持的方法:POST。

我查看了此处的常见问题解答部分并搜索了已经询问过的网络并尝试了几个步骤来对此进行排序。我试过了:

  1. 在我的编辑文件模板和控制器中使用 $user->username。

  2. 将路径从 PATCH 更改为 PUT(以及 POST,只需使用 store)

  3. 检查用户模型并确保我使用的“getRouteKeyName”工作正常,确实如此。
  4. 检查路线是否有冲突,没有,顺序/动词没问题。

有人可以帮忙吗?下面是我的代码。

路线如下:

// Snippet for seeing all the database queries. 
//DB::listen(function($query){var_dump($query->sql, $query->bindings);});

use Illuminate\Support\Facades\Route;

 // Home view, no sign-in required. 
Route::get('/', function () {
return view('welcome');
});

// These routes require and use auth middleware.   
Route::middleware('auth')->group(function(){

// TWeets main page.
Route::get('/tweets/', 'TweetsController@index')->name('home');
// Store a new tweet
Route::post('/tweets/', 'TweetsController@store');

// Profile area, view and update

// Use the 'name' attribute in route/model binding instead of the primary key = user:name 
Route::get('/profile/{user:username}/', 'ProfileController@show')->name('profile');

// Show form to edit the profile
Route::post('/profile/{user:username}/edit','ProfileController@edit')->name('edit_profile');
//->middleware('can:edit,user'); // Don't forget the wildcard.

// Finally, update the users profile information.   
Route::patch('/profile/{user:username}','ProfileController@update')->name('update_profile');

// Handles the follow/unfollow on a toggle method.
Route::post('/profile/{user:username}/follow/','FollowsController@store');

// Logs you out & directs to the homepage.
Route::get('/logout', '\App\Http\Controllers\Auth\LoginController@logout');

});

Auth::routes();

控制器如下:

 /**
 * Update the users profile after validation
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  int  $id
 * @return \Illuminate\Http\Response
 */
public function update(User $user)
{
        $validated = request()->validate([
            'name'=>'required',
            'username'=>'required',
            'password'=>'required',
            'password_confirmation'=>'required',
        ]);

         $user->update($validated);

    // Redirect to the tweets page which is called 'home'.
    return redirect(route('profile', $user->username));
}

模板:

<x-app>

<form class="w-full" method="POST" action="{{route('update_profile',$user)}}">

    @method('PATCH')
    @csrf


    <h2 class="text-xl mb-2 py-4 font-bold">Edit profile for {{$user->username}}</h2> 
    <p class="text-sm mb-5 mt-0">Below you an update your profile details.</p>

    <div class="flex flex-wrap -mx-3 mb-6">

        <div class="w-full px-3 mb-6 md:mb-0">
            <label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" for="grid-name">Name</label>
            <input class="appearance-none block w-full bg-gray-200 text-gray-700 border border-red-500 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white" id="name" type="text" placeholder="Mike Smith.." name="name" value="{{$user->name}}"/>
        </div>

        @error('name')
            <p>{{$message}}</p>
        @enderror

        <div class="w-full px-3 mb-6 md:mb-0">
            <label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" for="grid-username">Username</label>
            <input class="appearance-none block w-full bg-gray-200 text-gray-700 border border-red-500 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white" id="grid-username" type="text" placeholder="MikeSmith1..." name="username" value="{{$user->username}}"/>
        </div>

        @error('username')
            <p>{{$message}}</p>
        @enderror

        <div class="w-full px-3 mb-6 md:mb-0">
            <label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" for="grid-username">Email</label>
            <input class="appearance-none block w-full bg-gray-200 text-gray-700 border border-red-500 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white" id="grid-username" type="email" placeholder="MikeSmith@yahoo.com..." name="email" value="{{$user->email}}"/>
        </div>

        @error('email')
            <p>{{$message}}</p>
        @enderror


        <div class="w-full px-3">
            <label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" for="grid-password">Password</label>
            <input class="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white focus:border-gray-500" id="grid-password" type="password" name="password"/>

            <p class="mb-3 text-red-600 text-xs italic">Make it as long and as crazy as you'd like</p>
        </div>

        <div class="w-full px-3"> {{-- This HAS to be called "password_confirmation" --}}
            <label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" for="grid-password">Password Confirmation</label>
            <input class="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white focus:border-gray-500" id="grid-password_confirmation" type="password" name="password_confirmation"/>
        </div>

        <button type="submit" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 ml-2 mt-4 px-4 rounded">
            Update details
        </button> 

    </div>
</form>
</x-app>

模型:用户

 /**
 * Laravel <=6 - use this method, after v6, you can do this on the route itself. 
 * Using this so we can use a user name in the route, instead of the ID Laravel normally uses for route/model binding. Now you can use /profile/mikethornley 
 * This will still enable route/model binding to work and still find the user
 * @return [type] [description]
 */
public function getRouteKeyName()
{
    return 'username';
}

【问题讨论】:

  • 尝试在刀片中使用 dd($errors) 而不是 &lt;p&gt;{{$message}}&lt;/p&gt; 看看你会得到什么
  • 这不是我真正遇到的问题。问题是部分提交的表单抛出这个: Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException 此路由不支持 GET 方法。支持的方法:POST。我认为过去,错误将是可见的。

标签: laravel validation controller put


【解决方案1】:

这就是问题所在:

// Use the 'name' attribute in route/model binding instead of the primary key = user:name 
Route::get('/profile/{user:username}/', 'ProfileController@show')->name('profile');

// Finally, update the users profile information.   
Route::patch('/profile/{user:username}','ProfileController@update')->name('update_profile');

您的路线发生冲突...该帖子最终出现在 show() 方法中,这就是您收到错误的原因。

如果您想拥有参数,则需要对该发布路线进行一些更改。例如

Route::patch('/profile-update/{user:username}','ProfileController@update')->name('update_profile');

【讨论】:

  • 考虑到动词不同,这很奇怪,只是尝试了一下,但失败了。我也从未看过它的热门节目。我也刚刚清除了缓存。
  • @lewis4u 不,那么每个资源路由都会有这种行为:-)
  • 表单提交,如果完成,就像它最初所做的那样......问题是 GET 错误。这两条路线都使用不同的动词,所以应该没问题。我预计会被引导回更新表单并显示错误。
  • @MikeThornley 能否请您在控制器的 show() 方法中创建 dd('show') 并保持路由不变。那么你不应该得到这个错误:MethodNotAllowedHttpException The GET method is not supported for this route.
  • 完成了,我得到了::"show",这在呈现配置文件时是预期的。
猜你喜欢
  • 2020-03-16
  • 2018-01-31
  • 2016-05-31
  • 2016-10-24
  • 1970-01-01
  • 1970-01-01
  • 2019-02-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多