【问题标题】:Extend mysqli_result - Does it use store_result() or use_result()扩展 mysqli_result - 它使用 store_result() 还是 use_result()
【发布时间】:2016-12-25 19:02:34
【问题描述】:

我用一个返回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-&gt;store_result() 的装饰器。

【问题讨论】:

    标签: php mysqli


    【解决方案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。

    【讨论】:

      【解决方案2】:

      mysqli_resultuses buffered results from MySQL(强调我的)

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

      流程是这样的

      1. 您执行查询。 MySQL 发回结果
      2. mysqli_querymysqli_get_result(准备好的语句)会将此数据集加载到 mysqli_result 对象中

      您实际上必须不遗余力地执行异步查询

      【讨论】:

      • 除了我在MySQL中重载了“查询”方法并调用了real_query()。因此,SQL 不会返回任何内容。返回必须发生在 mysqli_result 构造函数或 fetch_object() 中。
      【解决方案3】:

      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,名称=Tom,Pass=tomcat

      2:ID=3,WisherID=2

      1:ID=2,名称=Jerry,Pass=jerrymouse

      2:ID=4,WisherID=2

      1:ID=6,名称=Tommy,Pass=tomcat

      2:ID=5,WisherID=1

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

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

      【讨论】:

        猜你喜欢
        • 2017-03-03
        • 1970-01-01
        • 2012-01-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-28
        相关资源
        最近更新 更多