首页 > 解决方案 > Laravel 中的 PUT/POST

问题描述

我是 Laravel 的新手,正在学习 Laracasts 的 [Laravel 6 from Scratch][1] 课程。该课程是免费的,但我买不起 Laracasts 会员,所以我不能在那里提问。

我已经完成了课程的第 6 节,控制器技术,并且在尝试扩展我们迄今为止所做的工作以添加一些新功能时遇到了意想不到的问题。该课程让学生构建页面,让用户显示文章列表、查看单个文章、创建和保存新文章,以及更新和保存现有文章。课程工作设想了一篇非常简单的文章,其中只包含一个 ID(在数据库中自动递增,网络用户不可见)、标题、摘录和正文,我得到了所有的功能,包括更新现有文章并保存。

更新表单将方法设置为 POST,但随后使用 @METHOD('PUT') 指令告诉浏览器它实际上应该执行 PUT。这在原始代码中完美运行。但是,既然我已经在表单中添加了另外两个字段,当我在编辑现有记录后单击提交时,保存失败并显示以下消息:

Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException
The PUT method is not supported for this route. Supported methods: GET, HEAD, POST.
http://localhost:8000/articles 

我不明白为什么在表单中添加两个字段会导致它中断。有人可以启发我吗?我将两个新字段/列添加到迁移中并运行 migrate:rollback 和 migrate。我还向可填充属性添加了新字段/列,并在 ArticlesController 中为它们添加了验证。

这是我的路由:

Route::get('/articles', 'ArticlesController@index');
Route::post('/articles', 'ArticlesController@store');
Route::get('/articles/create', 'ArticlesController@create');
Route::get('/articles/{article}', 'ArticlesController@show');
Route::get('/articles/{article}/edit', 'ArticlesController@edit');
Route::put('/articles/{article}', 'ArticlesController@update');
//Route::delete('/articles/{article}', ArticlesController@destroy');

这是我的 ArticlesController:

<?php

namespace App\Http\Controllers;

use App\Article;
use Illuminate\Http\Request;

class ArticlesController extends Controller
{
public function index()
{
    $articles = Article::latest()->get();
    return view ('articles.index', ['articles' => $articles]);
}

public function show(Article $article) 
{
    return view('articles.show', ['article' => $article]);
}

public function create() 
{
    return view('articles.create');
}

public function store() 
{
    //Stores a NEW article
    Article::create($this->validateArticle());
    return redirect('/articles');
}   

public function edit(Article $article) 
{
    return view('articles.edit', ['article' => $article]);
}

public function update(Article $article)
{
    //Updates an EXISTING article
    $article->update($this->validateArticle());
    return redirect('/articles/', $article->id);
}

public function validateArticle()
{
    return request()->validate([
        'title' => ['required', 'min:5', 'max:20'],
        'author' => ['required', 'min:5', 'max:30'],
        'photopath' => ['required', 'min:10', 'max:100'],
        'excerpt' => ['required', 'min:10', 'max:50'],
        'body' => ['required', 'min:50', 'max:500']
    ]);
}

public function destroy(Article $article)
{
    //Display existing record with "Are you sure you want to delete this? Delete|Cancel" option
    //If user chooses Delete, delete the record
    //If user chooses Cancel, return to the list of articles
}
}

这是我的编辑表单,edit.blade.php:

@extends('layout')

@section('content')
<div id="wrapper">
<div id="page" class="container">
    <h1>Update Article</h1>
    <form method="POST" action="/articles">
        @csrf
        @method('PUT')
        <div class="form-group">
            <label class="label" for="title">Title</label>
            <div class="control">
                <input class="form-control @error('title') errorborder @enderror" type="text" name="title" id="title" value="{{ $article->title }}">
                @error('title')
                    <p class="errortext">{{ $errors->first('title') }}</p> 
                @enderror
            </div>
        </div>
        <div class="form-group">
            <label class="label" for="author">Author</label>
            <div class="control">
                <input class="form-control @error('author') errorborder @enderror" type="text" name="author" id="author" value="{{ $article->author }}">
                @error('title')
                    <p class="errortext">{{ $errors->first('author') }}</p> 
                @enderror
            </div>
        </div>
        <div class="form-group">
            <label class="label" for="photopath">Path to Photo</label>
            <div class="control">
                <input class="form-control @error('photopath') errorborder @enderror" type="text" name="photopath" id="photopath" value="{{ $article->photopath }}">
                @error('title')
                    <p class="errortext">{{ $errors->first('photopath') }}</p> 
                @enderror
            </div>
        </div>
        <div class="form-group">
            <label class="label" for="excerpt">Excerpt</label>
            <div class="control">
                <textarea class="form-control @error('excerpt') errorborder @enderror" name="excerpt" id="excerpt">{{ $article->excerpt }}</textarea>
                @error('excerpt')
                    <p class="errortext">{{ $errors->first('excerpt') }}</p> 
                @enderror
            </div>
        </div>
        <div class="form-group">
            <label class="label" for="body">Body</label>
            <div class="control">
                <textarea class="form-control @error('body') errorborder @enderror" name="body" id="body">{{ $article->body }}</textarea>
                @error('body')
                    <p class="errortext">{{ $errors->first('body') }}</p> 
                @enderror
            </div>
        </div>
        <div class="control">
            <button class="btn btn-primary" type="submit">Submit</button>
        </div>
    </form>
</div>
</div>
@endsection
Is there anything else you need to see?



  [1]: https://laracasts.com/series/laravel-6-from-scratch/episodes/33?autoplay=true

标签: laravel

解决方案


你的 Laravel 路线是:

Route::put('/articles/{article}', 'ArticlesController@update');

因此,您的表单操作 url 应该与该 uri 匹配:

<form action="{{ url('/articles/'.$article->id) }}">

其中{article}参数是记录 ID(您可以在此处的文档中阅读更多信息)。

然后在你的控制器update()方法中,你有:

return redirect('/articles/', $article->id);

/articles这意味着使用状态代码重定向到(您可以在此处$article->id的文档中阅读更多信息)。我认为您正在尝试重定向到显示路线,即:

Route::get('/articles/{article}', 'ArticlesController@show');

因此,将,(逗号)更改为.(点)以将文章 ID 与 uri连接起来:

return redirect('/articles/' . $article->id);

推荐阅读