我有一个CRUD对象,并且我有两个对象admin和post,它们扩展了CRUD对象。当我通过时,我将在前端和后端进行验证,但是目前我正在进行后端验证。 CRUD对象具有全局创建,更新和验证方法。 Post对象将覆盖验证方法,并且可以正常工作。管理员将覆盖validate方法,并且似乎没有调用父级或子级。
以下示例:
<?php
class CRUD {
protected function validate(){
$this->errors =[]
//no error checking here, but when I put any error checking here it doesnt
//fire on admin either.
return $this->errors;
}
public function create(){
$this->validate();
if(!empty($this->errors){return false}
//query which works on all classes.
}
}
class Admin extends CRUD{
protected function validate(){
$this->errors = [];
//a bunch of error checking functions that work for post class
return $this->errors;
}
public function create(){
$this->hashpassword(); //just sets $this->password to a hash
return parent::create();
}
}
class Post extends CRUD {
protected function validate() {
$this->errors =[];
//a bunch of functioning validations
return $this->errors;
}
}
?>
是否按原样运行该函数,将override create()
函数注释掉,并使用不对密码进行哈希处理的继承版本,或者尝试将验证函数放在父类中,没有任何内容$this->errors
(用于管理员)。对于邮递班来说,它完全可以正常工作。我的问题是,为什么验证方法对Admin类无效?
**编辑副本并粘贴实际的类** CRUD类:
<?php
class DatabaseObject {
static protected $db;
static protected $table_name;
static protected $db_columns = [];
public $errors = [];
public static function set_db($db){
self::$db = $db;
}
static public function find_by_sql($sql){
$result = self::$db->query($sql);
if(!$result) {
exit("Database Query Failed");
}
//convert results into objects
$object_array=[];
while($record = $result->fetch_assoc()){
$object_array[] = static::instantiate($record);
}
$result->free();
return $object_array;
}
static public function find_all(){
$sql = "SELECT * FROM " . static::$table_name;
return static::find_by_sql($sql);
}
static public function find_by_id($id){
$sql = "SELECT * FROM " . static::$table_name;
$sql .= " WHERE id='" . self::$db->escape_string($id) . "'";
$object_array = static::find_by_sql($sql);
if(!$object_array){
return false;
}
return array_shift($object_array);
}
static protected function instantiate($record){
$object = new static;
//could assign things by hand but its faster and easier to do it dunamically
//plus it's reusable.
foreach($record as $property => $value){
if(property_exists($object, $property)){
$object->$property = $value;
}
}
return $object;
}
protected function validate() {
$this->errors = [];
$this->errors[] = "bar";
return $this->errors;
}
protected function create(){
$this->validate();
if(!empty($errors))
{return false;}
$attributes = $this->sanitize_attributes();
$sql = "INSERT INTO " . static::$table_name . " (";
$sql .= join(',', array_keys($attributes));
$sql .= ") VALUES ('";
$sql .= join("', '", array_values($attributes));
$sql .= "')";
$result = self::$db->query($sql);
if ($result){
$this->id = static::$db->insert_id;
}
return $result;
}
//attributes are the properties which have the db columns excluding id
protected function update(){
$this->validate();
if(!empty($errors)){return false;}
$attributes = $this->sanitize_attributes();
$attribute_pairs = [];
foreach($attributes as $key => $value) {
$attribute_pairs[] = "{$key}='{$value}'";
}
$sql = "UPDATE " . self::$db->escape_string(static::$table_name) . " SET ";
$sql .= join(', ', $attribute_pairs);
$sql .= " WHERE id='" . self::$db->escape_string($this->id) . "' ";
$sql .= "LIMIT 1";
$result = self::$db->query($sql);
return $result;
}
public function save(){
if(isset($this->id)){
return $this->update();
} else {
return $this->create();
}
}
public function merge_attributes($args){
foreach($args as $key => $value) {
if(property_exists($this, $key) && !is_null($value)){
$this->$key = $value;
}
}
}
public function attributes() {
$attributes = [];
foreach(static::$db_columns as $column) {
if($column == 'id'){ continue; }
$attributes[$column] = $this->$column;
}
return $attributes;
}
protected function sanitize_attributes() {
$attributes = $this->attributes();
$sanitized =[];
foreach($attributes as $key => $value){
$sanitized[$key] = self::$db->escape_string($value);
}
return $sanitized;
}
public function delete(){
$sql = "DELETE FROM " . self::$db->escape_string(static::$table_name) . " ";
$sql .= "WHERE id='";
$sql .= self::$db->escape_string($this->id);
$sql .= "' LIMIT 1";
$result = self::$db->query($sql);
return $result;
//after deleting the instance is still around
//which is useful so you can say $this->poop was deleted
//but we cant call CRUD functions
}
}
?>
管理类:
<?php
class Admin extends DatabaseObject {
static protected $table_name = 'admins';
static protected $db_columns = ['id', 'first_name', 'last_name', 'email', 'username', 'hashed_password'];
public $id;
public $first_name;
public $last_name;
public $email;
public $username;
public $password;
public $confirm_password;
protected $hashed_password;
protected $password_required = true;
public function __construct($args = []){
$this->first_name = $args['first_name'] ?? '';
$this->last_name = $args['last_name'] ?? '';
$this->email = $args['email'] ?? '';
$this->username = $args['username'] ?? '';
$this->password = $args['password'] ?? '';
$this->confirm_password = $args['confirm_password'] ?? '';
}
public function label() {
return $this->username . " Name: " . $this->first_name . " " . $this->last_name;
}
private function hash_password(){
$this->hashed_password = password_hash($this->password, PASSWORD_BCRYPT);
}
protected function validate() {
$this->errors = parent::validate();
$this->errors[] = "foo";
if(is_blank($this->first_name)) {
$this->errors[] = "First name cannot be blank.";
} elseif (!has_length($this->first_name, array('min' => 2, 'max' => 255))) {
$this->errors[] = "First name must be between 2 and 255 characters.";
}
if(is_blank($this->last_name)) {
$this->errors[] = "Last name cannot be blank.";
} elseif (!has_length($this->last_name, array('min' => 2, 'max' => 255))) {
$this->errors[] = "Last name must be between 2 and 255 characters.";
}
if(is_blank($this->email)) {
$this->errors[] = "Email cannot be blank.";
} elseif (!has_length($this->email, array('max' => 255))) {
$this->errors[] = "Last name must be less than 255 characters.";
} elseif (!has_valid_email_format($this->email)) {
$this->errors[] = "Email must be a valid format.";
}
if(is_blank($this->username)) {
$this->errors[] = "Username cannot be blank.";
} elseif (!has_length($this->username, array('min' => 8, 'max' => 255))) {
$this->errors[] = "Username must be between 8 and 255 characters.";
}
if(is_blank($this->password)) {
$this->errors[] = "Password cannot be blank.";
} elseif (!has_length($this->password, array('min' => 12))) {
$this->errors[] = "Password must contain 12 or more characters";
} elseif (!preg_match('/[A-Z]/', $this->password)) {
$this->errors[] = "Password must contain at least 1 uppercase letter";
} elseif (!preg_match('/[a-z]/', $this->password)) {
$this->errors[] = "Password must contain at least 1 lowercase letter";
} elseif (!preg_match('/[0-9]/', $this->password)) {
$this->errors[] = "Password must contain at least 1 number";
} elseif (!preg_match('/[^A-Za-z0-9\s]/', $this->password)) {
$this->errors[] = "Password must contain at least 1 symbol";
}
if(is_blank($this->confirm_password)) {
$this->errors[] = "Confirm password cannot be blank.";
} elseif ($this->password !== $this->confirm_password) {
$this->errors[] = "Password and confirm password must match.";
}
return $this->errors;
}
protected function create() {
$this->hash_password();
$result = parent::create();
return $result;
}
protected function update(){
if($this->password != ''){
$this->hash_password();
} else {
$this->password_required = false;
}
$result = parent::update();
return $result;
}
}
?>
答案 0 :(得分:0)
在设置$ this-> errors之前,需要在CRUD或Admin类中将 errors 添加为属性。
答案 1 :(得分:0)
如果您希望调用父方法validate
,则应在代码中包含parent::validate();
。从您提供的代码来看,您的Admin类如下所示:
class Admin extends CRUD{
protected function validate(){
$this->errors = parent::validate();
//a bunch of error checking functions that work for post class
return $this->errors;
}
public function create(){
$this->hashpassword(); //just sets $this->password to a hash
return parent::create();
}
}
将parent::validate()
的结果分配给$this->errors
的原因是因为validate方法重置了$this->errors
数组,从而消除了所有错误。