1

When using mysqli_fetch_object(), you can pass the name of an object as the second parameter. By doing so, mysqli creates the corresponding object and automatically sets the variables.

objectname {

// No defined properties

}

(...)

$object = mysqli_fetch_object($result, "objectname");

Under the assumption that $result contains data for "forname" and "surname", we would now have access to:

$object->forename;
$object->surname;

Is it possible to fetch the data into an associative array instead? Like shown here:

objectname {
    public $data = array();
}

(...)

$object = mysqli_fetch_object($result, "objectname");

And then having:

$object->data["forename"];
$object->data["surname"];

If not: What is the code, MySQLi uses to populate the object with mysqli_fetch_object()? Considering that MySQLi is even able to change predefined private variables, it is a total mystery for me.

  • Can you clarify what you are after as there have been a few answers which have been removed due to what is a perceived misunderstanding. Do you want to know how the code has access to private variables, how to return the result set as an array instead? – Nigel Ren Jan 30 '21 at 12:50
  • @NigelRen The goal is to fetch an object with the data as an array that is a property of the object. – Dharman Jan 30 '21 at 12:52
  • So isn't that something like `mysqli_fetch_array()` - followed by assign to object(constructor or otherwise)? – Nigel Ren Jan 30 '21 at 12:55
  • Correct me if i'm wrong, but I think the only way to do this would be to create an object, then do:-----------"$object->data = mysqli_fetch_assoc($result)" *basically as @NigelRen has just said, creating the object and assigning the assoc array to it* – Matthew Swallow Jan 30 '21 at 12:55
  • @NigelRen That would be a valid workaround. However, the property would be public in this case. The goal is to get an object with array `$data` as a private property – Dharman Jan 30 '21 at 12:56
  • 2
    @Dharman, being passed to a constructor or set method would allow control over the scope of the data. My point has been that if current answers have misunderstood the issue, I wanted to try and clarify it to help in useful answers being added (hopefully). – Nigel Ren Jan 30 '21 at 12:58
  • @NigelRen Feel free to add an answer now that you understand it. – Dharman Jan 30 '21 at 13:00
  • This sound like an odd thing to achieve, may I ask **why** you are trying to do that? Almost sounds like you would be happier with a [data transfer object](https://stackoverflow.com/questions/1051182/what-is-a-data-transfer-object-dto) – ArSeN Jan 30 '21 at 13:50
  • @ArSeN The idea is having all data retrived from the database in an array called $data. Then, right after the constructor was called, to create a copy of the $data array named $backup. Now the data saved in $data can be modified a lot. At the end of the script, there will be one call to a method named save(). That method checks for differences between $data and $backup and temporarily stores all changed columns in another $modified array. Finally, with the help of mysqli_query("UPDATE ... SET ".implode(', ', $modified).""), you can only updated modified data. And all at once, in one query. – shuunenkinenbi Jan 30 '21 at 14:51
  • I see! Thanks for the explanation. That makes sense - however: It sounds a lot to me like a functionality that an [Active Record model](https://stackoverflow.com/questions/1404405/what-is-the-purpose-of-active-records) would have and I'd recommend actually writing classes for this instead of trying to handle this with stdClass objects. – ArSeN Jan 30 '21 at 16:20

1 Answers1

1

Unfortunately, you can't do it with mysqli. Usually, I would recommend PDO in such situations but even PDO doesn't have such capability.

There is a workaround though. You can create your own class with a constructor and a private property.

class MyClass
{
    public function __construct(private array $data) {}
}

$stmt = $mysqli->prepare('SELECT id, name FROM users');
$stmt->execute();
$result = $stmt->get_result();

$data = [];
foreach ($result as $row) {
    $data[] = new MyClass($row);
}
var_dump($data);

In the code above I am iterating over the result set and creating a new object passing the row each time as a constructor argument. You can control the visibility of the property using this approach.

P.S. If you are using PHP 7 then you can define the class this way:

class MyClass
{
    private array $data;

    public function __construct(array $data)
    {
        $this->data = $data;
    }
}
Dharman
  • 30,962
  • 25
  • 85
  • 135