2017-09-01 50 views
0

我的想法是创建一个父类Db_object并将一些方法用于子类。我第一次提出的子类用户和测试所有的方法,他们都工作得很好,但是当我尝试使用其他类(照片)类相同的方法,我不能用create()update() & delete()无法在第二个子类中使用父类方法

我是编程新手,没有太多经验。以下是我迄今所做:

Db_object(家长):

<?php 
class Db_object 
{ 
    public static function find_all() 
    { 
     return static::find_by_query("SELECT * FROM " . static::$db_table . " "); 
    } 

    public static function find_by_id($user_id) 
    { 
     global $database; 

     $test_array = array(); 

     $the_result_array = static::find_by_query("SELECT * FROM " . static::$db_table . " WHERE id=$user_id LIMIT 1"); 
     return !empty($the_result_array) ? array_shift($the_result_array) : $test_array; 
    } 

    public static function find_by_query($sql) 
    { 
     global $database; 
     $result_set = $database->query($sql); 

     //We created an empty array, so that we can store values in it 
     $the_object_array = array(); 

     /*if($result_set === FALSE) 
     { 
      die("Error: " . mysqli_error()); 
     } 

     if (!empty($result_set)) 
     {*/ 
      // We use while loop to fetch the database table 
      while($row = mysqli_fetch_array($result_set)) 
      { 

       $the_object_array[] = static::instantiation($row); 
      } 
     /*}*/ 
     return $the_object_array; 
    } 

    //instantiation method loops through the databse record & assign those to object properties. 
    public static function instantiation($the_record) 
    { 
     $calling_class = get_called_class(); 
     $the_object = new $calling_class; 

     foreach ($the_record as $the_attribute => $value) 
     { 
      if($the_object->has_the_attribute($the_attribute)) 
      { 
       $the_object->$the_attribute = $value; 
      } 
     } 
     return $the_object; 
    } 

    private function has_the_attribute($the_attribute) 
    { 
     $object_properties = get_object_vars($this); 

     return array_key_exists($the_attribute, $object_properties); 
    } 

    //Method to get all the properties. 
    protected function properties() 
    { 
     $properties = array(); 
     foreach (static::$db_table_fields as $db_field) 
     { 
      if (property_exists($this, $db_field)) 
      { 
       $properties[$db_field] = $this->$db_field; 
      } 
     } 
     return $properties; 
    } 

    //We are looping through protected static $db_table_fields. 
    protected function clean_properties() 
    { 
     global $database; 

     $clean_properties = array(); 

     foreach($this->properties() as $key => $value) 
     { 
      $clean_properties[$key] = $database->escape_string($value); 
     } 
     return $clean_properties; 
    } 

    public function save() 
    { 
     return isset($this->id) ? $this->update() : $this->create(); 
    } 

    public function create() 
    { 
     global $database; 

     $properties = $this->clean_properties(); 

     $sql = "INSERT INTO " . static::$db_table . "(" . implode(",", array_keys($properties)) . ")"; 
     $sql .= "VALUES ('" . implode("','", array_values($properties)) . "')"; 

     if ($database->query($sql)) 
     { 
      //This method is responsible for pulling up the last query, then assigmimg the id to the object. 
      $this->id = $database->the_insert_id(); 
      return true; 
     } 
     else 
     { 
      return false; 
     } 
    } 

    public function update() 
    { 
     global $database; 

     $properties = $this->clean_properties(); 
     $property_pairs = array(); 

     foreach ($properties as $key => $value) 
     { 
      $property_pairs[] = "{$key}='{$value}'"; 
     } 

     $sql = "UPDATE " . static::$db_table . " SET "; 
     $sql .= implode(", ", $property_pairs); 
     $sql .= " WHERE id= " . $database->escape_string($this->id); 

     $database->query($sql); 
     return (mysqli_affected_rows($database->connection) == 1) ? true : false; 
    } 

    public function delete() 
    { 
     global $database; 

     $sql = "DELETE FROM " . static::$db_table . " "; 
     $sql .= "WHERE id=" . $database->escape_string($this->id); 
     $sql .= " LIMIT 1"; 

     $database->query($sql); 
     return (mysqli_affected_rows($database->connection) == 1) ? true : false; 
    } 
} 
?> 

