Laravel 请求在验证失败时不返回修改后的请求
Posted
技术标签:
【中文标题】Laravel 请求在验证失败时不返回修改后的请求【英文标题】:Laravel Request does not return the modified request on validation fail 【发布时间】:2021-03-24 16:15:21 【问题描述】:我最近更新了我的控制器以在保存之前使用请求来验证数据,最初我在控制器路由中使用了$request->validate()
,但我现在正处于我真的需要将其分离到请求中的阶段。
问题
在进行验证之前,我需要更改请求中的一些参数,我发现这可以使用prepareForValidation()
方法完成,而且效果很好,在验证期间请求中的值已被更改。如果验证失败,我的问题就会出现。我需要能够将我已更改的请求返回到视图,目前,在重定向之后,它似乎正在使用该请求,就像我运行 prepareForValidation()
之前一样。 (即,将标题返回为 'ABCDEFG' 而不是 'Changed The Title')。
在阅读了其他 SO 帖子和 Laravel 论坛帖子之后,看起来我需要覆盖 FormRequest::failedValidation()
方法(我已经完成了,请参见下面的代码),但是我仍在努力寻找方法将我更改后的请求传回。我已尝试编辑 failedValidation()
方法,我已在下方提供了详细信息。
期望与现实
期待
-
用户输入“ABCDEFG”作为标题并按保存。
请求中的标题(使用
prepareForValidation()
)被更改为“更改标题”。
验证失败,用户被重定向回创建页面。
标题字段的内容现在是“更改标题”。
现实
-
用户输入“ABCDEFG”作为标题并按保存。
请求中的标题(使用
prepareForValidation()
)被更改为“更改标题”。
验证失败,用户被重定向回创建页面。
标题字段的内容显示为“ABCDEFG”。
我尝试过的
将请求传递给ValidationException
类。
深入研究代码后,看起来ValidationException
允许将响应作为参数传递。
protected function failedValidation(Validator $validator)
throw (new ValidationException($validator, $this))
->errorBag($this->errorBag)
->redirectTo($this->getRedirectUrl());
但是这会导致Illuminate\Foundation\Http\Middleware\VerifyCsrfToken::addCookieToResponse
中的错误Call to undefined method Symfony\Component\HttpFoundation\HeaderBag::setCookie()
。
将请求闪烁到会话
我的下一次尝试是将我的请求闪现到会话中,这似乎不起作用,而不是我修改后的请求在会话中,它看起来是我运行 prepareForValidation()
之前的请求。
protected function failedValidation(Validator $validator)
$this->flash();
throw (new ValidationException($validator))
->errorBag($this->errorBag)
->redirectTo($this->getRedirectUrl());
返回响应而不是异常
我最后一次尝试使用withInput()
而不是异常返回响应。
protected function failedValidation(Validator $validator)
return redirect($this->getRedirectUrl())
->withErrors($validator)
->withInput();
但是看起来代码继续进入BlogPostController::store()
方法,而不是重定向回视图。
此时我没有想法,如果验证失败,我似乎无法将更改后的请求返回到视图!
其他说明
-
我几乎是 Laravel 新手,我曾使用过松散地基于 Laravel 的自定义框架,但这是我的第一个 CMS 项目。
我完全理解我可能走错了路,也许有更好的方法来更改请求并在验证失败时将其传回?
我这样做的目的是什么?最主要的是活动复选框。默认情况下它被选中(参见下面的刀片),如果用户取消选中它并按下保存,
active
不会在 HTTP 请求中传递,因此 active
在 Laravel 请求对象中不存在并且当用户返回,激活的复选框在不应该被选中时再次被选中。
那你为什么在你的例子中使用title
?我在帖子中使用了title
,因为我认为更容易看到我想要实现的目标。
感谢任何帮助,因为我目前已经花费了好几个小时试图解决这个问题。 ????
相关代码
BlogPostController.php
<?php
namespace App\Http\Controllers;
use App\BlogPost;
use Illuminate\Http\Request;
use App\Http\Requests\StoreBlogPost;
class BlogPostController extends Controller
/**
* Run the auth middleware to make sure the user is authorised.
*/
public function __construct()
$this->middleware('auth');
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
return view('admin.blog-posts.create');
/**
* Store a newly created resource in storage.
*
* @param StoreBlogPost $request
* @return \Illuminate\Http\Response
*/
public function store(StoreBlogPost $request)
$blogPost = BlogPost::create($request->all());
// Deal with the listing image upload if we have one.
foreach ($request->input('listing_image', []) as $file)
$blogPost->addMedia(storage_path(getenv('DROPZONE_TEMP_DIRECTORY') . $file))->toMediaCollection('listing_image');
// Deal with the main image upload if we have one.
foreach ($request->input('main_image', []) as $file)
$blogPost->addMedia(storage_path(getenv('DROPZONE_TEMP_DIRECTORY') . $file))->toMediaCollection('main_image');
return redirect()->route('blog-posts.edit', $blogPost->id)
->with('success', 'The blog post was successfully created.');
// Removed unrelated controller methods.
StoreBlogPost.php
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Validation\ValidationException;
class StoreBlogPost 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 [
'title' => 'required',
'url' => 'required',
'description' => 'required',
'content' => 'required',
];
/**
* Get the error messages for the defined validation rules.
*
* @return array
*/
public function messages()
return [
'title.required' => 'The Title is required',
'url.required' => 'The URL is required',
'description.required' => 'The Description is required',
'content.required' => 'The Content is required',
];
/**
* Prepare the data for validation.
*
* @return void
*/
protected function prepareForValidation()
$this->merge([
'active' => $this->active ?? 0,
'title' => 'Changed The Title',
]);
/**
* @see FormRequest
*/
protected function failedValidation(Validator $validator)
throw (new ValidationException($validator))
->errorBag($this->errorBag)
->redirectTo($this->getRedirectUrl());
create.blade.php
@extends('admin.layouts.app')
@section('content')
<div class="edit">
<form action=" route('blog-posts.store') " method="POST" enctype="multipart/form-data">
@method('POST')
@csrf
<div class="container-fluid">
<div class="row menu-bar">
<div class="col">
<h1>Create a new Blog Post</h1>
</div>
<div class="col text-right">
<div class="btn-group" role="group" aria-label="Basic example">
<a href=" route('blog-posts.index') " class="btn btn-return">
<i class="fas fa-fw fa-chevron-left"></i>
Back
</a>
<button type="submit" class="btn btn-save">
<i class="fas fa-fw fa-save"></i>
Save
</button>
</div>
</div>
</div>
</div>
<div class="container-fluid">
<div class="form-group row">
<label for="content" class="col-12 col-xl-2 text-xl-right col-form-label">Active</label>
<div class="col-12 col-xl-10">
<div class="custom-control custom-switch active-switch">
<input type="checkbox" name="active" value="1" id="active" class="custom-control-input" old('active', '1') ? 'checked' : '' >
<label class="custom-control-label" for="active"></label>
</div>
</div>
</div>
<div class="form-group row">
<label for="title" class="col-12 col-xl-2 text-xl-right col-form-label required">Title</label>
<div class="col-12 col-xl-10">
<input type="text" name="title" id="title" class="form-control" value=" old('title', '') ">
</div>
</div>
</div>
</form>
</div>
@endsection
【问题讨论】:
【参考方案1】:我遇到了同样的问题,这是我在挖掘 laravel 代码后找到的解决方案。
Laravel 似乎为FormRequest
创建了一个不同的对象,所以你可以这样做。
protected function failedValidation(Validator $validator)
// Merge the modified inputs to the global request.
request()->merge($this->input());
parent::failedValidation($validator);
【讨论】:
以上是关于Laravel 请求在验证失败时不返回修改后的请求的主要内容,如果未能解决你的问题,请参考以下文章
使用 laravel 请求类时,在数组错误上调用成员函数失败()