|
作者:线筝
原文:http://h5b.net/codeigniter-error_report-set_error_handler/
在CodeIgniter的那些坑(一)中,介绍了CodeIgniter的设置,会造成php没有任何的error.log,删掉那个设置之后,并且display_error=0之后,codeigniter偶尔还是会把错误暴露出来,这是为什么呐?
这个问题困扰了我们很久,后来我们就发现了CodeIgniter另外一个坑爹的设置,这是CodeIgniter/system/core/CodeIgniter.php的源码
PHP复制代码 <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* CodeIgniter
*
* An open source application development framework for PHP 5.1.6 or newer
*
* @package CodeIgniter
* @author ExpressionEngine Dev Team
* @copyright Copyright (c) 2008 - 2011, EllisLab, Inc.
* @license http://codeigniter.com/user_guide/license.html
* @link http://codeigniter.com
* @since Version 1.0
* @filesource
*/
// ------------------------------------------------------------------------
/**
* System Initialization File
*
* Loads the base classes and executes the request.
*
* @package CodeIgniter
* @subpackage codeigniter
* @category Front-controller
* @author ExpressionEngine Dev Team
* @link http://codeigniter.com/user_guide/
*/
/**
* CodeIgniter Version
*
* @var string
*
*/
define('CI_VERSION', '2.1.3');
/**
* CodeIgniter Branch (Core = TRUE, Reactor = FALSE)
*
* @var boolean
*
*/
define('CI_CORE', FALSE);
/*
* ------------------------------------------------------
* Load the global functions
* ------------------------------------------------------
*/
require(BASEPATH .'core/Common.php');
/*
* ------------------------------------------------------
* Load the framework constants
* ------------------------------------------------------
*/
if (defined('ENVIRONMENT') AND file_exists(APPPATH .'config/'.ENVIRONMENT .'/constants.php'))
{
require(APPPATH .'config/'.ENVIRONMENT .'/constants.php');
}
else
{
require(APPPATH .'config/constants.php');
}
/*
* ------------------------------------------------------
* Define a custom error handler so we can log PHP errors
* ------------------------------------------------------
*/
set_error_handler('_exception_handler');
if ( ! is_php ('5.3'))
{
@set_magic_quotes_runtime(0); // Kill magic quotes
}
/*
* ------------------------------------------------------
* Set the subclass_prefix
* ------------------------------------------------------
*
* Normally the "subclass_prefix" is set in the config file.
* The subclass prefix allows CI to know if a core class is
* being extended via a library in the local application
* "libraries" folder. Since CI allows config items to be
* overriden via data set in the main index. php file,
* before proceeding we need to know if a subclass_prefix
* override exists. If so, we will set this value now,
* before any classes are loaded
* Note: Since the config file data is cached it doesn't
* hurt to load it here.
*/
if (isset($assign_to_config['subclass_prefix']) AND $assign_to_config['subclass_prefix'] != '')
{
get_config (array('subclass_prefix' => $assign_to_config['subclass_prefix']));
}
/*
* ------------------------------------------------------
* Set a liberal script execution time limit
* ------------------------------------------------------
*/
if (function_exists("set_time_limit") == TRUE AND @ini_get("safe_mode") == 0)
{
@set_time_limit(300);
}
/*
* ------------------------------------------------------
* Start the timer... tick tock tick tock...
* ------------------------------------------------------
*/
$BM =& load_class ('Benchmark', 'core');
$BM->mark('total_execution_time_start');
$BM->mark('loading_time:_base_classes_start');
/*
* ------------------------------------------------------
* Instantiate the hooks class
* ------------------------------------------------------
*/
$EXT =& load_class ('Hooks', 'core');
/*
* ------------------------------------------------------
* Is there a "pre_system" hook?
* ------------------------------------------------------
*/
$EXT->_call_hook ('pre_system');
/*
* ------------------------------------------------------
* Instantiate the config class
* ------------------------------------------------------
*/
$CFG =& load_class ('Config', 'core');
// Do we have any manually set config items in the index.php file?
if (isset($assign_to_config))
{
$CFG->_assign_to_config ($assign_to_config);
}
/*
* ------------------------------------------------------
* Instantiate the UTF-8 class
* ------------------------------------------------------
*
* Note: Order here is rather important as the UTF-8
* class needs to be used very early on, but it cannot
* properly determine if UTf-8 can be supported until
* after the Config class is instantiated.
*
*/
$UNI =& load_class ('Utf8', 'core');
/*
* ------------------------------------------------------
* Instantiate the URI class
* ------------------------------------------------------
*/
$URI =& load_class ('URI', 'core');
/*
* ------------------------------------------------------
* Instantiate the routing class and set the routing
* ------------------------------------------------------
*/
$RTR =& load_class ('Router', 'core');
$RTR->_set_routing ();
// Set any routing overrides that may exist in the main index file
if (isset($routing))
{
$RTR->_set_overrides ($routing);
}
/*
* ------------------------------------------------------
* Instantiate the output class
* ------------------------------------------------------
*/
$OUT =& load_class ('Output', 'core');
/*
* ------------------------------------------------------
* Is there a valid cache file? If so, we're done...
* ------------------------------------------------------
*/
if ($EXT->_call_hook ('cache_override') === FALSE)
{
if ($OUT->_display_cache ($CFG, $URI) == TRUE)
{
exit;
}
}
/*
* -----------------------------------------------------
* Load the security class for xss and csrf support
* -----------------------------------------------------
*/
$SEC =& load_class ('Security', 'core');
/*
* ------------------------------------------------------
* Load the Input class and sanitize globals
* ------------------------------------------------------
*/
$IN =& load_class ('Input', 'core');
/*
* ------------------------------------------------------
* Load the Language class
* ------------------------------------------------------
*/
$LANG =& load_class ('Lang', 'core');
/*
* ------------------------------------------------------
* Load the app controller and local controller
* ------------------------------------------------------
*
*/
// Load the base controller class
require BASEPATH .'core/Controller.php';
function &get_instance ()
{
return CI_Controller ::get_instance();
}
if (file_exists(APPPATH .'core/'.$CFG->config['subclass_prefix'].'Controller.php'))
{
require APPPATH .'core/'.$CFG->config['subclass_prefix'].'Controller.php';
}
// Load the local application controller
// Note: The Router class automatically validates the controller path using the router->_validate_request().
// If this include fails it means that the default controller in the Routes.php file is not resolving to something valid.
if ( ! file_exists(APPPATH .'controllers/'.$RTR->fetch_directory().$RTR->fetch_class().'.php'))
{
show_error ('Unable to load your default controller. Please make sure the controller specified in your Routes.php file is valid.');
}
include(APPPATH .'controllers/'.$RTR->fetch_directory().$RTR->fetch_class().'.php');
// Set a mark point for benchmarking
$BM->mark('loading_time:_base_classes_end');
/*
* ------------------------------------------------------
* Security check
* ------------------------------------------------------
*
* None of the functions in the app controller or the
* loader class can be called via the URI, nor can
* controller functions that begin with an underscore
*/
$class = $RTR->fetch_class();
$method = $RTR->fetch_method();
if ( ! class_exists($class)
OR strncmp($method, '_', 1) == 0
OR in_array(strtolower($method), array_map('strtolower', get_class_methods('CI_Controller')))
)
{
if ( ! empty($RTR->routes['404_override']))
{
$x = explode('/', $RTR->routes['404_override']);
$class = $x[0];
$method = (isset($x[1]) ? $x[1] : 'index');
if ( ! class_exists($class))
{
if ( ! file_exists(APPPATH .'controllers/'.$class.'.php'))
{
show_404 ("{$class}/{$method}");
}
include_once(APPPATH .'controllers/'.$class.'.php');
}
}
else
{
show_404 ("{$class}/{$method}");
}
}
/*
* ------------------------------------------------------
* Is there a "pre_controller" hook?
* ------------------------------------------------------
*/
$EXT->_call_hook ('pre_controller');
/*
* ------------------------------------------------------
* Instantiate the requested controller
* ------------------------------------------------------
*/
// Mark a start point so we can benchmark the controller
$BM->mark('controller_execution_time_( '.$class.' / '.$method.' )_start');
$CI = new $class();
/*
* ------------------------------------------------------
* Is there a "post_controller_constructor" hook?
* ------------------------------------------------------
*/
$EXT->_call_hook ('post_controller_constructor');
/*
* ------------------------------------------------------
* Call the requested method
* ------------------------------------------------------
*/
// Is there a "remap" function? If so, we call it instead
if (method_exists($CI, '_remap'))
{
$CI->_remap ($method, array_slice($URI->rsegments, 2));
}
else
{
// is_callable() returns TRUE on some versions of PHP 5 for private and protected
// methods, so we'll use this workaround for consistent behavior
if ( ! in_array(strtolower($method), array_map('strtolower', get_class_methods($CI))))
{
// Check and see if we are using a 404 override and use it.
if ( ! empty($RTR->routes['404_override']))
{
$x = explode('/', $RTR->routes['404_override']);
$class = $x[0];
$method = (isset($x[1]) ? $x[1] : 'index');
if ( ! class_exists($class))
{
if ( ! file_exists(APPPATH .'controllers/'.$class.'.php'))
{
show_404 ("{$class}/{$method}");
}
include_once(APPPATH .'controllers/'.$class.'.php');
unset($CI);
$CI = new $class();
}
}
else
{
show_404 ("{$class}/{$method}");
}
}
// Call the requested method.
// Any URI segments present (besides the class/function) will be passed to the method for convenience
call_user_func_array(array(&$CI, $method), array_slice($URI->rsegments, 2));
}
// Mark a benchmark end point
$BM->mark('controller_execution_time_( '.$class.' / '.$method.' )_end');
/*
* ------------------------------------------------------
* Is there a "post_controller" hook?
* ------------------------------------------------------
*/
$EXT->_call_hook ('post_controller');
/*
* ------------------------------------------------------
* Send the final rendered output to the browser
* ------------------------------------------------------
*/
if ($EXT->_call_hook ('display_override') === FALSE)
{
$OUT->_display ();
}
/*
* ------------------------------------------------------
* Is there a "post_system" hook?
* ------------------------------------------------------
*/
$EXT->_call_hook ('post_system');
/*
* ------------------------------------------------------
* Close the DB connection if one exists
* ------------------------------------------------------
*/
if (class_exists('CI_DB') AND isset($CI->db))
{
$CI->db->close();
}
/* End of file CodeIgniter.php */
/* Location: ./system/core/CodeIgniter.php */ 复制代码
在这页代码中,我们发现了这么一句话
这个函数是什么意思呐,查看php文档就会发现这么简单的介绍
Sets a user function (error_handler) to handle errors in a script.
This function can be used for defining your own way of handling errors during runtime, for example in applications in which you need to do cleanup of data/files when a critical error happens, or when you need to trigger an error under certain conditions (using trigger_error()).
It is important to remember that the standard PHP error handler is completely bypassed for the error types specified by error_types unless the callback function returns FALSE. error_reporting() settings will have no effect and your error handler will be called regardless - however you are still able to read the current value of error_reporting and act appropriately. Of particular note is that this value will be 0 if the statement that caused the error was prepended by the @ error-control operator.
Also note that it is your responsibility to die if necessary. If the error-handler function returns, script execution will continue with the next statement after the one that caused an error.
The following error types cannot be handled with a user defined function: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING, and most of E_STRICT raised in the file where set_error_handler() is called.
If errors occur before the script is executed (e.g. on file uploads) the custom error handler cannot be called since it is not registered at that time.
大致意思就是,这个函数允许程序自己去处理错误。
全局搜索_exception_handler关键词,在CodeIgniter/system/libraries/Driver.php中的CI_Driver类的一个方法中
PHP复制代码 public function __call ($method, $args = array())
{
if (in_array($method, $this->methods))
{
return call_user_func_array(array($this->parent, $method), $args);
}
$trace = debug_backtrace();
_exception_handler (E_ERROR, "No such method '{$method}'", $trace[1]['file'], $trace[1]['line']);
exit;
} 复制代码
可以看出,这个方法抛出的错误,就会被CodeIgniter钩住,自己去处理。
所以要想全部屏蔽错误的显示,就必须将CodeIgniter/system/core/CodeIgniter.php中的
干掉。
这还是只是CodeIgniter坑爹默认设置的一部分,还有CodeIgniter的那些坑(三) |
|