Technology

PHP Error Logging Best Practices on Hosting Servers

PHP error logging looks like a small configuration detail, but on real hosting environments it often decides how quickly you find bugs, how safely you handle incidents and how clean your servers stay over time. Misconfigured settings such as ‘display_errors’, ‘error_log’ and incorrect log levels either hide critical problems or expose sensitive data directly on your site. In agency projects, SaaS products and classic WordPress or Laravel sites that we host at dchost.com, most recurring production issues we debug start with checking PHP logs and their configuration. When logs are noisy, missing or stored in the wrong place, troubleshooting takes longer and outages become more stressful than they need to be. In this guide we will walk through practical PHP error logging best practices tailored for shared hosting, VPS, dedicated servers and colocation. The goal is simple: show you exactly what to enable, what to disable, where to send logs, how to rotate them and how to stay secure and compliant while doing it.

İçindekiler

Why PHP Error Logging Matters on Real Hosting Environments

On a local development machine, you can afford to be sloppy with error settings. On a shared hosting account or VPS that serves paying customers, you cannot. Proper PHP error logging on hosting has several concrete benefits:

  • Faster debugging: clear, timestamped errors with file and line numbers cut root cause analysis time dramatically.
  • Early warning: deprecation notices and warnings highlight problems before they become fatal in the next PHP upgrade.
  • Security: logging to files instead of the browser prevents leaking SQL queries, file paths and API keys to visitors.
  • Performance: clean error logs make it easy to spot patterns like repeated timeouts, memory exhaustion or slow database calls.
  • Compliance and auditing: for e‑commerce and SaaS workloads, predictable logs are often required by internal policies or standards.

We also see that error logs are closely related to server resource usage. For example, an application that constantly hits ‘memory_limit’ or ‘max_execution_time’ thresholds will fill logs and slow down. If you want to go deeper on tuning those limits, you can read our detailed guide on choosing the right PHP memory_limit, max_execution_time and upload_max_filesize values after you finish this article.

Key PHP Error Logging Directives You Must Understand

There are four core directives you should always think about together when designing a logging strategy:

  • ‘display_errors’
  • ‘log_errors’
  • ‘error_log’
  • ‘error_reporting’ (log levels)

‘display_errors’ – what visitors see

This setting controls whether PHP errors are printed directly into the HTML output of your pages.

  • Development: ‘display_errors = On’ is acceptable on a private dev machine or local environment.
  • Staging and production: ‘display_errors = Off’ should be mandatory.

On shared hosting, leaving ‘display_errors’ enabled in production is one of the most common security mistakes we see. A single uncaught exception can reveal file paths, environment variables, SQL queries and internal library versions to any visitor. Even if you use a framework level error page, backing it with ‘display_errors = Off’ adds an extra layer of protection.

Best practice on hosting servers:

  • Set ‘display_errors = Off’ in the main configuration for all production domains.
  • Use framework or CMS specific debugMode / WP_DEBUG flags for more detailed local debugging instead of exposing raw PHP errors online.

‘log_errors’ – whether PHP writes to a log file

‘log_errors’ decides if PHP will send errors to its logging destination. On any serious site hosted at dchost.com we treat this as non‑optional.

  • All environments: ‘log_errors = On’.

On shared hosting, this often routes errors into a per‑site log under your home directory or into the web server error log. On VPS and dedicated servers, you have full control over where logs go and how they are rotated.

‘error_log’ – which file receives PHP errors

‘error_log’ sets the path to the file where errors will be written when ‘log_errors’ is enabled. Good choices here make day‑to‑day operations easier and prevent disk usage surprises.

Recommendations:

  • Per site log file: use a path inside your hosting account, such as ‘/home/account/logs/example.com-php-error.log’ on shared hosting or ‘/var/log/php/example.com-error.log’ on VPS.
  • Writable by PHP: make sure the PHP user (FPM pool user or Apache user) can create and write to the file.
  • Separate from access logs: keep PHP error logs separate from web server access logs so each file has a clear purpose.

On custom VPS setups with PHP‑FPM, separating logs per pool is extremely helpful. We explain per‑pool thinking in more detail in our article on choosing PHP session and cache storage backends and in our advanced guides on PHP‑FPM tuning.

