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;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章