【问题标题】:Laravel unique validation with where and joinLaravel 独特的验证与 where 和 join
【发布时间】:2018-06-03 03:55:30
【问题描述】:

我正在尝试在唯一验证规则中添加额外的 where 子句。但在此之前,我需要加入其他表。但我没有成功。

我有 2 张桌子:

团队

带有 id 和 name 字段

role_user_team

其中role_id、user_id和team_id是这三个键。

所以我需要检查 team.name 字段对于某个特定用户是否是唯一的。 我确实尝试过:

'name' => Rule::unique('teams')->where(function ($query){
    //return $query->where('account_id', 1);
    return $query->join('role_user', 'role_user.team_id', '=', 'teams.id')->where('role_user', Auth::user()->id);
          });

我知道问题出在连接上,但我不知道如何解决。 谢谢!

【问题讨论】:

  • 使用Auth::id() 而不是Auth::user()->id。对象Auth::user() 不能存在。
  • 我认为 where 子句中不允许加入...所以我需要一个新的验证规则来检查我想要的内容。 ¿对此有任何想法吗?
  • 确实,似乎加入不起作用,尽管这在任何地方都没有记录。闭包获得一个标准的查询构建器对象,因此您希望加入正常工作。但 querybuilder 对象似乎在之后被编辑,破坏了连接。

标签: php laravel laravel-5.5 laravel-validation


【解决方案1】:

这似乎是 Laravel 在对 DB 的实际查询完成之前如何处理 QueryBuilder 对象的错误。打印查询日志表明没有执行实际连接。这也可能是documentation (under "additional where clauses") 的不足之处,因为它没有提到使用 QueryBuilder 的限制。

最快的解决方案是动态扩展验证器,如下所示:

public function rules()
{
    Validator::extend('custom_rule', function ($attribute, $value) {
        // The user that's being edited, if any.
        $currentUser = $this->route('user');

        $query = User::join('addresses', function ($join) {
            $join->on('addresses.user_id', 'users.id')
                ->where('addresses.address_type', 'home');
        })->where($attribute, $value)->where('users.id', '!=', $currentUser->id ?? 0);

        // True means pass, false means fail validation.
        // If count is 0, that means the unique constraint passes.
        return !$query->count();
    });

    return [
        'name' => 'required|custom_rule',
    ];
}

【讨论】:

    【解决方案2】:

    Laravel 5.8 - 问题仍然存在。

    参见 \Illuminate\Validation\DatabasePresenceVerifier 类,方法 addConditions()。

    可以清楚地看到,如果一个验证规则条件是一个闭包,那么它是在嵌套的where部分里面执行的,这就排除了使用join的可能性:

    /**
     * Add the given conditions to the query.
     *
     * @param  \Illuminate\Database\Query\Builder  $query
     * @param  array  $conditions
     * @return \Illuminate\Database\Query\Builder
     */
    protected function addConditions($query, $conditions)
    {
        foreach ($conditions as $key => $value) {
            if ($value instanceof Closure) {
                $query->where(function ($query) use ($value) {
                    $value($query);
                });
            } else {
                $this->addWhere($query, $key, $value);
            }
        }
    
        return $query;
    }
    

    是的,在验证规则中使用 join 的唯一一种方法是制定自己的规则,就像 aross 所说的那样。

    【讨论】:

      【解决方案3】:

      Look at the documentation高级连接子句

      $query->join('role_user', function ($join) {
          return $join->on('role_user.team_id', '=', 'teams.id')->on('role_user', '=', Auth::id());
      });
      

      【讨论】:

        猜你喜欢
        • 2018-07-20
        • 2014-10-26
        • 1970-01-01
        • 2017-07-12
        • 2015-05-25
        • 1970-01-01
        • 1970-01-01
        • 2014-11-29
        • 2016-01-17
        相关资源
        最近更新 更多