为什么继承validation类的子类中$errors和指定Session变量无法赋值?
问题根源
- 所有验证子类都重写了
__construct构造方法,但既没有接收用户输入的$data参数,也没有主动调用父类validation的构造方法,导致子类实例的$user_data属性完全为空,验证逻辑的判断条件根本不会触发,自然不会设置$errors和对应的session变量。 - 你分别实例化了父类和3个子类,共4个完全独立的对象,子类产生的错误都存在各自实例的
$errors属性里,你打印的$validation是父类实例,只会保存空字段检查的错误,看不到子类的验证错误。 - 父类
validation的$errors属性没有初始化为空数组,首次追加错误时可能抛出PHP警告。
修复代码
<?php session_start(); class validation{ public $user_data; // 初始化errors为空数组 public $errors = []; public function __construct($data) { $this->user_data = $data; // 空字段检查 foreach($this->user_data as $key => $value){ if(empty($value)){ $_SESSION["{$key}_empty"] = "set"; $this->errors[] = "empty $key"; }else{ unset($_SESSION["{$key}_empty"]); } } // 存储输入值用于回显 foreach($this->user_data as $key => $value){ $_SESSION["{$key}_value"] = $value; } } } // 子类构造接收data,调用父类构造 class email_validate extends validation{ function __construct($data){ // 先调用父类构造初始化user_data和空字段检查 parent::__construct($data); if(!filter_var($this->user_data['email'], FILTER_VALIDATE_EMAIL)){ $this->errors[] = "inval email"; $_SESSION['inval email'] = 'set'; }else{ unset($_SESSION['inval email']); } } } class password_validate extends validation{ function __construct($data){ parent::__construct($data); if(strlen($this->user_data['password']) < 6){ $this->errors[] = "inval password"; $_SESSION['inval password'] = 'set'; }else{ unset($_SESSION['inval password']); } } } class repeat_password_validate extends validation{ function __construct($data){ parent::__construct($data); if($this->user_data['password'] !== $this->user_data['reppassword']){ $this->errors[] = "inval repeat password"; $_SESSION['inval rep password'] = 'set'; }else{ unset($_SESSION['inval rep password']); } } } $data = array( "email" => $_POST['email'], "password" => $_POST['password'], "reppassword" => $_POST['reppassword'] ); // 实例化各验证类时传入data $emailValidation = new email_validate($data); $passwordValidation = new password_validate($data); $repPasswordValidation = new repeat_password_validate($data); // 汇总所有错误 $allErrors = array_merge( $emailValidation->errors, $passwordValidation->errors, $repPasswordValidation->errors ); echo "<pre>"; print_r($allErrors); ?>
更优写法推荐
你当前的写法会重复跑多次空字段检查逻辑,性能较差,建议把验证逻辑从构造方法里拆成独立的验证方法,用同一个实例跑所有验证即可:
<?php session_start(); class validation{ public $user_data; public $errors = []; public function __construct($data) { $this->user_data = $data; // 只跑一次空字段检查 foreach($this->user_data as $key => $value){ if(empty($value)){ $_SESSION["{$key}_empty"] = "set"; $this->errors[] = "empty $key"; }else{ unset($_SESSION["{$key}_empty"]); } $_SESSION["{$key}_value"] = $value; } } // 邮箱验证方法 public function validateEmail(){ if(!filter_var($this->user_data['email'], FILTER_VALIDATE_EMAIL)){ $this->errors[] = "inval email"; $_SESSION['inval email'] = 'set'; }else{ unset($_SESSION['inval email']); } return $this; // 支持链式调用 } // 密码长度验证 public function validatePassword(){ if(strlen($this->user_data['password']) < 6){ $this->errors[] = "inval password"; $_SESSION['inval password'] = 'set'; }else{ unset($_SESSION['inval password']); } return $this; } // 重复密码验证 public function validateRepeatPassword(){ if($this->user_data['password'] !== $this->user_data['reppassword']){ $this->errors[] = "inval repeat password"; $_SESSION['inval rep password'] = 'set'; }else{ unset($_SESSION['inval rep password']); } return $this; } } $data = [ 'email' => $_POST['email'], 'password' => $_POST['password'], 'reppassword' => $_POST['reppassword'] ]; $validator = new validation($data); // 链式调用所有验证规则 $validator->validateEmail() ->validatePassword() ->validateRepeatPassword(); print_r($validator->errors); ?>
内容的提问来源于stack exchange,提问作者Skay skeleton
相关产品推荐
相关产品推荐

