PHP inheretance在一个实例上工作而不在另一个实例上工作

时间:2018-10-30 14:35:49

标签: php oop inheritance

我有一个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;
  }
}
?>

2 个答案:

答案 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数组,从而消除了所有错误。