{"id":3920,"date":"2026-01-01T18:15:46","date_gmt":"2026-01-01T15:15:46","guid":{"rendered":"https:\/\/www.dchost.com\/blog\/php-error-logging-best-practices-on-hosting-servers\/"},"modified":"2026-01-01T18:15:46","modified_gmt":"2026-01-01T15:15:46","slug":"php-error-logging-best-practices-on-hosting-servers","status":"publish","type":"post","link":"https:\/\/www.dchost.com\/blog\/en\/php-error-logging-best-practices-on-hosting-servers\/","title":{"rendered":"PHP Error Logging Best Practices on Hosting Servers"},"content":{"rendered":"<div class=\"dchost-blog-content-wrapper\"><p>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 &#8216;display_errors&#8217;, &#8216;error_log&#8217; 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, <a href=\"https:\/\/www.dchost.com\/vps\">VPS<\/a>, <a href=\"https:\/\/www.dchost.com\/dedicated-server\">dedicated server<\/a>s 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.<\/p>\n<div id=\"toc_container\" class=\"toc_transparent no_bullets\"><p class=\"toc_title\">\u0130&ccedil;indekiler<\/p><ul class=\"toc_list\"><li><a href=\"#Why_PHP_Error_Logging_Matters_on_Real_Hosting_Environments\"><span class=\"toc_number toc_depth_1\">1<\/span> Why PHP Error Logging Matters on Real Hosting Environments<\/a><\/li><li><a href=\"#Key_PHP_Error_Logging_Directives_You_Must_Understand\"><span class=\"toc_number toc_depth_1\">2<\/span> Key PHP Error Logging Directives You Must Understand<\/a><ul><li><a href=\"#8216display_errors8217_what_visitors_see\"><span class=\"toc_number toc_depth_2\">2.1<\/span> &#8216;display_errors&#8217; \u2013 what visitors see<\/a><\/li><li><a href=\"#8216log_errors8217_whether_PHP_writes_to_a_log_file\"><span class=\"toc_number toc_depth_2\">2.2<\/span> &#8216;log_errors&#8217; \u2013 whether PHP writes to a log file<\/a><\/li><li><a href=\"#8216error_log8217_which_file_receives_PHP_errors\"><span class=\"toc_number toc_depth_2\">2.3<\/span> &#8216;error_log&#8217; \u2013 which file receives PHP errors<\/a><\/li><li><a href=\"#8216error_reporting8217_log_levels_and_noise_control\"><span class=\"toc_number toc_depth_2\">2.4<\/span> &#8216;error_reporting&#8217; \u2013 log levels and noise control<\/a><\/li><\/ul><\/li><li><a href=\"#Development_vs_Staging_vs_Production_Different_Defaults\"><span class=\"toc_number toc_depth_1\">3<\/span> Development vs Staging vs Production: Different Defaults<\/a><ul><li><a href=\"#Recommended_development_settings\"><span class=\"toc_number toc_depth_2\">3.1<\/span> Recommended development settings<\/a><\/li><li><a href=\"#Recommended_staging_settings\"><span class=\"toc_number toc_depth_2\">3.2<\/span> Recommended staging settings<\/a><\/li><li><a href=\"#Recommended_production_settings\"><span class=\"toc_number toc_depth_2\">3.3<\/span> Recommended production settings<\/a><\/li><\/ul><\/li><li><a href=\"#Where_to_Configure_PHP_Error_Logging_on_Hosting\"><span class=\"toc_number toc_depth_1\">4<\/span> Where to Configure PHP Error Logging on Hosting<\/a><ul><li><a href=\"#Shared_hosting_with_cPanel_or_DirectAdmin\"><span class=\"toc_number toc_depth_2\">4.1<\/span> Shared hosting with cPanel or DirectAdmin<\/a><ul><li><a href=\"#Using_control_panel_editors\"><span class=\"toc_number toc_depth_3\">4.1.1<\/span> Using control panel editors<\/a><\/li><li><a href=\"#Using_8216userini8217_on_shared_hosting\"><span class=\"toc_number toc_depth_3\">4.1.2<\/span> Using &#8216;.user.ini&#8217; on shared hosting<\/a><\/li><li><a href=\"#Using_8216htaccess8217_Apache_module_only\"><span class=\"toc_number toc_depth_3\">4.1.3<\/span> Using &#8216;.htaccess&#8217; (Apache module only)<\/a><\/li><\/ul><\/li><li><a href=\"#VPS_dedicated_server_and_colocation_setups\"><span class=\"toc_number toc_depth_2\">4.2<\/span> VPS, dedicated server and colocation setups<\/a><ul><li><a href=\"#Example_PHPFPM_pool_config_snippet\"><span class=\"toc_number toc_depth_3\">4.2.1<\/span> Example PHP\u2011FPM pool config snippet<\/a><\/li><\/ul><\/li><\/ul><\/li><li><a href=\"#Choosing_the_Right_Log_Levels_with_8216error_reporting8217\"><span class=\"toc_number toc_depth_1\">5<\/span> Choosing the Right Log Levels with &#8216;error_reporting&#8217;<\/a><ul><li><a href=\"#Recommended_patterns_for_modern_PHP\"><span class=\"toc_number toc_depth_2\">5.1<\/span> Recommended patterns for modern PHP<\/a><\/li><li><a href=\"#Framework_level_logging_vs_PHP_level_logging\"><span class=\"toc_number toc_depth_2\">5.2<\/span> Framework level logging vs PHP level logging<\/a><\/li><\/ul><\/li><li><a href=\"#Organising_and_Rotating_PHP_Error_Logs\"><span class=\"toc_number toc_depth_1\">6<\/span> Organising and Rotating PHP Error Logs<\/a><ul><li><a href=\"#Persite_and_perenvironment_log_files\"><span class=\"toc_number toc_depth_2\">6.1<\/span> Per\u2011site and per\u2011environment log files<\/a><\/li><li><a href=\"#Log_rotation_on_VPS_and_dedicated_servers\"><span class=\"toc_number toc_depth_2\">6.2<\/span> Log rotation on VPS and dedicated servers<\/a><\/li><li><a href=\"#Log_rotation_on_shared_hosting\"><span class=\"toc_number toc_depth_2\">6.3<\/span> Log rotation on shared hosting<\/a><\/li><\/ul><\/li><li><a href=\"#Security_Privacy_and_Compliance_in_PHP_Logs\"><span class=\"toc_number toc_depth_1\">7<\/span> Security, Privacy and Compliance in PHP Logs<\/a><ul><li><a href=\"#Practical_mitigation_steps\"><span class=\"toc_number toc_depth_2\">7.1<\/span> Practical mitigation steps<\/a><\/li><\/ul><\/li><li><a href=\"#Practical_Configuration_Examples\"><span class=\"toc_number toc_depth_1\">8<\/span> Practical Configuration Examples<\/a><ul><li><a href=\"#Minimal_production_8216phpini8217_style_configuration\"><span class=\"toc_number toc_depth_2\">8.1<\/span> Minimal production &#8216;php.ini&#8217; style configuration<\/a><\/li><li><a href=\"#Per_site_override_with_8216userini8217_on_shared_hosting\"><span class=\"toc_number toc_depth_2\">8.2<\/span> Per site override with &#8216;.user.ini&#8217; on shared hosting<\/a><\/li><li><a href=\"#Temporarily_enabling_extra_logging_with_8216ini_set8217\"><span class=\"toc_number toc_depth_2\">8.3<\/span> Temporarily enabling extra logging with &#8216;ini_set&#8217;<\/a><\/li><li><a href=\"#Using_8216error_log8217_function_inside_PHP_code\"><span class=\"toc_number toc_depth_2\">8.4<\/span> Using &#8216;error_log&#8217; function inside PHP code<\/a><\/li><\/ul><\/li><li><a href=\"#Monitoring_Centralised_Logging_and_Alerting\"><span class=\"toc_number toc_depth_1\">9<\/span> Monitoring, Centralised Logging and Alerting<\/a><ul><li><a href=\"#Centralising_logs_from_multiple_servers\"><span class=\"toc_number toc_depth_2\">9.1<\/span> Centralising logs from multiple servers<\/a><\/li><li><a href=\"#VPS_level_log_management_and_alerts\"><span class=\"toc_number toc_depth_2\">9.2<\/span> VPS level log management and alerts<\/a><\/li><li><a href=\"#Correlating_PHP_logs_with_web_server_logs\"><span class=\"toc_number toc_depth_2\">9.3<\/span> Correlating PHP logs with web server logs<\/a><\/li><\/ul><\/li><li><a href=\"#Bringing_It_All_Together_on_dchostcom\"><span class=\"toc_number toc_depth_1\">10<\/span> Bringing It All Together on dchost.com<\/a><\/li><\/ul><\/div>\n<h2><span id=\"Why_PHP_Error_Logging_Matters_on_Real_Hosting_Environments\">Why PHP Error Logging Matters on Real Hosting Environments<\/span><\/h2>\n<p>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:<\/p>\n<ul>\n<li><strong>Faster debugging<\/strong>: clear, timestamped errors with file and line numbers cut root cause analysis time dramatically.<\/li>\n<li><strong>Early warning<\/strong>: deprecation notices and warnings highlight problems before they become fatal in the next PHP upgrade.<\/li>\n<li><strong>Security<\/strong>: logging to files instead of the browser prevents leaking SQL queries, file paths and API keys to visitors.<\/li>\n<li><strong>Performance<\/strong>: clean error logs make it easy to spot patterns like repeated timeouts, memory exhaustion or slow database calls.<\/li>\n<li><strong>Compliance and auditing<\/strong>: for e\u2011commerce and SaaS workloads, predictable logs are often required by internal policies or standards.<\/li>\n<\/ul>\n<p>We also see that error logs are closely related to server resource usage. For example, an application that constantly hits &#8216;memory_limit&#8217; or &#8216;max_execution_time&#8217; thresholds will fill logs and slow down. If you want to go deeper on tuning those limits, you can read our detailed guide on <a href='https:\/\/www.dchost.com\/blog\/en\/php-ayarlarini-dogru-yapmak-memory_limit-max_execution_time-ve-upload_max_filesize-kac-olmali\/'>choosing the right PHP memory_limit, max_execution_time and upload_max_filesize values<\/a> after you finish this article.<\/p>\n<h2><span id=\"Key_PHP_Error_Logging_Directives_You_Must_Understand\">Key PHP Error Logging Directives You Must Understand<\/span><\/h2>\n<p>There are four core directives you should always think about together when designing a logging strategy:<\/p>\n<ul>\n<li>&#8216;display_errors&#8217;<\/li>\n<li>&#8216;log_errors&#8217;<\/li>\n<li>&#8216;error_log&#8217;<\/li>\n<li>&#8216;error_reporting&#8217; (log levels)<\/li>\n<\/ul>\n<h3><span id=\"8216display_errors8217_what_visitors_see\">&#8216;display_errors&#8217; \u2013 what visitors see<\/span><\/h3>\n<p>This setting controls whether PHP errors are printed directly into the HTML output of your pages.<\/p>\n<ul>\n<li><strong>Development<\/strong>: &#8216;display_errors = On&#8217; is acceptable on a private dev machine or local environment.<\/li>\n<li><strong>Staging and production<\/strong>: &#8216;display_errors = Off&#8217; should be mandatory.<\/li>\n<\/ul>\n<p>On shared hosting, leaving &#8216;display_errors&#8217; 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 &#8216;display_errors = Off&#8217; adds an extra layer of protection.<\/p>\n<p>Best practice on hosting servers:<\/p>\n<ul>\n<li>Set &#8216;display_errors = Off&#8217; in the main configuration for all production domains.<\/li>\n<li>Use framework or CMS specific debugMode \/ WP_DEBUG flags for more detailed local debugging instead of exposing raw PHP errors online.<\/li>\n<\/ul>\n<h3><span id=\"8216log_errors8217_whether_PHP_writes_to_a_log_file\">&#8216;log_errors&#8217; \u2013 whether PHP writes to a log file<\/span><\/h3>\n<p>&#8216;log_errors&#8217; decides if PHP will send errors to its logging destination. On any serious site hosted at dchost.com we treat this as non\u2011optional.<\/p>\n<ul>\n<li><strong>All environments<\/strong>: &#8216;log_errors = On&#8217;.<\/li>\n<\/ul>\n<p>On shared hosting, this often routes errors into a per\u2011site 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.<\/p>\n<h3><span id=\"8216error_log8217_which_file_receives_PHP_errors\">&#8216;error_log&#8217; \u2013 which file receives PHP errors<\/span><\/h3>\n<p>&#8216;error_log&#8217; sets the path to the file where errors will be written when &#8216;log_errors&#8217; is enabled. Good choices here make day\u2011to\u2011day operations easier and prevent disk usage surprises.<\/p>\n<p>Recommendations:<\/p>\n<ul>\n<li><strong>Per site log file<\/strong>: use a path inside your hosting account, such as &#8216;\/home\/account\/logs\/example.com-php-error.log&#8217; on shared hosting or &#8216;\/var\/log\/php\/example.com-error.log&#8217; on VPS.<\/li>\n<li><strong>Writable by PHP<\/strong>: make sure the PHP user (FPM pool user or Apache user) can create and write to the file.<\/li>\n<li><strong>Separate from access logs<\/strong>: keep PHP error logs separate from web server access logs so each file has a clear purpose.<\/li>\n<\/ul>\n<p>On custom VPS setups with PHP\u2011FPM, separating logs per pool is extremely helpful. We explain per\u2011pool thinking in more detail in our article on <a href='https:\/\/www.dchost.com\/blog\/en\/php-session-ve-cache-depolamasini-dogru-secmek-dosya-redis-ve-memcachedin-wordpress-ve-laravel-performansina-etkisi\/'>choosing PHP session and cache storage backends<\/a> and in our advanced guides on PHP\u2011FPM tuning.<\/p>\n<h3><span id=\"8216error_reporting8217_log_levels_and_noise_control\">&#8216;error_reporting&#8217; \u2013 log levels and noise control<\/span><\/h3>\n<p>&#8216;error_reporting&#8217; decides which types of errors and notices are logged. It is a bitmask, but practically you will use the constants PHP provides.<\/p>\n<p>Typical options:<\/p>\n<ul>\n<li>&#8216;E_ALL&#8217; \u2013 log every type of issue including notices and deprecations.<\/li>\n<li>&#8216;E_ALL &amp; ~E_NOTICE&#8217; \u2013 hide notices but log everything else.<\/li>\n<li>&#8216;E_ALL &amp; ~E_DEPRECATED &amp; ~E_STRICT&#8217; \u2013 often used to reduce noise from older libraries that you cannot change quickly.<\/li>\n<\/ul>\n<p>Best practice today for PHP 7.4, 8.0, 8.1, 8.2 and later is usually:<\/p>\n<ul>\n<li><strong>Development<\/strong>: &#8216;error_reporting = E_ALL&#8217;. See every possible problem.<\/li>\n<li><strong>Staging<\/strong>: &#8216;error_reporting = E_ALL&#8217;, but treat deprecations as tasks for the next release.<\/li>\n<li><strong>Production<\/strong>: start with &#8216;E_ALL&#8217;, and only exclude specific categories if they are extremely noisy and you have a plan to fix them.<\/li>\n<\/ul>\n<p>Completely turning down &#8216;error_reporting&#8217; 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.<\/p>\n<h2><span id=\"Development_vs_Staging_vs_Production_Different_Defaults\">Development vs Staging vs Production: Different Defaults<\/span><\/h2>\n<p>Healthy hosting setups treat development, staging and production differently. Error logging is one of the clearest places to see this separation.<\/p>\n<h3><span id=\"Recommended_development_settings\">Recommended development settings<\/span><\/h3>\n<ul>\n<li>&#8216;display_errors = On&#8217;<\/li>\n<li>&#8216;log_errors = On&#8217;<\/li>\n<li>&#8216;error_reporting = E_ALL&#8217;<\/li>\n<li>&#8216;error_log&#8217; pointing to an easily accessible file inside your project tree<\/li>\n<\/ul>\n<p>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.<\/p>\n<h3><span id=\"Recommended_staging_settings\">Recommended staging settings<\/span><\/h3>\n<ul>\n<li>&#8216;display_errors = Off&#8217;<\/li>\n<li>&#8216;log_errors = On&#8217;<\/li>\n<li>&#8216;error_reporting = E_ALL&#8217;<\/li>\n<li>&#8216;error_log&#8217; stored in a space where your team can download and inspect it easily<\/li>\n<\/ul>\n<p>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 <a href='https:\/\/www.dchost.com\/blog\/en\/paylasimli-hostingde-wordpress-staging-ortami-kurmak-adim-adim-uygulamali-rehber\/'>creating a WordPress staging environment on shared hosting<\/a> and apply the logging recommendations there.<\/p>\n<h3><span id=\"Recommended_production_settings\">Recommended production settings<\/span><\/h3>\n<ul>\n<li>&#8216;display_errors = Off&#8217; (non\u2011negotiable)<\/li>\n<li>&#8216;log_errors = On&#8217;<\/li>\n<li>&#8216;error_reporting = E_ALL&#8217; or a slightly reduced mask only if justified<\/li>\n<li>&#8216;error_log&#8217; stored in a directory that is not publicly accessible over the web<\/li>\n<\/ul>\n<p>If your application framework has its own logging system (for example Monolog in Laravel or built\u2011in debug.log in WordPress), keep PHP logging enabled anyway. Framework logs often miss low\u2011level engine problems like extensions failing to load or fatal parse errors that occur before your framework code runs.<\/p>\n<h2><span id=\"Where_to_Configure_PHP_Error_Logging_on_Hosting\">Where to Configure PHP Error Logging on Hosting<\/span><\/h2>\n<p>On a local machine there is usually one &#8216;php.ini&#8217; file. On hosting platforms you often have several layers of configuration: global PHP, per\u2011user overrides and per\u2011directory or per\u2011site settings. Knowing where to change which directive avoids conflicts and surprises.<\/p>\n<h3><span id=\"Shared_hosting_with_cPanel_or_DirectAdmin\">Shared hosting with cPanel or DirectAdmin<\/span><\/h3>\n<p>On shared hosting at dchost.com, customers generally have three ways to control PHP error settings:<\/p>\n<ol>\n<li><strong>Control panel PHP editor<\/strong> (MultiPHP INI editor or similar) \u2013 easiest option for global settings per domain.<\/li>\n<li><strong>&#8216;.user.ini&#8217; files<\/strong> \u2013 per\u2011directory overrides when you cannot or do not want to use the panel UI.<\/li>\n<li><strong>&#8216;.htaccess&#8217; directives<\/strong> \u2013 on Apache based setups using &#8216;php_flag&#8217; and &#8216;php_value&#8217; when PHP runs as an Apache module (increasingly rare, but still seen in legacy stacks).<\/li>\n<\/ol>\n<h4><span id=\"Using_control_panel_editors\">Using control panel editors<\/span><\/h4>\n<p>Typical flow:<\/p>\n<ul>\n<li>Open your hosting panel and navigate to the PHP options or MultiPHP INI editor.<\/li>\n<li>Select the domain or subdomain.<\/li>\n<li>Set &#8216;display_errors&#8217; to &#8216;Off&#8217;, &#8216;log_errors&#8217; to &#8216;On&#8217; and &#8216;error_reporting&#8217; to the level you want.<\/li>\n<li>If available, set a custom &#8216;error_log&#8217; path under your home directory, for example &#8216;\/home\/username\/logs\/example.com-php-error.log&#8217;.<\/li>\n<\/ul>\n<p>This approach is recommended for most users because it centralises settings and reduces the risk of typos in custom files.<\/p>\n<h4><span id=\"Using_8216userini8217_on_shared_hosting\">Using &#8216;.user.ini&#8217; on shared hosting<\/span><\/h4>\n<p>When you need per\u2011folder control, for example for a staging subfolder, you can create a file named &#8216;.user.ini&#8217; in that directory with content like:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">display_errors = Off\nlog_errors = On\nerror_reporting = E_ALL\nerror_log = \/home\/username\/logs\/staging-example-php-error.log\n<\/code><\/pre>\n<p>PHP will apply these overrides for all scripts under that directory tree. Remember that &#8216;.user.ini&#8217; is read periodically, not on every request, so changes might take a short time to become active.<\/p>\n<h4><span id=\"Using_8216htaccess8217_Apache_module_only\">Using &#8216;.htaccess&#8217; (Apache module only)<\/span><\/h4>\n<p>If PHP is integrated as an Apache module (not via FPM), you may encounter older syntax like:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">php_flag display_errors Off\nphp_flag log_errors On\nphp_value error_reporting E_ALL\nphp_value error_log \/home\/username\/logs\/example.com-php-error.log\n<\/code><\/pre>\n<p>On modern setups with PHP\u2011FPM, this form usually does not work. In that case, stick to the control panel or &#8216;.user.ini&#8217; approach.<\/p>\n<h3><span id=\"VPS_dedicated_server_and_colocation_setups\">VPS, dedicated server and colocation setups<\/span><\/h3>\n<p>On your own server or a VPS from dchost.com, you have full control of PHP configuration. Common places to adjust error logging include:<\/p>\n<ul>\n<li>Global &#8216;php.ini&#8217; (for CLI and default FPM settings).<\/li>\n<li>Per\u2011pool PHP\u2011FPM configuration files such as &#8216;\/etc\/php\/8.2\/fpm\/pool.d\/example.com.conf&#8217;.<\/li>\n<li>Per\u2011vhost overrides via &#8216;php_admin_value&#8217; in Nginx or Apache configs.<\/li>\n<\/ul>\n<p>For per\u2011site isolation, we strongly recommend assigning each site its own FPM pool with its own &#8216;php_admin_value[error_log]&#8217; path. This complements the process isolation strategies we describe in our guide on <a href='https:\/\/www.dchost.com\/blog\/en\/php-session-ve-queue-iscileri-icin-ayri-php-fpm-islem-havuzu-kurmak\/'>isolating PHP session and queue workers using separate PHP\u2011FPM pools<\/a>.<\/p>\n<h4><span id=\"Example_PHPFPM_pool_config_snippet\">Example PHP\u2011FPM pool config snippet<\/span><\/h4>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">[example.com]\nuser = example\ngroup = example\nlisten = \/run\/php-fpm-example.sock\n\nphp_admin_value[display_errors] = Off\nphp_admin_value[log_errors] = On\nphp_admin_value[error_reporting] = E_ALL\nphp_admin_value[error_log] = \/var\/log\/php\/example.com-error.log\n<\/code><\/pre>\n<p>&#8216;php_admin_value&#8217; in FPM means the value cannot be overridden by user scripts, which is ideal for enforcing &#8216;display_errors = Off&#8217; in production.<\/p>\n<h2><span id=\"Choosing_the_Right_Log_Levels_with_8216error_reporting8217\">Choosing the Right Log Levels with &#8216;error_reporting&#8217;<\/span><\/h2>\n<p>Log levels determine how much signal versus noise you get from logs. Setting &#8216;error_reporting&#8217; correctly is one of the biggest gains you can get with a single directive.<\/p>\n<h3><span id=\"Recommended_patterns_for_modern_PHP\">Recommended patterns for modern PHP<\/span><\/h3>\n<p>For PHP 7.4 and 8.x, good starting points are:<\/p>\n<ul>\n<li><strong>Development<\/strong>: &#8216;error_reporting = E_ALL&#8217;<\/li>\n<li><strong>Staging<\/strong>: &#8216;error_reporting = E_ALL&#8217;<\/li>\n<li><strong>Production (ideal)<\/strong>: &#8216;error_reporting = E_ALL&#8217;<\/li>\n<li><strong>Production (legacy code)<\/strong>: &#8216;error_reporting = E_ALL &amp; ~E_DEPRECATED &amp; ~E_USER_DEPRECATED&#8217;<\/li>\n<\/ul>\n<p>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\u2011do list for code upgrades, not something to hide forever. Clean logs make future PHP upgrades significantly safer, as we cover in our article about <a href='https:\/\/www.dchost.com\/blog\/en\/php-8-x-yukseltme-kontrol-listesi-wordpress-laravelde-geriye-uyumluluk-opcache-preload-ve-fpm-havuz-ayarlari-nasil-tatli-tatli-kurulur\/'>upgrading to PHP 8.x<\/a>.<\/p>\n<h3><span id=\"Framework_level_logging_vs_PHP_level_logging\">Framework level logging vs PHP level logging<\/span><\/h3>\n<p>Many frameworks have their own log level concepts (debug, info, warning, error, critical). These are separate from PHPs &#8216;error_reporting&#8217; but work together:<\/p>\n<ul>\n<li>Use PHP &#8216;error_reporting&#8217; to capture engine level problems: parse errors, fatal errors, warnings, deprecations.<\/li>\n<li>Use framework log levels to control application specific noise and business events.<\/li>\n<\/ul>\n<p>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.<\/p>\n<h2><span id=\"Organising_and_Rotating_PHP_Error_Logs\">Organising and Rotating PHP Error Logs<\/span><\/h2>\n<p>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.<\/p>\n<h3><span id=\"Persite_and_perenvironment_log_files\">Per\u2011site and per\u2011environment log files<\/span><\/h3>\n<p>Best practice is to split logs along boundaries that match how you deploy and debug:<\/p>\n<ul>\n<li>Separate log file per site: &#8216;example.com-error.log&#8217;, &#8216;api.example.com-error.log&#8217;, &#8216;admin.example.com-error.log&#8217;.<\/li>\n<li>Separate log file per environment: &#8216;example.com-staging-error.log&#8217;, &#8216;example.com-prod-error.log&#8217;.<\/li>\n<\/ul>\n<p>This way a staging tests error will not flood your production logs, and you can set different rotation policies if needed.<\/p>\n<h3><span id=\"Log_rotation_on_VPS_and_dedicated_servers\">Log rotation on VPS and dedicated servers<\/span><\/h3>\n<p>On self\u2011managed servers, you should configure &#8216;logrotate&#8217; or an equivalent tool to keep PHP logs under control. A typical &#8216;logrotate&#8217; config for a PHP error log might look like:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">\/var\/log\/php\/example.com-error.log {\n    daily\n    rotate 14\n    compress\n    missingok\n    notifempty\n    create 640 www-data www-data\n    sharedscripts\n    postrotate\n        \/usr\/sbin\/service php8.2-fpm reload &gt; \/dev\/null 2&gt;\/dev\/null || true\n    endscript\n}\n<\/code><\/pre>\n<p>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 <a href='https:\/\/www.dchost.com\/blog\/en\/vps-disk-kullanimi-ve-logrotate-ayarlariyla-no-space-left-on-device-hatasini-onlemek\/'>VPS disk usage and logrotate to avoid no space left on device errors<\/a>.<\/p>\n<h3><span id=\"Log_rotation_on_shared_hosting\">Log rotation on shared hosting<\/span><\/h3>\n<p>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:<\/p>\n<ul>\n<li>Periodically download and clean logs manually.<\/li>\n<li>Set up a small PHP or shell script that truncates old logs and schedule it with cron.<\/li>\n<li>Use panel provided log management tools if available.<\/li>\n<\/ul>\n<p>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.<\/p>\n<h2><span id=\"Security_Privacy_and_Compliance_in_PHP_Logs\">Security, Privacy and Compliance in PHP Logs<\/span><\/h2>\n<p>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:<\/p>\n<ul>\n<li><strong>Credentials and tokens<\/strong>: database passwords, API keys, session tokens accidentally sent to error_log from &#8216;var_dump&#8217; or uncaught exceptions.<\/li>\n<li><strong>Personal data<\/strong>: email addresses, phone numbers or IP addresses logged in cleartext.<\/li>\n<li><strong>Internal paths and stack traces<\/strong>: detailed file system layout that can help an attacker.<\/li>\n<\/ul>\n<h3><span id=\"Practical_mitigation_steps\">Practical mitigation steps<\/span><\/h3>\n<ul>\n<li><strong>Never<\/strong> log full payment card data, passwords or full authentication tokens. Mask them before logging.<\/li>\n<li>Sanitise or hash user identifiers when possible.<\/li>\n<li>Ensure &#8216;error_log&#8217; paths are outside the public web root (for example &#8216;\/home\/user\/public_html&#8217; for files and &#8216;\/home\/user\/logs&#8217; for logs).<\/li>\n<li>Limit read access to logs to the appropriate system users and, if applicable, panel sub\u2011users.<\/li>\n<li>Define a retention policy and delete or anonymise logs older than necessary.<\/li>\n<\/ul>\n<p>If you operate in regulated environments or serve EU residents, it is worth reading our dedicated guide on <a href='https:\/\/www.dchost.com\/blog\/en\/kvkk-ve-gdpr-icin-log-anonimlestirme-ip-maskeleme-ve-pseudonymization\/'>log anonymisation and IP masking techniques for KVKK and GDPR compliance<\/a>. The same principles apply to PHP error logs.<\/p>\n<h2><span id=\"Practical_Configuration_Examples\">Practical Configuration Examples<\/span><\/h2>\n<p>To make all of this more concrete, here are a few minimal, real\u2011world configurations you can adapt.<\/p>\n<h3><span id=\"Minimal_production_8216phpini8217_style_configuration\">Minimal production &#8216;php.ini&#8217; style configuration<\/span><\/h3>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">display_errors = Off\nlog_errors = On\nerror_reporting = E_ALL\nerror_log = \/var\/log\/php\/global-error.log\n<\/code><\/pre>\n<p>Use this as a global baseline, then override &#8216;error_log&#8217; per site or per FPM pool.<\/p>\n<h3><span id=\"Per_site_override_with_8216userini8217_on_shared_hosting\">Per site override with &#8216;.user.ini&#8217; on shared hosting<\/span><\/h3>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">; \/home\/username\/public_html\/.user.ini\n\n; Hide errors from visitors\ndisplay_errors = Off\n\n; Log everything, including warnings and deprecations\nlog_errors = On\nerror_reporting = E_ALL\n\n; Store the log under your account but outside public_html\nerror_log = \/home\/username\/logs\/example.com-php-error.log\n<\/code><\/pre>\n<h3><span id=\"Temporarily_enabling_extra_logging_with_8216ini_set8217\">Temporarily enabling extra logging with &#8216;ini_set&#8217;<\/span><\/h3>\n<p>Sometimes you need deeper logs for a specific script without changing global settings. In those cases, you can use &#8216;ini_set&#8217; at the top of a PHP file (remember to remove it later):<\/p>\n<pre class=\"language-php line-numbers\"><code class=\"language-php\">&lt;?php\nini_set('display_errors', '0');\nini_set('log_errors', '1');\nini_set('error_reporting', (string) E_ALL);\nini_set('error_log', '\/home\/username\/logs\/checkout-debug.log');\n\n\/\/ ... rest of the script\n<\/code><\/pre>\n<p>This is especially useful in complex e\u2011commerce flows. Combine it with insights from our article on <a href='https:\/\/www.dchost.com\/blog\/en\/e-ticaret-siteleri-icin-log-analizi-donusum-kaybi-4xx-5xx-ve-odeme-hatalarini-yakalamak\/'>log analysis for e\u2011commerce sites to catch lost conversions and payment errors<\/a> to build targeted debugging around your checkout process.<\/p>\n<h3><span id=\"Using_8216error_log8217_function_inside_PHP_code\">Using &#8216;error_log&#8217; function inside PHP code<\/span><\/h3>\n<p>PHPs &#8216;error_log&#8217; function lets you send custom messages to the same error log file, which is great for debugging without exposing information to users:<\/p>\n<pre class=\"language-php line-numbers\"><code class=\"language-php\">&lt;?php\n$orderId = 1234;\nerror_log('Starting payment validation for order ' . $orderId);\n\n\/\/ business logic here\n\nerror_log('Payment validation OK for order ' . $orderId);\n<\/code><\/pre>\n<p>Because this writes to the configured &#8216;error_log&#8217; file, you get a chronological view that mixes engine errors with your own checkpoints.<\/p>\n<h2><span id=\"Monitoring_Centralised_Logging_and_Alerting\">Monitoring, Centralised Logging and Alerting<\/span><\/h2>\n<p>For a single low\u2011traffic 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.<\/p>\n<h3><span id=\"Centralising_logs_from_multiple_servers\">Centralising logs from multiple servers<\/span><\/h3>\n<p>On multi\u2011server 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 <a href='https:\/\/www.dchost.com\/blog\/en\/birden-fazla-sunucuda-log-yonetimi-elk-ve-loki-stack-ile-merkezi-hosting-loglama\/'>centralising logs for multiple servers with ELK and Loki<\/a> walks through a practical setup that works well with PHP error logs too.<\/p>\n<h3><span id=\"VPS_level_log_management_and_alerts\">VPS level log management and alerts<\/span><\/h3>\n<p>On a single VPS, you can still get a lot of value from structured logging and alerts. We have a detailed guide on <a href='https:\/\/www.dchost.com\/blog\/en\/vps-log-yonetimi-nasil-rayina-oturur-grafana-loki-promtail-ile-merkezi-loglama-tutma-sureleri-ve-alarm-kurallari\/'>VPS log management with Grafana Loki and Promtail<\/a> 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 &#8216;more than X PHP fatal errors in 5 minutes&#8217; can save hours of downtime.<\/p>\n<h3><span id=\"Correlating_PHP_logs_with_web_server_logs\">Correlating PHP logs with web server logs<\/span><\/h3>\n<p>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 &#8216;error_log&#8217; usually tells you exactly which request failed and why. If you want a refresher on reading web server logs efficiently, our guide on <a href='https:\/\/www.dchost.com\/blog\/en\/hosting-sunucu-loglarini-okumayi-ogrenin-apache-ve-nginx-ile-4xx-5xx-hatalarini-teshis-rehberi\/'>how to read web server logs to diagnose 4xx\u20135xx errors<\/a> is a good companion to this article.<\/p>\n<h2><span id=\"Bringing_It_All_Together_on_dchostcom\">Bringing It All Together on dchost.com<\/span><\/h2>\n<p>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:<\/p>\n<ul>\n<li>Always keep &#8216;display_errors&#8217; disabled in staging and production.<\/li>\n<li>Always keep &#8216;log_errors&#8217; enabled and send errors to a dedicated &#8216;error_log&#8217; file.<\/li>\n<li>Use &#8216;error_reporting = E_ALL&#8217; as your default and only reduce it when you have a concrete reason.<\/li>\n<li>Split logs per site and per environment, then rotate and monitor them.<\/li>\n<li>Mask sensitive data, store logs outside the web root and respect legal retention requirements.<\/li>\n<\/ul>\n<p>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.<\/p>\n<p>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.<\/p>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>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 &#8216;display_errors&#8217;, &#8216;error_log&#8217; and incorrect log levels either hide critical problems or expose sensitive data directly on [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":3921,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26],"tags":[],"class_list":["post-3920","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-teknoloji"],"_links":{"self":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/posts\/3920","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/comments?post=3920"}],"version-history":[{"count":0,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/posts\/3920\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/media\/3921"}],"wp:attachment":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/media?parent=3920"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/categories?post=3920"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/tags?post=3920"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}