用户(一切似乎做工精细):

<?php 
include ("init.php"); 

class User extends Db_object 
{ 
    protected static $db_table = "users"; 
    protected static $db_table_fields = array('username', 'password', 'first_name', 'last_name'); 
    public $id; 
    public $username; 
    public $password; 
    public $first_name; 
    public $last_name; 

    public static function verify_user($username, $password) 
    { 
     global $database; 

     //To senatize Username & Password. 
     $username = $database->escape_string($username); 
     $password = $database->escape_string($password); 

     $sql = "SELECT * FROM " . self::$db_table . " WHERE "; 
     $sql .= "username = '{$username}' "; 
     $sql .= "AND password = '{$password}' "; 
     $sql .= "LIMIT 1"; 

     $the_result_array = self::find_by_query($sql); 
     return !empty($the_result_array) ? array_shift($the_result_array) : false; 
    } 
} 
?> 

照片(创建,更新和删除不起作用):

<?php 
//include ("init.php"); 

class Photo extends Db_object 
{ 
    protected static $db_table = "photos"; 
    protected static $db_table_fields = array('photo_id', 'title', 'description', 'file_name', 'type', 'size'); 
    public $photo_id; 
    public $title; 
    public $description; 
    public $file_name; 
    public $type; 
    public $size; 


} 
?> 

而且,这是query()方法,从数据库类:

public function query($sql) 
    { 
     $result = mysqli_query($this->connection, $sql); 
     return $result; 
    } 

我没有得到任何类型的错误。如果代码中有任何混淆,请问,我会尽力解释。

+0

你可以分享你的错误代码的一部分吗? – iwaduarte

+0

根据我的说法,错误应该在这个方法中:'public static function find_by_query($ sql) { global $ database; $ result_set = $ database-> query($ sql); $ the_object_array = array(); 而($行= mysqli_fetch_array($ result_set)) { $ the_object_array [] =静态::实例化($行); } return $ the_object_array; }' – user8077853

+0

我会从不使用'$ database'作为全局。我会注入或静态连接。' – Rasclatt

回答

0

继我的评论,看看这些修改是否适合你。我不明白你为什么在课堂上制作动态属性,我不认为这是完全必要的。它主要muddies了类,并使其更难管理:

