error_log()
Logging PHP errors with the error_log() function and its parameters.
Logging PHP Errors with the Error Log Function
Printing errors to the screen with echo or var_dump() is fine while you build a feature, but it is the wrong tool in production: screen output is visible to visitors, gets lost on AJAX calls, and disappears the moment the request ends. The built-in error_log() function solves this by sending a message somewhere durable — a log file, an email, or the operating system logger — so you can review it later.
This guide explains what error_log() does, walks through each parameter with runnable examples, and covers the gotchas (trailing newlines, the error_log ini directive, what not to log) that trip people up in real projects.
What the error_log() function does
error_log() writes a single message to a destination you choose. It does not trigger PHP's error machinery, change the exit code, or stop the script — it only records text. The return value is a bool: true on success, false if the message could not be written (for example, the log file is not writable).
Because it is just "append this string somewhere", error_log() is the simplest way to leave breadcrumbs in code that runs without a developer watching — cron jobs, queue workers, webhooks, and any production request.
Function signature
error_log(
string $message,
int $message_type = 0,
?string $destination = null,
?string $additional_headers = null
): bool| Parameter | Meaning |
|---|---|
$message | The text to log. Newlines are not added for you (see the gotcha below). |
$message_type | Where to send it — 0, 1, 3, or 4. See the table further down. |
$destination | The file path (type 3) or email address (type 1). |
$additional_headers | Extra email headers, used only with type 1. |
The default: log to PHP's configured destination
The most common call passes only the message and lets PHP route it to wherever the server is configured to send errors (the error_log ini directive, or the SAPI/system logger if that is unset):
<?php
error_log("Payment gateway returned an unexpected status code");This is exactly where uncaught warnings and notices already go, so your manual messages land next to PHP's own. To see the current target at runtime, read the ini value:
<?php
echo ini_get('error_log') ?: '(SAPI / system default)';Logging to a specific file (type 3)
Type 3 appends the message to a file you name in $destination. This is the workhorse for application-specific logs:
<?php
$message = "Error: Unable to connect to the database";
error_log($message, 3, "/var/log/php-errors.log");Unlike type 0, type 3 writes the message verbatim — no timestamp, no severity, and crucially no trailing newline. If you forget the newline, every call runs together on one line:
<?php
$log = sys_get_temp_dir() . "/app.log";
error_log("first", 3, $log);
error_log("second", 3, $log);
echo file_get_contents($log); // firstsecondAdd PHP_EOL yourself (and usually a timestamp) so each entry is a readable line:
<?php
$log = sys_get_temp_dir() . "/app.log";
$line = date('[Y-m-d H:i:s] ') . "Cache miss for user 42" . PHP_EOL;
error_log($line, 3, $log);
echo file_get_contents($log);
// [2026-06-21 10:00:00] Cache miss for user 42All message types
$message_type | Destination |
|---|---|
0 (default) | PHP's configured error handler — the error_log ini directive or the SAPI/system logger. |
1 | Email — sends $message to the address in $destination via the mail() mechanism. $additional_headers adds headers like From:. |
3 | Appends $message to the file path in $destination (no newline added). |
4 | Logs directly to the SAPI logging handler (for example, the web server's error log). |
Type 2 (send over a TCP socket) existed in old PHP versions and was removed in PHP 8; do not rely on it.
Emailing critical errors (type 1)
For rare, high-severity failures you can have PHP email you. Use sparingly — a noisy error that fires once per request can flood an inbox:
<?php
error_log(
"FATAL: order processor crashed",
1,
"[email protected]",
"From: [email protected]\r\n"
);In production, a logging library that batches and rate-limits alerts is a better fit than emailing on every call.
A realistic catch-and-log pattern
In application code you usually log inside a catch block, record enough context to reproduce the problem, then show the user a generic message:
<?php
function chargeCustomer(int $cents): bool
{
if ($cents <= 0) {
throw new InvalidArgumentException("Amount must be positive, got $cents");
}
// ... real charge logic ...
return true;
}
try {
chargeCustomer(-5);
} catch (Throwable $e) {
error_log(sprintf(
"[%s] %s in %s:%d",
date('Y-m-d H:i:s'),
$e->getMessage(),
$e->getFile(),
$e->getLine()
));
echo "Sorry, we couldn't process your payment.";
}The detailed message goes to the log; the visitor only sees the friendly line. This separation is the whole point of error_log().
Common gotchas
- No newline with type 3. Append
PHP_EOLyourself or your entries concatenate. - The
error_logini directive sets the default. When you omit$message_type/$destination, the message goes whereverini_get('error_log')points. On a fresh CLI install that may bestderr; on a web server it may be a specific file. - The file must be writable by the PHP process. A
falsereturn often means a permissions problem on the directory or file. display_errorsanderror_logare independent. Turning off on-screen errors does not stop logging, and vice versa — control them separately.- Never log secrets. Passwords, API keys, full credit-card numbers, and session tokens must never reach a log file. Redact them before calling
error_log().
Related functions
set_error_handler()— route PHP's own warnings and notices through your code so you can callerror_log()consistently.set_exception_handler()— catch and log otherwise-uncaught exceptions in one place.trigger_error()— raise a user-level error that the error handler (and thus logging) will pick up.error_reporting()— choose which error levels are reported in the first place.syslog()— send messages straight to the system logger with a severity level.
Conclusion
error_log() is the simplest durable way to record what went wrong in code that no developer is watching. Use type 3 with a timestamp and PHP_EOL for application log files, fall back to the default destination to sit alongside PHP's own errors, and reserve email (type 1) for genuinely critical events. Pair it with set_error_handler() and set_exception_handler() to capture everything in one place — and never write secrets to a log.