282

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.

9 Answers 9

427

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.

8
  • 47
    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.
    – hakre
    Commented Apr 16, 2013 at 23:31
  • 10
    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/…
    – Matthieu
    Commented Jan 8, 2014 at 8:47
  • 1
    I have a question, how to get the error.log file to get created in my htdocs folder instead?
    – Tommy
    Commented Mar 5, 2014 at 21:51
  • I guess you just change the folder from tmp/php-error.log to which ever location you desire?
    – Luke
    Commented Apr 16, 2014 at 12:37
  • This crashes my PHP in 5.4.0
    – Ky -
    Commented May 10, 2014 at 3:05
109

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
  • 2
    Except PHP cannot log anything if there was a fatal error. Commented Jul 7, 2021 at 13:24
63

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
  • 5
    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/… Commented Mar 9, 2018 at 22:51
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
  • 8
    This is very specifically to do with Apache's PHP module, however. Commented Apr 4, 2016 at 21:02
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
  • 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). Commented Sep 15, 2021 at 23:23
  • Kinda intense, @PeterMortensen :D Really intense.
    – Hop hop
    Commented Jan 22, 2023 at 5:30
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
  • 1
    Why should display_errors be disabled if you enable log_errors? Doesn't make sense in my opinion. :) Commented Aug 20, 2010 at 14:34
  • 6
    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.
    – Shabbyrobe
    Commented Aug 20, 2010 at 14:38
  • 3
    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.
    – Pihhan
    Commented Jul 31, 2013 at 13:49
  • 2
    Displaying errors on production makes PHP more popular :)
    – PeterM
    Commented Jul 19, 2018 at 18:10
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

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

-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
  • echo "Can’t open to write '$filename' Check Permissions";? For a function that's intended to log errors? Seriously? Commented Aug 4, 2022 at 13:58
  • 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. Commented Aug 4, 2022 at 14:00

Not the answer you're looking for? Browse other questions tagged or ask your own question.