【问题标题】:Extend mysqli_result扩展 mysqli_result
【发布时间】:2017-03-03 02:20:42
【问题描述】:

我已经扩展了 PHP 的 mysqli 类,它工作正常。但是如何让它在查询时返回一个自定义结果对象(或用于插入/更新/删除等的布尔值)?

namespace MyApp;
class MySQLi extends \mysqli {
    public function query($query, $resultmode = null) {
        // This needs to return a MySQLiResult or a boolean
    }
}
class MySQLiResult extends \mysqli_result {
}

这样做我可以返回一个 MySQLiResult 对象,但我不知道如何为非基于选择的查询返回一个布尔值:

public function query($query, $resultmode = null) {
    $this->real_query($query); 
    return new MySQLiResult($this);
}

更新:

这是我最终使用的:

class MySQLi extends \mysqli {

    public function query($query, $resultmode = null) {
        $result = parent::query($query, $resultmode);
        return is_bool($result) ? $result : new MySQLiResult($result);
    }

}


class MySQLiResult {

    private $result;

    public function __construct(mysqli_result $result) {
        $this->result = $result;
    }

    public function __call($name, $arguments) {
        return call_user_func_array(array($this->result, $name), $arguments);
    }

    public function __set($name, $value) {
        $this->result->$name = $value;
    }

    public function __get($name) {
        return $this->result->$name;
    }

}

【问题讨论】:

    标签: php oop mysqli


    【解决方案1】:

    可能最简单的做法是将您的MySQLiResult 类视为mysqli_result 的装饰器。例如

    class MySQLiResult
    {
        private $result;
    
        public function __construct(\mysqli_result $result)
        {
            $this->result = $result;
        }
    }
    

    然后您可以将方法调用代理到内部结果并在需要时进行装饰(添加功能)。

    【讨论】:

    • 没错,不过我试图避免这样做。
    • @Petah 您仍然可以扩展 mysqli_result,但是如果不先获得正常结果然后对其进行调整,我无法看到返回您的课程。
    • 你可以,如果你使用$this->real_query($query); return new MySQLiResult($this);,但是对于非基于选择的查询不会返回布尔值。
    • @Peta you 可以使用它(这是您的问题)。我使用 PDO ;)
    • 不是我想要的,但足够接近
    【解决方案2】:

    Phil 的回答是可以的,但是可以通过检查mysqli::field_count 来扩展 MySQLi_Result。 查看documentation 以获取mysqli::field_count

    在使用 mysqli_store_result() 函数来确定查询是否应该在不知道查询性质的情况下产生非空结果集时,此函数很有用。

    这正是我们所需要的。

    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;
            }
    
            throw new MySQL_Exception($this->error, $this->errno);
        }
    }
    

    现在您可以从 MySQLi_Result 扩展您的结果类并实现一些有用的接口,例如 SeekableIterator,以便您可以在结果集上使用 foreach

    class MySQL_Result extends MySQLi_Result implements Countable, SeekableIterator, ArrayAccess
    {
        ...
    }
    

    【讨论】:

    • 从 PHP v5.4+ 开始,mysqli_result 实现了 Traversable 接口,因此已经能够使用像 foreach($mysqli->query($SQL) as $row){...} 这样的 foreach 循环语法遍历结果集
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-12
    • 2019-02-25
    • 2020-09-10
    • 2014-09-23
    • 2020-12-11
    相关资源
    最近更新 更多