當我們需要通過驗證器 validate
來對資料庫中的欄位做唯一性校驗時,可以通過 unique
規則實現,但 tp
並沒有很詳細的說明如何使用。
這裡結合我日常開發中的一些場景,給大家整理一下:
unique
語法規則
// modelClassName 你需要關聯校驗的模型類名(直接寫表名會比較硬編碼)
// col1^col2 參與唯一校驗的欄位
// [
// ['col1', '=', $formData['col1']],
// ['col2', '=', $formData['col2']],
// ]
// $pkId 「編輯」場景防自殺
// [['id', '<>', $pkId]]
protectd $rule = [
"colName" => "require|unique:modelClassName,col1[^col2][,$pkId]"
]
模型
/**
* @property int $id
* @property string $name 唯一
* @property int $age
* @property int $deleted 軟刪除
class User extends Model
{
protected $connection = "db_app";//多庫連結配置
}
校驗器基類
根據表單資料中是否有 pkId
來動態的調整 unique
的校驗規則
<?php
namespace app\common\validate;
use think\Validate;
/**
* Class MaterialTypeValidate
*
* @package app\prt\validate
* @see \think\Validate::unique 解析器
*/
class BaseValidate extends Validate
{
/**
* 根據表單資料動態掛載 pkId
* 編輯時的 unique 校驗 應使用 pkId 來忽略當前行
* 同時如果有軟刪除 那麼還要加入 deleted=0 的條件來限制只校驗有效記錄
* formData ['col1' => xxx, 'col2' => xxx, 'deleted'=>0]
* unique|modelName,col1^col2^deleted,pkId
* unique多欄位校驗時驗證器會檢查表單資料有對應的欄位 有才會生成查詢條件
* 為了忽略軟刪除要讓表單資料中的 deleted=0 顯示定義,排除已刪除的資料
* BaseValidate constructor.
*
* @param int $pkId
* @param array $rules
* @param array $message
* @param array $field
*/
public function __construct($pkId = 0, array $rules = [], array $message = [], array $field = [])
{
parent::__construct($rules, $message, $field);
// 有 id 則為編輯,追加pkId條件
// 無 id 則為新增,全域性唯一檢查
array_walk($this->rule, function (&$row) use ($pkId) {
$row = str_replace(",{pkId}", "," . $pkId ?? "", $row);
}, $this->rule);
}
}
新增時需要校驗全域性有效記錄
的欄位唯一性,編輯
時需要校驗 除當前記錄外
的欄位唯一性。
<?php
namespace app\http\validate;
use app\common\validate\BaseValidate;
use app\http\model\User;
/**
* Class UserValidate
*
* @package app\http\validate
*/
class UserValidate extends BaseValidate
{
protected $rule = [
'id' => 'require|number',
'name' => 'require|unique:' . User::class . ',name^deleted,{pkId}',
'age' => 'require|number',
];
protected $message = [
'id.require' => 'id無效',
'id.number' => 'id無效',
'name.require' => '姓名必須',
'name.unique' => '姓名重複',
'age.require' => '年齡必須',
'age.number' => '年齡無效',
];
protected $scene = [
'add' => ['name', 'age'],
'edit' => ['id', 'name', 'age'],
];
}
例項
public function save($userData)
{
// 根據有無 id 來動態渲染 unique 條件的校驗範圍
$validate = new UserValidate($userData['id'] ?? 0);
// 只校驗未刪除的有效資料
if (User::hasSoftDelete()) {
$userData['deleted'] = 0;
}
if (empty($userData['id'])) {
$validateRes = $validate->scene('add')->check($userData);
} else {
$validateRes = $validate->scene('edit')->check($userData);
}
if (!$validateRes) {
throw new Exception($validate->getError());
}
}
unique
的解析器
\think\Validate::unique