Laravel 验证:具有多列和 soft_delete 的唯一性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31198559/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 11:52:06  来源:igfitidea点击:

Laravel validation: unique with multiple columns and soft_delete

validationlaravellaravel-4

提问by ppalmeida

I am trying to do a Laravel validation rules as follow:

我正在尝试执行 Laravel 验证规则,如下所示:

"permalink" => "required|unique:posts,permalink,hotel_id,deleted_at,NULL|alpha_dash|max:255",

The explanation to the rules is:

规则的解释是:

I have a table "Posts" in my system with the following fields (among others): hotel_id, permalink, deleted_at. If MySQL would allow make an unique index with null values, the sql would be:

我的系统中有一个“帖子”表,其中包含以下字段(以及其他字段):hotel_id、permalink、deleted_at。如果 MySQL 允许使用空值创建唯一索引,则 sql 将是:

ALTER TABLE `posts` 
ADD UNIQUE `unique_index`(`hotel_id`, `permalink`, `deleted_at`);

So: I just add a new row IF: the combinationof hotel_id, permalinkand deleted_atfield (witch must be NULL) are unique.

所以:我刚加入新行IF:该组合hotel_idpermalinkdeleted_at场(巫婆必须为NULL)是唯一的。

If there is already a row where the permalink and hotel_id field are the same and 'deleted_at' field is NULL, the validation would return FALSE and the row wouldnt be inserted in the database.

如果已经有一行永久链接和hotel_id 字段相同并且'deleted_at' 字段为NULL,则验证将返回FALSE,并且该行不会插入到数据库中。

Well. I don't know why, but the query Laravel is building looks like:

好。我不知道为什么,但 Laravel 正在构建的查询如下所示:

SELECT count(*) AS AGGREGATE FROM `posts` 
WHERE `hotel_id` = the-permalink-value AND `NULL` <> deleted_at)

What the heck...

有没有搞错...

The query I was hoping Laravel build to validation is:

我希望 Laravel 构建验证的查询是:

SELECT count(*) AS AGGREGATE FROM `posts` 
WHERE `permalink` = 'the-permalink-value' AND `hotel_id` = ? AND `deleted_at` IS NULL

Could someone explain me how this effectively works? Because everywhere I look it looks like this:

有人可以解释我这是如何有效工作的吗?因为我到处看它看起来像这样:

$rules = array(
   'field_to_validate' =>
   'unique:table_name,field,anotherField,aFieldDifferentThanNull,NULL',
);

Does anyone could help me?

有没有人可以帮助我?

Thank you

谢谢

回答by ppalmeida

all.

全部。

Finally, I got a proper understanding of the validation (at least, I think so), and I have a solution that, if it is not beautiful, it can helps someone.

最后,我对验证有了正确的理解(至少,我是这么认为的),并且我有一个解决方案,如果它不漂亮,它可以帮助某人。

My problem, as I said before, was validate if a certain column (permalink) is unique ONLY IF other columns values had some specific values. The problem is the way Laravel validation string rules works. Lets get to it:

正如我之前所说,我的问题是验证某个列(永久链接)是否唯一,仅当其他列值具有某些特定值时。问题在于 Laravel 验证字符串规则的工作方式。让我们开始吧:

First I wrote this: "permalink" => "required|unique:posts,permalink,hotel_id,deleted_at,NULL|alpha_dash|max:255",

首先我写了这个:“永久链接”=>“必需|唯一:posts,permalink,hotel_id,deleted_at,NULL|alpha_dash|max:255”,

And it was generating bad queries. Now look at this:

它产生了错误的查询。现在看看这个:

'column_to_validate' => 'unique:table_name,column_to_validate,id_to_ignore,other_column,value,other_column_2,value_2,other_column_N,value_N',

So. The unique string has 3 parameters at first: 1) The table name of the validation 2) The name of the column to validate the unique value 3) The ID of the column you want to avoid (in case you are editing a row, not creating a new one).

所以。唯一字符串首先有 3 个参数:1) 验证的表名 2) 验证唯一值的列名 3) 要避免的列的 ID(如果您正在编辑一行,而不是创建一个新的)。

After this point, all you have to do is put the other columns in sequence like "key,value" to use in your unique rule.

在这一点之后,您所要做的就是将其他列按顺序排列,例如“键,值”,以在您的唯一规则中使用。

Oh, easy, an? Not so quickly, paw. If you're using a STATIC array, how the heck you will get your "currently" ID to avoid? Because $rules array in Laravel Model is a static array. So, I had to came up with this:

哦,简单,一个?没那么快,爪子。如果您使用的是 STATIC 数组,那么您将如何避免使用“当前”ID?因为 Laravel 模型中的 $rules 数组是一个静态数组。所以,我不得不想出这个:

  public static function getPermalinkValidationStr() {
    $all = Input::all();
    # If you are just building the frozenNode page, just a simple validation string to the permalink field:
    if(!array_key_exists('hotel', $all)) {
      return 'required|alpha_dash|max:255';
    }

    /* Now the game got real: are you saving a new record or editing a field? 
If it is new, use 'NULL', otherwise, use the current id to edit a row.
*/
    $hasId = isset($all['id']) ? $all['id'] : 'NULL';

# Also, check if the new record with the same permalink belongs to the same hotel and the 'deleted_at' field is NULL:

    $result = 'required|alpha_dash|max:255|unique:posts,permalink,' . $hasId . ',id,hotel_id,' . $all['hotel'] . ',deleted_at,NULL';
    return $result;
  }

And, in the FrozenNode rules configuration:

并且,在 FrozenNode 规则配置中:

'rules' => array(
    'hotel_id' => 'required',
    'permalink' => Post::getPermalinkValidationStr()
  ),

Well. I dont know if there is a easiest way of doing this (or a much better approach). If you know something wrong on this solution, please, make a comment, I will be glad to hear a better solution. I already tried Ardent and Observer but I had some problems with FrozenNode Administrator.

好。我不知道是否有最简单的方法(或更好的方法)。如果您知道此解决方案有问题,请发表评论,我会很高兴听到更好的解决方案。我已经尝试过 Ardent 和 Observer,但是我在使用 FrozenNode Administrator 时遇到了一些问题。

Thank you.

谢谢你。