سلام به همه من طبق آموزش های خودتون دارم میرم جلو اما یه به یه مشکل بر خوردم من وقتی از قابلیت ارث بری استفاده می کنم کد های کلاس parent می افتن بالا و برای همین اون varriable هایی که توی کلاس child استفاده کردم میافته زیر اونا برای همین توی فانکشن های بالایی اون رو نمی شناسه و بعد از اون فانکشن ها تعریف می شن اول با متغیر table_name مشکل داشتم که اون رو رفتم بیرون کلاس child تعریف کردم و اینجوری درست شد حالا میخوام توی کلاس user که متغیر های id و username و password و first_name و last_name تعریف می شن هم یه کاری بکنم و اما باید بگم توی ویدیو های شما این کار روش کار می کنه وقتی که static کردمشون هم باز نشد.

کلاس `datbase_object

class DatabaseObject {
      protected static $table_name;
      protected static $db_fields;

      public static function find_all() {
          return static::find_by_sql("SELECT * FROM " . static::$table_name);
      }

      public static function find_by_id($id = 0) {
          $result_array = static::find_by_sql("SELECT * FROM " . static::$table_name . " WHERE id={$id} LIMIT 1");
          return !empty($result_array) ? array_shift($result_array) : false;
      }

      public static function find_by_sql($sql = "") {
          global $database;
          $result_set = $database->query($sql);
          $object_array = array();
          while ($row = $database->fetch_array($result_set)) {
              $object_array[] = static::instantiate($row);
          }
          return $object_array;
      }

      private static function instantiate($record) {
          // Could check that $record exists and is an array
          $class_name = get_called_class();
          $object = new $class_name;
          // Simple, long-form approach:
          // $object->id                = $record['id'];
          // $object->username  = $record['username'];
          // $object->password  = $record['password'];
          // $object->first_name = $record['first_name'];
          // $object->last_name     = $record['last_name'];
          // More dynamic, short-form approach:
          foreach ($record as $attribute => $value) {
              if ($object->has_attribute($attribute)) {
                  $object->$attribute = $value;
              }
          }
          return $object;
      }

      private function has_attribute($attribute) {
          // We don't care about the value, we just want to know if the key exists
          // Will return true or false
          return array_key_exists($attribute, $this->attributes());
      }

      protected function attributes() {
          // return an array of attribute keys and their values
          $attributes = array();
          foreach (static::$db_fields as $field) {
              if (property_exists($this, $field)) {
                  $attributes[$field] = $this->$field;
              }
          }
          return $attributes;
      }

      protected function sanitized_attributes() {
          global $database;
          $clean_attributes = array();
          // sanitize the values before submitting
          // Note: does not alter the actual value of each attribute
          foreach ($this->attributes() as $key => $value) {
              $clean_attributes[$key] = $database->escape_value($value);
          }
          return $clean_attributes;
      }

      public function save() {
          // A new record won't have an id yet.
          return isset($this->id) ? $this->update() : $this->create();
      }

      public function create() {
          global $database;
          // Don't forget your SQL syntax and good habits:
          // - INSERT INTO table (key, key) VALUES ('value', 'value')
          // - single-quotes around all values
          // - escape all values to prevent SQL injection
          $attributes = $this->sanitized_attributes();
          $sql = "INSERT INTO " . static::$table_name . " (";
          $sql .= join(", ", array_keys($attributes));
          $sql .= ") VALUES ('";
          $sql .= join("', '", array_values($attributes));
          $sql .= "')";
          if ($database->query($sql)) {
              $this->id = $database->insert_id();
              return true;
          } else {
              return false;
          }
      }

      public function update() {
          global $database;
          // Don't forget your SQL syntax and good habits:
          // - UPDATE table SET key='value', key='value' WHERE condition
          // - single-quotes around all values
          // - escape all values to prevent SQL injection
          $attributes = $this->sanitized_attributes();
          $attribute_pairs = array();
          foreach ($attributes as $key => $value) {
              $attribute_pairs[] = "{$key}='{$value}'";
          }
          $sql = "UPDATE " . static::$table_name . " SET ";
          $sql .= join(", ", $attribute_pairs);
          $sql .= " WHERE id=" . $this->id;
          $database->query($sql);
          return ($database->affected_rows() == 1) ? true : false;
      }

      public function delete() {
          global $database;
          // Don't forget your SQL syntax and good habits:
          // - DELETE FROM table WHERE condition LIMIT 1
          // - escape all values to prevent SQL injection
          // - use LIMIT 1
          $sql = "DELETE FROM " . static::$table_name;
          $sql .= " WHERE id=" . $this->id;
          $sql .= " LIMIT 1";
          $database->query($sql);
          return ($database->affected_rows() == 1) ? true : false;

          // NB: After deleting, the instance of User still
          // exists, even though the database entry does not.
          // This can be useful, as in:
          //   echo $user->first_name . " was deleted";
          // but, for example, we can't call $user->update()
          // after calling $user->delete().
      }
  }

و کلاس User

class User extends DatabaseObject {
      protected static $table_name = "users";
      public $id;
      public $username;
      public $password;
      public $first_name;
      public $last_name;

      public function full_name() {
          if (isset($this->first_name) && isset($this->last_name)) {
              return $this->first_name . " " . $this->last_name;
          } else {
              return "";
          }
      }

      public static function authenticate($username = "", $password = "") {
          global $database;
          $username = mysqli_real_escape_string($username);
          $password = mysqli_real_escape_string($password);

          $sql = "SELECT * FROM users ";
          $sql .= "WHERE username = '{$username}' ";
          $sql .= "AND password = '{$password}' ";
          $sql .= "LIMIT 1";
          $result_array = self::find_by_sql($sql);
          return !empty($result_array) ? array_shift($result_array) : false;
      }
  }

و فایل test که توی اون دارم کار ها رو انجام میدم.

<?php
require_once ("../../includes/config.php");
require_once ("../../includes/user.php");
require_once ("../../includes/database.php");
require_once ("../../includes/session.php");
require_once ("../../includes/functions.php");
require_once ("../../includes/logger.php");
?>
<?php include_layout_template("../layouts/admin_header.php") ?>
<?php
$user = User::find_by_id(3);
$user->password = "122";
$user->update();

?>
<?php include_layout_template("../layouts/admin_footer.php") ?>

این مشکل قبل از این که من کد ها رو بیارم توی database_object وجود نداشت پس فکر می کنم که اشکال از همین باشه

و اما ارور ها رو هم بگم که شاید از چیز دیگه ای بود بگید.

Warning: Creating default object from empty value in E:\wamp64\www\photo_gallery\public\admin\test.php on line 12

و

Fatal error: Call to undefined method stdClass::update() in E:\wamp64\www\photo_gallery\public\admin\test.php on line 13

بعد از این که کد های خودم درست کار نکرد رفتم و دقیقا کد های شما که توی فایل تمرینی بود کپی کردم اما باز هم کار نکرد.

خیلی ممنون می شم اگر کمک بکنید.