‘error_reporting’ – log levels and noise control

‘error_reporting’ decides which types of errors and notices are logged. It is a bitmask, but practically you will use the constants PHP provides.

Typical options:

  • ‘E_ALL’ – log every type of issue including notices and deprecations.
  • ‘E_ALL & ~E_NOTICE’ – hide notices but log everything else.
  • ‘E_ALL & ~E_DEPRECATED & ~E_STRICT’ – often used to reduce noise from older libraries that you cannot change quickly.

Best practice today for PHP 7.4, 8.0, 8.1, 8.2 and later is usually:

  • Development: ‘error_reporting = E_ALL’. See every possible problem.
  • Staging: ‘error_reporting = E_ALL’, but treat deprecations as tasks for the next release.
  • Production: start with ‘E_ALL’, and only exclude specific categories if they are extremely noisy and you have a plan to fix them.

Completely turning down ‘error_reporting’ in production to avoid large log files is a mistake. Instead, keep proper levels and solve disk usage with log rotation, as we describe later in this article.

Development vs Staging vs Production: Different Defaults

Healthy hosting setups treat development, staging and production differently. Error logging is one of the clearest places to see this separation.

Recommended development settings

  • ‘display_errors = On’
  • ‘log_errors = On’
  • ‘error_reporting = E_ALL’
  • ‘error_log’ pointing to an easily accessible file inside your project tree

Here the focus is rapid feedback. You want to see everything, even minor notices, so that future upgrades to PHP 8.x are painless. Our PHP 8 upgrade checklist, for example, relies heavily on developers having clean logs before switching PHP versions.

Recommended staging settings

  • ‘display_errors = Off’
  • ‘log_errors = On’
  • ‘error_reporting = E_ALL’
  • ‘error_log’ stored in a space where your team can download and inspect it easily

On staging you simulate production as closely as possible but keep error reporting maximal. This helps catch issues before they land in front of real users. If you are working with WordPress, setting up a staging environment even on shared hosting is straightforward; you can follow our tutorial on creating a WordPress staging environment on shared hosting and apply the logging recommendations there.

Recommended production settings

  • ‘display_errors = Off’ (non‑negotiable)
  • ‘log_errors = On’
  • ‘error_reporting = E_ALL’ or a slightly reduced mask only if justified
  • ‘error_log’ stored in a directory that is not publicly accessible over the web

If your application framework has its own logging system (for example Monolog in Laravel or built‑in debug.log in WordPress), keep PHP logging enabled anyway. Framework logs often miss low‑level engine problems like extensions failing to load or fatal parse errors that occur before your framework code runs.

Where to Configure PHP Error Logging on Hosting

On a local machine there is usually one ‘php.ini’ file. On hosting platforms you often have several layers of configuration: global PHP, per‑user overrides and per‑directory or per‑site settings. Knowing where to change which directive avoids conflicts and surprises.

Shared hosting with cPanel or DirectAdmin

On shared hosting at dchost.com, customers generally have three ways to control PHP error settings:

  1. Control panel PHP editor (MultiPHP INI editor or similar) – easiest option for global settings per domain.
  2. ‘.user.ini’ files – per‑directory overrides when you cannot or do not want to use the panel UI.
  3. ‘.htaccess’ directives – on Apache based setups using ‘php_flag’ and ‘php_value’ when PHP runs as an Apache module (increasingly rare, but still seen in legacy stacks).

Using control panel editors

Typical flow:

  • Open your hosting panel and navigate to the PHP options or MultiPHP INI editor.
  • Select the domain or subdomain.
  • Set ‘display_errors’ to ‘Off’, ‘log_errors’ to ‘On’ and ‘error_reporting’ to the level you want.
  • If available, set a custom ‘error_log’ path under your home directory, for example ‘/home/username/logs/example.com-php-error.log’.

This approach is recommended for most users because it centralises settings and reduces the risk of typos in custom files.

Using ‘.user.ini’ on shared hosting

When you need per‑folder control, for example for a staging subfolder, you can create a file named ‘.user.ini’ in that directory with content like:

display_errors = Off
log_errors = On
error_reporting = E_ALL
error_log = /home/username/logs/staging-example-php-error.log

