简体   繁体   English

如何扩展CodeIgniter数据库实用程序类

[英]How to extend the CodeIgniter Database Utility Class

Problem : 问题

When I updated my CodeIgniter 2.2.0 application to use the mysqli database drivers, it broke CodeIgniter's backup function of the Database Utility Class . 当我更新我的CodeIgniter 2.2.0应用程序以使用mysqli数据库驱动程序时,它破坏了CodeIgniter的Database Utility Class备份功能 Where I used to successfully get a database backup, I'm now getting an error... 我以前成功获得数据库备份的地方,我现在收到错误...

Unsupported feature of the database platform you are using. 您正在使用的数据库平台不支持的功能。

The error simply means that the CodeIgniter backup function from the Database Utility Class does not support mysqli . 该错误只是意味着Database Utility Class中的CodeIgniter备份功能不支持mysqli As per the online docs, only MySQL is supported. 根据在线文档,仅支持MySQL。

However, I prefer not to use the deprecated mysql database driver. 但是,我不想使用已弃用的mysql数据库驱动程序。


Possible Workaround (not allowed) : 可能的解决方法(不允许)

I thought I could solve this by simply extending CodeIgniter's Database Utility class. 我想我可以通过简单地扩展CodeIgniter的Database Utility类来解决这个问题。 However, CodeIgniter does not allow this as per documentation ... 但是, CodeIgniter根据文档不允许这样做 ......

Note: The Database classes can not be extended or replaced with your own classes. 注意:数据库类不能扩展或替换为您自己的类。


Another Workaround (fatal error) : 另一种解决方法(致命错误)

EDIT: my answer and the accepted answer are based on this workaround. 编辑: 我的答案接受的答案是基于这种解决方法。

This GitHub page describes a method for extending the Database Class by creating a MY_Loader class to extend the core. 此GitHub页面描述了通过创建MY_Loader类来扩展核心来扩展数据库类的方法。

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

However, when I attempted this solution, I got this fatal error... 但是,当我尝试这个解决方案时,我得到了这个致命错误......

Filename: core/MY_Loader.php, Line Number: 49 文件名:core / MY_Loader.php,行号:49

Fatal error: Call to undefined method CI_DB_mysqli_driver::where() in /home/account/codeigniter/system/libraries/Session.php on line 217 致命错误:在第217行的/home/account/codeigniter/system/libraries/Session.php中调用未定义的方法CI_DB_mysqli_driver :: where()

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

I am using the MY_Loader exactly as described at the link above, and MY_DB_mysqli_utility looks like this... 我完全按照上面的链接描述使用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
        .....
    }

}

( I'm not entirely sure if this GitHub workaround is failing because it's out of date, I overlooked something, or if it's because I'm trying to use it on CI_DB_mysqli_utility instead of CI_DB_mysqli_driver . ) 我不完全确定这个GitHub解决方法是否失败,因为它已经过时,我忽略了一些东西,或者是因为我试图在CI_DB_mysqli_utility而不是CI_DB_mysqli_driver上使用它。

EDIT : this workaround was failing because it was meant only for extending the _driver and not the _utility ... two completely different functions. 编辑 :这个解决方法是失败的,因为它只是为了扩展_driver而不是_utility ...两个完全不同的功能。


A Working Solution (not ideal) : 工作解决方案(不理想)

The only working solution I've found has been to edit the CodeIgniter System files. 我发现的唯一可行解决方案是编辑CodeIgniter系统文件。 For obvious reasons, I'd prefer not to do this. 出于显而易见的原因,我宁愿不这样做。

The "broken" backup function located at system/database/drivers/mysqli/mysqli_utility.php is as follows... 位于system/database/drivers/mysqli/mysqli_utility.php的“损坏”备份功能如下......

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

There is an Ellis Lab thread that shows a function that works... 有一个Ellis Lab线程显示一个有效的功能......

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

I got it working by editing the core system file with the new _backup function. 我通过使用新的_backup函数编辑核心系统文件来实现_backup

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

So what else can/should I do here? 那么我还能/我应该做什么呢?

CodeIgniter's backup function is not supported by the mysqli driver, and I'm not allowed to extend the CodeIgniter Database Utility, leaving me with no alternative but to edit the core system files. mysqli驱动程序不支持CodeIgniter的备份功能,我不允许扩展CodeIgniter数据库实用程序,让我别无选择,只能编辑核心系统文件。 I seem to be stuck and I'm coming here to see if I missed anything or if there's anything else I can do instead of editing the core system files. 我好像被卡住了,我来这儿看我是否错过了什么,或者我还能做什么,而不是编辑核心系统文件。


