验证Nova中的突变值

时间:2019-01-29 00:28:56

标签: validation laravel-nova

我正在验证Nova中标签的字段,并且每个字段都是唯一的。如果用户输入first name,它将存储为first-name。但是,带有first name的第二个条目将通过验证,因为该值在数据库中不存在。但是,当需要存储它时,它也已更改为first-name,因此它无法满足数据库中的UNIQUE约束。

我看过Nova验证的源代码,它在获取验证规则之前会抓取所有字段的副本,因此我无法更改规则本身中要检查的数据。

如何验证一个值在变异后而不是变异前是唯一的?

1 个答案:

答案 0 :(得分:0)

可以向/nova/routes/api.php中的Nova路由添加自定义中间件。由于中间件是在请求到达Nova之前运行的,因此此时可以更改字段。

// Resource Management...
Route::get('/{resource}', 'ResourceIndexController@handle');
Route::get('/{resource}/count', 'ResourceCountController@show');
Route::delete('/{resource}/detach', 'ResourceDetachController@handle');
Route::put('/{resource}/restore', 'ResourceRestoreController@handle');
Route::delete('/{resource}/force', 'ResourceForceDeleteController@handle');
Route::get('/{resource}/{resourceId}', 'ResourceShowController@handle');
Route::post('/{resource}', 'ResourceStoreController@handle');
Route::put('/{resource}/{resourceId}', 'ResourceUpdateController@handle')->middleware('pre-mutate');
Route::delete('/{resource}', 'ResourceDestroyController@handle');

我在pre-mutate中添加了名为Route::put('/{resource}/{resourceId}', 'ResourceUpdateController@handle')的中间件。

新的中间件已添加到/app/Http/Kernel.php

/**
 * The application's route middleware.
 *
 * These middleware may be assigned to groups or used individually.
 *
 * @var array
 */
protected $routeMiddleware = [
    'auth' => \App\Http\Middleware\Authenticate::class,
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
    'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
    'can' => \Illuminate\Auth\Middleware\Authorize::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    'pre-mutate' => \App\Http\Middleware\PreMutate::class,
    'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
    'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
];

然后将中间件添加到app/Http/Middleware/PreMutate.php中:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Str;
use Symfony\Component\HttpFoundation\ParameterBag;

class PreMutate
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request $request
     * @param  \Closure $next
     *
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        // Make sure only the Articles resource is affected
        if ($request->route()->parameters()['resource'] === 'articles') {
            if ($request->request->has('tag_name')) {
                $request->request->set('tag_name',  Str::slug($request->request->get('tag_name')));
            }
        }

        return $next($request);
    }
}

可能有更好的方法将此请求转发到适当的模型以正确更改值,而不是直接在其他人不希望查找的中间件中应用规则,但这应该会让您入门。 / p>