PHP will apply these overrides for all scripts under that directory tree. Remember that ‘.user.ini’ is read periodically, not on every request, so changes might take a short time to become active.

Using ‘.htaccess’ (Apache module only)

If PHP is integrated as an Apache module (not via FPM), you may encounter older syntax like:

php_flag display_errors Off
php_flag log_errors On
php_value error_reporting E_ALL
php_value error_log /home/username/logs/example.com-php-error.log

On modern setups with PHP‑FPM, this form usually does not work. In that case, stick to the control panel or ‘.user.ini’ approach.

VPS, dedicated server and colocation setups

On your own server or a VPS from dchost.com, you have full control of PHP configuration. Common places to adjust error logging include:

  • Global ‘php.ini’ (for CLI and default FPM settings).
  • Per‑pool PHP‑FPM configuration files such as ‘/etc/php/8.2/fpm/pool.d/example.com.conf’.
  • Per‑vhost overrides via ‘php_admin_value’ in Nginx or Apache configs.

For per‑site isolation, we strongly recommend assigning each site its own FPM pool with its own ‘php_admin_value[error_log]’ path. This complements the process isolation strategies we describe in our guide on isolating PHP session and queue workers using separate PHP‑FPM pools.

Example PHP‑FPM pool config snippet

[example.com]
user = example
group = example
listen = /run/php-fpm-example.sock

php_admin_value[display_errors] = Off
php_admin_value[log_errors] = On
php_admin_value[error_reporting] = E_ALL
php_admin_value[error_log] = /var/log/php/example.com-error.log

‘php_admin_value’ in FPM means the value cannot be overridden by user scripts, which is ideal for enforcing ‘display_errors = Off’ in production.

Choosing the Right Log Levels with ‘error_reporting’

Log levels determine how much signal versus noise you get from logs. Setting ‘error_reporting’ correctly is one of the biggest gains you can get with a single directive.

Recommended patterns for modern PHP

For PHP 7.4 and 8.x, good starting points are:

  • Development: ‘error_reporting = E_ALL’
  • Staging: ‘error_reporting = E_ALL’
  • Production (ideal): ‘error_reporting = E_ALL’
  • Production (legacy code): ‘error_reporting = E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED’

The legacy pattern is a temporary compromise when using older frameworks or plugins that spam deprecation notices. The key is to treat those notices as a to‑do list for code upgrades, not something to hide forever. Clean logs make future PHP upgrades significantly safer, as we cover in our article about upgrading to PHP 8.x.

Framework level logging vs PHP level logging

Many frameworks have their own log level concepts (debug, info, warning, error, critical). These are separate from PHPs ‘error_reporting’ but work together:

  • Use PHP ‘error_reporting’ to capture engine level problems: parse errors, fatal errors, warnings, deprecations.
  • Use framework log levels to control application specific noise and business events.

On hosting infrastructure, we often aggregate both PHP logs and application logs into central systems. That is where separation into different files and sensible log levels really pays off.

Organising and Rotating PHP Error Logs

Great logging without retention planning leads to another classic hosting problem: full disks. PHP error logs can grow quickly on busy sites, especially if a single warning is triggered on every request.

Per‑site and per‑environment log files

Best practice is to split logs along boundaries that match how you deploy and debug:

  • Separate log file per site: ‘example.com-error.log’, ‘api.example.com-error.log’, ‘admin.example.com-error.log’.
  • Separate log file per environment: ‘example.com-staging-error.log’, ‘example.com-prod-error.log’.

This way a staging tests error will not flood your production logs, and you can set different rotation policies if needed.

Log rotation on VPS and dedicated servers

On self‑managed servers, you should configure ‘logrotate’ or an equivalent tool to keep PHP logs under control. A typical ‘logrotate’ config for a PHP error log might look like:

/var/log/php/example.com-error.log {
    daily
    rotate 14
    compress
    missingok
    notifempty
    create 640 www-data www-data
    sharedscripts
    postrotate
        /usr/sbin/service php8.2-fpm reload > /dev/null 2>/dev/null || true
    endscript
}

