289

How do I turn on all error and warnings and log them to a file, but to set up all of that within the script (not changing anything in php.ini)?

I want to define a file name and so that all errors and warnings get logged into it.

10 Answers 10

436

Use the following code:

ini_set("log_errors", 1);
ini_set("error_log", "/tmp/php-error.log");
error_log( "Hello, errors!" );

Then watch the file:

tail -f /tmp/php-error.log

Or update php.ini as described in this blog entry from 2008.

Sign up to request clarification or add additional context in comments.

8 Comments

ini_set does only work if that code is executed. Not useful for code that has parse errors because the error will be before the code is executed. Instead write those changes into the php.ini.
If you can't edit php.ini, you should be able to add this in the .htaccess : php_flag log_errors on php_value error_log /home/path/public_html/domain/PHP_errors.log. See perishablepress.com/…
I have a question, how to get the error.log file to get created in my htdocs folder instead?
I guess you just change the folder from tmp/php-error.log to which ever location you desire?
This crashes my PHP in 5.4.0
|
112

See

  • error_log — Send an error message somewhere

Example

error_log("You messed up!", 3, "/var/tmp/my-errors.log");

You can customize error handling with your own error handlers to call this function for you whenever an error or warning or whatever you need to log occurs. For additional information, please refer to the Chapter Error Handling in the PHP Manual

1 Comment

Except PHP cannot log anything if there was a fatal error.
65

Simply put these codes at top of your PHP/index file:

error_reporting(E_ALL); // Error/Exception engine, always use E_ALL

ini_set('ignore_repeated_errors', TRUE); // always use TRUE

ini_set('display_errors', FALSE); // Error/Exception display, use FALSE only in production environment or real server. Use TRUE in development environment

ini_set('log_errors', TRUE); // Error/Exception file logging engine.
ini_set('error_log', 'your/path/to/errors.log'); // Logging file path

1 Comment

That's only if you also want all errors to be displayed in output and/or to the browser, in addition to logging. display_errors should NEVER be turned on on a live production server -- that directive is specifically for output to the user, and has no effect on logging. php.net/manual/en/…
28

Add this code in file .htaccess (as an alternative to file php.ini or the ini_set function):

<IfModule mod_php5.c>
php_flag log_errors on 
php_value error_log ./path_to_MY_PHP_ERRORS.log
# php_flag display_errors on 
</IfModule>
  • as commented: this is for Apache-type servers, and not for Nginx or others.

1 Comment

This is very specifically to do with Apache's PHP module, however.
16

That's my personal short function

# logging
/*
[2017-03-20 3:35:43] [INFO] [file.php] Here we are
[2017-03-20 3:35:43] [ERROR] [file.php] Not good
[2017-03-20 3:35:43] [DEBUG] [file.php] Regex empty

mylog ('hallo') -> INFO
mylog ('fail', 'e') -> ERROR
mylog ('next', 'd') -> DEBUG
mylog ('next', 'd', 'debug.log') -> DEBUG file debug.log
*/
function mylog($text, $level='i', $file='logs') {
    switch (strtolower($level)) {
        case 'e':
        case 'error':
            $level='ERROR';
            break;
        case 'i':
        case 'info':
            $level='INFO';
            break;
        case 'd':
        case 'debug':
            $level='DEBUG';
            break;
        default:
            $level='INFO';
    }
    error_log(date("[Y-m-d H:i:s]")."\t[".$level."]\t[".basename(__FILE__)."]\t".$text."\n", 3, $file);
}

2 Comments

An explanation would be in order. E.g., what is the idea/gist? Please respond by editing (changing) your answer, not here in comments (without "Edit:", "Update:", or similar - the answer should appear as if it was written today).
Kinda intense, @PeterMortensen :D Really intense.
8

Take a look at the log_errors configuration option in php.ini. It seems to do just what you want to. I think you can use the error_log option to set your own logging file too.

When the log_errors directive is set to On, any errors reported by PHP would be logged to the server log or the file specified with error_log. You can set these options with ini_set too, if you need to.

(Please note that display_errors should be disabled in php.ini if this option is enabled)

4 Comments

Why should display_errors be disabled if you enable log_errors? Doesn't make sense in my opinion. :)
Because there's no need to output the content of the errors to the public on a production server, especially if the text of the error is being discreetly logged into a file.
Display errors should be always disabled on production server. Not if error logging is configured to somewhere else, but always. Errors are logged to apache error log by default, that is often enough.
Displaying errors on production makes PHP more popular :)
2

None of these answers mention the importance or relevance to Agile teams; professional-level development work is more often than not done within the context of a squad.

Keeping in mind that many development teams use a task-tracking tool such as JIRA, I prefer to use a timestamp to log each error as a separate file:

error_reporting(E_ALL);
ini_set('log_errors', 1);
ini_set('error_log', $_SERVER['DOCUMENT_ROOT'] . '/logs/php/php-errors-' . time() . '.txt');

Using this approach, it is easy for a Project Manager or Team Lead to then isolate each error as a specific file that can then be attached to a unique JIRA defect, assigned to a developer, and tracked (the timestamp can be linked within the defect to easily track while the defect fix is In-Progress). When the issue is closed, then the file can be deleted from the log directory, while a copy of it (if needed for future reference) can be accessed in the JIRA.

1 Comment

Won't log error 500.
0

To log all errors in a file, including Fatal error 500, we are forced to use the php.ini mechanism, as PHP itself could not handle such fatal errors. Generic answer for 2024:


Log PHP errors:

Example is production safe (won't display errors on the webpage), given for PHP.8.3, on Debian 12, with the PHP-FPM user being www-data (This the default):

nano /etc/php/8.3/fpm/php.ini

Add to the bottom:

log_errors = on
error_log = /var/log/php8.3-fpm.log

Give ownership to that log file to the www-data user:

chown www-data:www-data /var/log/php8.3-fpm.log

Allow writing to that log file by the owner:

chmod 660 /var/log/php8.3-fpm.log

Restart PHP-FPM service:

sudo systemctl restart php8.3-fpm

Read PHP potential errors logs in realtime:

tail -f /var/log/php8.3-fpm.log

Optionnal: Log connections times

Edit the PHP-FPM configuration file:

nano /etc/php/8.3/fpm/pool.d/www.conf

Add this to the bottom:

php_admin_value[error_log] = /var/log/php8.3-fpm.log
php_admin_flag[log_errors] = on

listen = /run/php/php8.3-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
user = www-data
group = www-data

Restart PHP-FPM service:

sudo systemctl restart php8.3-fpm

Optionnal: Write in that log from PHP.

fwrite(fopen("/var/log/php8.3-fpm.log", "w"), json_encode($MYVAR));

Optionnal: Write the remote IP adress, from PHP.

fwrite(fopen("/var/log/php8.3-fpm.log", "w"), "New connection from: " .$_SERVER["REMOTE_ADDR"] . " \n");

Comments

-1

In addition, you need the "AllowOverride Options" directive for this to work. (Apache 2.2.15)

Comments

-2

here's my log function:

You can edit the log rows by editing $maxLogs=5, also the order to write your logs $logOrder='top'

<?php
lg('script start','start');

#Code......
lg('script end','End of code');

function lg($str,$mod='Your Log Category'){
    $ts = microtime(true);
    if(!defined('logTimer')){
        define('logTimer',microtime(true));
    }
    $diff=abs(round(($ts-logTimer)*1000,2));
    $maxLogs=5;
    $logOrder='top';#new Logs at top
    
    
    $filename = './log.txt';
    $log=[];
    if(!file_exists($filename)){
        if(!file_put_contents($filename,json_encode($log,128))){
            echo "Can’t open to write '$filename' Check Permissions";
            return;
        }
    }else{
        $c=file_get_contents($filename);
        if(trim($c)==''){$c='[]';}
        
        $log =@json_decode($c,true);
        if(!is_Array($log)){$log=[];}
    }
    $new=['mod'=>$mod,'date'=> date('Y-m-d H:i:s')." Scripttime: ".$diff."ms",'log'=>$str];
    if($logOrder=='top'){
        array_unshift($log , $new);
        $log=array_slice($log,0,$maxLogs);
        }else{
        $log[]=$new;
        $log=array_slice($log,0-$maxLogs,$maxLogs);
    }
    
    
    $logs=json_encode($log,128);
    if(!file_put_contents($filename,$logs) ){echo ("Can’t open to write '$filename' Check Permissions") ;return;}
    return $str;
}
?>

The Output looks like:

[
    {
        "mod": "delete",
        "date": "2022-08-04 13:48:02 0.33ms",
        "log": "test 2"
    },
    {
        "mod": "start",
        "date": "2022-08-04 13:48:29 0ms",
        "log": "test"
    },
    {
        "mod": "delete",
        "date": "2022-08-04 13:48:29 0.27ms",
        "log": "test 2"
    },
    {
        "mod": "start",
        "date": "2022-08-04 13:48:34 0ms",
        "log": "test"
    },
    {
        "mod": "delete",
        "date": "2022-08-04 13:48:34 0.92ms",
        "log": "test 2"
    }
]

2 Comments

echo "Can’t open to write '$filename' Check Permissions";? For a function that's intended to log errors? Seriously?
Also, read up on the race condition. You'll have your file deleted in no time on a live server. Let alone performance issues. In your place I'd leave this code alone and look at the accepted answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.