Different methods to debug PHP code

This week, I was asked for help setting up Xdebug with PhpStorm on a Linux laptop in combination with Docker. I might write about that in an upcoming blog post, but today, I want to focus on different methods to debug code in PHP.

1. echo, print_r, var_dump – the quick but ugly way

Anyone who ever developed something in PHP has used one of the “output functions”. With echo you can output a generic value like a string or number. For arrays and objects, you would use print_r or var_dump.


  • Simple: The methods are easy to use. You don’t have to install anything to use them.
  • Quick insight: When you just want to output a value at a certain line, it’s easy to get the current value at that line.


  • Output limitations: The methods are rather simple. You only get the value of that one variable, but no “context”. As the output is often rendered into an HTML document, you might have to wrap it in a <pre> tag for array/objects or you have to check them in the source code view.
  • Intrusive: When you output the variables, you do might do that while rendering a template. This means that your layout/design gets distorted.
  • Insecure: When you use this technique on a live website, the output is visible to any visitor. Not only does this look like an error, it was also be a security issue, when the content of the data you debug should not be visible.
  • Needs cleanup: Even if you only use this technique while developing locally, you always have to remember this code, before you deploy the code or commit and push it into version control. It’s easy to miss some lines which then end up on a live website.

2. error_log, file_put_contents – logging to a file

Instead of a direct output on the screen, you could write the debugging output into a file. This has some advantages, but some other drawbacks:


  • Separation of concerns: Logging debugging information to a file keeps the application code free of debugging output. You could even introduce your own debugging function as wrapper to the error_log or file_put_contents functions and check inside of this function, if the “debug mode” is active.
  • Persistent records: If you have this “debug mode” activated, you can save the logged information into the file over a longer period of time and check the file for potential issues. It also enables you to debug requests from other people, so you might be able to find issues, you don’t “see” youself.
  • Not distorted output: Your output on the website keeps clean, as any debugging information is only written to a file.


  • Manual inspection: You don’t get the debug information instantly. If you run this on a live website, you might even see the debug information of another person. Running a tail command on your file might help with a more “real time” debugging.
  • Harder to debug: If you use a common debug file for all functions, you will get all debug information without any “context”, so when want to identify the file/line a specific log message was written, you might have to prefix them with the __FILE__ and __LINE__ and maybe even add the date/time, so you know then the log entry was written.
  • Overhead: Logging information to a file can decrease the performance of your site, especially when you debug a lot of data. You should also check the file size of the debug file from time to time and make sure to deactivate the debugging mode, as you can easily fill up all remaining space on your server with a huge log file.
  • Insecurity: Yes, also using a debug file can cause a security issue, in case the log file is publicly available. If it is not publicly available, then debugging with a log file requires you to have access through a terminal or by downloading it. WordPress for example stores the debug.log in the wp-content folder and exposes it to anyone visiting the site. But you can change the path, to make this more secure.

3. Debug plugins – getting the best of both variants

For WordPress, I usually always use the Query Monitor plugin. This plugin offers multiple actions to debug variables. One of them is the qm/debug action.


  • No direct output: Using this action, you don’t output the logged information into the page, so the site does not get distroted.
  • Security: You usually only see the debug information of Query Monitor (and the hook), if you are an administrator of the site. But you can even use it (with the help of a cookie), while logged out.
  • No debug file needed: It does send the debug information with the response, and does not store a file on the server, so the disadvantages of the previous method don’t apply here.


  • Debug code in your application code: Like with the other methods, you still have to write debug code into your application code. You would then also deploy this code on a live website or commit and push it into a repository. So while this might be OK for “unpublished” code, you would rather not want to have it in a plugin/theme you have published. So before releasing a new version of the plugin/theme you would need to remove this debug code.
  • Cannot debug broken pages: As this debugging methods requires the Query Monitor plugin, you cannot debug a fatal error, that would not allow the Query Monitor to display that error.
  • Only your errors: You cannot use this method to debug issues another person is having with your site, and you probably don’t want to give them the permissions to use Query Monitor themselves.

4. Xdebug – next level of debugging

If you haven’t heard of Xebug and/or never used it: use it right after finishing reading this blog post! For me, it is the best tool to debug complex issues. Xdebug is a PHP extension, that needs to be installed and activated. You also need an IDE like PhpStorm or VS Code to use it, but then it can really help you find these hard to debug issues.


  • No additional code needed: Instead of writing any debugging functions into your code, you rather set a “breakpoint” in your IDE to a specific line.
  • Debug all the things: Once a breakpoint is reached, you can debug any variable! So you are not limit to a single variable to debug, but you can see the value of all of them. You can also see the “call stack”, so every function that was called before reaching this point. You can also step back to these functions and inspect the parameters they were called with.
  • Only investigate special cases: Let’s say your code only breaks in certain cases, so when a variable has a specific value. In this case, you can use a conditional breakpoint that only stops, when this condition is met.
  • Test “what if…”: So you found an issue with a variable and its value, and wonder if the code would run as expected with a different value? Well, when you are at a breakpoint, you can overwrite the current value of a variable and then resume, to see what would happen.


  • Hard to setup: If you have never used Xdebug before, it might be hard to set it up. You have to install and activate the PHP extension on the machine you are running the code at, and you have to configure your IDE. When using it with Docker, you also have to make sure that the PHP container can “communicate” with your IDE. While it has become a lot easier and PhpStorm nowadays needs (almost) zero configuration, getting it working for the first time might not be easy. I usually use it in combination with DDEV and now know how to get it running quickly. But your setup might differ.
  • Might break your request: As you “stop” the request while debugging, it might be possible that your site will not render, once you stepped through your code. That is usually the case if you use nginx as the webserver, as you will get an error 500 because the “PHP backend” times out.
  • Not really usable on live environments: While Xdebug is great for development on a local environment, it is not the best tool to be used on a live website. Xdebug has a huge performance impact on the system. Also, due to the fact that Xdebug has to “communicate” with your IDE, it might be hard to impossible to get a setup that works with your IDE and a live site.


There are different methods to debug PHP code, and all oft of them have their pros and cons – even more than I have mentioned in this blog post. In some cases, a quick debug with echo might be all you need. But there have been some issues, I would never have been able to find without the help of Xdebug. So I would highly recommend finding a setup that works for you.

I asked some people about their debugging methods. Around 40% use method 1 frequently, some 5% use method 2 and “only” 55% have used Xdebug before. I hope I can find a way to convince the other 45% to finally start using Xdebug in as their debugging tool.

How about you? Have you used Xdebug? Do you use other methods I have not mentioned, that really work well for you? Then please leave a comment.

Posted by

Bernhard is a full time web developer who likes to write WordPress plugins in his free time and is an active member of the WP Meetups in Berlin and Potsdam.

Leave a Reply

Your email address will not be published. Required fields are marked *