搜尋

PHP錯誤機制

Aug 21, 2017 am 10:16 AM
php機制錯誤


PHP 的錯誤機制也是非常複雜的,做了幾年php,也沒有仔細總結過,現在就補上這一課。

特別說明:文章的PHP版本使用5.5.32

PHP的錯誤等級

首先要了解php有哪些錯誤。截至到php5.5,總共有16個錯誤等級

##注意:嘗試下面的程式碼的時候請確保開啟error_log:

##

error_reporting(E_ALL);
ini_set('display_errors', 'On');

# E_ERROR

這種錯誤是致命錯誤,會在頁面顯示Fatal Error, 當出現這種錯誤的時候,程式就無法繼續執行下去了

錯誤範例:

// Fatal error: Call to undefined function hpinfo() in /tmp/php/index.php on line 5
hpinfo();  //E_ERROR



注意,如果有未被捕獲的例外,也是會觸發這個層級的。

// Fatal error: Uncaught exception 'Exception' with message 'test exception' in /tmp/php/index.php:5 Stack trace: #0 {main} thrown in /tmp/php/index.php on line 5
throw new Exception("test exception");


E_WARNING

這個錯誤只是警告,不會終止腳本,程式也會繼續進行,顯示的錯誤訊息是Warning。例如include一個不存在的檔案。

//Warning: include(a.php): failed to open stream: No such file or directory in /tmp/php/index.php on line 7
//Warning: include(): Failed opening 'a.php' for inclusion (include_path='.:/usr/share/pear:/usr/share/php') in /tmp/php/index.php on line 7
include("a.php"); //E_WARNING

E_NOTICE

#這種錯誤程度更為輕微一些,提示你這個地方不應該這麼寫。這個也是運行時錯誤,這個錯誤的程式碼可能在其他地方沒有問題,只是在當前上下文情況下出現了問題。

例如$b變數不存在,我們把它賦值給另外一個變數

#

//Notice: Undefined variable: b in /tmp/php/index.php on line 9
$a = $b; //E_NOTICE

E_PARSE

這個錯誤是編譯時候發生的,在編譯期發現語法錯誤,不能進行語法分析。

例如下面的z沒有設定為變數。

// Parse error: syntax error, unexpected '=' in /tmp/php/index.php on line 20
z=1; // E_PARSE

E_STRICT

這個錯誤是PHP5之後引入的,你的程式碼可以運行,但不是PHP建議的寫法。

例如在函數形參傳遞++符號

// Strict Standards: Only variables should be passed by reference in /tmp/php/index.php on line 17
function change (&$var) {
  $var += 10;
}
 
$var = 1;
change(++$var);
// E_STRICT


#E_RECOVERABLE_ERROR

#這個等級其實是ERROR等級的,但是它是期望被捕獲的,如果沒有被錯誤處理捕獲,表現和E_ERROR是一樣的。

經常出現在形參定義了類型,但呼叫的時候傳入了錯誤類型。它的錯誤提醒也比E_ERROR的fatal error前面多了一個Catachable的字樣。

//Catchable fatal error: Argument 1 passed to testCall() must be an instance of A, instance of B given, called in /tmp/php/index.php on line 37 and defined in /tmp/php/index.php on line 33
class A {
}
 
class B {
}
 
function testCall(A $a) {
}
 
$b = new B();
testCall($b);


E_DEPRECATED

這個錯誤表示你用了一個舊版本的函數,而這個函數後期版本可能被禁用或不維護了。

例如curl的CURLOPT_POSTFIELDS使用@FILENAME來上傳檔案的方法

// Deprecated: curl_setopt(): The usage of the @filename API for file uploading is deprecated. Please use the CURLFile class instead in /tmp/php/index.php on line 42
$ch = curl_init("http://www.remotesite.com/upload.php");
curl_setopt($ch, CURLOPT_POSTFIELDS, array('fileupload' => '@'. "test"));


E_CORE_ERROR, E_CORE_WARNING

##這兩個錯誤是由PHP的引擎產生的,在PHP初始化過程中發生。

E_COMPILE_ERROR, E_COMPILE_WARNING

這兩個錯誤是由PHP引擎產生的,在編譯過程中發生。

E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE, E_USER_DEPRECATED,

這些錯誤都是用戶製造的,使用trigger_error,這裡就相當於一個口子給用戶觸發出各種錯誤類型。這是一個很好逃避try catch異常的方式。

