I’m wanting to create a new instance of my Class and assign it’s attributes the values that are returned. The reason for this is I’m creating a series of methods inheriting from the calling class, as opposed to using static methods which I already had working.
Example of what I’m using currently:
public static function findById($id) { $id = self::escapeParam($id); $idVal = is_int($id) ? "i" : "s"; $sql = "SELECT * FROM ".static::$db_table." WHERE id = ? LIMIT 1"; return static::findByQuery($sql,$idVal,$id); } public static function findByQuery($sql,$bindChar = '',$bindVal = '') { try { $callingClass = get_called_class(); $object = new $callingClass; $statement = Database::$connection->prepare($sql); if(!empty($bindChar)) : $statement->bind_param($bindChar, $bindVal); endif; if($statement->execute()) : $result = $statement->get_result(); $object = $result->fetch_object(); endif; $statement->close(); if(!empty($object)) : return $object; endif; } catch(Exception $e) { } }
What I tried was writing an instantiation method that creates a new instance of my class, and then assign each attribute of the object the value it returns from an array from a tutorial I did. However, the tutorial was fairly outdated and didn’t use any new syntax or binding, so I was trying to rework this.
Example from the tutorial below:
public static function find_by_id($id) { global $database; $the_result_array = static::find_by_query("SELECT * FROM " . static::$db_table . " WHERE id = $id LIMIT 1"); return !empty($the_result_array) ? array_shift($the_result_array) : false; } public static function find_by_query($sql) { global $database; $result_set = $database->query($sql); $the_object_array = array(); while($row = mysqli_fetch_array($result_set)) { $the_object_array[] = static::instantation($row); } return $the_object_array; } public static function instantation($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) { return property_exists($this, $the_attribute); }
What I was trying to do from the tutorial, was to return my result as an array using a while, and then assigning a variable by passing the built array into the static::instantation()
method, but it doesn’t seem to ever be working correctly, as any public functions I create in my calling class (Admin for example) aren’t called after as they don’t exist due to the Class not being instantiated.
Advertisement
Answer
mysqli_result::fetch_object()
accepts the class name as the first argument. You can pass the class name as an argument to that method and get the instance of the model. I am not sure why you have that much code but consider my example which I wrote based on your own code:
<?php class Model { public static function findByQuery(string $sql, ?string $bindChar = null, ?string $bindVal = null): ?static { $statement = Database::$connection->prepare($sql); if ($bindChar) : $statement->bind_param($bindChar, $bindVal); endif; $statement->execute(); $result = $statement->get_result(); return $result->fetch_object(static::class); } } class User extends Model { private $id; } class Database { public static mysqli $connection; } mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); Database::$connection = new mysqli('localhost', 'user', 'password', 'test'); $user = User::findByQuery('SELECT ? as id', 's', 'Dharman'); var_dump($user);
The output from that example is:
object(User)#4 (1) { ["id":"User":private]=> string(7) "Dharman" }
As you can see, the code created an instance of the class using late-static binding and it also assigned the value to a private property, which you can’t do otherwise.
P.S. My example is a little bit tidier. I added parameter typing and removed a lot of unnecessary code. In particular, I remove empty try-catch which is a terrible practice.