我最終擴展了Validator類來定義自定義驗證器規則。我在我的應用程序的first_name
字段上檢查它,主要是因爲我不想在生成全名時做額外的工作。除了將其作爲一個複合值之外,在考慮問題後不需要這個複合值,我只需將其設置爲檢查指定字段的所有值的AND
即可。您可以指定任意數量的字段,並且如果其中一個字段不存在於驗證程序數據中,它將引發異常。我甚至不確定這是否可以完全用現有的unique
規則來完成,但無論如何這是一個很好的練習。
'first_name' => 'unique_multiple_fields:members,first_name,last_name'
我的驗證子類代碼:
use Illuminate\Validation\Validator as IlluminateValidator;
class CustomValidatorRules extends IlluminateValidator
{
/**
* Validate that there are no records in the specified table which match all of the
* data values in the specified fields. Returns true iff the number of matching
* records is zero.
*/
protected function validateUniqueMultipleFields($attribute, $value, $parameters)
{
if (is_null($parameters) || empty($parameters)) {
throw new \InvalidArgumentException('Expected $parameters to be a non-empty array.');
}
if (count($parameters) < 3) {
throw new \InvalidArgumentException('The $parameters option should have at least 3 items: table, field1, field2, [...], fieldN.');
}
// Get table name from first parameter, now left solely with field names.
$table = array_shift($parameters);
// Uppercase the table name, remove the 's' at the end if it exists
// to get the class name of the model (by Laravel convention).
$modelName = preg_replace("/^(.*)([s])$/", "$1", ucfirst($table));
// Create the SQL, start by getting only the fields specified in parameters
$select = $modelName::select($parameters);
// Generate the WHERE clauses of the SQL query.
foreach ($parameters as $fieldName) {
$curFieldVal = ($fieldName === $attribute) ? $value : $this->data[$fieldName];
if (is_null($curFieldVal)) {
// There is no data for the field specified, so fail.
throw new \Exception("Expected `{$fieldName}` data to be set in the validator.");
}
// Add the current field name and value
$select->where($fieldName, '=', $curFieldVal);
}
// Get the number of fields found
$numFound = $select->count();
return ($numFound === 0);
}
}
如果你很好奇,我沒有得到它採用複合方法本來我一直在尋找工作。代碼如下。原來,'分隔符'是完全沒有意義的,因此我最終重構了它以使用上面指定的多字段方法。
use Illuminate\Validation\Validator as IlluminateValidator;
class CustomValidatorRules extends IlluminateValidator
{
/**
* Validate that the final value of a set of fields - joined by an optional separator -
* doesn't match any records in the specified table. Returns true iff the number of
* matching records is zero.
*/
protected function validateUniqueComposite($attribute, $value, $parameters)
{
if (is_null($parameters) || empty($parameters)) {
throw new \InvalidArgumentException('Expected $parameters to be a non-empty array.');
}
if (count($parameters) < 3) {
throw new \InvalidArgumentException('The $parameters option should have at least 3 items: table, field1, field2, [...], fieldN.');//, [separator].');
}
// Get table name from first parameter
$table = array_shift($parameters);
// Determine the separator
$separator = '';
$lastParam = array_pop($parameters);
if (! isset($this->data[$lastParam])) {
$separator = $lastParam;
}
// Get the names of the rest of the fields.
$fields = array();
foreach ($parameters as $fieldName) {
array_push($fields, $table . "." . $fieldName);
}
$fields = implode(', ', $fields);
$dataFieldValues = array();
foreach ($parameters as $fieldName) {
$curFieldVal = ($fieldName === $attribute) ? $value : $this->data[$fieldName];
if (is_null($curFieldVal)) {
throw new \Exception("Expected `{$fieldName}` data.");
}
array_push($dataFieldValues, $curFieldVal);
}
$compositeValue = implode($separator, $dataFieldValues);
// Uppercase the table name, remove the 's' at the end if it exists
// to get the class name of the model (by Laravel convention).
$modelName = preg_replace("/^(.*)([s])$/", "$1", ucfirst($table));
$raw = \DB::raw("concat_ws('" . $separator . "', " . $fields . ")");
$model = new $modelName;
// Generate the SQL query
$select = $modelName::where($raw, '=', $compositeValue);
$numFound = $select->count();
return ($numFound === 0);
}
}
當您設置'$ modelName'時,您將刪除字符串末尾的's'。這並不總是得到單數形式的正確方法(想'box'=>'盒子')。你可以通過使用Laravel的'str_plural()'([檢查文檔](http://laravel.com/docs/4.2/helpers#strings))來改進它。對於那些使用非英文模型/表名的人,你應該關注這種多元化(或者簡單地將表名稱傳遞給驗證)。 – 2015-05-08 09:03:08
感謝您的提示。我將它添加到此項目的修補程序隊列中。 – Derek 2015-05-08 14:21:20