Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 在带有autoloader的errorhandler中使用MySQLi扩展类_Php_Mysql_Class_Error Handling_Autoload - Fatal编程技术网

Php 在带有autoloader的errorhandler中使用MySQLi扩展类

Php 在带有autoloader的errorhandler中使用MySQLi扩展类,php,mysql,class,error-handling,autoload,Php,Mysql,Class,Error Handling,Autoload,我在PHP中使用以下组合时遇到了一个问题: 一个自定义类加载器“classloader”,作为一个单例实现,并使用spl\U autoload\U寄存器注册,它只需要\U一次就可以包含这些类。没什么特别的,只是一些在磁盘上组织类的路径 扩展mysqli类的数据库类“DB”。它是从目前只知道一个实例的工厂创建的。它只不过加载正确的配置并提供一些快捷方式 一个自定义的errorhandler“errorhandler”,作为一个单例实现,它使用DB类将通知和警告记录到数据库中 所有这些都很好;c

我在PHP中使用以下组合时遇到了一个问题:

  • 一个自定义类加载器“classloader”,作为一个单例实现,并使用spl\U autoload\U寄存器注册,它只需要\U一次就可以包含这些类。没什么特别的,只是一些在磁盘上组织类的路径
  • 扩展mysqli类的数据库类“DB”。它是从目前只知道一个实例的工厂创建的。它只不过加载正确的配置并提供一些快捷方式
  • 一个自定义的errorhandler“errorhandler”,作为一个单例实现,它使用DB类将通知和警告记录到数据库中
所有这些都很好;classloader加载类,DB类正确执行查询,errorhandler将错误记录在数据库中

…除非在调用任何数据库操作之前发生错误。 在这种情况下,PHP崩溃并且崩溃得很厉害;没有错误消息或任何东西,甚至没有任何回音或变量转储,甚至没有4xx或5xx代码。 浏览器只是报告没有收到任何内容

我发现了一些“修复”:

  • 不要在我的“DB”类中扩展mysqli类;这使得它不起作用,但似乎表明扩展mysqli导致了问题
  • 全局自动加载我自己的“DB”类,或者在ErrorHandler.php类文件的顶部自动加载
  • 在获取ErrorHandler类中的实例之前,使用require_显式地加载“DB”类一次
我仍然可以在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'));
数据库

Config是一个具有一些公共属性的单例

错误处理程序

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, $errstr, $errfile, $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, $errstr, $errfile, $errline, $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, $errstr, $errfile, $errline);
            }

            // Log
            if (ini_get('log_errors')) {
                error_log(sprintf("PHP %s:  %s in %s on line %d", $errors, $errstr, $errfile, $errline));
            }
            break;
        }

        // Exit/return strategy
        switch ($errno) {
            case E_ERROR:
            case E_USER_ERROR:
                die();
                break;
        }
        return TRUE;
    }
}
类ErrorHandler扩展对象{
/*
*回溯中的条带递归问题
*/
私有静态函数_filter_backtrace($array,$depth=0){
$result=array();
foreach($name=>$value的数组){
开关(gettype($value)){
案例“对象”:
案例“未知类型”:
案例“资源”:
打破
案例“数组”:
//$result[$name]=self:_filter\u backtrace($value);
打破
违约:
//$result[$name]=$value;
}
}
返回$result;
}
私有函数_handle_db($errno、$errstr、$errfile、$errline、$backtrace){
$db=db::get(Config::get());
$db->dieOnError(true);//防止错误处理程序中出现无限循环
//数据库查询在这里
$db->dieOnError(false);//表示未死亡。
}
私有函数_u构造(){
}
私有静态$\u实例=null;
公共静态函数get(){
if(self::$\u实例===null){
self::$\u实例=新self();
}
返回self::$\u实例;
}
公共函数句柄($errno、$errstr、$errfile、$errline){
//无错误?返回而不报告
如果(!($errno&error\u reporting())){
返回;
}
//错误类型
交换机($errno){
案件通知:
案例E_用户通知:
$errors=“通知”;
打破
案例E_警告:
案例E_用户_警告:
$errors=“Warning”;
打破
案例E_错误:
案例E_用户_错误:
$errors=“致命错误”;
打破
违约:
$errors=“未知”;
打破
}
//$backtrace=self::_filter_backtrace(数组_移位(debug_backtrace());
$backtrace=array();
开关(配置::get()->错误日志){
案例“db”:
ErrorHandler::_handle_db($errno、$errstr、$errfile、$errline、$backtrace);
打破
违约:
//倾倒
if(ini\u get(“显示错误”)){
printf(“
\n%s:%s在%s中的%d行上,$errors,$errstr,$errfile,$errline”); } //日志 if(ini\u get('log\u errors')){ 错误日志(sprintf(“PHP%s:%s在%s中的第%d行,$errors,$errstr,$errfile,$errline)); } 打破 } //退出/返回策略 交换机($errno){ 案例E_错误: 案例E_用户_错误: 模具(); 打破 } 返回TRUE; } }
当数据库不可用时,您不能使用错误处理程序登录数据库

如果在初始化数据库之前调用错误处理程序,则会出现这种情况

您需要为这种情况实施回退。错误处理程序可以创建数据库,或者您需要先创建数据库,或者在这种情况下登录到文件,因为文件通常是可用的


在任何情况下调试你的问题都要考虑使错误登录到一个错误日志(PHP已经提供了,只是配置它),然后你<强>遗嘱< /强>当你触发这个问题时,找出你的具体问题是什么,它会给你更多的信息来更好地解决你的问题。(例如,删除记录器和数据库之间依赖关系中的缺陷).

我不确定这是否与您的问题有关。我看到一个发送到服务器的请求没有响应,这意味着响应中没有标题或正文。如果我没有记错,那是因为服务器超时。现在,我不记得这是在哪里发生的,但我需要它
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, $errstr, $errfile, $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, $errstr, $errfile, $errline, $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, $errstr, $errfile, $errline);
            }

            // Log
            if (ini_get('log_errors')) {
                error_log(sprintf("PHP %s:  %s in %s on line %d", $errors, $errstr, $errfile, $errline));
            }
            break;
        }

        // Exit/return strategy
        switch ($errno) {
            case E_ERROR:
            case E_USER_ERROR:
                die();
                break;
        }
        return TRUE;
    }
}