Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extend mysqli_result - Does it use store_result() or use_result()

Tags:

php

mysqli

I wrote a child of mysqli with a query method that returns a child of mysqli_result. This result child will have additional methods unique to my app.

public MySQL extends mysqli
{
    public function query($query)
    {
        if ($this->real_query($query)) {
            if ($this->field_count > 0) {
                return new MySQL_Result($this);
            }
            return true;
        }
        return false;
    }

}

class MySQL_Result extends mysqli_result
{
    public function fetch_objects() {
        $rows = array();
        while($row = $this->fetch_object())
            $rows[$row->id] = $row;
        return $rows;
    }
}

What I can't figure out is whether fetch_object() uses buffered or unbuffered SQL data.

The constructor of mysqli_result isn't visible in mysqli.php, so I can't see if its calling $mysqli->store_result() or $mysqli->use_result().

I tried adding these methods to MySQL but neither function is echoed.

    public function store_result($option='a') {
        echo "STORE RESULT<br/>";
    }

    public function use_result($option='a') {
        echo "USE RESULT<br/>";
    }

Does this mean that the mysqli_result constructor doesn't call either? If so, how does it access the SQL data when fetch_object is called?

I want buffered SQL data. If I can't figure out what the child constructor is doing, I may have to replace the result child class with a decorator that calls $mysqli->store_result().

like image 553
Nick Avatar asked Nov 26 '22 03:11

Nick


1 Answers

The answer is neither. The constructor of mysqli_result doesn't call any of these methods. However, mysqli_query() internally calls mysql_store_result() or mysql_use_result() which are C level API functions. Even if you extend mysqli class, you won't see your new methods getting called though. You have to understand that mysqli extension is written in C, not in PHP. The way that the code is written cannot be expressed in PHP very easily.

If you are using mysqli::real_query() to execute SQL then you need to take care of calling either mysqli_store_result() or mysqli_use_result() function yourself. Of course, these functions will return mysqli_result object instead of your MySQL_Result one. It's going to be impossible to inherit from this class.

You can use composition instead of inheritance. You would pass mysqli_result object you get from either of these two functions into the constructor of your MySQL_Result class.

For example:

class MySQL
{
    private mysqli $mysqli;

    public function __construct(string $host, string $username, string $passwd, string $dbname)
    {
        $this->mysqli = new mysqli($host, $username, $passwd, $dbname);
    }

    public function query(string $query): MySQL_Result | bool
    {
        if ($this->mysqli->real_query($query)) {
            if ($this->mysqli->field_count > 0) {
                return new MySQL_Result($this->mysqli->store_result());
            }
            return true;
        }
        return false;
    }
}

class MySQL_Result
{
    public function __construct(private mysqli_result $result)
    {
    }

    public function fetch_objects()
    {
        $rows = array();
        while ($row = $this->result->fetch_object()) {
            $rows[$row->id] = $row;
        }
        return $rows;
    }
}

Important: The functionality that you require is already available with PDO. If you don't have a good reason to use mysqli, try using PDO instead.

like image 110
Dharman Avatar answered Dec 23 '22 23:12

Dharman