PHP Logging Makes Debugging Code Easy

For many, logging with PHP feels out of reach, difficult, or they are just unsure how to do this simple task. PHP logging is a powerful method tool to keep track of what a variables value is at different stages of code processing, view what the output of a function is, etc. This is a great way to stop pulling your hair out as you review code and it looks correct yet you don’t get the expected results.

How do you log data out of PHP? How do you see – and better yet follow – the log data in a readable and method? This tutorial will discuss all of these – but the short answer is to use the PHP error_log function to write data to a file. That log file can then be followed – or tailed – using the Linux tail command or SnakeTail on a Windows machine. These tail tools will stream all new data output to the log file to prevent refreshing and hunting for new data added to the log file.

Some PHP frameworks and platforms have logging methods. These are essentially wrapper functions around this same process. In some regard they do add a lot of value like adding a timestamp by default, making it easier to specify the file name to log to, etc. And in many ways the solution provided here is more cumbersome as it doesn’t utilize some of those conveniences. That said, sometimes with convenience comes a cost. I know in Magento for example, you have to define the logger in the class constructor and re-run the dependency injection compiling, etc. That process – to output some simple strings – can be more trouble than it’s worth at times… if the extended class doesn’t need to add a constructor, you now need to add it and properly call the parent functions constructor, etc. Then wait a few minutes for the php bin/magento di:compile process to run. If you’ve been in this situation, you know the pain and can only ask yourself – is this really the best way?? My opinion is no.

So while this method takes a few more characters and a bit more repetition, it does offer a quick solution that does what you’d expect it to – log data to a file.

Write log data to a file with PHP

Error Logging with PHP

The PHP error_log function [docs] is a quick and universal tool to write log data to a file. It does have a few arguments that are required, but that’s important to tell the function what to do with the data being passed to it.

error_log Arguments

The first argument is the log data that will be written to the file. The error_log function does NOT write a new line to the file. For that reason, PHP_EOL was appended to the log message to write a new line to the file. PHP_EOL is a PHP constant variable of the end of line character for the platform [docs].

The second line needs to be set to 3 to log to a file.

The third argument is the file to write to. A relative path to the script could be used, but it’s far easier to specify an absolute path on the filesystem so that the command is universal regardless of how many directories deep the script is, etc.

File Pathing by Operating System

On Linux / Unix / Mac OSX based systems, a forward slash (/) is used in the file name path. Example: /path/to/file.log will start looking at the root of the filesystem into directory path and then directory to and file file.log. Where as path/to/file.log will start looking from the current directory.

On a Windows based system however, the backslash (\) character is used in the file naming path. However, there is a bit of a complication here… In PHP the backslash (\) is an escape character [docs] and thus \\ is needed to get PHP to recognize the \ character for the pathing correctly. In other words, if in the Windows Explorer a file is located at C:\data\log\file.log. But since the \ needs to be converted to \\ for PHP to recognize it, the path used in the error_log function would be C:\\data\\log\file.log.

Log File Locations

Log files can be written anywhere on the file system. If the file path specified doesn’t exist, the PHP error_log function will create it. In some cases a generic debug.log file is helpful. In other cases when multiple projects are under development at once, it can be helpful to separate each into their own log files named per project.

Most web servers have an access.log file and error.log file that can give clues to what is happening from the webserver level. Those can offer a lot of insights without any custom logging. On a Linux file system using Nginx these will typically be found in the /var/log/nginx/ directory and on a Windows XAMPP system typically look in C:\xampp\apache\logs\. But each system and install is unique, so the file locations will vary.

Logging Arrays and Objects

The error_log function can only log strings – not objects. This presents an issue with arrays as, well, they aren’t strings… But an array can be converted to a string fairly easily for output using the print_r PHP function [docs]. print_r accepts 2 arguments. The first being the array, and the second being return of type boolean – which for the sake of logging, needs to be set to true.

The syntax is this:

This will output log data like this:

PHP objects can be output to log data using this same method. However keep in mind that objects can grow to be very large and at times it’s possible they will cause an error due to running out of memory. Also the methods (or functions) won’t output, which isn’t all that surprising as they are logic and not data. If issues arise in logging an object, adjust to log specific properties of the object instead of the entire object. Here is an example of how logging an object with PHP works in practice. Notice that the method within the object doesn’t get logged yet the static properties do.

Following Log Files

Constantly closing and reopening a log file to read the new entries is not an efficient method of debugging while developing. The better way is to follow – or tail log files, which displays the new entries to the log files immediately. And with a multi-monitor setup, the tail can be setup on a screen to always view and monitor what is happening.

Tail Log Files on Linux / Unix / Mac OSX Platforms

Linux and Unix (which is the backbone of Mac OSX) operating systems almost always come with the tail command built in [manual]. Thanks to this handy feature, as long as a connection to the server is made via a terminal or SSH session, all the tools needed are present.

The tail command in itself displays the last 10 lines at the end of a file without following the new entries. However the -f or -F arguments can be added to follow the file and display the new lines as they are added. The -f argument follows the file. -F does the same but adds a retry which means that if the file is deleted and added (say via logrotate [manual] to ensure files don’t grow too large) this will continue to read the new file.

The syntax is this:

It can be helpful to mark a certain log line – for example the last line analyzed before triggering code to run again. Pressing enter in the terminal will create blank lines in the tail output only and not affect the log file data in anyway. But this leaves a visible gap to help separate runs of a script and log data.

Tail Log Files on Windows with SnakeTail

SnakeTail is a Windows based application that follows log files – showing the new entries as they come in. Multiple log files can be opened at once to keep track of separate scripts, access logs as well as error logs, etc. at the same time.

SnakeTail is available for download from their website: SnakeTail from SnakeNest

Once installed choose File -> Open File and select the log file to follow. That’s it. The next step is to trigger log data and analyze it.

SnakeTail comes with a highlighting feature to mark and navigate between log lines. Choose Edit -> Bookmarks -> Toggle Bookmark (Ctrl+F2) to bookmark a line. Once multiple bookmarks have been added, easily navigate between them with F2 and Shift+F2 (or using the Edit -> Bookmarks option again. But let’s be honest – developers don’t like using a mouse and menus… it’s too slow.

Common Log Line Examples

Class and Function Identifier

This is a common log line to put at the top of a function to identify what class, function, and line was run. This is great for helping to identify if a function was called, in what sequence compared to other functions, etc.

Date Prefix to Log Line

Adding a date/time prefix can be helpful for log files that will be referenced in the future. The standard php date() function is used here. This function offers many date/time format codes [reference], but the c format is a universally accepted format.