我有一条POST
路线:/tasks/{task}/start
,该路线要求用户执行任务。但是在声明之前,我需要验证该任务尚未启动(可能已由其他人启动)。
Laravel为验证请求参数提供了出色的支持。
如果参数有任何问题,那么laravel会使用巧妙的方法来传达这些错误。如果请求是使用Ajax发出的,则验证失败将导致格式正确的json出现错误。如果该请求是从网络发出的,则它将重定向您到withErrors
。
我想要上述行为,但用于验证请求的模型是否处于正确的状态以进行修改。
现在我可以做类似的事情:
public function start(Request $request, Task $task) {
if ($task->isStarted()) {
if ($request->isAjax()) {
abort(400, "The task was already started");
} else {
redirect()->back()->withErrors("The task was already started");
}
}
// Task is not started. Let's start it...
}
但是我想知道是否存在某种本机支持,可以通过模型状态验证请求,并让Laravel处理错误的传达。
编辑
我找到了另一种解决方案,但看起来很笨拙:
Validator::make($request->all(), [])->after(function ($validator) use ($task) {
if ($task->isStarted()) {
$validator->errors()->add('task', 'The task was already started');
}
})->validate();
答案 0 :(得分:0)
最终结果将如下所示:
public function start(Request $request, Task $task)
{
$this->authorize('start', $task);
// Task is not started. Let's start it...
}
您如何实现的?定义策略即可完成。让我们创建一个TaskPolicy
。
在控制台中运行:
php artisan make:policy TaskPolicy
app / Providers / AuthServiceProvider.php
protected $policies = [
\App\Task::class => \App\TaskPolicy::class,
];
app / Policies / TaskPolicy.php
<?php
namespace App\Policies;
use App\User;
use App\Task;
class TaskPolicy
{
/**
* Determine if the given task can be started/claimed by the user.
*
* @param \App\User $user
* @param \App\Task $task
* @return bool
*/
public function start(User $user, Task $task)
{
// do your checks here.. you have access to the authenticated user and task
return !$task->isStarted();
}
}
如开篇所述:
public function start(Request $request, Task $task)
{
$this->authorize('start', $task);
// Task is not started. Let's start it...
}
查看documentation了解更多信息。如果只执行一次,则可能要使用盖茨。
如果授权失败,此错误将自动以json
或html
的形式返回。它将返回403
错误。
编辑
您当然可以在控制器中以不同方式处理授权。
您可以代替$this->authorize('start', $task)
进行操作:
if (\Auth::user()->cannot('start', $task) ) {
}
此外,在您的刀片视图中,我假设您有类似的东西
<form method="post" action="route-here">
<button type="submit">Start Task</button>
</form>
您可以使用@can .. @ endcan将其包裹起来:
@can('start', @task)
<form method="post" action="route-here">
<button type="submit">Start Task</button>
</form>
@endcan
这样,如果用户无法启动任务,用户将不会看到该按钮。