如何扩展 CodeIgniter 数据库实用程序类
Posted
技术标签:
【中文标题】如何扩展 CodeIgniter 数据库实用程序类【英文标题】:How to extend the CodeIgniter Database Utility Class 【发布时间】:2015-01-22 20:12:13 【问题描述】:问题:
当我更新我的 CodeIgniter 2.2.0 应用程序以使用 mysqli
数据库驱动程序时,它破坏了 CodeIgniter 的 backup function of the Database Utility Class。我曾经成功获得数据库备份的地方,现在却出现错误...
您正在使用的数据库平台的功能不受支持。
该错误仅表示数据库实用程序类中的 CodeIgniter 备份功能不支持mysqli
。根据在线文档,仅支持 MySQL。
但是,我不想使用已弃用的 mysql
数据库驱动程序。
可能的解决方法(不允许):
我想我可以通过简单地扩展 CodeIgniter 的 Database Utility 类来解决这个问题。但是,CodeIgniter does not allow this as per documentation...
注意:数据库类不能扩展或替换为您自己的类。
另一种解决方法(致命错误):
编辑:my answer 和 the accepted answer 基于此解决方法。
此 GitHub 页面描述了一种通过创建 MY_Loader
类来扩展核心来扩展数据库类的方法。
https://github.com/bcit-ci/CodeIgniter/wiki/Extending-Database-Drivers
但是,当我尝试此解决方案时,我收到了这个致命错误...
文件名:core/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_Loader
与上面链接中描述的完全一样,MY_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
... 两个完全不同的功能。 p>
可行的解决方案(不理想):
我找到的唯一可行的解决方案是编辑 CodeIgniter 系统文件。出于显而易见的原因,我不想这样做。
位于system/database/drivers/mysqli/mysqli_utility.php
的“坏掉”备份函数如下...
function _backup($params = array())
// Currently unsupported
return $this->db->display_error('db_unsuported_feature');
有一个 Ellis Lab 线程显示了一个有效的函数......
https://ellislab.com/forums/viewthread/194645/
我通过使用新的_backup
函数编辑核心系统文件使其工作。
function _backup($params = array())
// the working backup function is here
.....
那么我还能/应该在这里做什么?
mysqli
驱动程序不支持 CodeIgniter 的备份功能,并且不允许我扩展 CodeIgniter 数据库实用程序,让我别无选择,只能编辑核心系统文件。我似乎被卡住了,我来这里看看我是否遗漏了什么,或者除了编辑核心系统文件,我还能做些什么。
编辑:请注意,CodeIgniter v3 中的数据库实用程序类完全支持mysqli
。
【问题讨论】:
如果mysqldump
在您的系统上可用,如果我是您,我会考虑向它发出系统调用。
【参考方案1】:
由于内存和脚本超时,使用 php 进行数据库备份在某种程度上受到限制。 用 mysqldump 创建一个 cronjob 来做备份怎么样?
但是,如果这不是一个选项,this 可能会有所帮助
【讨论】:
谢谢,但问题不在于 PHP、超时或内存,我已经有一个可用的mysqli
备份功能。问题是如何在不编辑 CodeIgniter 核心文件的情况下扩展/修复 CodeIgniter 驱动程序?
我不确定是否真的需要这样做来实现目标。也许这在 CI v3 中已修复?
CodeIgniter v3 还没有正式发布,即便如此,需要检查和改变的东西太多了。换句话说,这不仅仅是上传一个新的系统文件集的问题。【参考方案2】:
数据库类不能扩展或替换为您自己的类。
这些类甚至不是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
should be overriden,根据您的喜好覆盖其余部分)
或者,对来自system/database/drivers/mysqli
的文件进行粗暴的复制/粘贴/搜索和替换可能会更快(它还会使您的自定义驱动程序独立于内置的 mysqli 驱动程序,这可能是也可能不是一件好事)
现在您应该可以将config/database.php
修改为您的新驱动程序了
免责声明:未经测试:)
【讨论】:
这很有趣。我宁愿不在system
中的任何地方存储任何自定义,但是您的建议仍然比修改核心文件本身要好得多。【参考方案3】:
涉及自定义加载程序 (Extending Database Drivers) 的解决方案与此相关:扩展数据库驱动程序。您不能只用 *_utility
类替换 *_driver
类。
$my_driver_file = APPPATH.'libraries/'.$my_driver.EXT; // *driver* required!!
相反,我会覆盖CI_Loader::dbutil()
method。像这样的东西应该可以工作:
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 */
免责声明:未经测试:)
【讨论】:
是的,我应该更仔细地研究一下这个解决方案。感谢您指出这一点,我接下来要试试这个。 谢谢!有用。详情见我的回答。【参考方案4】:基于accepted solution by @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
,因此不需要此解决方法。
【讨论】:
你确定$class = 'CI_DB_' . $CI->db->dbdriver . '_utility';
吗?看起来您正在实例化默认类。
@RandomSeed,是的,我确定...因为没有MY_DB_
类...这是默认@ 987654333@ 类虽然是在 MY_Loader 中自定义的。这与 dbutil()
函数逐行完全相同,除了我注入自己的实用程序文件的部分。任何其他更改都会破坏它。
我唯一使用MY_DB_
的地方是我的自定义实用程序文件的名称。在内部,除了备用代码外,它与默认对应项相同。
我明白了。我很困惑,因为在您最初的尝试中,您定义了 class MY_DB_mysqli_utility extends CI_DB_mysqli_utility
。
条件require()
很聪明。为了进一步推动它,我真的会从默认实用程序类派生一个具有自定义名称的类,并在与require()
相同的条件下构建$class
。如果出现错误,您将立即知道加载了哪个版本。以上是关于如何扩展 CodeIgniter 数据库实用程序类的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 CodeIgniter 的表单验证类验证“不匹配”类型?