error_log
Sends an error message to the server log, a specific file, a SAPI handler, or an email address.
error_log(string $message, int $message_type = 0, ?string $destination = null, ?string $additional_headers = null): bool- Added in PHP 4.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$message | string | The message to log. It is not truncated by PHP, but the destination may impose its own limits. |
$message_typeoptional | int= 0 | Where the message goes: 0 = PHP's system logger (the error_log ini setting), 1 = email to destination, 3 = appended to the file named by destination, 4 = the SAPI logging handler. 2 is no longer an option. |
$destinationoptional | ?string= null | The email address when message_type is 1, or the file path when message_type is 3. Ignored otherwise. |
$additional_headersoptional | ?string= null | Extra mail headers, used only when message_type is 1. |
Return value
booltrue on success or false on failure. When message_type is 0 the function always returns true regardless of whether the write succeeded.
Changelog
- PHP 8.0.0destination and additional_headers are now nullable.
error_log() writes a line to wherever PHP has been told to record errors. With the default $message_type of 0 it goes to the destination in the error_log ini setting — a file, or the system logger such as syslog or the Windows event log if none is set. Under a web SAPI that usually means the web server's error log.
Choosing a message type
Type 3 appends to a file you name. It is the right choice for an application-specific log, but PHP does not add a trailing newline, so include \n yourself or your entries will run together on one line. Type 4 hands the message to the SAPI's own logger, which under FPM keeps it in the same stream as PHP's own errors. Type 1 emails the message; it depends on a working mail configuration and should never be wired to anything that can fire in a loop.
What it does not do
It adds no timestamp and no severity when writing to a file with type 3 — you format the whole line. Newlines inside $message break log parsers, so flatten multi-line data before logging. And a false return usually means the destination is unwritable, which is silent unless you check it.
Example
<?php
// Goes to the destination configured by the error_log ini setting.
error_log('payment gateway returned an unexpected status');
// Appends to a file; note the explicit newline.
$line = sprintf("[%s] order %d failed\n", date('c'), 4711);
$ok = error_log($line, 3, 'app.log');
var_dump($ok);
echo file_get_contents('app.log');When to use it
- Record an unexpected API response to the server log without exposing it to the user
- Append structured JSON lines to an application-specific log file
- Log the details captured by a custom error handler before rendering a generic error page
Frequently asked questions
Where does error_log write by default?
To the destination in the error_log ini directive; if that is empty, to the SAPI's logger, which for a web server means its error log and for CLI means stderr. Check the value with ini_get('error_log').
Why is my error_log output all on one line?
message_type 3 writes the string exactly as given and adds no line ending. Append "\n" to every message yourself.
What is the difference between error_log and trigger_error?
trigger_error() raises a real PHP error that error handlers and error_reporting() see, while error_log() just writes text to a log and bypasses the error system entirely.
More examples
Structured JSON log lines
Each call appends one JSON object per line, the format log shippers expect. json_encode() also flattens any newlines in the context values, which keeps one event on exactly one line.
<?php
function logEvent(string $event, array $context = []): void {
$payload = json_encode(['ts' => date('c'), 'event' => $event] + $context);
error_log($payload . "\n", 3, 'events.log');
}
logEvent('checkout.failed', ['order' => 4711, 'reason' => 'card_declined']);
echo file_get_contents('events.log');Logging from a custom error handler
The handler routes every error into the server log and returns true, so PHP's built-in handler never prints anything. The user sees only the normal page output while the detail survives in the log.
<?php
set_error_handler(function (int $no, string $msg, string $file, int $line): bool {
error_log(sprintf('[%d] %s in %s:%d', $no, $msg, $file, $line));
return true; // handled: nothing is shown to the user
});
trigger_error('cache backend unreachable', E_USER_WARNING);
echo "request continues normally\n";
restore_error_handler();Checking the return value
The first write succeeds and returns true. The second targets a directory that does not exist, so PHP emits a warning and returns false. Because logging failures are otherwise invisible, check the return value when the destination is user-configurable.
<?php
$ok = error_log("first line\n", 3, 'writable.log');
var_dump($ok);
// An unwritable destination returns false rather than throwing.
$bad = @error_log("second line\n", 3, 'no-such-dir/deep.log');
var_dump($bad);
echo file_get_contents('writable.log');
Discussion