on
May 06, 2021
PHP has been one of the top (if not best) server-side scripting languages in the world for decades. However, let’s be honest – error logging in PHP is not the most straightforward or intuitive. It involves tweaking a few configuration options plus some playing around to get used to. Once you have everything set up and figured out (like you will after reading this post), things seem much easier, and you realize how helpful error logging can turn out to be for your application – from debugging and troubleshooting to monitoring and maintenance.
And this is why we are covering error logging in PHP in this post. We will start by revisiting the importance of logging errors in your application. We will then explore errors in PHP – their different types, and how they can be output. Next, we will look at all the error logging configurations in PHP, and understand how we can tweak these to our liking, before we see some error logging examples, and explore functions in PHP that allow us to write errors to log files. This post is a complete guide to error logging in PHP.
Here’s an outline of what we’ll be covering so you can easily navigate or skip ahead in the guide:
- Importance of Logging Errors
- PHP Error Types
- Where Can PHP Errors be Output
- Enabling and Configuring Error Reporting in PHP
- Logging Errors in PHP
- PHP’s Error Logging Functions
- error_log()
- trigger_error()
- syslog()
- set_error_handler()
- Popular PHP Logging Libraries
Importance of Logging Errors
Errors in software systems have this terrible reputation of being associated with failing things and breaking functionality. As a result, many of us often fail to recognize the importance of these loud red strings that bring our attention to faults, inconsistencies, and inaccuracies in our code – mistakes that can cost us dearly if allowed to fall through the cracks. Therefore, it is worthwhile for some of us to change our outlook towards error messages – to track, log, and organize them – and embrace their importance.
There’s a reason developers and organizations build and leverage dedicated logging systems that keep track of errors that arise throughout an application’s lifecycle. These logs provide useful information about what went wrong, when, where, and how it can be fixed.
For small-scale personal projects, it is common for developers not to feel the need to spend time setting up an effective logging system. This seems plausible because your code and end-user interactions are much more manageable for smaller projects. However, the requirement for effectively logging and maintaining errors and other information grows exponentially as your application scales. For larger applications, catering to thousands of users, it becomes unwieldy to track errors and updates across hundreds of components in real-time. Putting in place a system that can record the status of the very many events that an application’s operation entails allows organizations to maintain a clear record of their performance. This allows for more transparency and therefore ensures that no issues go unnoticed. As a result, this makes your application more reliable, easy to maintain, monitor, and debug.
Now that we are hopefully convinced that error logging is a worthwhile expedition, let us look at the different types of errors in PHP.
PHP Error Types
Broadly, there are five types of errors in PHP:
1. Fatal run-time Errors (E_ERROR)
These errors typically happen when an operation in your code cannot be performed. This leads to your code exiting. An example of a fatal error would be when you call a function that hasn’t been defined in your code, shown below:
<?php
function foo() {
echo "Function foo called.";
}
boo(); // undefined function 'boo'
?>
Error output –>
Fatal error: Uncaught Error: Call to undefined function boo() in code/my-php/index.php:5 Stack trace: #0 {main} thrown in code/my-php/index.php on line 5.
2. Warning Errors (E_WARNING)
A warning error is more gentle and less obtrusive in that it does not halt the execution. It presents a friendly reminder of something amiss in your code – a mistake that might not fail things immediately or fail anything at all but suggests a more accurate way of doing things that make your code more foolproof. These warnings can also save developers from issues that might pose a much bigger threat in the future. An example of a warning error would be when you try to include a file in PHP using an incorrect file path, as shown below:
<?php
include('filename.txt'); // arbitrary file that is not present
echo "Hello world";
?>
Error output ->
Warning: include(filename.txt): failed to open stream: No such file or directory in code/my-php/index.php on line 2
3. Parse Errors (E_PARSE)
Parse errors are also known as syntax errors as they arise from syntactical mistakes in your code. These errors are raised during the compilation of your code, making it exit before it runs. A common example of a parse error is missing a semicolon at the end of a code statement, shown below:
<?php
echo Hello world // no quotes or semicolon used
?>
Error output ->
Parse error: syntax error, unexpected 'world' (T_STRING), expecting ',' or ';' in code/my-php/index.php on line 2.
4. Notice Errors (E_NOTICE)
Notice errors are minor errors that are encountered during run-time, and just like warning errors, do not halt the execution. They usually occur when the script is attempting to access an undefined variable, for example, as shown below:
<?php
$a = 1;
$c = $a + $b; // undefined variable $b
?>
Error output ->
Notice: Undefined variable: b in code/my-php/index.php on line 3
5. User Errors (E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE)
User errors are user-defined, i.e., present a custom user-generated message raised explicitly from the code to capture a specific condition. These errors are manually raised by developers using the trigger_error function instead of the PHP engine. They are further classified as fatal, warning, and notice errors, but we’ll group them all as user errors for simplicity.
Where can PHP Errors be Output?
There are two primary places where we can have our errors presented in PHP – through inline errors and dedicated error log files.
Inline Errors
Inline errors are those that show up on your webpage in the browser or your terminal via STDOUT in a command-line environment. These errors prove to be quite useful during development – for developers to debug their code, fix issues, and get information about the overall execution. Below is an example of what these errors usually look like in the browser:
Though this proves to be super helpful for developers, you should be very careful in ensuring that these errors are not output when your application goes into production – for two reasons – end-user experience and security. You can toggle the displaying of these errors using the display_error directive in your system’s configuration. We’ll dive deeper into this in the next section.
Error Log Files
Inline errors are not persistent in memory, i.e., they are not saved anywhere and are only viewed as long as the browser or terminal session is alive. Additionally, you’ll only want to have them in a development environment. Conversely, as the theme of this post suggests, logging your errors is the more intelligent and more systematic approach towards maintaining large-scale applications. These are persistent in memory and provide information about the operation of your application across multiple components in one place, making it easier for monitoring and troubleshooting.
PHP, therefore, allows you to direct all your errors to specific log files; these files store timestamps, error stack traces, custom messages, and other helpful information about the source of the error and how to fix it. You can specify the path of your custom log file using the error_log directive of your system configuration. Here’s an example of an error log file:
You can also choose to have your errors logged to the system’s log file, usually located in – /var/log/syslog. We’ll cover this in a later section in the post.
Now let’s look at how we can configure where and how we want our errors logged.
Enabling and Configuring Error Reporting in PHP
As we discussed previously, logging in PHP is slightly less straightforward than other languages and frameworks. You might have to tweak a few options in configuration files to customize logging patterns. For example, when you install PHP on your machine, the initial configuration comes with some aspects of error logging disabled. This differs from system to system, and therefore, you should manually check these settings before getting started.
Logging Configuration Options in php.ini File
The configuration options are in the php.ini file. This file is read when PHP starts up and allows developers to play around with PHP’s functionality. Usually, this file can be found somewhere in the /etc/php directory on most Linux systems.
There are a bunch of directives (options) pertaining to the logging of errors in PHP that we can configure in this php.ini file:
- display_errors (default: 1)
Display errors are the inline errors we previously looked at. This directive can be used to good effect during development to output PHP error messages to the browser or terminal. However, for applications in production, you should likely turn this off to save your users from a poor website experience due to obscure error messages. Not only that, but this also protects you from exposing valuable information about the internals of your application as a security measure.
- display_startup_errors (default: 0)
As the name suggests, this is to output any errors that take place when PHP starts up. These usually do not provide any valuable information about your application specifically, and therefore need not be turned on.
- log_errors (default: 0)
This directive allows you to toggle the logging of errors to the specified path (in the next directive). Because this is turned off by default, it would be advisable to toggle this to 1 for recording your application’s error messages in a log file.
- error_log (default: 0)
This directive allows you to specify the path of your log file. You can also set this to “syslog” for directing all your error log messages to the system log.
- error_reporting (default: null)
The error_reporting directive allows you to customize which error levels you want reported, and which you are okay with going unreported. For example, you can use the directive as shown below to have all errors reported: error_reporting = E_ALL
- track_errors (default: 0)
This directive allows you to access the last raised error message in the $php_errormsg global variable in your code and can keep track of errors across your whole project.
After making changes to your php.ini file, you will need to restart the server for the changes to take effect.
The ini_set() Function
However, if you are unable to locate the php.ini file, or prefer overriding your project’s global configuration options, there is also an option to update these directives using the ini_set() function in your PHP code. For example, the below code can be used for customizing error reporting in your project:
<?php
// enabling error logging
ini_set('log_errors', 1);
// Customize reporting of errors
ini_set('error_reporting', E_WARNING | E_ERROR | E_PARSE | E_NOTICE);
// specify error log file path
ini_set('error_log', '/tmp/my-logs.log');
?>
The error_reporting() Function
One can also modify the error_reporting configuration option using the error_reporting() function from inside your code during run-time. As in the ini_set function, you can use bitwise operators like OR (|), AND (&), NOT (~), etc., when specifying the error levels to be reported. Below are a few examples of how this function can be used.
// Report only selected kinds of errors
error_reporting(E_ERROR | E_PARSE | E_NOTICE);
or
// Report all errors except E_WARNING
error_reporting(E_ALL & ~E_WARNING);
Now that we have got the system configurations and overall setup out of the way, let’s look at an example of how errors in your project code can be logged to files on your system.
Logging Errors in PHP
First, we will override the logging configuration parameters using the ini_set() function to enable error logging and specify the log file’s path. Then we’ll write some erroneous code to have PHP raise an error that we would like to have logged.
<?php
ini_set('log_errors', 1); // enabling error logging
ini_set('error_log', '/path/my-error-file.log'); // specifying log file path
echo $b; // undefined variable should raise error
?>
After opening the web page on our browser, let’s open the ‘my-error-file.log’ file to see if the error message was logged. Here is the log file output:
[28-Feb-2021 13:34:36 UTC] PHP Notice: Undefined variable: b in code/my-php/index.php on line 5
As you can see, our notice error was logged with a timestamp. As our code encounters more and more errors, this file will keep getting populated with corresponding timestamps. Note that we haven’t explicitly turned off display_errors, so these error messages are likely to be logged to the browser web page – something you might want to avoid during production.
This was an example of capturing errors raised by PHP in log files. Now let’s look at how we can raise and log custom error messages for our application.
PHP’s Error Logging Functions
So far, we looked at errors raised by PHP – errors about your code execution. However, oftentimes you would want to also capture custom errors, with custom error messages specific to the functioning of your application. These so-called errors might not necessarily fail your code or halt its execution, but can indicate conditions characterized as erroneous and noteworthy for your application. These can act as indications to the organization about anomalous behavior that the team might want to look into and fix.
To facilitate this, PHP provides a set of functions that we can use to actively log errors in our code.
error_log()
The most common method for actively logging errors is the error_log() function. This sends a string argument for the error message to the log file.
error_log (string $message, int $message_type=0, string $destination=?, string $extra_headers=?) : bool
It also takes many other parameters to send error messages over email or specific log files. However, for the sake of simplicity, we won’t be covering that here.
The interesting thing about this function is it logs your error message to the file specified in the configuration (or to the system log), regardless of the value of the log_errors directive. Let’s take a very simple example of logging an error when a specific condition in our code is met.
<?php
ini_set('error_log', '/path/my-error-file.log');
$a = 5;
$b = 10;
$c = $a + $b;
if ($c < 20) {
error_log("Sum is less than 20."); // logging custom error message
}
?>
Here is the output of the log file:
[28-Feb-2021 13:31:50 UTC] Sum is less than 20
Similarly, you can also log the values of variables in your code to provide additional context about your errors. Let’s see an example for that:
<?php
ini_set('error_log', '/path/my-error-file.log');
$languagesArray = array("PHP", "Python", "Node.js");
error_log("Lorem ipsum. Array data -> ".print_r($languagesArray, true));
?>
Here’s the output of the log file ->
[28-Feb-2021 13:49:28 UTC] Lorem ipsum. Array data -> Array
(
[0] => PHP
[1] => Python
[2] => Node.js
)
trigger_error()
The trigger_error() function can be used to raise a user-defined error/warning/notice. You can also specify the error type based on the condition. This allows you to customize its reporting and other behavior – for example, using an error type of E_USER_ERROR. We can cause the code to exit immediately compared to an E_USER_WARNING error.
trigger_error (string $error_msg, int $error_type=E_USER_NOTICE) : bool
The difference between trigger_error and error_log is that the former only generates a user error and depends on your system’s logging configurations to handle this error message (whether displayed or logged). error_log, on the other hand, will log your message regardless of the system’s configuration.
Here is the code for the same example we saw previously:
<?php
ini_set('log_errors', 1); // enabling error logging
ini_set('error_log', '/path/my-error-file.log'); // specifying log file path
$a = 5;
$b = 10;
$c = $a + $b;
if ($c < 20) {
trigger_error("Sum is less than 20.", E_USER_ERROR);
echo "This will not be printed!";
}
?>
This adds a similar log entry to what we saw previously, but with an error level, plus the conventional error source information (log file output below):
[01-Mar-2021 01:16:56 UTC] PHP Fatal error: Sum is less than 20. in code/my-php/index.php on line 10
syslog()
You can also choose to directly send an error message to the system’s log using the syslog() function.
syslog (int $priority, string $message) : bool
The first argument is the error’s priority level – LOG_ERR, LOG_WARNING, LOG_NOTICE, LOG_ALERT, LOG_EMERG, etc. (more about it here). The second argument is the actual message’s text. This is how the function can be used:
<?php
// opening logger connection
openlog('myApp', LOG_CONS | LOG_NDELAY | LOG_PID, LOG_USER | LOG_PERROR
); // more information about params in documentation
syslog(LOG_WARNING, "My error message!");
closelog();
?>
This should reflect in your system’s logger (usually in /var/log/syslog) as:
Mar 1 13:27:15 zsh php: My error message!
set_error_handler()
To customize the handling of all the user-defined errors throughout your code, PHP allows you to specify a custom error handler function to override the default handling of errors. This makes it easy for organizations to modify how they want their errors logged, the corresponding error messages send method, and much more. The set_error_handler() function helps with this.
set_error_handler (callable $error_handler, int $error_types=E_ALL | E_STRICT) : mixed
It takes as an argument our custom error handler function, which will define the handling of our errors, and look something like this:
handler (int $errno, string $errstr, string $errfile=?, int $errline=?, array $errcontext=?) : bool
This takes in many parameters like the error number, error string, corresponding file, etc. Let’s understand this better using the same previous example:
<?php
// custom error handler function ->
function myErrorHandler($errno, $errstr, $errfile, $errline, $errcontext){
$message = date("Y-m-d H:i:s - "); // timestamp in error message
$message .= "My Error: [" . $errno ."], " . "$errstr in $errfile on line $errline, \n"; // custom error message
$message .= "Variables:" . print_r($errcontext, true) . "\r\n";
error_log($message, 3, "/path/my-error-file.log");
die("There was a problem, please try again."); // exit code
}
set_error_handler("myErrorHandler");
$a = 5;
$b = 10;
$c = $a + $b;
if ($c < 20) {
trigger_error("Sum is less than 20.", E_USER_WARNING);
}
echo "This will not be printed!";
?>
Here, we define a custom error handler function where we modify the error message a bit, log it, and exit the code. Then, when we use the trigger_error() function, its logging is handled by the above function, which takes care of the rest. This is what the output in the log file looks like:
2021-03-01 06:58:07 - My Error: [512], Sum is less than 20. in code/my-php/index.php on line 22,
Variables:Array
(
[a] => 5
[b] => 10
[c] => 15
)
As you can see, this can be used to fully customize error logging in applications, allowing organizations to prioritize aspects of errors and contexts that are more important for their application.
Popular PHP Logging Libraries
Thanks to the huge PHP community support on the internet, there have been very many logging libraries that aim to provide more functionality and ease the overall process for developers and organizations. Each of the renowned PHP frameworks that you must have heard of come equipped with logging libraries built-in. There are also now logging standards established, like the PSR-3 (PHP Standards Recommendation) logger interface, that defines a standardized interface to follow for logging libraries.
Below is a list of some of the most popular logging libraries in PHP:
- Monolog
- Analog
- KLogger
- Log4PHP
Feel free to check these out to see what default error logging in PHP is missing out on.
Wrapping Up
In this post, we covered everything about errors and logging in PHP. We discussed the importance of logging mechanisms in your application, looked at the different types of errors in PHP, and explored the various configuration options and PHP functions that we can use to log errors effectively.
Now that you have a decent understanding of everything, go ahead and start implementing error logging for your application! It doesn’t matter if you are working on a small project where things might seem under control even without log files. Logging your errors is considered one of the top “best practices” in software development that becomes exponentially more important as your applications grow and scale.
To learn more about logging in PHP in general, feel free to check out the Tutorial: Log to Console in PHP on our blog!
To up your application monitoring game by identifying bottlenecks and gaining effective application performance insights, check out ScoutAPM to get started with a 14-day free trial!
Happy coding!
PHP – язык программирования, который существует достаточно давно. Он популярен и хорошо известен. Используется для создания веб-приложений, а также клиент-серверных моделей. С помощью PHP можно разрабатывать как простые, так и более сложные программы.
Сегодня предстоит познакомиться с логами ошибок PHP. Необходимо выяснить, что собой представляет «баг» и какими бывают сбои. Также предстоит разобраться с тем, что такое логирование, для чего оно необходимо. Соответствующие данные пригодятся как новичкам, так и уже более опытным разработчикам. Они особо важны при отладке программного обеспечения.
Ошибка – это…
Ошибка в the PHP – структура данных, которая указывает на то, что «что-то пошло не так» в процессе исполнения исходного кода. Это своеобразный сбой системы.
Рассматриваемый ЯП позволяет различными способами имитировать ошибку. Наиболее простой вариант – это функция die:
С ее помощью удается завершить программу и сообщить системе о сбое. Принципы обработки «багов» можно контролировать.
The error в PHP вызывается при помощи функции trigger_error:
По умолчанию система выведет лог некритического уведомления. Условно все «сбои» программного обеспечения в рассматриваемом ЯП могут быть поделены на две категории:
- Обычные.
- Исключения. Они появились с PHP5. Могут быть созданы без проблем за счет статической типизации.
Сбои в the PHP встречаются различных типов. Он этот момента зависит логирование информации.
Типы сбоев в языке
Перед изучением log error the PHP необходимо выяснить, каких типов бывают «баги»:
- Синтаксические. Указывают на то, что в скрипте функции написаны неправильно. Пример – пропуск точки с запятой или «забытая» скобка.
- Фатальные. По названию становится ясно, что такой «баг» является критичным. Он приводит к сбою работы приложения. Функции могут выдать непредсказуемый результат. Чаще всего из-за них программное обеспечение вовсе выходит из строя.
- Предупреждающие. При их появлении скрипт продолжает работать. Обычно появляются из-за того, что в системе «что-то пошло не так» и сейчас это не представляет опасности, но в будущем может стать серьезной проблемой. Данной категории неполадок необходимо уделять особое внимание.
- Уведомления об ошибках. Напоминают предыдущий вариант сбоев в the PHP. Не вызывают остановку реализации скрипта. Это менее «важные» баги, чем в предыдущем случае.
Использование логирования помогает разработчикам не только отлавливать, но и своевременно исправлять the errors в коде.
Особенности записи
Все параметры исходного скрипта, включая версию, будут записываться в отдельный файл. Он называется the php.ini. С его помощью можно активировать лог программных ошибок. Когда на сервере применяется какая-нибудь панель управления, соответствующую опцию допускается подключить там. В противном случае, лог будет активироваться вручную.
Чтобы активировать the php log, потребуется в файл php.ini вставить фрагмент кода, указанный выше. При активации display_errors сбои будут выводиться на экран. В разделе error_log необходимо указать путь к файлу, в который записывается информация. Она пригодится разработчику для непосредственной отладки исходного проекта.
Теперь потребуется создать документ php-errors.log. Ему выдаются права, позволяющие записывать в файл информацию – в Debian-подобных системах Apache будет работать от имени системного пользователя www-data:
Нужно перезапустить сервер:
или.
После этого система начнет записывать все сбои, произошедшие в приложении во время работы, в специально отведенный файл. Это – только один из нескольких возможных вариантов реализации логирования в рассматриваемом языке. Далее будут представлены иные подходы к операции.
Использование htaccess
The error log php может быть активирован альтернативным способом. Следующий вариант не требует редактирования документа php.ini. Он используется тогда, когда разработчик имеет дело с Apache и mod_php.
Данный прием подразумевает редактирование .htaccess в корне сайта. Там необходимо вставить следующую запись:
Для выключения опции логирования используется команда:
Преимущество соответствующего приема заключается в том, что его можно применять в клиент-серверных моделях с отсутствующими root-правами. Выставленные параметры будут относиться не ко всему серверу, а только к странице, в корне которого добавляется .htaccess. при использовании fast_cgi директива php_flag не работает – возникает ошибка 500.
Все и сразу
А вот наиболее простой вариант отображения всех «багов» в приложении. Достаточно внести следующую запись в скрипт:
Представленный фрагмент функционирует так:
- Функция ini_set постарается переопределить конфигурацию, обнаруженную в ini-документе.
- Display_errors и display_startup_errors – доступные директивы. Первая отвечает за факт отображения сообщений о сбоях у пользователя. Обычно она не используется для «рядового» функционирования сервиса. Display_errors подойдет для разработки.
- Display_startup_errors – самостоятельная директива.
Рассмотренный прием не позволяет отображать синтаксические неполадки? Пропущенные точки с запятыми, отсутствие фигурные скобки и опечатки.
Подробные предупреждения и уведомления
Изучая тему the error log, необходимо обратить внимание на подробные предупреждения и уведомления. Иногда такие сообщения сигнализируют о наличии фатальных сбоев, которые будут реализованы при определенных обстоятельствах. Скрыть «баги», но отображать только предупреждающие окна (warnings) можно при помощи следующего способа:
Для того, чтобы отображать предупреждения и уведомления, требуется указать «E_Warning|E_Notice». В виде аргументов могут быть использованы такие параметры как:
- e_error;
- e_warning;
- e_parse;
- e_notice.
Для сообщения обо всех сбоях, исключая уведомления, достаточно задать параметр e_all &~ e_notice, где e_all – это все поддерживаемые характеристики для функции error_reporting.
Функция логирования
У веб-странице на хостинге сообщения о неполадках не должны показываться конечным пользователям. Эти данные все равно записываются в журналы (логи). Воспользоваться ими при отладке программного обеспечения и сервера удается несколькими способами.
Элементарное решение – это применение функции error-log. Она включает в себя четыре параметра:
- подробная информация о сбое и факте регистрации информации в журнале;
- тип;
- значение;
- заголовок.
Обязательно для использования функции логирования должен быть указан только первый атрибут.
Если type не определен, по умолчанию он равняет 0. Это значит, что информация из используемого журнала будет добавлена к файлу лога, определенному на веб-сервере. Type = 1 отправляет журнал сбоев по указанному адресу.
Для записи сообщений в отдельный документ используется type 3. После него указывается местоположение файла лога. Соответствующее пространство должно быть доступно для записи веб-сервером.
Выше – пример соответствующей записи.
Конфигурация сервера
Логирование in the PHP можно производить при помощи настроек сервера. Лучший способ регистрации возникающих неполадок – регистрация в файле конфигурации веб-приложения. Данный прием актуален для ситуаций, когда у разработчика имеются права администратора для того или иного сервера.
Для Apache необходимо использовать следующий фрагмент PHP:
В Nginx директива будет иметь иное название:
Теперь понятно, как работать с the error-log in PHP. Это «базовые» навыки, которые помогут формировать журналы ошибок и выводить их в отдельные документы. Лучше изучить вопросы отладки в упомянутом языке помогут дистанционные компьютерные курсы.
Давайте поговорим о безопасности при обработке данных, связанной с выводом отладочной информации в браузер посетителя. Очень часто, при обработке клиентских данных весь вывод отладочной информации, как и ошибок, программисты отправляют в браузер посетителя, совершенно не задумываясь при этом о дальнейшем профилировании проекта и его усовершенствовании, а также о том, что своими же руками они предоставляют конфиденциальные технические данные работы проекта любому желающему, да и попросту раздражают этим рядового пользователя.
Это при том, что PHP уже давно обладает богатым набором функций и средств для логирования, журналирования и сбора ошибок и непредвиденных ситуаций. Кроме этого часть ошибок так и остается «за кадром», которые можно выявить и устранить уже в процессе работы, тем самым повышая стабильность сайта и избегая потери новых посетителей, которые, столкнувшись с определенными трудностями и ошибками, попросту уйдут на другой ресурс.
Итак, перейдем к сути вопроса. Допустим, у нас есть страница, отображающая новости раздела, в контексте которой согласно id страницы $_GET[‘ limitfrom’] категории $_GET[‘id’] мы выбираем количество новостей $_GET[‘limit’] из связанной таблицы материалов `news`.
Обычно (утрировано и упращенно) это выглядит, например, так:
<?php $id = $_GET['id']; $limitfrom = $_GET['limitfrom']; $limit = $_GET['limit']; $sql = 'SELECT * FROM news WHERE category_id =' . (int)$id.' LIMIT '. (int)$limitfrom.','.(int)$limit; $resource = mysql_query($sql); If($resource && is_resource(resource)){ //обработка данных } else { echo mysql_error(); die(); } ?>
Пример «взят» не из воздуха, вот так, приблизительно, но в более сложной форме выглядит разбитие на постраничную навигацию в разделах известного новостного движка DLE. А также вот так (echo mysql_error(); die()) выводится, зачастую, в браузер посетителя возникновение mysql ошибки в Joomla 1.5 и более новых версий (чуть сложнее, но смысл остается тот же).
Здесь была осознанно допущена одна оплошность. Дело в том, что данный вариант будет работать отлично! И в повседневной работе программист не увидит выполнение echo mysql_error().
Но почему не следует выводить в браузер отладочную информацию и ошибки исполнения PHP?
Итак, первое, из за того, что мы обходимся без проверки, что же приходит со стороны клиента, например, отрицательные значения $id и $limit, которые допускаются для типа данных integer, или несуществующие значения приведут к выводу отладочной информации mysql_error(). Итак, ясным по белому, мы дадим информацию злоумышленнику о существующих таблицах и пищу для размышления, как же проще осуществить mysql injection в другом месте, где используются эти же таблицы при составлении запросов. Или же в некоторых случаях покажем посетителям техническую информацию, которую видеть они не должны. С одной стороны здесь нам помогут более строгие проверки входных данных. Перепишем этот пример с использованием выше сказанного:
<?php $id = abs((int)$_GET['id']); $limit = abs((int)$_GET['limit']); $limit = $limit ? $limit : 10; $limitfrom = abs((int)$_GET['limitfrom']); $sql = 'SELECT * FROM news ' .($id && !empty($id) ? 'WHERE category_id='. $id : '') .( $limitfrom && !empty($limitfrom) ? ' LIMIT '. $limitfrom.', '. $limit.'' : ' LIMIT '. $limit.''); $resource = mysql_query($sql); If($resource && is_resource(resource)){ //обработка данных } else { echo mysql_error(); die(); } ?>
Мы предотвратили, как минимум, возникновение нескольких исключительных ситуаций. Мы знаем, что нам нужны только лишь целые положительные значения $id,$limit – поэтому используем явное приведени типов для этих переменных, оператор приведения к целому (int) и функцию получения целого числа abs(). Также мы знаем, что количество выбранных новостей не должно быть равно нулю, поэтому определяем минимальный «порог» в 10 новостей $limit = $limit ? $limit : 10;, формируя запрос, мы проверяем данные, и если они есть и отличны от 0, то добавляем их в mysql запрос по частям.
Все бы хорошо, но и здесь могут быть подводные камни. И все равно существует некоторая вероятность того, что при манипуляции с входными данными злоумышленник увидит вывод той самой информации echo mysql_error();. Зачастую это может получиться даже чисто случайно.
Другой распространенный пример. Многие программисты добавляют вывод технической информации еще на этапе подключения к базе данных. Что, в случае отсутствия соединения с базой данных (сверх нагрузки/временной недоступности сервера баз данных) также выводит отладочную информацию посетителям. При этом там, зачастую, могут в простом тексте встречаться даже логин/название базы/хост подключения к базе данных. А сам программист может никогда и не увидеть подобной информации, и даже не узнать о временном полягании проекта (например из за превышения числа подсоединений к базе данных в случае с увеличением аудитории, как итог: при частом повторении проблемы потеря новых посетителей, раскрытие важных технических данных).
А ведь сбор такой информации бывает полезным для профилирования приложения и дальнейшего его усовершенствования (обеспечения стабильности работы). Для выявления «подводных» камней в стабильной работе сайта.
Итак, давайте обратимся к документации по php. К разделу о создании собственных исключений и перенаправлении отладочной информации и ошибок, логировании и журналировании.
Какие функции и данные для логирования в PHP могут быть полезны?
- trigger_error – для генерации исключения.
- ini_set , error_reporting – для подавления вывода ошибок
- set_error_handler – для установки собственной функции «перехвата» ошибок
- register_shutdown_function – для отлова критических ошибок (которая работает, как нужно, начиная с php 5.2)
- error_get_last – функция получения последней ошибки, произошедшей в скрипте, очень полезна в случае прерывания скрипта из за возникновения критической ошибки
- $_SERVER – суперглобальный массив – источник информации – где и когда и какая ошибка произошла
- getenv – функция для получения значения переменных среды окружения сервера, в том случае, если какие-то данные в суперглобальном массиве $_SERVER отсутствуют
Давайте напишем свой перехватичк исключительных ситуаций для дальнейшего логирования данных об ошибках. Суть заключается в следующем, мы переопределим вывод отладочной информации с помощью собственной функции в текстовый файл в определенной папке /errors, чтобы его не смогли прочесть извне, присвоим ему расширение .php (можно и при помощи запрета прямого доступа извне к этой папке, но данный метод более универсален для любых серверов и не требует дополнительной настройки окружения сервера) и добавим первой строчкой <?php die(«Forbidden.»); ?>, название же зададим ему, совпадающее с текущей датой, чтобы было проще ориентироваться. В итоге один файл ошибок – одна дата.Также мы добавим «перехват» критических ошибок. И при помощи функции trigger_error для логирования непредвиденных ситуаций и генерации собственных ошибок типа E_USER:
Примечание автора: желательно подключить подобный код как можно раньше, еще на этапе инициализации созданного php приложения:
<?php error_reporting(0); ini_set('error_reporting','0'); ini_set('display_errors', '0'); ini_set('display_startup_errors', '0'); ini_set('ignore_repeated_errors', '1'); define ('ROOT_PATH', dirname(dirname(__FILE__))."/"); //запретить/разрешить вывод ошибок define('_ERR_HANDLING',true); //где будем хранить файлы ошибок define('_ERR_DIR',ROOT_PATH.'errs/'); function error_reporting_log($error_num, $error_var=null, $error_file=null, $error_line=null) { $error_desc= ''; $error_desc = 'Error'; switch ($error_num){ case E_WARNING: $error_desc = 'E_WARNING'; break; case E_USER_WARNING: $error_desc = 'E_USER_WARNING'; break; case E_NOTICE: $error_desc = 'E_NOTICE'; break; case E_USER_NOTICE: $error_desc = 'E_USER_NOTICE'; break; case E_USER_ERROR: $error_desc = 'E_USER_ERROR'; break; case E_ERROR: $error_desc = 'E_USER_ERROR'; break; default: $error_desc = 'E_ALL'; break; } $date_file = date('y-m-d H:I:S'); $logfile= LOG_FILE; $url = $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']; $date_time = date('d.m.y - H:i:s'); $ip= isset($_SERVER['REMOTE_ADDR']) && !empty($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : getenv('REMOTE_ADDR ') ; $from= isset($_SERVER['HTTP_REFERRER'])&& !empty($_SERVER['HTTP_REFERRER'])? $_SERVER['HTTP_REFERRER'] :getenv('HTTP_REFERRER'); $errortext = $error_desc.': '.$error_var."\t".' Line: '.$error_line."\t".' File: '.$error_file."\t".' Link: '.$url."\t".' Date: '.$date_time."\t".'IP: '.$ip."\t".' FROM:'.$from."\n"; unset($from,$error_desc, $error_var,$error_line, $error_file,$url,$date_time,$error_write); $secuire= '<?php die("Forbidden."); ?>'; if(is_file($logfile)&&is_writeable($logfile)){ $fp = fopen($logfile,'r'); if($fp && is_resource($fp)){ $strings= fgets($fp); if(isset($strings)&&!empty($strings) &&strpos($strings,$secuire)===false){ unlink($logfile); } fclose($fp); }; unset($fp); } if(!is_file($logfile)){ $dir= dirname($logfile); if(is_dir($dir)&&is_writable($dir)){ $fp = fopen($logfile,'w+'); if(is_resource($fp)){ flock($fp,LOCK_EX); fwrite($fp,$secuire."\n"); flock($fp,LOCK_UN); fclose($fp); $fp= null; } unset($dir,$fp); } } unset($secuire); if(is_file($logfile)&&!is_writable($logfile)){ chmod($logfile,0775); } if(is_file($logfile)&&is_writeable($logfile)){ $fp = fopen($logfile,'a+'); if(is_resource($fp)){ flock($fp,LOCK_EX); fwrite($fp,$errortext); flock($fp,LOCK_UN); fclose($fp); $fp= null; unset($fp); } } unset($logfile); return true; } function err_handler(){ if(_ERR_HANDLING){ $error_reporting= ''; $error_reporting= ini_get('error_reporting'); $error_reporting= $error_reporting?$error_reporting:E_ALL; error_reporting(E_ERROR); $date_file = date('dmY').'.php'; $dir= _ERR_DIR; $path= $dir.$date_file; $logfile= ''; if(!is_dir($dir) || !is_writable($dir)){ if(is_dir($dir)&&!is_writable($dir)){ chmod($dir,0775); } else if(!is_dir($dir)){ $isdir= false; $isdir= mkdir($dir,0775); } if(!$isdir&&!is_writable($dir)){ $dir= ROOT_PATH; $path= $date_file; } } if(is_dir($dir) && is_writable($dir)){ if(!is_file($path)){ $fp= fopen($path,'w+'); if($fp && is_resource($fp)){ $secuire= '<?php die("Forbidden."); ?>'; flock($fp,LOCK_EX); fwrite($fp,$secuire."\n"); flock($fp,LOCK_UN); fclose($fp); $fp= null; unset($secuire); } } if(is_file($path) && !is_writable($path)){ chmod($path,0775); } if(is_file($path) && is_writable($path)){ ini_set('display_errors',0); set_error_handler('error_reporting_log', (E_ALL & ~E_NOTICE)); $logfile= $path; define('LOG_FILE',$logfile); } unset($date_file,$dir,$path,$logfile); } error_reporting($error_reporting); unset($error_reporting); } } function critical_error(){ $error = error_get_last(); if(is_array($error) && sizeof($error) && isset($error['type']) && $error['type'] == E_ERROR && !empty($error['message']) && !empty($error['file']) && !empty($error['line'])){ error_reporting_log($error['type'], $error['message'],$error['file'],$error['line']); } } if(function_exists('register_shutdown_function') && function_exists('error_get_last') && _ERR_HANDLING){ register_shutdown_function('critical_error'); } err_handler();
Что здесь происходит? При помощи функции ini_set и error_reporting мы подавляем вывод ошибок в браузер посетителя, константами определяем местоположение нашей директории для хранения логов ошибок define(‘_ERR_DIR’,ROOT_PATH.’errs/’);. Определенная в самом начале константа (bool) _ERR_HANDLING – при значении true разрешит перенаправление всех наших ошибок в файлы, при значении false дальнейшие инструкции выполняться не будут. Для перехвата самих ошибок используется функция error_reporting_log, которая принимает тип ошибки, сообщение об ошибке, имя файла, где произошла ошибка, и строку, в которой она произошла. В ней мы собираем кроме этой информации, и другие полезные данные. А именно:
- $_SERVER[‘HTTP_REFERRER’] — откуда пришел посетитель, с какой страницы?
- $_SERVER[‘REMOTE_ADDR’] — ip посетителя,
- $_SERVER[‘HTTP_HOST’]. $_SERVER[ ‘REQUEST_URI’] – полный адрес страницы вместе со строкой запроса, на которой возникла ошибка
- date(‘y-m-d H:I:S’) — текущее время возникновения ошибки.
Зачастую, подобной информации хватит с головой и для логирования и исправления ошибок, которые были не замечены на этапе разработки, так и для отлова злоумышленников. Но есть один тип ошибок, который не будет перехвачен. Это критические ошибки PHP E_ERROR, которые приводят к прерыванию php скрипта . Начиная с версии PHP 5.2 для перехвата критических ошибок можно определить собственную функцию при мопощи register_shutdown_function. Мы создаем собственную функцию для этих целей critical_error, в которой при помощи функции error_get_last получаем информацию о текущей ошибке. Так как данная функция будет всегда выполняться после завершения php скрипта, мы логируем информацию только об ошибках с типом E_ERROR.
Можно было бы использовать функцию error_log с указанием пути к источнику логирования, но было отдано предпочтение простым файловым функциям, при помощи которых можно установить функцией flockприоритетное эксклюзивное запирание во избежание попыток одновременной записи в логфайл несколькими скриптами (и возникновения «битых» файлов).
Давайте на примере все того же скрипта с mysql рассмотрим принцип логирования mysql ошибок (впрочем, по такому же принципу можно построить логирование любых внештатных ситуаций):
<?php $id = abs((int)$_GET['id']); $limit = abs((int)$_GET['limit']); $limit = $limit ? $limit : 10; $limitfrom = abs((int)$_GET['limitfrom ']); $sql = 'SELECT * FROM news ' .($id && !empty($id) ? 'WHERE category_id='. $id : '') .( $limitfrom && !empty($limitfrom) ? ' LIMIT '. $limitfrom.', '. $limit.'' : ' LIMIT '. $limit.''); $resource = mysql_query($sql); If($resource && is_resource(resource)){ //обработка данных } else { $string = print_f( 'Ошибка mysql при получении новостей из категории с ID: %d,' . 'на странице: %d , ' . 'информация о запросе: %s,' . ' информация об ошибке: %s', $id,$limitfrom, $sql, mysql_error()); trigger_error($string,E_USER_ERROR); die(); } ?>
Вот и все, в файле ошибок при возникновении ошибки mysql будет добавлена новая строка с подробной информацией. Таким способом вы сможете логировать практически любую полезную для вас информацию, скрыв ее от Ваших посетителей. А сбор и анализ подобной информации поможет в дальнейшем в повышении стабильности и совершенствовании Вашего проекта.
Примечание автора: также для генерации и перехвата ошибок Вы можете использовать конструкции try{}catch(Exeption $e){ thrown(throw new Exception(«$name contains the word name»);}
Примечание автора: правилом хорошего тона при перехвате и обработке ошибок (особенно критических, которые ведут к невозможности предоставить посетителю необходимую информацию, за которой он, собственно, и пришел к Вам на сайт) является создание для каждого вида подобных ошибок статической страницы с объяснением на человекопонятном языке без технических данных сути проблемы (также на такой странице можно оставить контакты админитрации) и перенаправление посетителя на нужную страницу в ходе возникновения ошибки.
Например, в приведенном примере с категориями можно создать страницу с подобным текстом:
Уважаемый посетитель!
Новости данной категории временно недоступны или отсутствуют, возможно, часть новостей была удалена, так как устарела, перемещена в архив (ссылка на архив) или другую категорию, Вы пришли к нам по несуществующей ссылке. Перейдите, пожалуйста, на главную страницу сайта (ссылка на главную страницу сайта) или в начало данной категории (ссылка в начало категории), также вы сможете воспользоваться поиском по сайту (ссылка на поиск), или обратите внимание на наши информационные блоки (якорная ссылка на информационные блоки), если Вам необходима именно эта информация, свяжитесь с нами (контактные данные).
Просим Вас уведомить нас о сложившийся ситуации любым удобным для Вас способом
(контактные данные)
Во первых: ваши же посетители будут четко, понятно и информативно ставить Вас в известность о произошедшей ситуации, во вторых: тем самым Вы сбережете их нервы, и даже в случае возникновения непредвиденной ситуации посетители могут продолжить изучать Ваш ресурс.
Информация к размышлению, что можно сделать лучше в этом скрипте?
- Предусмотреть архивацию/удаление данных логирования по истечению определенного периода.
- Предусмотреть помесячную отсылку подобных данных для анализа администратору проекта на email, jabber.
- Предусмотреть сбор и вывод логируемой информации в браузер для определенных пользователей после авторизации (например, экстренная отладка для админа).
- Заменить функциональный подход расширяемыми классами.
Если у вас сайт на PHP, даже самый простой, время от времени в его скриптах могут возникать ошибки. Это может привести к различным неприятным последствиям, от некорректной работы некоторых компонентов сайта (например, формы обратной связи), до недоступности сайта целиком. Как самостоятельно распознать тип ошибки PHP и понять, что с ней делать дальше?
Этот материал поможет вам, во-первых, самостоятельно оценить ситуацию (и, возможно, даже решить ее), а во-вторых, точно ускорит диагностику и решение проблемы при обращении в службу поддержки. Самые ценные советы по устранению наиболее частых ошибок PHP, связанных с лимитами оперативной памяти, вы найдете в конце статьи.
Как обнаружить ошибку PHP на сайте
1. Встроенными средствами браузера
Итак, если на сайте вместо привычной страницы ничего не отображается (вы видите “пустую страницу”), то, вероятнее всего, в одном из скриптов возникла ошибка. В этом можно убедиться, воспользовавшись встроенными «Инструментами разработчика» вашего браузера. В каждом браузере они могут называться немного по-разному, но суть от этого не меняется.
Например, в браузере Google Chrome это вкладка Dev Tools (или «Инструменты разработчика»). В Mozilla Firefox — это расширение Firebug (его нужно установить отдельно в меню Adds On) или же вкладка Developer.
Внутри «Инструментов разработчика» нас интересует вкладка, которая называется Network (или Net, или каким-то похожим образом).
Если на странице сайта присутствует ошибка, в этой вкладке вы увидите код ответа 500 (“Internal Server Error”).
2. Если вывод сообщений об ошибках в браузер отключен
Случается, что вывод сообщений об ошибках в браузер отключён. Чтобы сообщение об ошибке отображалось в браузере, достаточно добавить в файл .htaccess в корневой директории сайта следующую строку:
php_value display_errors on
Файл .htaccess вы найдете по адресу: /home/login/domains/domain.ru/public_html/, где вместо login следует подставить логин вашего аккаунта, а вместо domain.ru — домен вашего сайта.
После сохранения файла .htaccess и обновления страницы вы сможете увидеть ошибку.
Если сайтом используется, например, CMS WordPress, то отображение ошибок можно также включить, заменив в файле wp-config.php:
define(‘WP_DEBUG’, false);
на:
define(‘WP_DEBUG’, true);
3. С помощью журнала ошибок PHP
Иногда по различным причинам отображать ошибки в браузере нежелательно. В этом случае лучше всего сохранять их в какой-нибудь файл, например errors.log — журнал ошибок PHP. Для этого достаточно в файле .htaccess добавить следующую строку:
php_value error_log /home/login/domains/domain.ru/log/errors.log
Здесь /home/login/domains/domain.ru/log/errors.log — это полный путь до файла, в который будут записываться ошибки PHP (если файла с таким именем нет, он будет создан автоматически при появлении ошибки).
Теперь, если мы снова зайдем на сайт с ошибкой (либо обновим страницу с ошибкой), то в errors.log будут записаны сообщения об ошибках.
Журнал ошибок PHP можно просмотреть, например, с помощью файлового менеджера в Панели управления, открыв файл errors.log:
Также можно открыть файл с ошибками и нажать кнопку “Включить автообновление”. Таким образом, новые записи в журнале можно просматривать в реальном времени.
Расшифровка ошибок PHP
Как правило, в сообщении об ошибке достаточно подробно указано где именно и при выполнении какой части кода она возникла. Например:
Здесь ошибка заключается в следующем:
Fatal error: Call to undefined function weblizar_get_options() in /home/login/domains/domain.ru/public_html/wp-content/themes/enigma/header.php on line 14
“Вызов неопределенной функции weblizar_get_options() в файле используемой на сайте темы enigma”.
Вероятнее всего, был поврежден один из файлов темы, поэтому можно восстановить только директорию темы ./wp-content/themes/enigma/ , а не всего сайта.
Что делать, в зависимости от типа ошибки PHP
Условно ошибки PHP можно разбить на 4 уровня:
- PARSE ERROR
- FATAL ERROR
- WARNING
- NOTICE
Parse Error
Возникают, если уже на этапе проверки кода интерпретатором PHP найдена ошибка. Чаще всего это синтаксические ошибка (например, пропущенная точка с запятой). Скорее всего, такая ошибка возникла в результате последних внесенных на сайт изменений.
Что делать?
1. Если вы НЕ специалист в PHP, восстановите сайт из последней резервной копии на тот момент, когда сайт работал без ошибок.
2. Если вы специалист и самостоятельно вносили правки в код сайта, вы наверняка сможете отследить синтаксическую ошибку и исправить ее. Но проще все же воспользоваться пунктом 1.
Fatal Error и Warning
Возникают, если при выполнении кода какой-то его участок не может быть выполнен (например, попытка открыть несуществующий файл). Разница между 2-ым и 3-им уровнем в том, что при получении “критической ошибки” (FATAL ERROR) выполнение скрипта завершится, а при получении “предупреждения” (WARNING) — нет.
Что делать?
Восстановите сайт из последней доступной резервной копии на тот момент, когда он работал без ошибок.
Notice
К этому уровню ошибок относятся различные “замечания”, суть которых обычно отображена в тексте ошибки.
Что делать?
Если замечание самостоятельно исправить не получается, обратитесь в службу поддержки или же восстановите сайт из последней доступной резервной копии на тот момент, когда он работал без ошибок.
Частые ошибки PHP и их решение
Fatal Error: Allowed Memory
Означает, что для выполнения какой-либо части кода PHP не хватает выделенной оперативной памяти. При этом лимит памяти ограничен какими-то директивами «изнутри» сайта (то есть где-либо в скриптах сайта, либо директивой memory_limit в файле .htaccess). Чтобы исправить это, измените данный лимит в большую сторону, например, в файле .htaccess.
Для этого найдите в .htaccess такую директиву:
php_value memory_limit 128M
Вместо 128M укажите желаемый размер ограничения. Обратите внимание, что символ «M» (латинская M) указывается слитно со значением.
Помните, что есть максимальные значения памяти, отведенной на выполнение скриптов PHP, предусмотенные вашим тарифом хостинга (например, на тарифах виртуального хостинга это 512 Мб, премиум — 1024 Мб). Уточните эти значения у вашего провайдера, если они не указаны явно.
Fatal Error: Out of memory
То же самое, что и предыдущая ошибка, с той разницей, что достигнут лимит памяти, заданный “снаружи”. Обратите внимание на параметр “Памяти на процесс, Мб, не более“ в условиях пользования нашим сервисом.
Для решения вопроса в данном случае, скорее всего, потребуется либо оптимизация скриптов, чтобы они потребляли меньше памяти, либо разбиение процессов на части. Например, объемную загрузку или выгрузку данных, если она упирается в данный лимит, имеет смысл производить частями.
Также в этом случае мы советуем попробовать отключить акселераторы PHP, если они у вас подключены.
Unable to allocate memory for pool
Сайтам на аккаунте не хватает выделенной на тарифном плане памяти для акселераторов PHP.
Для решения проблемы вы можете отключить использование акселераторов в Панели управления хостингом, в разделе «Управление персональным веб-сервером».
Также, например, можно отключить акселератор APC для определенного сайта, добавив в файл .htaccess корневой директории следующую директиву:
php_value apc.cache_by_default off
Обычно имеет смысл оставлять APC для использования на самом посещаемом из ваших сайтов — это позволит использовать именно на нем преимущества акселератора, не заполняя его память данными с других, менее посещаемых сайтов.
В случаях, когда акселератор объективно необходим для корректной и комфортной работы сайтов и его отключение нежелательно, напишите в службу поддержки.
Мы постараемся предложить возможные варианты решения.
Желаем вам приятной работы!
В этом руководстве мы расскажем о различных способах того, как в PHP включить вывод ошибок. Мы также обсудим, как записывать ошибки в журнал (лог).
Как быстро показать все ошибки PHP
Самый быстрый способ отобразить все ошибки и предупреждения php — добавить эти строки в файл PHP:
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
Что именно делают эти строки?
Функция ini_set попытается переопределить конфигурацию, найденную в вашем ini-файле PHP.
Display_errors и display_startup_errors — это только две из доступных директив. Директива display_errors определяет, будут ли ошибки отображаться для пользователя. Обычно директива dispay_errors не должна использоваться для “боевого” режима работы сайта, а должна использоваться только для разработки.
display_startup_errors — это отдельная директива, потому что display_errors не обрабатывает ошибки, которые будут встречаться во время запуска PHP. Список директив, которые могут быть переопределены функцией ini_set, находится в официальной документации .
К сожалению, эти две директивы не смогут отображать синтаксические ошибки, такие как пропущенные точки с запятой или отсутствующие фигурные скобки.
Отображение ошибок PHP через настройки в php.ini
Если ошибки в браузере по-прежнему не отображаются, то добавьте директиву:
display_errors = on
Директиву display_errors следует добавить в ini-файл PHP. Она отобразит все ошибки, включая синтаксические ошибки, которые невозможно отобразить, просто вызвав функцию ini_set в коде PHP.
Актуальный INI-файл можно найти в выводе функции phpinfo (). Он помечен как “загруженный файл конфигурации” (“loaded configuration file”).
Отображать ошибки PHP через настройки в .htaccess
Включить или выключить отображение ошибок можно и с помощью файла .htaccess, расположенного в каталоге сайта.
php_flag display_startup_errors on
php_flag display_errors on
.htaccess также имеет директивы для display_startup_errors и display_errors.
Вы можете настроить display_errors в .htaccess или в вашем файле PHP.ini. Однако многие хостинг-провайдеры не разрешают вам изменять ваш файл PHP.ini для включения display_errors.
В файле .htaccess также можно включить настраиваемый журнал ошибок, если папка журнала или файл журнала доступны для записи. Файл журнала может быть относительным путем к месту расположения .htaccess или абсолютным путем, например /var/www/html/website/public/logs
.
php_value error_log logs/all_errors.log
Включить подробные предупреждения и уведомления
Иногда предупреждения приводят к некоторым фатальным ошибкам в определенных условиях. Скрыть ошибки, но отображать только предупреждающие (warning) сообщения можно вот так:
error_reporting(E_WARNING);
Для отображения предупреждений и уведомлений укажите «E_WARNING | E_NOTICE».
Также можно указать E_ERROR, E_WARNING, E_PARSE и E_NOTICE в качестве аргументов. Чтобы сообщить обо всех ошибках, кроме уведомлений, укажите «E_ALL & ~ E_NOTICE», где E_ALL обозначает все возможные параметры функции error_reporting.
Более подробно о функции error_reporting ()
Функция сообщения об ошибках — это встроенная функция PHP, которая позволяет разработчикам контролировать, какие ошибки будут отображаться. Помните, что в PHP ini есть директива error_reporting, которая будет задана этой функцией во время выполнения.
error_reporting(0);
Для удаления всех ошибок, предупреждений, сообщений и уведомлений передайте в функцию error_reporting ноль. Можно сразу отключить сообщения отчетов в ini-файле PHP или в .htaccess:
error_reporting(E_NOTICE);
PHP позволяет использовать переменные, даже если они не объявлены. Это не стандартная практика, поскольку необъявленные переменные будут вызывать проблемы для приложения, если они используются в циклах и условиях.
Иногда это также происходит потому, что объявленная переменная имеет другое написание, чем переменная, используемая для условий или циклов. Когда E_NOTICE передается в функцию error_reporting, эти необъявленные переменные будут отображаться.
error_reporting(E_ALL & ~E_NOTICE);
Функция сообщения об ошибках позволяет вам фильтровать, какие ошибки могут отображаться. Символ «~» означает «нет», поэтому параметр ~ E_NOTICE означает не показывать уведомления. Обратите внимание на символы «&» и «|» между возможными параметрами. Символ «&» означает «верно для всех», в то время как символ «|» представляет любой из них, если он истинен. Эти два символа имеют одинаковое значение в условиях PHP OR и AND.
error_reporting(E_ALL);
error_reporting(-1);
ini_set('error_reporting', E_ALL);
Эти три строки кода делают одно и то же, они будут отображать все ошибки PHP. Error_reporting(E_ALL) наиболее широко используется разработчиками для отображения ошибок, потому что он более читабелен и понятен.
Включить ошибки php в файл с помощью функции error_log ()
У сайта на хостинге сообщения об ошибках не должны показываться конечным пользователям, но эта информация все равно должна быть записана в журнал (лог).
Простой способ использовать файлы журналов — использовать функцию error_log, которая принимает четыре параметра. Единственный обязательный параметр — это первый параметр, который содержит подробную информацию об ошибке или о том, что нужно регистрировать. Тип, назначение и заголовок являются необязательными параметрами.
error_log("There is something wrong!", 0);
Параметр type, если он не определен, будет по умолчанию равен 0, что означает, что эта информация журнала будет добавлена к любому файлу журнала, определенному на веб-сервере.
error_log("Email this error to someone!", 1, "someone@mydomain.com");
Параметр 1 отправит журнал ошибок на почтовый ящик, указанный в третьем параметре. Чтобы эта функция работала, PHP ini должен иметь правильную конфигурацию SMTP, чтобы иметь возможность отправлять электронные письма. Эти SMTP-директивы ini включают хост, тип шифрования, имя пользователя, пароль и порт. Этот вид отчетов рекомендуется использовать для самых критичных ошибок.
error_log("Write this error down to a file!", 3, "logs/my-errors.log");
Для записи сообщений в отдельный файл необходимо использовать тип 3. Третий параметр будет служить местоположением файла журнала и должен быть доступен для записи веб-сервером. Расположение файла журнала может быть относительным путем к тому, где этот код вызывается, или абсолютным путем.
Журнал ошибок PHP через конфигурацию веб-сервера
Лучший способ регистрировать ошибки — это определить их в файле конфигурации веб-сервера.
Однако в этом случае вам нужно попросить администратора сервера добавить следующие строки в конфигурацию.
Пример для Apache:
ErrorLog "/var/log/apache2/my-website-error.log"
В nginx директива называется error_log.
error_log /var/log/nginx/my-website-error.log;
Теперь вы знаете, как в PHP включить отображение ошибок. Надеемся, что эта информация была вам полезна.