trigger_error("Cannot pide by zero", E_USER_ERROR);
// E_USER_ERROR
// E_USER_WARING
// E_USER_NOTICE
// E_USER_DEPRECATED


E_ALL

E_STRICT出外的所有錯誤和警告訊息。

錯誤控制

php中有很多配置和參數是可以控制錯誤,以及錯誤的日誌顯示的。第一步,我們要了解的是php中的有關錯誤的配置有哪些?

我們按照php+php-fpm的模型來說,會影響php錯誤顯示的其實是有兩個設定文件,一個是php本身的設定檔php.ini,另一個是php-fpm的配置文件,php-fpm.conf。

php.ini中的設定

error_reporting = E_ALL  // 报告错误级别,什么级别的
error_log = /tmp/php_errors.log // php中的错误显示的日志位置
display_errors = On // 是否把错误展示在输出上,这个输出可能是页面,也可能是stdout
display_startup_errors = On // 是否把启动过程的错误信息显示在页面上,记得上面说的有几个Core类型的错误是启动时候发生的,这个就是控制这些错误是否显示页面的。
log_errors = On // 是否要记录错误日志
log_errors_max_len = 1024 // 错误日志的最大长度
ignore_repeated_errors = Off // 是否忽略重复的错误
track_errors = Off // 是否使用全局变量$php_errormsg来记录最后一个错误
xmlrpc_errors = 0 //是否使用XML-RPC的错误信息格式记录错误
xmlrpc_error_number = 0 // 用作 XML-RPC faultCode 元素的值。
html_errors = On  // 是否把输出中的函数等信息变为HTML链接
docref_root = http://manual/en/ // 如果html_errors开启了,这个链接的根路径是什么
fastcgi.logging = 0 // 是否把php错误抛出到fastcgi中

我们经常会被问到,error_reporting和display_errors有什么区别呢?这两个函数是完全不一样的。

PHP默认是会在日志和标准输出(如果是fpm模式标准输出就是页面)
error_reporting的参数是错误级别。表示什么样子的级别才应该触发错误。如果我们告诉PHP,所有错误级别都不需要触发错误,那么,不管是日志,还是页面,都不会显示这个错误,就相当于什么都没有发生。
display_errors是控制是否要在标准输出展示错误信息
log_errors则是控制是否要在日志中记录错误信息。

error_log是显示错误日志的位置,这个在php-fpm中往往会被重写,于是往往会发现的是cli和fpm的错误日志竟然不是在同一个文件中。

ignore_repeated_errors这个标记控制的是如果有重复的日志,那么就只会记录一条,比如下面的程序:

error_reporting(E_ALL);
ini_set('ignore_repeated_errors', 1);
ini_set('ignore_repeated_source', 1);
 
$a = $c; $a = $c; //E_NOTICE
//Notice: Undefined variable: c in /tmp/php/index.php on line 20




本来会出现两次NOTICE的,但是现在,只会出现一次了…

track_errors开启会把最后一个错误信息存储到变量里面去,这个可能在对记日志的时候会有一些用处吧。不过我觉得真是没啥用…

html_errors 和 docref_root 两个是个挺有人性化的配置,配置了这两个参数以后,我们返回的错误信息中如果有一些在文档中有的信息,就会变成链接形式。

error_reporting(E_ALL);
ini_set('html_errors', 1);
ini_set('docref_root', "https://secure.php.net/manual/zh/");
 
include("a2.php"); //E_WARNING


能让你快速定位到我们出现错误的地方。是不是很人性~

php-fpm中的配置

error_log = /var/log/php-fpm/error.log // php-fpm自身的日志
log_level = notice // php-fpm自身的日志记录级别
php_flag[display_errors] = off // 覆盖php.ini中的某个配置变量,可被程序中的ini_set覆盖
php_value[display_errors] = off // 同php_flag
php_admin_value[error_log] = /tmp/www-error.log // 覆盖php.ini中的某个配置变量,不可被程序中的ini_set覆盖
php_admin_flag[log_errors] = on // 同php_admin_value
catch_workers_output = yes // 是否抓取fpmworker的输出
request_slowlog_timeout = 0 // 慢日志时长
slowlog = /var/log/php-fpm/www-slow.log // 慢日志记录

