1 <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); 2 // ------------------------------------------------------------------------ 3 4 /** 5 * Exceptions Class 6 */ 7 class CI_Exceptions { 8 var $action; 9 var $severity; 10 var $message; 11 var $filename; 12 var $line; 13 14 /** 15 * Nesting level of the output buffering mechanism 16 */ 17 var $ob_level; 18 19 /** 20 * List if available error levels 21 */ 22 var $levels = array( 23 E_ERROR => 'Error', 24 E_WARNING => 'Warning', 25 E_PARSE => 'Parsing Error', 26 E_NOTICE => 'Notice', 27 E_CORE_ERROR => 'Core Error', 28 E_CORE_WARNING => 'Core Warning', 29 E_COMPILE_ERROR => 'Compile Error', 30 E_COMPILE_WARNING => 'Compile Warning', 31 E_USER_ERROR => 'User Error', 32 E_USER_WARNING => 'User Warning', 33 E_USER_NOTICE => 'User Notice', 34 E_STRICT => 'Runtime Notice' 35 ); 36 37 38 /** 39 * Constructor 40 */ 41 public function __construct() 42 { 43 $this->ob_level = ob_get_level(); 44 // Note: Do not log messages from this constructor. 45 } 46 47 // -------------------------------------------------------------------- 48 49 /** 50 * Exception Logger 51 */ 52 function log_exception($severity, $message, $filepath, $line) 53 { 54 $severity = ( ! isset($this->levels[$severity])) ? $severity : $this->levels[$severity]; 55 56 log_message('error', 'Severity: '.$severity.' --> '.$message. ' '.$filepath.' '.$line, TRUE); 57 } 58 59 // -------------------------------------------------------------------- 60 61 /** 62 * 404 Page Not Found Handler 63 */ 64 function show_404($page = '', $log_error = TRUE) 65 { 66 $heading = "404 Page Not Found"; 67 $message = "The page you requested was not found."; 68 69 // By default we log this, but allow a dev to skip it 70 if ($log_error) 71 { 72 log_message('error', '404 Page Not Found --> '.$page); 73 } 74 75 echo $this->show_error($heading, $message, 'error_404', 404); 76 exit; 77 } 78 79 // -------------------------------------------------------------------- 80 81 /** 82 * 先解释一下show_php_error,show_error,和show_404之间的关系和区别。 83 * show_php_error()是代码本身的一些错误,例如变量未定义之类的,平时我们调试的时候经常见到的一些错误,是不小心写错代码而导致的。 84 * show_error()是有意识触发的错误,不是代码写错,而是代码不当,或者用户操作不当,比如找不到控制器,指定方法之类的,CI就show一 85 * 个错误出来,当然开发者也可以调用此方法响应一个错误信息,某种程度上类似于catch到一个exception之后的处理,然后根据exception 86 * 发出不同的提示信息。 87 * show_404()是show_error()中的一种特殊情况,就是请求不存在的情况,响应一个404错误。 88 */ 89 /** 90 * General Error Page 91 */ 92 function show_error($heading, $message, $template = 'error_general', $status_code = 500) 93 { 94 //默认是500,内部服务错误。是指由于程序代码写得不恰当而引起的,因此向浏览器回应一个内部错误。 95 set_status_header($status_code); 96 97 $message = '<p>'.implode('</p><p>', ( ! is_array($message)) ? array($message) : $message).'</p>'; 98 99 //此处的作用与show_php_error()中的相应位置作用一样。 100 if (ob_get_level() > $this->ob_level + 1) 101 { 102 ob_end_flush(); 103 } 104 ob_start(); 105 include(APPPATH.'errors/'.$template.'.php'); 106 $buffer = ob_get_contents(); 107 ob_end_clean(); 108 109 //这里是return,因为一般情况下,是使用core/Common.php中,全局函数show_error()间接使用当前Exception::show_error()方法。 110 return $buffer; 111 } 112 113 // -------------------------------------------------------------------- 114 115 /** 116 * Native PHP error handler 117 */ 118 function show_php_error($severity, $message, $filepath, $line) 119 { 120 //取得对应错误级别相对的说明。在$this->levels中定义。 121 $severity = ( ! isset($this->levels[$severity])) ? $severity : $this->levels[$severity]; 122 123 $filepath = str_replace("\", "/", $filepath); 124 125 //为了安全起见,只显示错误文件最后两段路径信息。 126 if (FALSE !== strpos($filepath, '/')) 127 { 128 $x = explode('/', $filepath); 129 $filepath = $x[count($x)-2].'/'.end($x); 130 } 131 132 133 /* 134 * 如果还没看过core/Loader.php,下面这个判断可能让人有点迷惑。 135 * ob_get_level()是取得当前缓冲机制的嵌套级别。(缓冲是可以一层嵌一层的。) 136 * 右边的$this->ob_level是在__construct()里面同样通过ob_get_level()被赋值的。 137 * 也就是说,有可能出现:Exception组件被加载时(也就是应用刚开始运行时)的缓冲级别(其实也就是程序最开始的时候的缓冲级别,那时 138 * 候是还没有ob_start()过的),与发生错误的时候的缓冲级别相差1。 139 * 在控制器执行$this->load->view("xxx");的时候,实质,Loader引入并执行这个视图文件的时候,是先把缓冲打开,即 140 * 先ob_start(),所有输出放到缓冲区(详见:core/Loader.php中的_ci_load()),然后再由Output处理输出。 141 * 因此,如果是在视图文件发生错误,则就会出现缓冲级别相差1的情况,此时先把输出的内容给flush出来,然后再把错误信息输出。 142 * 143 */ 144 if (ob_get_level() > $this->ob_level + 1) 145 { 146 ob_end_flush(); 147 } 148 ob_start(); 149 //错误信息模板,位于应用目录errors/下。 150 include(APPPATH.'errors/error_php.php'); 151 $buffer = ob_get_contents(); 152 ob_end_clean(); 153 echo $buffer; 154 } 155 156 157 }