扩展mysqli_result - 它是否使用store_result()或use_result()

时间:2016-12-25 19:02:34

标签: php mysqli php-mysqlidb

我用一个返回mysqli_result子节点的查询方法写了一个mysqli的孩子。此结果子项将具有我的应用程序独有的其他方法。

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;
    }
}

我无法弄清楚fetch_object()是否使用缓冲或无缓冲的SQL数据。

mysqli_result中看不到mysqli.php的构造函数,因此无法查看其是否正在调用$mysqli->store_result()$mysqli->use_result()

我尝试将这些方法添加到MySQL但两种功能都没有被回应。

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

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

这是否意味着mysqli_result构造函数也没有调用?如果是这样,在调用fetch_object时如何访问SQL数据?

................

我想要缓冲的SQL数据。如果我无法弄清楚子构造函数在做什么,我可能必须用调用$mysqli->store_result()的装饰器替换结果子类。

我是PHP / OOP的新手,非常感谢反馈。谢谢。

3 个答案:

答案 0 :(得分:1)

答案都不是。 mysqli_result 的构造函数不调用任何这些方法。但是,mysqli_query() 在内部调用 mysql_store_result()mysql_use_result(),它们是 C 级 API 函数。即使你扩展 mysqli 类,你也不会看到你的新方法被调用。您必须了解 mysqli 扩展是用 C 编写的,而不是用 PHP 编写的。代码的编写方式无法用 PHP 轻松表达。

如果您使用 mysqli::real_query() 来执行 SQL,那么您需要自行调用 mysqli_store_result()mysqli_use_result() 函数。当然,这些函数将返回 mysqli_result 对象而不是您的 MySQL_Result 对象。从这个类继承将是不可能的。

您可以使用组合代替继承。您将从这两个函数中获得的 mysqli_result 对象传递给 MySQL_Result 类的构造函数。

例如:

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;
    }
}

重要提示:您需要的功能已经在 PDO 中可用。如果您没有充分的理由使用 mysqli,请尝试使用 PDO。

答案 1 :(得分:0)

mysqli_result uses buffered results from MySQL(强调我的)

  

查询默认使用缓冲模式。这意味着查询结果会立即从MySQL服务器传输到PHP,然后保存在PHP进程的内存中。这允许额外的操作,例如计算行数,以及移动(寻找)当前结果指针。它还允许在处理结果集时在同一连接上发出进一步的查询。缓冲模式的缺点是较大的结果集可能需要相当多的内存。内存将保持占用状态,直到未设置对结果集的所有引用或显式释放结果集,这将在请求结束时自动发生。术语&#34;存储结果&#34;也用于缓冲模式,因为整个结果集一次存储。

这个过程就是这个

  1. 您执行查询。 MySQL发回结果
  2. mysqli_querymysqli_get_result(预编译语句)会将此数据集加载到mysqli_result对象
  3. 您实际上必须不遗余力地执行异步查询

答案 2 :(得分:0)

看来mysqli_result正在使用缓冲的SQL数据。

我写了一个测试用例,它交替访问两个查询中的行。如果数据是无缓冲的,则SQL服务器将很忙,无法回答第二个查询。

/* Open a connection */
$mysqli = new MysqlDB("127.0.0.1", "phpuser", "phpuserpw", "wishlist");
if (mysqli_connect_errno())
   return;

if ($result = $mysqli->query("SELECT * FROM wishers")) {

    $res2 = $mysqli->query("SELECT * FROM wishes");

    echo "Mem = ".memory_get_usage()."<br/>";

    while($row = $result->fetch_row()) {
        $row2 = $res2->fetch_row();

        printf ("1: ID=%s,  Name=%s, Pass=%s<br/>",$row[0],$row[1], $row[2]);
        printf ("2: ID=%s,  WisherID=%s<br/>", $row2[0], $row2[1]);

        echo "Row Mem = ".memory_get_usage()."<br/>";
    }

1:ID = 1,Name = Tom,Pass = tomcat

2:ID = 3,WisherID = 2

1:ID = 2,Name = Jerry,Pass = jerrymouse

2:ID = 4,WisherID = 2

1:ID = 6,Name = Tommy,Pass = tomcat

2:ID = 5,WisherID = 1

..........................

由于两个查询都有效,因此必须缓冲数据。