thinkphp5.0 unique验证器一些有意思的事情

场景

  • thinkphp的文档向来是很简陋, 所以当用出了一些问题的时候,需要看看源码
  • 公司的一个项目使用thinkphp5.0,今天验证bug, 同事设置了场景 edit, create场景分别校验,其中一个场景是校验店名是否唯一, 同事采用了这样的策略(为了避免编辑模式, 店名唯一性校验不通过的问题)
    • 存在id,并且店名没有更改的时候,不校验店名的唯一性(即所谓的edit场景)
    • 其实这样搞逻辑也是可以自洽的,但是我们的业务场景还有一个可以文件批量导入的功能,那里有些疏漏,导致了同名的店铺出现了,所以在更新的时候,吊诡的事情出现了 : 店铺的唯一性没有校验

thinkphp官方的解释

  • 鬼才能明白unique是怎么回事

解决

  • thinkphp5.0 内置了更新和新建的唯一性的解决方案, 下面是源码
    • map[map[pk] = [‘neq’, data[data[pk]];
    • 只要更新的时候带上id

unqiue 源码

    /**
     * 验证是否唯一
     * @access protected
     * @param mixed     $value  字段值
     * @param mixed     $rule  验证规则 格式:数据表,字段名,排除ID,主键名
     * @param array     $data  数据
     * @param string    $field  验证字段名
     * @return bool
     */
    protected function unique($value, $rule, $data, $field)
    {
        if (is_string($rule)) {
            $rule = explode(',', $rule);
        }
        if (false !== strpos($rule[0], '\\')) {
            // 指定模型类
            $db = new $rule[0];
        } else {
            try {
                $db = Loader::model($rule[0]);
            } catch (ClassNotFoundException $e) {
                $db = Db::name($rule[0]);
            }
        }
        $key = isset($rule[1]) ? $rule[1] : $field;

        if (strpos($key, '^')) {
            // 支持多个字段验证
            $fields = explode('^', $key);
            foreach ($fields as $key) {
                $map[$key] = $data[$key];
            }
        } elseif (strpos($key, '=')) {
            parse_str($key, $map);
        } else {
            $map[$key] = $data[$field];
        }

        $pk = isset($rule[3]) ? $rule[3] : $db->getPk();
        if (is_string($pk)) {
            if (isset($rule[2])) {
                $map[$pk] = ['neq', $rule[2]];
            } elseif (isset($data[$pk])) {
                $map[$pk] = ['neq', $data[$pk]];
            }
        }
        if ($db->where($map)->field($pk)->find()) {
            return false;
        }
        return true;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章