error_log() 是發送錯誤資訊到某個地方的一個函數,在程式編程中比較常見,尤其是在程式調試階段。
本文將用執行個體講解一下error_log()這個函數的用法,以及一些需要注意的問題。
代碼如下 |
複製代碼 |
<?php $str='這是條錯誤資訊。'; error_log($str,3,'errors.log'); ?> |
上述是最常用的error_log()例子,它的作用是把一條資訊寫入errors.log這個檔案裡,這個檔案如果不存在則自動建立。在這個例子中,我們看到有一個參數“3”,注意這個數字“3”不能更改也不能去掉。
下面列舉一下使用error_log()這個函數的過程中可能出現的問題:
(1)程式報錯提示:Warning: error_log() [function.error-log]: failed to open stream: Permission denied in ...on line ...
上述錯誤的出現,是因為檔案沒有寫入權限,開啟該目錄的檔案寫入權限即可。
(3)寫入到log檔案中的資訊不能換行
使用error_log()寫入log檔案,會發現文字是沒有換行的,可以對以上代碼做如下改進:
代碼如下 |
複製代碼 |
<?php $str="這是條錯誤資訊。rn"; error_log($str,3,'errors.log'); ?> |
注意$str,用的是雙引號(php單引號和雙引號的區別),還在字串結尾加上了rn。這跟第一個執行個體那個寫法是不同的。
下面我再分享兩個自訂記錄出錯日誌執行個體
代碼如下 |
複製代碼 |
<?php function exceptionHandler(){ error_reporting(E_ALL ^ E_NOTICE); date_default_timezone_set('Etc/GMT-8'); //設定時區 ini_set('display_errors',0); //將錯誤記錄到日誌 ini_set('error_log','D:\'.date('Y-m-d').'_weblog.txt'); ini_set('log_errors',1); //開啟錯誤記錄檔記錄 ini_set('ignore_repeated_errors',1); //不重複記錄出現在同一個檔案中的同一行代碼上的錯誤資訊。 $user_defined_err = error_get_last(); if($user_defined_err['type'] > 0) { switch($user_defined_err['type']){ case 1: $user_defined_errType = '致命的執行階段錯誤(E_ERROR)'; break; case 2: $user_defined_errType = '非致命的執行階段錯誤(E_WARNING)'; break; case 4: $user_defined_errType = '編譯時間文法解析錯誤(E_PARSE)'; break; case 8: $user_defined_errType = '運行時提示(E_NOTICE)'; break; case 16: $user_defined_errType = 'PHP內部錯誤(E_CORE_ERROR)'; break; case 32: $user_defined_errType = 'PHP內部警告(E_CORE_WARNING)'; break; case 64: $user_defined_errType = 'Zend指令碼引擎內部錯誤(E_COMPILE_ERROR)'; break; case 128: $user_defined_errType = 'Zend指令碼引擎內部警告(E_COMPILE_WARNING)'; break; case 256: $user_defined_errType = '使用者自訂錯誤(E_USER_ERROR)'; break; case 512: $user_defined_errType = '使用者自訂警告(E_USER_WARNING)'; break; case 1024: $user_defined_errType = '使用者自訂提示(E_USER_NOTICE)'; break; case 2048: $user_defined_errType = '代碼提示(E_STRICT)'; break; case 4096: $user_defined_errType = '可以捕獲的致命錯誤(E_RECOVERABLE_ERROR)'; break; case 8191: $user_defined_errType = '所有錯誤警告(E_ALL)'; break; default: $user_defined_errType = '未知類型'; break; } $msg = sprintf('%s %s %s %s %s',date("Y-m-d H:i:s"),$user_defined_errType,$user_defined_err['message'],$user_defined_err['file'],$user_defined_err['line']); error_log($msg,0); } } register_shutdown_function('exceptionHandler'); ?> 調用方法 <meta charset="utf-8"> <?php //檔案2:【test.php】 include('error.class.php'); echo $_COOKIE['aaaaadfa']; //此cookie不存在就會產生一個錯誤,用來做測試用 echo $_SESSION['aaaaadfa']; //此session不存在就會產生一個錯誤,用來做測試用 ?> |
例2 日誌記錄類
代碼如下 |
複製代碼 |
<?php /********************************************************** * File name: LogsClass.class.php * Class name: 日誌記錄類 * Create date: 2008/05/14 * Update date: 2008/09/28 * Author: blue * Description: 日誌記錄類 * Example: //設定路徑和檔案名稱 * $dir="a/b/".date("Y/m",time()); * $filename=date("d",time()).".log"; * $logs=new Logs($dir,$filename); * $logs->setLog("test".time()); * //使用預設 * $logs=new Logs(); * $logs->setLog("test".time()); * //記錄資訊數組 * $logs=new Logs(); * $arr=array( * 'type'=>'info', * 'info'=>'test', * 'time'=>date("Y-m-d H:i:s",time()) * ); * $logs->setLog($arr); **********************************************************/ class Logs { private $_filepath; //檔案路徑 private $_filename; //記錄檔名 private $_filehandle; //檔案控制代碼 /** *作用:初始化記錄類 *輸入:檔案的路徑,要寫入的檔案名稱 *輸出:無 */ public function Logs($dir = null, $filename = null) { //預設路徑為當前路徑 $this->_filepath = empty ( $dir ) ? '' : $dir; //預設為以時間+.log的檔案檔案 $this->_filename = empty ( $filename ) ? date ( 'Y-m-d', time () ) . '.log' : $filename; //產生路徑字串 $path = $this->_createPath ( $this->_filepath, $this->_filename ); //判斷是否存在該檔案 if (! $this->_isExist ( $path )) { //不存在 //沒有路徑的話,預設為目前的目錄 if (! empty ( $this->_filepath )) { //建立目錄 if (! $this->_createDir ( $this->_filepath )) { //建立目錄不成功的處理 die ( "建立目錄失敗!" ); } } //建立檔案 if (! $this->_createLogFile ( $path )) { //建立檔案不成功的處理 die ( "建立檔案失敗!" ); } } //產生路徑字串 $path = $this->_createPath ( $this->_filepath, $this->_filename ); //開啟檔案 $this->_filehandle = fopen ( $path, "a+" ); } /** *作用:寫入記錄 *輸入:要寫入的記錄 *輸出:無 */ public function setLog($log) { //傳入的數組記錄 $str = ""; if (is_array ( $log )) { foreach ( $log as $k => $v ) { $str .= $k . " : " . $v . "n"; } } else { $str = $log . "n"; } //寫日誌 if (! fwrite ( $this->_filehandle, $str )) { //寫日誌失敗 die ( "寫入日誌失敗" ); } } /** *作用:判斷檔案是否存在 *輸入:檔案的路徑,要寫入的檔案名稱 *輸出:true | false */ private function _isExist($path) { return file_exists ( $path ); } /** *作用:建立目錄(引用別人超強的代碼-_-;;) *輸入:要建立的目錄 *輸出:true | false */ private function _createDir($dir) { return is_dir ( $dir ) or ($this->_createDir ( dirname ( $dir ) ) and mkdir ( $dir, 0777 )); } /** *作用:建立記錄檔 *輸入:要建立的目錄 *輸出:true | false */ private function _createLogFile($path) { $handle = fopen ( $path, "w" ); //建立檔案 fclose ( $handle ); return $this->_isExist ( $path ); } /** *作用:構建路徑 *輸入:檔案的路徑,要寫入的檔案名稱 *輸出:構建好的路徑字串 */ private function _createPath($dir, $filename) { if (empty ( $dir )) { return $filename; } else { return $dir . "/" . $filename; } } /** *功能: 解構函式,釋放檔案控制代碼 *輸入: 無 *輸出: 無 */ function __destruct() { //關閉檔案 fclose ( $this->_filehandle ); } } ?> |
修正:
1,不用每寫一條日誌就進行次檔案的IO的操作,在對象聲明時開啟檔案控制代碼
2,支援數群組類型的日誌記錄
3,可使用預設路徑和預設檔案,為目前的目錄下的YYYY-MM-DD.log檔案
總結
個人更喜歡系統內建的函數,如果系統內建的日誌記錄函數滿足不了我們就可以使用下面自訂函數。