Laravel验证';独特';没有按预期工作


Laravel validation 'unique' not working as expected

我正在为一个网站开发一个帮助中心,我在Laracast论坛上问了这个问题,但我还没有找到解决方案。不幸的是,给我们它的路线/url路径:

routes.php

Route::resource('admin/help-centre/category', 'AdminHelpCentreCategoryController');
Route::resource('admin/help-centre/category/{category}/section', 'AdminHelpCentreSectionController');
Route::resource('admin/help-centre/category/{category}/section/{section}/article', 'AdminHelpCentreArticleController');

Category和Section验证按预期工作,但由于某种原因,即使它是相同的逻辑,据我所知,Article验证似乎没有按预期工作。以下是我的验证规则(我已经删除了多余的部分,只留下了标题字段):

HelpCentreCategoryRequest.php

/* Insert ------------------------------------- */
    $rules = [
        'title' => 'required|min:3|unique:help_centre_categories',
    ];
/* Update ------------------------------------- */
    if ($method == 'PATCH') {
        $rules = [
            'title' => 'required|min:3|unique:help_centre_categories,title,'.$this->category->id,
        ];
    }

HelpCentreSectionRequest.php

/* Insert ------------------------------------- */
    $rules = [
        'title' => 'required|min:3|unique:help_centre_sections,title,NULL,id,category_id,'.$this->category->id,
    ];

/* Update ------------------------------------- */
    if ($method == 'PATCH') {
        $rules = [
            'title' => 'required|min:3|unique:help_centre_sections,title,'.$this->section->id.',id,category_id,'.$this->category->id,
        ];
    }

我会解释只是为了澄清。。。对于Categories,在INSERT上,它会检查该标题是否已经存在,如果存在,则不进行验证。UPDATE做的完全相同,只是它在检查中忽略了自己,这样它仍然可以验证标题是否没有更改。所以我输入了两个类别,一个叫Category 1,另一个叫Category 2

Section请求也是如此,只是它只检查您创建它的指定类别中的Section。我已经测试过了,它有效。我可以将foobar插入Category 1,将foobar插入Category 2,但如果我尝试将另一个foo添加到Category 1Category 2中,它不会验证,因为它是重复的,这是正确的。但是,如果我尝试将Category 1中的foo更新为bar,它将不允许它,而且如果我尝试在不进行任何更改的情况下更新foo,它会忽略自身(行),从而允许它通过并不会引发验证错误。因此,一切都应该如此。

现在,对于我的文章验证,我使用了与Section验证完全相同的过程/查询验证,只是更改了表/列/变量以适应,如下所示:

HelpCentreArticleRequest.php

/* Insert ------------------------------------- */
    $rules = [
        'title' => 'required|min:3|unique:help_centre_articles,title,NULL,id,section_id,'.$this->section->id,
    ];

/* Update ------------------------------------- */
    if ($method == 'PATCH') {
        $rules = [
            'title' => 'required|min:3|unique:help_centre_articles,title,'.$this->article->id.',id,section_id,'.$this->section->id,
        ];
    }

这应该与HelpCentreSectionRequest.php完全相同,因此在类别的每个部分中只允许一篇文章标题的副本,而在类别的不同部分中允许一篇标题相同的文章。该部分工作正常,但是,如果我在Category 1 / Section 1中插入foobar,然后将foo更新为bar,这允许更改,而对我来说,这不应该,因为bar已经存在于Category 1 / Section 1中。

不过我显然错了,否则它也会像我预期的那样起作用。但我就是看不出问题出在哪里?

以下是数据库模式,只是为了避免任何麻烦,并且可以确认表/列名匹配(再次删除外键和额外列):

Schema::create('help_centre_categories', function(Blueprint $table)
{
    $table->increments('id')->unsigned();
    $table->string('title');
});
Schema::create('help_centre_sections', function(Blueprint $table)
{
    $table->increments('id')->unsigned();
    $table->integer('category_id')->unsigned();
    $table->string('title');
});
Schema::create('help_centre_articles', function(Blueprint $table)
{
    $table->increments('id')->unsigned();
    $table->integer('category_id')->unsigned();
    $table->integer('section_id')->unsigned();
    $table->string('title');
});

我还查看了文章请求中的if声明,该声明在顶部的Laracast论坛链接中提到。你也可以在这里找到估价文档,但为了便于阅读,这是我使用的主要部分:

Adding Additional Where Clauses
You may also specify more conditions that will be added as "where" clauses to the query:
'email' => 'unique:users,email_address,NULL,id,account_id,1'
In the rule above, only rows with an account_id of 1 would be included in the unique check.

首先,你的代码很难分析,如果我是你,我会使用数组语法:

   $rules = [
        'title' => ['required'. 'min:3'],
   ];
   $uniqueRule = 'unique:help_centre_categories';
   /* Update ------------------------------------- */
    if ($method == 'PATCH') {
       $uniqueRule.='title,'.$this->category->id
    }
    $rules['title'][] = $uniqueRule;

第二件事是$method变量。我不知道它是从哪里来的,但假设它保持正确的值,你可能应该这样改变你的条件:

if (strtoupper($method) == 'PATCH' || strtoupper($method) == 'PUT') {
 ...
}

最后,如果我尝试使用一个Request类同时用于存储和更新,我通常会这样做:

$segments = $this->segments();
$id = intval(end($segments));
if ($id != 0) {
 // now you know it's update
}

如果你的方法不起作用,你可以试试上面的方法。

编辑

Request对象中,可以使用getMethod()方法,例如:

public function rules() 
{
   $method = $this->getMethod();
   if ($method == 'PUT' || $method == 'PATCH') {
        // now you do what you want for update
   }
   // rest of code goes here
}

对于更新,您应该验证$method是PUT还是PATCH