W3docs

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
ParameterMeaning
$messageThe text to log. Newlines are not added for you (see the gotcha below).
$message_typeWhere to send it — 0, 1, 3, or 4. See the table further down.
$destinationThe file path (type 3) or email address (type 1).
$additional_headersExtra 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); // firstsecond

Add 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 42

All message types

$message_typeDestination
0 (default)PHP's configured error handler — the error_log ini directive or the SAPI/system logger.
1Email — sends $message to the address in $destination via the mail() mechanism. $additional_headers adds headers like From:.
3Appends $message to the file path in $destination (no newline added).
4Logs 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_EOL yourself or your entries concatenate.
  • The error_log ini directive sets the default. When you omit $message_type/$destination, the message goes wherever ini_get('error_log') points. On a fresh CLI install that may be stderr; on a web server it may be a specific file.
  • The file must be writable by the PHP process. A false return often means a permissions problem on the directory or file.
  • display_errors and error_log are 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().
  • set_error_handler() — route PHP's own warnings and notices through your code so you can call error_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.

Practice

Practice
What functions does PHP have to handle errors and exceptions?
What functions does PHP have to handle errors and exceptions?
Was this page helpful?