This keeps 14 days of daily compressed logs and makes sure files are recreated with correct permissions. We go deeper into disk usage and rotation strategies in our article on VPS disk usage and logrotate to avoid no space left on device errors.

Log rotation on shared hosting

On shared hosting, the platform usually handles rotation for global Apache or Nginx logs. For custom PHP logs under your home directory, you have a few options:

  • Periodically download and clean logs manually.
  • Set up a small PHP or shell script that truncates old logs and schedule it with cron.
  • Use panel provided log management tools if available.

Whatever method you use, always check your disk quota and inode usage periodically. Large or numerous log files are a common cause of hitting account limits.

Security, Privacy and Compliance in PHP Logs

Logs are not just a technical tool; they also contain data that may be sensitive under privacy regulations such as GDPR and local laws. At dchost.com we see three recurring categories of risk in PHP logs:

  • Credentials and tokens: database passwords, API keys, session tokens accidentally sent to error_log from ‘var_dump’ or uncaught exceptions.
  • Personal data: email addresses, phone numbers or IP addresses logged in cleartext.
  • Internal paths and stack traces: detailed file system layout that can help an attacker.

Practical mitigation steps

  • Never log full payment card data, passwords or full authentication tokens. Mask them before logging.
  • Sanitise or hash user identifiers when possible.
  • Ensure ‘error_log’ paths are outside the public web root (for example ‘/home/user/public_html’ for files and ‘/home/user/logs’ for logs).
  • Limit read access to logs to the appropriate system users and, if applicable, panel sub‑users.
  • Define a retention policy and delete or anonymise logs older than necessary.

If you operate in regulated environments or serve EU residents, it is worth reading our dedicated guide on log anonymisation and IP masking techniques for KVKK and GDPR compliance. The same principles apply to PHP error logs.

Practical Configuration Examples

To make all of this more concrete, here are a few minimal, real‑world configurations you can adapt.

Minimal production ‘php.ini’ style configuration

display_errors = Off
log_errors = On
error_reporting = E_ALL
error_log = /var/log/php/global-error.log

Use this as a global baseline, then override ‘error_log’ per site or per FPM pool.

Per site override with ‘.user.ini’ on shared hosting

; /home/username/public_html/.user.ini

; Hide errors from visitors
display_errors = Off

; Log everything, including warnings and deprecations
log_errors = On
error_reporting = E_ALL

; Store the log under your account but outside public_html
error_log = /home/username/logs/example.com-php-error.log

Temporarily enabling extra logging with ‘ini_set’

Sometimes you need deeper logs for a specific script without changing global settings. In those cases, you can use ‘ini_set’ at the top of a PHP file (remember to remove it later):

<?php
ini_set('display_errors', '0');
ini_set('log_errors', '1');
ini_set('error_reporting', (string) E_ALL);
ini_set('error_log', '/home/username/logs/checkout-debug.log');

// ... rest of the script

This is especially useful in complex e‑commerce flows. Combine it with insights from our article on log analysis for e‑commerce sites to catch lost conversions and payment errors to build targeted debugging around your checkout process.

Using ‘error_log’ function inside PHP code

PHPs ‘error_log’ function lets you send custom messages to the same error log file, which is great for debugging without exposing information to users:

<?php
$orderId = 1234;
error_log('Starting payment validation for order ' . $orderId);

// business logic here

error_log('Payment validation OK for order ' . $orderId);

Because this writes to the configured ‘error_log’ file, you get a chronological view that mixes engine errors with your own checkpoints.

Monitoring, Centralised Logging and Alerting

For a single low‑traffic site, manually inspecting PHP error logs may be enough. As soon as you host multiple projects, or run a single application with meaningful revenue, you will want monitoring and centralisation.

Centralising logs from multiple servers

On multi‑server architectures or when you host tens of client sites, having PHP logs spread across many VPS instances becomes impossible to manage manually. In those scenarios we recommend shipping logs to a central system such as ELK or Loki. Our article on centralising logs for multiple servers with ELK and Loki walks through a practical setup that works well with PHP error logs too.

VPS level log management and alerts