php-fpm的配置中也有一个error_log配置,这个很经常会和php.ini中的error_log配置弄混。但他们记录的东西是不一样的,php-fpm的error_log只记录php-fpm本身的日志,比如fpm启动,关闭。

而php.ini中的error_log是记录php程序本身的错误日志。

那么在php-fpm中要覆盖php.ini中的error_log配置,就需要使用到下面几个函数:

  • php_flag

  • php_value

  • php_admin_flag

  • php_admin_value

这四个函数admin的两个函数说明这个变量设置完之后,不能在代码中使用ini_set把这个变量重新赋值了。而php_flag/value就仍然以php代码中的ini_set为准。

slowlog是fpm记录的,可以使用request_slowlog_timeout设置判断慢日志的时长。

总结

我们经常弄混的就是日志问题,以及某些级别的日志为何没有记录到日志中。最主要的是要看error_log,display_errors, log_errors这三个配置,只是在看配置的时候,我们还要注意区分php.ini里面的配置是什么,php-fpm.ini里面的配置是什么。

好吧,我觉得弄懂这些配置,基本就没有php日志记录不了的WTF的问题了。

以上是PHP錯誤機制的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
使用PHP會話的局限性是什麼?使用PHP會話的局限性是什麼?Apr 30, 2025 am 12:04 AM

PHPsessionshaveseverallimitations:1)Storageconstraintscanleadtoperformanceissues;2)Securityvulnerabilitieslikesessionfixationattacksexist;3)Scalabilityischallengingduetoserver-specificstorage;4)Sessionexpirationmanagementcanbeproblematic;5)Datapersis

解釋負載平衡如何影響會話管理以及如何解決。解釋負載平衡如何影響會話管理以及如何解決。Apr 29, 2025 am 12:42 AM

負載均衡會影響會話管理,但可以通過會話複製、會話粘性和集中式會話存儲解決。 1.會話複製在服務器間複製會話數據。 2.會話粘性將用戶請求定向到同一服務器。 3.集中式會話存儲使用獨立服務器如Redis存儲會話數據,確保數據共享。

說明會話鎖定的概念。說明會話鎖定的概念。Apr 29, 2025 am 12:39 AM

Sessionlockingisatechniqueusedtoensureauser'ssessionremainsexclusivetooneuseratatime.Itiscrucialforpreventingdatacorruptionandsecuritybreachesinmulti-userapplications.Sessionlockingisimplementedusingserver-sidelockingmechanisms,suchasReentrantLockinJ

有其他PHP會議的選擇嗎?有其他PHP會議的選擇嗎?Apr 29, 2025 am 12:36 AM

PHP會話的替代方案包括Cookies、Token-basedAuthentication、Database-basedSessions和Redis/Memcached。 1.Cookies通過在客戶端存儲數據來管理會話,簡單但安全性低。 2.Token-basedAuthentication使用令牌驗證用戶,安全性高但需額外邏輯。 3.Database-basedSessions將數據存儲在數據庫中,擴展性好但可能影響性能。 4.Redis/Memcached使用分佈式緩存提高性能和擴展性,但需額外配

在PHP的上下文中定義'會話劫持”一詞。在PHP的上下文中定義'會話劫持”一詞。Apr 29, 2025 am 12:33 AM

Sessionhijacking是指攻擊者通過獲取用戶的sessionID來冒充用戶。防範方法包括:1)使用HTTPS加密通信;2)驗證sessionID的來源;3)使用安全的sessionID生成算法;4)定期更新sessionID。

PHP的完整形式是什麼?PHP的完整形式是什麼?Apr 28, 2025 pm 04:58 PM

文章討論了PHP,詳細介紹了其完整形式,在We​​b開發中的主要用途,與Python和Java的比較以及對初學者的學習便利性。

PHP如何處理形式數據?PHP如何處理形式數據?Apr 28, 2025 pm 04:57 PM

PHP使用$ \ _ post和$ \ _獲取超級全局的php處理數據,並通過驗證,消毒和安全數據庫交互確保安全性。

PHP和ASP.NET有什麼區別?PHP和ASP.NET有什麼區別?Apr 28, 2025 pm 04:56 PM

本文比較了PHP和ASP.NET,重點是它們對大規模Web應用程序,性能差異和安全功能的適用性。兩者對於大型項目都是可行的,但是PHP是開源和無關的,而ASP.NET,

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),