Maison  >  Article  >  développement back-end  >  Mécanisme d'erreur PHP

Mécanisme d'erreur PHP

炎欲天舞
炎欲天舞original
2017-08-21 10:16:351540parcourir


Le mécanisme d'erreur de PHP est également très compliqué. Je travaille en PHP depuis plusieurs années et je ne l'ai pas soigneusement résumé. Je vais rattraper cette leçon maintenant.

Remarque spéciale : la version PHP de l'article utilise 5.5.32

Niveau d'erreur PHP

Tout d'abord, vous devez comprendre quelles erreurs il y a dans php. Depuis php5.5, il existe un total de 16 niveaux d'erreur

Remarque : assurez-vous d'activer error_log lorsque vous essayez le code suivant :


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

E_ERROR

Cette erreur est une erreur fatale et affichera Erreur fatale sur la page Lorsque cette erreur se produit, le programme ne peut pas continuer à s'exécuter

Exemple d'erreur :

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



Notez que s'il y a une exception non interceptée, ce niveau sera également déclenché.

// 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

Cette erreur est juste un avertissement et ne terminera pas le script, le programme continuez, le message d'erreur affiché est Avertissement. Par exemple, incluez un fichier qui n'existe pas.


//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

Cette erreur est plus mineure et vous rappelle que cet endroit ne doit pas être écrit ainsi. Il s'agit également d'une erreur d'exécution. Un mauvais code peut ne pas poser de problèmes ailleurs, mais uniquement dans le contexte actuel.

Par exemple, la variable $b n'existe pas, on l'affecte à une autre variable


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

Cette erreur se produit lors de la compilation. Des erreurs de syntaxe sont détectées lors de la compilation et l'analyse syntaxique ne peut pas être effectuée.

Par exemple, z ci-dessous n'est pas défini comme variable.


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

Cette erreur a été introduite après PHP5. Votre code peut s'exécuter, mais ce n'est pas la façon dont PHP recommande de l'écrire. .

Par exemple, passer le symbole ++ dans un paramètre de fonction

// 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

Ce niveau est en fait le niveau ERROR, mais il devrait être capturé s'il n'est pas capturé par le traitement des erreurs, les performances sont les mêmes que E_ERROR.

se produit souvent lorsque le paramètre formel définit un type, mais qu'un type incorrect est transmis lors de l'appel. Son rappel d'erreur comporte également le mot Catachable devant l'erreur fatale de E_ERROR.

//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

Cette erreur signifie que vous avez utilisé une ancienne version de la fonction, et cette fonction est postérieur. La version peut être désactivée ou n'est plus maintenue.

Par exemple, CURLOPT_POSTFIELDS de curl utilise @FILENAME pour télécharger des fichiers

// 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

Ces deux erreurs sont générées par le moteur PHP et se produisent lors du processus d'initialisation de PHP.

E_COMPILE_ERROR, E_COMPILE_WARNING

Ces deux erreurs sont générées par le moteur PHP et se produisent lors du processus de compilation.

E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE, E_USER_DEPRECATED,

Ces erreurs sont toutes causées par les utilisateurs. L'utilisation de trigger_error équivaut à un trou qui déclenche divers types d'erreurs pour les utilisateurs. C'est un bon moyen d'échapper aux exceptions 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 tous les messages d'erreur et d'avertissement.

Contrôle des erreurs

Il existe de nombreuses configurations et paramètres en php qui peuvent contrôler les erreurs et l'affichage du journal des erreurs. La première étape, ce que nous devons savoir, c'est quelles sont les configurations incorrectes en PHP ?

Selon le modèle php+php-fpm, il existe en fait deux fichiers de configuration qui affecteront l'affichage des erreurs php. L'un est le fichier de configuration php.ini de php lui-même, et l'autre est php-fpm. . Fichier de configuration, php-fpm.conf.

Configuration dans 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的问题了。

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn