【发布时间】:2016-05-20 00:41:18
【问题描述】:
我正在学习 Laravel 5。我正在尝试构建一个简单的表单来编辑数据库中的现有记录,但我对在这种情况下如何使用 withInput() 和 old() 感到困惑。
例如,考虑以下路由和控制器:
<?php
// routes.php
use App\Book;
Route::get( '/book', [ 'as' => 'book.edit', function() {
$book = Book::find(1);
return view( 'book', [
'title' => $book->title
] );
} ] );
Route::post( '/book', [ 'as' => 'book.update', function() {
$validator = Validator::make( Request::all(), [
// This validator will (almost) always fail. This is deliberate, to
// illustrate the problem I'm describing.
'title' => 'in:zzzzz|required'
] );
if ( $validator->fails() ) {
return redirect( route('book.edit') )
->withInput()
->withErrors( $validator );
}
// TODO: save book
} ] );
下面是对应的模板:
<!-- book.blade.php -->
<form action="{{ route('book.update') }}" method="post">
<label>Book Title:</label>
<input type="text" name="title" value="{{ $title }}">
@if ($errors->has('title'))
<strong>{{ $errors->first('title') }}</strong>
@endif
<button type="submit">Save</button>
{{ csrf_field() }}
</form>
现在,考虑以下用户流程:
用户请求 GET /book(我们将此页面加载称为 #1)。
book.edit控制器从数据库中加载书名(恰好是“50 种灰色”),并将该字符串传递给视图。用户会看到该字段中预填充了“50 种灰色”值的表单。到目前为止,一切顺利。用户将标题修改为“两个城市的故事”,然后提交表单。
book.update路由处理了这个请求,发现它无效。它将用户重定向回book.edit路由(我们将此页面加载称为#2)。book.edit重新渲染相同的视图,再次将title的值设置为“50 种灰色”(这是不正确的)。
这是我要解决的部分:如何在页面加载 #1 时显示数据库中的标题,但在页面加载 #2 时重新显示用户的输入?
现在,我明白了为什么这段代码会这样。我只是不明白我是如何应该这样做的。
可能的解决方案(以及我不喜欢它们的原因):
在我的模板中,我可以使用
value="{{ old('title') }}"而不是value="{{ $title }}"。这将解决页面加载 #2 的问题 - 但这意味着title字段将在页面加载 #1 时为空白。-
我可以在视图中添加一些逻辑——例如:
{{ if $wasRedirected ? old('title') : $title }}这只是感觉很老套和错误——它似乎不应该出现在视图中。 我可以在
book.edit请求中添加一些逻辑——比如'title' => $wasRedirected ? Request::get('title') : $book->title。这也让人感觉很老套和错误。
我可能只是误解了一些东西,或者遗漏了一些明显的东西。在 Laravel 5 中通常如何处理编辑表单的这一方面?应该有标准模式吧?
【问题讨论】:
-
似乎一种常见的解决方案是安装the Forms & HTML component from Laravel Collective,它提供了方便的方法,您可以在视图中使用这些方法自动确定要显示的内容。我对这个选项持开放态度——但有没有办法在原版 Laravel 中做到这一点,而无需借助第三方插件?