On a single VPS, you can still get a lot of value from structured logging and alerts. We have a detailed guide on VPS log management with Grafana Loki and Promtail that shows how to collect PHP, web server and system logs into one place, set retention and build simple but effective alert rules. Even a basic alert such as ‘more than X PHP fatal errors in 5 minutes’ can save hours of downtime.

Correlating PHP logs with web server logs

When debugging, always look at PHP error logs and web server access or error logs together. For example, a 500 HTTP status code in Nginx or Apache logs plus a timestamped PHP fatal error in ‘error_log’ usually tells you exactly which request failed and why. If you want a refresher on reading web server logs efficiently, our guide on how to read web server logs to diagnose 4xx–5xx errors is a good companion to this article.

Bringing It All Together on dchost.com

Proper PHP error logging is not about memorising every directive; it is about establishing a few clear rules and applying them consistently across your hosting stack:

  • Always keep ‘display_errors’ disabled in staging and production.
  • Always keep ‘log_errors’ enabled and send errors to a dedicated ‘error_log’ file.
  • Use ‘error_reporting = E_ALL’ as your default and only reduce it when you have a concrete reason.
  • Split logs per site and per environment, then rotate and monitor them.
  • Mask sensitive data, store logs outside the web root and respect legal retention requirements.

At dchost.com, our shared hosting, VPS, dedicated server and colocation customers benefit from sane, secure PHP defaults plus the flexibility to tune logging per project. Whether you manage a single WordPress site or a portfolio of Laravel and custom PHP applications, you can start by cleaning up your PHP error settings today and then build on that with monitoring, centralised logging and better deployment practices.

If you are planning a new project or migrating an existing one, our team can help you choose the right hosting architecture and configure PHP, web server and logging settings so that you see problems early, not after they impact your users. Explore our hosting plans at dchost.com or contact us for a review of your current setup and we will be happy to guide you toward a calmer, more observable PHP environment.

Frequently Asked Questions

No, you should not enable display_errors in any public production environment. When display_errors is On, PHP prints raw error messages directly into the HTML output. Those messages often reveal file system paths, SQL queries, environment variables or even parts of your source code. Attackers can use that information to map your application and find weaknesses. Instead, set display_errors to Off, enable log_errors and send errors to a dedicated error_log file outside the web root. If you need user friendly error pages, use your framework or CMS to render them while keeping raw PHP details in the logs only.

The exact location depends on how your hosting account is configured. Common patterns are a php_errorlog or error_log file inside the sites root folder, or a dedicated logs directory under your home directory such as /home/username/logs/domain-php-error.log. On cPanel or DirectAdmin you can usually set or see the current error_log path in the PHP options or MultiPHP INI editor section. If you are not sure, create a small phpinfo script, access it from the browser and search for the error_log directive to see the active path. Remember that logs should live outside the public_html directory whenever possible for security.

For most modern applications, the best default is error_reporting = E_ALL even on live sites, combined with display_errors = Off and log_errors = On. This ensures you capture all fatals, warnings, notices and deprecations in your logs without exposing them to visitors. If you maintain legacy code that generates a lot of deprecation warnings you cannot fix immediately, a temporary compromise is error_reporting = E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED. The important part is to treat those excluded messages as technical debt and plan upgrades. Avoid turning error_reporting too low, because that hides real issues that could break the site on the next PHP update.

Rotation frequency depends on traffic and log volume, but a good starting point is daily rotation with 7 to 30 days of retention. For busy sites, daily compressed logs make it easier to search without filling disks. On a VPS or dedicated server you can configure tools such as logrotate to handle this automatically by defining rules per log file. For small, low traffic sites, weekly rotation might be sufficient. What matters most is that you automate the process, compress old logs, and ensure new log files are created with correct permissions. Also keep an eye on both total disk space and inode counts, since thousands of tiny log files can also cause issues.

Yes. PHPs built in error_log function lets you write your own messages into the configured error_log file. For example, error_log('Starting checkout for user ' . $userId); will append that line to the same file used for PHP errors, which is very useful when you want extra context around a bug without exposing information to the browser. This works well for complex workflows such as checkouts or API integrations, where you want to mark steps like request sent, response received and validation passed. Just remember to remove or reduce very noisy debug lines after you finish troubleshooting so your logs stay focused and easy to read.