php – 在自动加载器的错误处理程序中使用MySQLi扩展类
我遇到了在
PHP中使用以下组合的问题:
>自定义类加载器“ClassLoader”,实现为单例并在spl_autoload_register中注册,它执行require_once以包含类.没什么特别的,只是在磁盘上组织类的一些路径. 所有这一切都很好;类加载器加载类,DB类正确执行查询,错误处理程序记录数据库中的错误. …除非在调用任何数据库操作之前发生错误. 我发现了一些“修复”: >不要在我的“DB”类中扩展mysqli类;这使得它不起作用,但似乎表明扩展mysqli会导致问题. 我仍然可以在ErrorHandler中自动加载其他类,但是当我实例化“DB”时,PHP似乎崩溃了. 从我看到的,唯一合理的解释似乎是mysqli中的某些内容与在ErrorHandler类中首次实例化的范围有关,因为所有有效的修复似乎都共享范围方面,但这似乎没有任何意义上的. 有谁知道这里发生了什么? 类加载器… class ClassLoader { private $_paths = array(); private function __construct() { // ... bunch of $this->append() calls with all paths and 3rd party libs } private static $_instance = null; public static function get() { if (self::$_instance === null) { self::$_instance = new self(); } return self::$_instance; } public function append($path,$format = '$.class.php') { if (!array_key_exists($path,$this->_paths)) { $this->_paths[$path] = $format; return true; } return false; } public function autoload($class_name) { foreach ($this->_paths as $path => $format) { $file = $path.'/'.str_replace('$',$class_name,$format); if (file_exists($file)) { require_once($file); return true; } } return false; } } $autoloader = ClassLoader::get(); $autoloader->append(dirname(__FILE__).'/classes'); spl_autoload_register(array($autoloader,'autoload')); D B… class DB extends mysqli { private static $_instances = array(); public static function get(Config $config) { $hash = md5(serialize($config)); if (!array_key_exists($hash,self::$_instances)) { self::$_instances[$hash] = new self($config); } return self::$_instances[$hash]; } private $_prefix = ''; private $_die = false; public function dieOnError($die) { $this->_die = $die; } private function __construct(Config $config) { parent::__construct( $config->host,$config->username,$config->password,$config->database ); if ($this->connect_error) { _report_error($this->connect_errno,$this->connect_error); } $this->_prefix = $config->prefix; } } Config是一个拥有一些公共属性的单身人士. 的ErrorHandler class ErrorHandler extends Object { /* * Strip recursion problems in the backtrace */ private static function _filter_backtrace($array,$depth = 0) { $result = array(); foreach ($array as $name => $value) { switch (gettype($value)) { case 'object': case 'unknown type': case 'resource': break; case 'array': //$result[$name] = self::_filter_backtrace($value); break; default: //$result[$name] = $value; } } return $result; } private function _handle_db($errno,$errstr,$errfile,$errline,$backtrace) { $db = DB::get(Config::get()); $db->dieOnError(true); // prevents infinite loops in error handler // DB query here $db->dieOnError(false); // for non-dying. } private function __construct() { } private static $_instance = null; public static function get() { if (self::$_instance === null) { self::$_instance = new self(); } return self::$_instance; } public function handle($errno,$errline) { // No error? Return without reporting if (!($errno & error_reporting())) { return; } // Type of error switch ($errno) { case E_NOTICE: case E_USER_NOTICE: $errors = "Notice"; break; case E_WARNING: case E_USER_WARNING: $errors = "Warning"; break; case E_ERROR: case E_USER_ERROR: $errors = "Fatal Error"; break; default: $errors = "Unknown"; break; } //$backtrace = self::_filter_backtrace(array_shift(debug_backtrace())); $backtrace = array(); switch (Config::get()->error_log) { case 'db': ErrorHandler::_handle_db($errno,$backtrace); break; default: // Dump if (ini_get("display_errors")) { printf("<br />n<b>%s</b>: %s in <b>%s</b> on line <b>%d</b><br /><br />n",$errors,$errline); } // Log if (ini_get('log_errors')) { error_log(sprintf("PHP %s: %s in %s on line %d",$errline)); } break; } // Exit/return strategy switch ($errno) { case E_ERROR: case E_USER_ERROR: die(); break; } return TRUE; } } 解决方法
当错误处理程序不可用时,您无法将错误处理程序记录到数据库中.
如果在初始化数据库之前调用错误处理程序,则会出现这种情况. 您需要为此案例实施回退.错误处理程序可以创建数据库,或者您需要首先创建数据库,或者在这种情况下您需要登录到文件,因为文件通常是可用的. 在任何情况下调试你的问题考虑启用错误记录到错误日志(PHP提供此功能,只需配置它),然后你会发现当你触发问题时你的具体问题,这将为你提供更多的信息解决您的问题(例如,删除记录器和数据库之间的依赖关系中的缺陷). (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |