如何扩展 CodeIgniter 数据库实用工具类


How to extend the CodeIgniter Database Utility Class

问题

当我更新我的 CodeIgniter 2.2.0 应用程序以使用mysqli数据库驱动程序时,它破坏了 CodeIgniter 的数据库实用程序类备份功能。 我曾经成功获取数据库备份的地方,现在出现错误...

您正在使用的数据库平台不支持的功能。

该错误仅表示数据库实用程序类中的 CodeIgniter 备份功能不支持 mysqli 。 根据在线文档,仅支持 MySQL。

但是,我不想使用已弃用的mysql数据库驱动程序。

<小时 />

可能的解决方法(不允许):

我认为我可以通过简单地扩展CodeIgniter的数据库实用程序类来解决这个问题。 但是,CodeIgniter 不允许根据文档执行此操作...

注: 数据库类不能扩展或替换为您自己的类。

<小时 />

另一种解决方法(致命错误):

编辑:我的答案和接受的答案基于此解决方法。

此 GitHub 页面介绍了通过创建MY_Loader类来扩展核心来扩展数据库类的方法。

https://github.com/bcit-ci/CodeIgniter/wiki/Extending-Database-Drivers

但是,当我尝试此解决方案时,我遇到了这个致命错误......

文件名: 核心/MY_Loader.php, 行号: 49

致命错误:在第 217 行调用/home/account/codeigniter/system/libraries/Session.php 中的未定义方法 CI_DB_mysqli_driver::where()

第 49 行是:$db =& new $my_driver(get_object_vars($db));

我完全按照上面的链接所述使用MY_LoaderMY_DB_mysqli_utility看起来像这样......

<?php class MY_DB_mysqli_utility extends CI_DB_mysqli_utility {
    function __construct($params){
        parent::__construct($params);
        log_message('debug', 'Extended DB driver class instantiated!');
    }
    function _backup($params = array())
    {
        // the working backup function is here
        .....
    }
}

我不完全确定这个 GitHub 解决方法是否失败了,因为它已经过时了,我忽略了一些东西,或者是否因为我试图在 CI_DB_mysqli_utility 上使用它而不是CI_DB_mysqli_driver

编辑:此解决方法失败,因为它仅用于扩展_driver而不是_utility...两个完全不同的功能。

<小时 />

工作解决方案(不理想):

我发现的唯一有效的解决方案是编辑CodeIgniter系统文件。 出于显而易见的原因,我宁愿不这样做。

位于system/database/drivers/mysqli/mysqli_utility.php的"损坏"备份功能如下...

function _backup($params = array())
{
    // Currently unsupported
    return $this->db->display_error('db_unsuported_feature');
}

有一个埃利斯实验室线程显示了有效的功能...

https://ellislab.com/forums/viewthread/194645/

我通过使用新的_backup功能编辑核心系统文件来使其工作。

function _backup($params = array())
{
    // the working backup function is here
    .....
}
<小时 />

那么我还能/应该在这里做什么?

mysqli驱动程序不支持CodeIgniter的备份功能,并且不允许我扩展CodeIgniter数据库实用程序,这使我别无选择,只能编辑核心系统文件。 我似乎被卡住了,我来这里看看我是否错过了什么,或者我是否可以做任何其他事情,而不是编辑核心系统文件。

<小时 />

编辑:请注意,CodeIgniter v3 中的数据库实用程序类完全支持 mysqli

基于@RandomSeed接受的解决方案...

我从 CodeIgniter 的 Loader 类中获取了 dbutil() 函数,并将其完全复制到我的自定义MY_Loader扩展中。

然后,它将从任何驱动程序加载默认实用程序文件,我只需将其重定向以检查位于我的application/libraries目录中的自定义数据库实用程序文件是否存在。 如果该文件存在,请使用它,否则使用默认文件。

MY_Loader.php

<?php class MY_Loader extends CI_Loader {
    public function dbutil()
    {
        if (! class_exists('CI_DB'))
        {
            $this->database();
        }
        $CI =& get_instance();
        // for backwards compatibility, load dbforge so we can extend dbutils off it
        // this use is deprecated and strongly discouraged
        $CI->load->dbforge();
        require_once(BASEPATH . 'database/DB_utility.php');
        // START custom >>
        // path of default db utility file
        $default_utility = BASEPATH . 'database/drivers/' . $CI->db->dbdriver . '/' . $CI->db->dbdriver . '_utility.php';
        // path of my custom db utility file
        $my_utility = APPPATH . 'libraries/MY_DB_' . $CI->db->dbdriver . '_utility.php';
        // set custom db utility file if it exists
        if (file_exists($my_utility))
        {
            $utility = $my_utility;
            $extend = 'MY_DB_';
        }
        else
        {
            $utility = $default_utility;
            $extend = 'CI_DB_';
        }
        // load db utility file
        require_once($utility);
        // set the class
        $class = $extend . $CI->db->dbdriver . '_utility';
        // << END custom
        $CI->dbutil = new $class();
    }
}

application/libraries/MY_DB_mysqli_utility.php

<?php
    class MY_DB_mysqli_utility extends CI_DB_utility {
    // everything in here is same as default mysqli_utility
    ....
    // EXCEPT the _backup() function is my own
    function _backup($params = array())
    {
        //  my custom backup code
        ....

我对这个解决方案非常满意,因为它让我的 CodeIgniter 核心文件完全保持不变。 如果我移动或忘记使用我的自定义实用程序文件,它将静默回退到默认驱动程序的实用程序文件。


编辑:请注意,CodeIgniter v3 中的数据库实用程序类完全支持mysqli否定了对此解决方法的任何需求。

涉及自定义加载程序(扩展数据库驱动程序)的解决方案与此相关:扩展数据库驱动程序。您不能只是将*_driver类替换为*_utility类。

$my_driver_file = APPPATH.'libraries/'.$my_driver.EXT; // *driver* required!!

相反,我会覆盖CI_Loader::dbutil()方法。这样的事情应该有效:

public function dbutil()
{
    /* snip for brevity */
    $class = config_item('subclass_prefix').'DB_'.$db->dbdriver.'_utility';
    $filename = APPPATH.'libraries/'.$class.EXT;
    require_once($filename);
    /* snip for brevity */
 }

免责声明:未经测试:)

数据库类不能扩展或替换为您自己的类。

这些类甚至不是final,所以我会忽略这个通知并派生我自己的驱动程序(根据DB.php行 140-143):

  • system/database/drivers/中创建一个新文件夹,例如 mysupersqli/
  • 创建一组mysupersqli_[driver|forge|result|utility].php文件
  • 在上面的每个文件中,声明一个类CI_DB_mysupersqli_[driver|forge|result|utility],扩展其CI_DB_mysqli_*对应项(CI_DB_mysupersqli_driver::$dbdriver应该被覆盖,根据自己的喜好覆盖其余部分)
  • 或者,残酷地复制/粘贴/搜索和替换system/database/drivers/mysqli的文件可能会更快(它还会使您的自定义驱动程序独立于内置的MySQLI驱动程序,这可能是也可能不是一件好事)
  • 现在您应该能够修改config/database.php到您的新驱动程序

免责声明:未经测试:)

由于内存和脚本超时,使用 php 进行数据库备份在某种程度上受到限制。如何创建一个使用 mysqldump 进行备份的 cronjob?

但是,如果这不是一个选项,也许这会有所帮助