278

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Gorep
  • 2,805
  • 2
  • 16
  • 3

9 Answers9

415

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.

Dave Jarvis
  • 30,436
  • 41
  • 178
  • 315
Aman
  • 4,786
  • 1
  • 17
  • 17
  • 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 Apr 16 '13 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 http://perishablepress.com/how-to-enable-php-error-logging-via-htaccess/ – Matthieu Jan 08 '14 at 08:47
  • 1
    I have a question, how to get the error.log file to get created in my htdocs folder instead? – Tommy Mar 05 '14 at 21:51
  • I guess you just change the folder from `tmp/php-error.log` to which ever location you desire? – Luke Apr 16 '14 at 12:37
  • This crashes my PHP in 5.4.0 – Ky - May 10 '14 at 03:05
  • @Tommy, So what was the error? Does changing the value of `error_log` work? – Pacerier Feb 23 '15 at 04:08
  • Could you explain `tail` is that linux command line tail recursion or windows? – Kellen Stuart Oct 19 '16 at 19:21
  • @KolobCanyon Tail is a Linux command (http://man7.org/linux/man-pages/man1/tail.1.html) – sianipard Dec 16 '16 at 14:51
107

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

Edward
  • 4,453
  • 8
  • 44
  • 82
Gordon
  • 312,688
  • 75
  • 539
  • 559
60

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
Yousha Aleayoub
  • 4,532
  • 4
  • 53
  • 64
  • 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. http://www.php.net/manual/en/errorfunc.configuration.php#ini.display_errors – Aaron Wallentine Mar 09 '18 at 22:51
26

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.
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
T.Todua
  • 53,146
  • 19
  • 236
  • 237
15

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);
}
Juergen Schulze
  • 1,515
  • 21
  • 29
  • An explanation would be in order. E.g., what is the idea/gist? Please respond by [editing (changing) your answer](https://stackoverflow.com/posts/44745716/edit), not here in comments (***without*** "Edit:", "Update:", or similar - the answer should appear as if it was written today). – Peter Mortensen Sep 15 '21 at 23:23
  • Kinda intense, @PeterMortensen :D Really intense. – Hop hop Jan 22 '23 at 05:30
7

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)

Amal Murali
  • 75,622
  • 18
  • 128
  • 150
Frxstrem
  • 38,761
  • 9
  • 79
  • 119
  • 1
    Why should `display_errors` be disabled if you enable `log_errors`? Doesn't make sense in my opinion. :) – Guido Hendriks Aug 20 '10 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 Aug 20 '10 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 Jul 31 '13 at 13:49
  • 2
    Displaying errors on production makes PHP more popular :) – PeterM Jul 19 '18 at 18:10
1

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.

CSSBurner
  • 1,565
  • 15
  • 13
-1

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

Stéphane
  • 425
  • 2
  • 7
  • 21
-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"
    }
]
dazzafact
  • 2,570
  • 3
  • 30
  • 49
  • `echo "Can’t open to write '$filename' Check Permissions";`? For a function that's intended to log errors? *Seriously?* – Your Common Sense Aug 04 '22 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. – Your Common Sense Aug 04 '22 at 14:00