class DbObject 
    { 
     # Put the base properties in the parent class 
     private static $database; 
     protected $db_table_fields = array(); 
     protected $db_table, 
        $properties; 

     public function __construct() 
     { 
      # Fetch any arguments into the construct 
      $args = func_get_args(); 
      # If a database is passed, assign it 
      if(!empty($args[0]) && is_a($args[0],'mysqli')) 
       self::$database = $args[0]; 
     } 
     # Create a db connection retrieval method 
     public function getDb() 
     { 
      # I use PDO, but I think the instanceof MySQLi is correct... 
      $con = (self::$database instanceof mysqli)? self::$database : false; 
      # If not assigned, throw error 
      if(!$con) 
       throw new Exception('Database is not set.'); 

      return $con; 
     } 
     # I renamed your methods to camel case 
     public function findAll() 
     { 
      if(empty($this->db_table)) 
       throw new Exception('Table name is not set yet.'); 

      return (empty($this->db_table))? false : $this->findByQuery("SELECT * FROM " . $this->db_table . " "); 
     } 
     # Remove static 
     public function findById($user_id) 
     { 
      $test_array = array(); 
      # If you don't bind, at least check it's numeric 
      if(!is_numeric($user_id)) 
       return $test_array(); 

      $the_result_array = $this->findByQuery("SELECT * FROM " . $this->db_table . " WHERE id={$user_id} LIMIT 1"); 
      return !empty($the_result_array) ? array_shift($the_result_array) : $test_array; 
     } 
     # Remove static 
     public function findByQuery($sql) 
     { 
      $database = $this->getDb(); 
      $result_set = $database->query($sql); 
      # We created an empty array, so that we can store values in it 
      $the_object_array = array(); 
      // We use while loop to fetch the database table 
      while($row = mysqli_fetch_assoc($result_set)) { 
       $the_object_array[] = $row; 
      } 
      return $the_object_array; 
     } 
     //Method to get all the properties. 
     protected function properties() 
     { 
      $this->properties = array(); 

      if(empty($this->db_table_fields) || !is_array($this->db_table_fields)) 
       return $this->properties; 

      foreach($this->db_table_fields as $db_field) { 
       if (!isset($this->properties[$db_field])) { 
        $this->properties[$db_field] = $this->db_field; 
       } 
      } 

      return $this->properties; 
     } 

     protected function cleanProperties() 
     { 
      $database = $this->getDb(); 
      $clean_properties = array(); 

      foreach($this->properties() as $key => $value) { 
       $clean_properties[$key] = $database->escape_string($value); 
      } 
      return $clean_properties; 
     } 

     public function save() 
     { 
      return isset($this->id) ? $this->update() : $this->create(); 
     } 

     public function create() 
     { 
      $database = $this->getDb(); 
      $properties = $this->cleanProperties(); 

      $sql = "INSERT INTO " . $this->db_table . "(" . implode(",", array_keys($properties)) . ")"; 
      $sql .= "VALUES ('" . implode("','", array_values($properties)) . "')"; 

      if ($database->query($sql)) { 
       $this->id = $database->the_insert_id(); 
       return true; 
      } 
      else { 
       return false; 
      } 
     } 

     public function update() 
     { 
      $database = $this->getDb(); 
      $properties = $this->cleanProperties(); 
      $property_pairs = array(); 

      foreach ($properties as $key => $value) { 
       $property_pairs[] = "{$key}='{$value}'"; 
      } 

      $sql = "UPDATE " . $this->db_table . " SET "; 
      $sql .= implode(", ", $property_pairs); 
      $sql .= " WHERE id= " . $database->escape_string($this->id); 

      $database->query($sql); 
      return (mysqli_affected_rows($database->connection) == 1) ? true : false; 
     } 

     public function delete() 
     { 
      $database = $this->getDb(); 
      $sql = "DELETE FROM " . $this->db_table . " "; 
      $sql .= "WHERE id=" . $database->escape_string($this->id); 
      $sql .= " LIMIT 1"; 
      $database->query($sql); 
      return (mysqli_affected_rows($database->connection) == 1); 
     } 

     public function getTableFields() 
     { 
      return $this->db_table_fields; 
     } 

     public function describe() 
     { 
      return $this->findByQuery("describe ".$this->db_table); 
     } 
    } 


class User extends DbObject 
    { 
     protected $db_table = "users"; 
     protected $db_table_fields = array('username', 'password', 'first_name', 'last_name'); 
     private $id, 
       $username, 
       $password, 
       $first_name, 
       $last_name; 

     public function verifyUser($username, $password) 
     { 
      try { 
       $database = $this->getDb(); 
       //To senatize Username & Password. 
       $username = $database->escape_string($username); 
       $password = $database->escape_string($password); 

       $sql = "SELECT * FROM " . $this->db_table . " WHERE "; 
       $sql .= "username = '{$username}' "; 
       $sql .= "AND password = '{$password}' "; 
       $sql .= "LIMIT 1"; 

       $the_result_array = $this->findByQuery($sql); 
      } 
      catch (Exception $e) { 
       trigger_error($e->getMessage(),E_USER_NOTICE); 
      } 

      return !empty($the_result_array) ? array_shift($the_result_array) : false; 
     } 
    } 

class Photo extends DbObject 
    { 
     protected $db_table = "photos"; 
     protected $db_table_fields = array('photo_id', 'title', 'description', 'file_name', 'type', 'size'); 
     private $photo_id, 
       $title, 
       $description, 
       $file_name, 
       $type, 
       $size; 
    } 

使用方法:

# Create the database connection 
$MySql = new MySQLi('localhost','username','password','dbname'); 
# Create instance of User pass database 
$User = new User($MySql); 
# Create instance of Photo. Since db is static, you don't have pass database 
# into subsequent extended classes 
$Photo = new Photo(); 
# Describe user table 
print_r($User->describe()); 
# Describe photos table 
print_r($Photo->describe());