EDIT : Note that the Database Utility Class in CodeIgniter v3 fully supports mysqli . 编辑 :请注意CodeIgniter v3中的数据库实用程序类完全支持mysqli

Based on accepted solution by @RandomSeed ... 基于@RandomSeed公认的解决方案 ......

I took the dbutil() function from CodeIgniter's Loader class and copied it exactly into my custom MY_Loader extension. 我从CodeIgniter的Loader类中获取了dbutil()函数,并将其完全复制到我的自定义MY_Loader扩展中。

Then where it would load the default utility file from whichever driver, I simply redirected it to check for the existence of my custom database utility file located in my application/libraries directory. 然后,它将从任何驱动程序加载默认实用程序文件,我只是重定向它以检查我的application/libraries目录中是否存在我的自定义数据库实用程序文件。 If the file exists, use it, otherwise use the default file. 如果文件存在,请使用它,否则使用默认文件。

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
        ....

I'm very happy with this solution as it leaves my CodeIgniter core files completely untouched. 我对这个解决方案非常满意,因为它使我的CodeIgniter核心文件完全不受影响。 If I move or forget to use my custom utility file, it silently falls back to the default driver's utility file. 如果我移动或忘记使用我的自定义实用程序文件,它会无声地回退到默认驱动程序的实用程序文件。


EDIT : Note that the Database Utility Class in CodeIgniter v3 fully supports mysqli negating any need for this workaround. 编辑 :请注意CodeIgniter v3中的数据库实用程序类完全支持mysqli否定对此变通办法的任何需要。

The Database classes can not be extended or replaced with your own classes. 数据库类不能扩展或替换为您自己的类。

These classes are not even final , so I would just ignore this notice and derive my own driver (as per DB.php lines 140-143): 这些类甚至都不是final ,所以我会忽略这个通知并派生出我自己的驱动程序(根据DB.php行):

  • create a new folder in system/database/drivers/ , eg mysupersqli/ system/database/drivers/创建一个新文件夹,例如mysupersqli/
  • create a set of files mysupersqli_[driver|forge|result|utility].php 创建一组文件mysupersqli_[driver|forge|result|utility].php
  • in each above file, declare a class CI_DB_mysupersqli_[driver|forge|result|utility] that extends its CI_DB_mysqli_* counterpart ( CI_DB_mysupersqli_driver::$dbdriver should be overriden , override the rest to your liking) 在每个上面的文件中,声明一个扩展其CI_DB_mysqli_*对应的类CI_DB_mysupersqli_[driver|forge|result|utility]应覆盖 CI_DB_mysupersqli_driver::$dbdriver ,根据自己的喜好覆盖其余部分)
  • alternatively, a brutal copy/paste/search&replace of the files from system/database/drivers/mysqli might be quicker (it would also make your custom driver independant from the the built-in mysqli driver, which may or may not be a good thing) 或者,一个残酷的复制/粘贴/搜索和替换system/database/drivers/mysqli中的文件可能会更快(它也会使你的自定义驱动程序独立于内置的mysqli驱动程序,这可能是也可能不是一件好事)
  • now you should be able to modify config/database.php to your new driver 现在你应该能够将config/database.php修改为你的新驱动程序

Disclaimer: not tested :) 免责声明:未经测试:)

The solution involving a custom loader ( Extending Database Drivers ) is relevant to just that: extending database drivers. 涉及自定义加载器( 扩展数据库驱动程序 )的解决方案仅与以下内容相关:扩展数据库驱动程序。 You can't just replace a *_driver class with an *_utility class. 你不能只用*_utility类替换*_driver类。

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

Instead, I would override the CI_Loader::dbutil() method . 相反,我会覆盖CI_Loader::dbutil()方法 Something like this should work: 这样的事情应该有效:

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 */
 }

Disclaimer: not tested :) 免责声明:未经测试:)

Since making a db backup with php is somehow limited due to memory and script timeout. 由于内存和脚本超时,因为使用php进行数据库备份在某种程度上受限制。 How about creating a cronjob doing backups with mysqldump? 如何创建一个使用mysqldump进行备份的cronjob?

However if this is not an option maybe this helps 但是,如果这不是一个选项, 可能会有所帮助

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM