我有一个返回true
或false
的验证函数。
然而,我希望它提供的信息,什么问题是,当有一个。
假设函数是这样的:
function is_valid($val) {
$result = true;
if( rule_1_not_met ) $result = false;
if( rule_2_not_met ) $result = false;
return $result;
}
像这样使用
$val = $_GET['some_param'];
if(!is_valid($val)) $out .= 'Not so helpful feedback.';
...
我想我可以这样修改:
function is_valid($val) {
$result = array(true, array());
if( rule_1_not_met ) $result[1][] = 'Reason 1';
if( rule_2_not_met ) $result[1][] = 'Reason 2';
if(count($result[1]) > 0) $result[0] = false;
return $result;
}
并像这样使用:
$val = $_GET['some_param'];
$validation_result = is_valid($val);
if(!$validation_result[0]) $out .= implode('<br/>', $validation_result[1]);
...
我的问题是
- 我在吗,为了意想不到的结果?
- 是否有更好的方法来实现这一点?
注:会让这个社区变成wiki
你的思路是对的,但我想用这种方式来做
function is_valid($val,&$mes) {
$result = true;
if( rule_1_not_met ) { $mes[]='message one'; $result = false; }
if( rule_2_not_met ) { $mes[]='Message two'; $result = false; }
return $result;
}
$mes=array();
if(isvalid($val,$mes) ===false) $out .= implode('<br/>', $mes);
在我看来,你提出的解决方案很好。唯一的问题是,您必须记住$validation_result[0]
是状态,$validation_result[1]
包含消息。这对您来说可能没问题,但如果其他人使用您的代码,则很难维护。您可以做的一件事是,当您调用函数时,您可以使用数组解构至少存储具有有意义的变量名的结果。例如:
[$valid, $errors] = is_valid($val);
if(!$valid) $out .= implode('<br/>', $errors);
由于上面提到的原因,我喜欢Brad Thomas的解决方案,即创建一个包含消息和状态的专门类。由于属性已命名,因此您不必猜测如何访问验证信息。而且,当您尝试访问它们的属性时,大多数好的ide都会自动完成。
我也有一个替代的解决方案。而不是包含一个布尔值true或false。只返回消息数组。调用者只需要检查返回的数组是否有非零的错误数。下面是一个例子:
function get_errors($val) {
$errors = array();
if( rule_1_not_met ) $errors[] = 'Reason 1';
if( rule_2_not_met ) $errors[] = 'Reason 2';
return $errors;
}
那么调用者会这样使用它:
$val = $_GET['some_param'];
$validation_result = get_errors($val);
if (count($validation_result) > 0) $out .= implode('<br/>', $validation_result);
可以使用Result对象封装返回数据、消息和状态。
。
class Result( $bResult, $sMessage, $mData ) {
public function __construct() {
$this->bResult = $bResult;
$this->sMessage = $sMessage;
$this->mData = $mData;
}
}
在你的代码中:
$result = new Result(true, 'some helpful message here', null);
$reasons = array();
function is_valid($val)
{
global $reasons;
if ( rule_1_not_met ) $reasons[] = 'Reason 1';
if ( rule_2_not_met ) $reasons[] = 'Reason 2';
if ( count($reasons) == 0 )
return TRUE;
else
return FALSE;
}
if (!is_valid($condition))
{
echo 'Was not valid for these reasons<br />';
foreach($reasons as $reason)
echo $reason, '<br>';
}
else
echo 'Is valid!';
这个问题很老了,它展示了坏的和过时的做法。使用global
是不被允许的,在这种情况下使用引用也是一样的。
只有凯夫·约翰逊的回答是直接的,但用法仍然可能令人困惑。一个更好的解决方案是写一个类,但不要像Brad Thomas的答案那样愚蠢。
class NumberValidator
{
protected $errors;
public function validate($number)
{
if(!is_numeric($number))
{
$this->errors[] = "The value provided is not numeric";
return false;
}
if($number < 10)
{
$this->errors[] = "The number is less than 10";
return false;
}
return true;
}
public function getErrors()
{
return $this->errors;
}
}
然后可以这样使用
$validator = new NumberValidator();
if($validator->validate($number)) {
/*success*/
}
和$validator->getErrors()
可以用在其他地方