我有:
在isCorrect方法中,我有:
switch ($type):
case 'email':
isEmailCorrect();
case 'password':
isPasswordCorrect();
case 'x':
isXCorrect();
isEmailCorrect(),isPasswordCorrect()和isXCorrect()可以访问包含所有错误消息的同一属性
现在,我有:
现在,在调用isCorrect()方法的文件中,我有:
$EmailValidator = new EmailValidator();
$PasswordValidator = new PasswordValidator();
$XValidator = new XValidator();
$EmailValidator->isCorrect()
,$PasswordValidator->isCorrect()
和$XValidator->isCorrect()
无法访问包含所有错误消息的同一媒体资源
$ errormessages在不同类的不同实例中。他们应该是一个,但是三个。
现在怎么办?
答案 0 :(得分:2)
我认为你应该开发另一个类:ValidatorChain,它接受任意数量的验证器,并聚合它已经测试过的所有验证器的错误消息
有关参考,请参阅docs on Zend Framework's Validator Chain
修改强>
现在我重新评估你的问题(感谢Bryan M的评论);为什么您希望每个Validator都能访问其他Validator的错误消息?我会说收集每个Validators的错误消息是层次结构中较高层对象的责任。
但是,如果您希望各个验证器能够根据上下文执行操作,换句话说,根据其他验证器的结果,我想您可以向{{1}添加$ context参数} 方法。例如,这可以接受任意数量的Validators或类似的东西。
类似的东西:
isCorrect
用法:
interface ValidatorInterface
{
public function isCorrect( array $context );
public function getMessages();
}
abstract class ValidatorContextOptions
{
const SHOULD_BE_PRESENT = 'shouldBePresent';
const SHOULD_NOT_BE_PRESENT = 'shouldNotBePresent';
const SHOULD_BE_VALID = 'shouldBeValid';
}
class EmailValidator implements ValidatorInterface
{
protected $_field;
protected $_contextOptions = array();
protected $_messages = array();
public function __construct( $field, array $contextOptions )
{
$this->_field = $field;
$this->_contextOptions = $contextOptions;
}
public function isCorrect( array $context = null )
{
foreach( $this->_contextOptions as $field => $options )
{
foreach( $options as $option )
{
switch( $option )
{
case ValidatorContextOptions::SHOULD_NOT_BE_PRESENT:
if( isset( $context[ $field ] )
&& $context[ $field ] instanceof ValidatorInterface )
{
$this->_messages[] = $field . ' should not be present';
return false;
}
break;
case ValidatorContextOptions::SHOULD_BE_PRESENT:
if( !isset( $context[ $field ] )
|| !$context[ $field ] instanceof ValidatorInterface )
{
$this->_messages[] = $field . ' should be present';
return false;
}
break;
case ValidatorContextOptions::SHOULD_BE_VALID:
if( !isset( $context[ $field ] )
|| !$context[ $field ] instanceof ValidatorInterface
|| !$context[ $field ]->isCorrect() )
{
$this->_messages[] = $field . ' should be valid';
return false;
}
break;
}
}
}
// some dummy function which you should replace with real validation
return isAnEmailAddress( $this->_field );
}
public function getMessages()
{
return $this->_messages;
}
}
我在这里展示的,需要更多的思考(而且我真的意味着很多),如同地狱,绝对不是防弹。但是我希望你能抓住我对这个问题的看法。
此外,您在哪里插入需要验证的验证器中的值?
答案 1 :(得分:0)
您可以创建一个外部属性工厂来控制对您的属性的访问,假设您正在讨论属性文件,这是我通常采用的方法。
如果您指的是共享字段,那么您可以将它放在基类中并以这种方式访问它。
答案 2 :(得分:0)
我经常使用Zend_Validate类来执行验证,并将任何错误消息聚合到正在验证的对象上的属性(以及控制有效状态的标志)。
我的设置与此类似:
class User {
public $email;
protected $_errorMessages = array();
public function validate()
{
$valid = true;
$emailValidator = new EmailValidator();
if (!$emailValidator->isCorrect($this->email)) {
$valid = false;
// validation message are added to the $errormessages property in
// the validator class upon failure of isCorrect()
$this->_errorMessages[] = $emailValidator->getMessages();
}
// repeat this for all your validators
return $valid
}
public function getErrorMessages()
{
return $this->_errorMessages();
}
}
// in your page....
if (!$user->validate()) {
$messages = $user->getErrorMessages();
}
答案 3 :(得分:0)
如果我读了你,你想要多个实例共享相同的错误消息属性,这样你就可以实例化几个验证器,并让它们全部贡献给一个数组。
如果是这种情况,有几种方法可以做到。一种方法是创建一个验证器管理器类,负责实例化和注册验证器。然后,一旦验证完成,您可以调用$validator_manager->getErrors()
来汇总在其中注册的所有验证器中出现的错误。
您可以使用的另一种方法是使用单个错误存储类,您可以在每个验证程序的构造函数中获取该类。然后,每个验证器的addError()
方法将作业委托给单例。
还有其他方法,但基本上你将不得不使用另一个对象来管理验证器或存储错误。
答案 4 :(得分:0)
下面提到的人使用单身人士。
我不相信这是一种很好的设计模式,特别是因为通常认为单身人士是“反模式”并经常过度/误用。
尽管如此,记住这一点,这是一个例子:
<?php
//Error Class implemented as a Singleton
class ErrorClass
{
static private $instance = false;
static private $errorMessages;
function getInstance() {
if (!self::$instance) {
self::$instance = new ErrorClass();
self::$errorMessages = "No errors;";
}
return self::$instance;
}
public function setError($errorMessage){
self::$instance->errorMessages .= $errorMessage;
}
public function getError(){
return self::$instance->errorMessages;
}
}
abstract class AbstractClass
{
// Force Extending class to define this method
abstract protected function isCorrect($b);
// Common Method for setting error
public function setError($errorMessage) {
ErrorClass::getInstance()->setError($errorMessage);
}
// Common Method for getting error
public function getError() {
return ErrorClass::getInstance()->getError();
}
}
class EmailValidator extends AbstractClass
{
public function isCorrect($b) {
if(!$b) {
$this->setError('EmailValidator->isCorrect();');
}
}
}
class PasswordValidator extends AbstractClass
{
public function isCorrect($b) {
if(!$b) {
$this->setError('PasswordValidator->isCorrect();');
}
}
}
// Then in your code
$errorState = 1; // used for testing purposes
$EmailValidator = new EmailValidator();
$EmailValidator->isCorrect($errorState);
$PasswordValidator = new PasswordValidator();
$PasswordValidator->isCorrect($errorState);
echo $EmailValidator->getError();
echo $PasswordValidator->getError();