2. 现在我们将注意力转向Application/Form/Factory
类,并添加属性和设置器,允许我们附加Application/Filter/Filter
和Application/Filter/Validator
的实例。我们还需要定义$data
,它将用于保留过滤和验证的数据。
复制 const DATA_NOT_FOUND = 'Data not found. Run setData()' ;
const FILTER_NOT_FOUND = 'Filter not found. Run setFilter()' ;
const VALIDATOR_NOT_FOUND = 'Validator not found. Run setValidator()' ;
protected $filter;
protected $validator;
protected $data;
public function setFilter ( Filter $filter)
{
$this -> filter = $filter;
}
public function setValidator ( Validator $validator)
{
$this -> validator = $validator;
}
public function setData ($data)
{
$this -> data = $data;
}
3. 接下来,我们定义了一个validate()
方法,该方法调用嵌入式Application/Filter/Validator
实例的process()
方法。我们检查$data
和$validator
是否存在。如果不存在,就会抛出相应的异常,并指示需要先运行哪个方法。
复制 public function validate ()
{
if ( ! $this -> data)
throw new RuntimeException ( self:: DATA_NOT_FOUND);
if ( ! $this -> validator)
throw new RuntimeException ( self:: VALIDATOR_NOT_FOUND);
4. 调用process()
方法后,我们将验证结果消息与表单元素消息关联起来。需要注意的是,process()
方法会返回一个布尔值,代表数据集的整体验证状态。当表单在验证失败后重新显示时,错误信息将出现在每个元素旁边。
复制 $valid = $this -> validator -> process ( $this -> data ) ;
foreach ( $this -> elements as $element) {
if ( isset ( $this -> validator -> getResults ()
[$element -> getName () ] ) ) {
$element -> setErrors ( $this -> validator -> getResults ()
[$element -> getName () ] -> messages ) ;
}
}
return $valid;
}
5. 以类似的方式,我们定义了一个filter()
方法,该方法调用嵌入式Application/Filter/Filter
实例的process()
方法。与步骤3中描述的validate()
方法一样,我们需要检查$data
和$filter
是否存在。如果缺少任何一个,我们将抛出一个带有适当消息的RuntimeException
。
复制 public function filter ()
{
if ( ! $this -> data)
throw new RuntimeException ( self:: DATA_NOT_FOUND);
if ( ! $this -> filter)
throw new RuntimeException ( self:: FILTER_NOT_FOUND);
6. 然后我们运行process()
方法,产生一个Result
对象数组,其中$item
属性代表过滤链的最终结果。然后我们对结果进行循环,如果对应的$element
键匹配,则将值属性设置为过滤后的值。我们还添加过滤过程中产生的任何消息。当表单重新显示时,所有的值属性都会显示过滤后的结果。
复制 $this -> filter -> process ( $this -> data ) ;
foreach ( $this -> filter -> getResults () as $key => $result) {
if ( isset ( $this -> elements[$key] ) ) {
$this -> elements[$key]
-> setSingleAttribute ( 'value' , $result -> item ) ;
if ( isset ( $result -> messages )
&& count ( $result -> messages ) ) {
foreach ($result -> messages as $message) {
$this -> elements[$key] -> addSingleError ( $message ) ;
}
}
}
}
}
复制 <? php
use Application \ Form \ Generic ;
define ( 'VALIDATE_SUCCESS' , 'SUCCESS: form submitted ok!' ) ;
define ( 'VALIDATE_FAILURE' , 'ERROR: validation errors detected' ) ;
$wrappers = [
Generic :: INPUT => [ 'type' => 'td' , 'class' => 'content' ] ,
Generic :: LABEL => [ 'type' => 'th' , 'class' => 'label' ] ,
Generic :: ERRORS => [ 'type' => 'td' , 'class' => 'error' ]
];
$elements = [
'first_name' => [
'class' => 'Application\Form\Generic' ,
'type' => Generic :: TYPE_TEXT ,
'label' => 'First Name' ,
'wrappers' => $wrappers ,
'attributes' => [ 'maxLength' => 128 , 'required' => '' ]
] ,
'last_name' => [
'class' => 'Application\Form\Generic' ,
'type' => Generic :: TYPE_TEXT ,
'label' => 'Last Name' ,
'wrappers' => $wrappers ,
'attributes' => [ 'maxLength' => 128 , 'required' => '' ]
] ,
// etc.
];
// overall form config
$formConfig = [
'name' => 'prospectsForm' ,
'attributes' => [
'method' => 'post' ,
'action' => 'chap_06_tying_filters_to_form.php'
] ,
'row_wrapper' => [ 'type' => 'tr' , 'class' => 'row' ] ,
'form_wrapper' => [
'type' => 'table' ,
'class' => 'table' ,
'id' => 'prospectsTable' ,
'class' => 'display' , 'cellspacing' => '0'
] ,
'form_tag_inside_wrapper' => FALSE ,
];
$assignments = [
'first_name' => [ [ 'key' => 'length' ,
'params' => [ 'min' => 1 , 'max' => 128 ]] ,
[ 'key' => 'alnum' ,
'params' => [ 'allowWhiteSpace' => TRUE ]] ,
[ 'key' => 'required' , 'params' => []] ] ,
'last_name' => [ [ 'key' => 'length' ,
'params' => [ 'min' => 1 , 'max' => 128 ]] ,
[ 'key' => 'alnum' ,
'params' => [ 'allowWhiteSpace' => TRUE ]] ,
[ 'key' => 'required' , 'params' => []] ] ,
'address' => [ [ 'key' => 'length' ,
'params' => [ 'max' => 256 ]] ] ,
'city' => [ [ 'key' => 'length' ,
'params' => [ 'min' => 1 , 'max' => 64 ]] ] ,
'state_province' => [ [ 'key' => 'length' ,
'params' => [ 'min' => 1 , 'max' => 32 ]] ] ,
'postal_code' => [ [ 'key' => 'length' ,
'params' => [ 'min' => 1 , 'max' => 16 ] ] ,
[ 'key' => 'alnum' ,
'params' => [ 'allowWhiteSpace' => TRUE ]] ,
[ 'key' => 'required' , 'params' => []] ] ,
'phone' => [ [ 'key' => 'phone' , 'params' => []] ] ,
'country' => [ [ 'key' => 'in_array' ,
'params' => $countries ] ,
[ 'key' => 'required' , 'params' => []] ] ,
'email' => [ [ 'key' => 'email' , 'params' => [] ] ,
[ 'key' => 'length' ,
'params' => [ 'max' => 250 ] ] ,
[ 'key' => 'required' , 'params' => [] ] ] ,
'budget' => [ [ 'key' => 'float' , 'params' => []] ]
];
复制 <? php
require __DIR__ . '/../Application/Autoload/Loader.php' ;
Application \ Autoload \ Loader :: init ( __DIR__ . '/..' ) ;
include __DIR__ . '/chap_06_post_data_config_messages.php' ;
include __DIR__ . '/chap_06_post_data_config_callbacks.php' ;
include __DIR__ . '/chap_06_tying_filters_to_form_definitions.php' ;
复制 use Application \ Form \ Factory ;
use Application \ Filter \ { Validator , Filter };
$form = Factory :: generate ( $elements ) ;
$form -> setFilter ( new Filter ($callbacks[ 'filters' ] , $assignments[ 'filters' ]) ) ;
$form -> setValidator ( new Validator ($callbacks[ 'validators' ] , $assignments[ 'validators' ]) ) ;
复制 $message = '' ;
if ( isset ( $_POST[ 'submit' ] ) ) {
$form -> setData ( $_POST ) ;
if ($form -> validate () ) {
$message = VALIDATE_SUCCESS;
} else {
$message = VALIDATE_FAILURE;
}
$form -> filter () ;
}
?>
复制 <?= $form -> render ( $form , $formConfig ) ; ?>