How to Debug PHP Code – A Very Simple Guide

Welcome to a tutorial on how to debug PHP code. When it comes to troubleshooting, some beginners immediately foam in the mouth and go into a trance of “very difficult, need advanced tools, only for experts”… No. Debugging PHP does not require any special skills nor tools.

The simplest form of debugging in PHP involves:

  1. Turning on error reporting.
  2. Reading the error messages.
  3. Tracing where the problem is and fixing it.

That’s all to the “difficult debugging”. But just how are these done? Read on to find out!

ⓘ I have included a zip file with all the example source code at the start of this tutorial, so you don’t have to copy-paste everything… Or if you just want to dive straight in.

 

 

TABLE OF CONTENTS

Error Reporting Common Errors Tracing & Tips
Useful Bits & Links The End

 

1) ERROR REPORTING

The first step of debugging in PHP is to stop working in the dark, learn how to get the error message at the very least. Graduate from asking silly questions such as “it does not work” and “I don’t know what went wrong”.

 

PHP GENERAL ERROR REPORTING MECHANICS

When it comes to error reporting in PHP, there are 2 general mechanics:

  • Displaying the error (on the screen).
  • Saving the error into a log file.

 

DISPLAY ERRORS

PHP will show error messages by default, but some of you guys should have already experienced “the system just stopped with no error messages”. That is probably because the error display is turned off. To “fix” that, we can either:

  • Set display_errors = 1 in php.ini.
  • Or turn it on in the PHP script with ini_set('display_errors', 1)

So why do people turn off the error display in the first place? To not scare the non-technical users away.

 

 

ERROR LOG

Then comes the second error reporting mechanism. An elegant way of handling errors is not to display them on the screen, but to save it into a log file. There are 2 directives that control error logging in PHP:

  • log_errors = 1 will save the error messages in a log file.
  • error_log = PATH/ERROR.LOG is where the log file is located.
  • Both directives can also be set in the PHP script itself – ini_set('log_errors', 1) and ini_set('error_log', 'PATH/ERROR.LOG')

So yes, if error messages are somehow not showing up on the screen, it is a good idea to enable error logging and checking the log file instead.

 

ERROR LEVEL

Finally, we have something called the “error level”, set with the error_reporting directive. In a nutshell, this tells PHP to report only when errors of a certain severity level have occurred.

  • E_ERROR Fatal errors.
  • E_WARNING Warnings, non-fatal errors.
  • E_NOTICE Notices, non-fatal.
  • E_ALL All kinds of errors.

For example:

  • To report all kinds of errors error_reporting = E_ALL, or in PHP script error_reporting(E_ALL)
  • Report only when critical errors happen error_reporting = E_ERROR or error_reporting(E_ERROR)
  • Report all errors, except for notices error_reporting = E_ALL & ~E_NOTICE and error_reporting(E_ALL & ~E_NOTICE)

Easy enough?

 

2) COMMON ERRORS

Now that you have eyes on an error message, the next step is to make some sense of what it means. Here are some common examples.

 

FATAL ERRORS

Fatal error: Uncaught Error: Call to undefined function doesnotexist() in D:\http\test\error-fatal.php:2 Stack trace: #0 {main} thrown in D:\http\error-fatal.php on line 2
error-fatal.php
<?php
$foobar = doesnotexist();
require "doesnotexist.php";

Fatal errors will abruptly stop the script and break the system, there is simply no way that you can miss fatal errors. Even if the error reporting is turned off, a weird broken script is just going to raise eyebrows. Fatal errors commonly include undefined functions and missing files (silly typo mistakes).

 

 

SYNTAX ERRORS

Parse error: syntax error, unexpected ‘$hello’ (T_VARIABLE) in D:\http\error-syntax.php on line 3
error-syntax.php
<?php
$foobar = "Doge Bork"
$hello = "World";
$arr = ["Foo", "Bar'};

Silly things such as missing a semi-colon or comma. Sometimes using the wrong operators.

 

WARNINGS

Warning: A non-numeric value encountered in D:\http\error-warn.php on line 3
error-warn.php
<?php
function addition ($x, $y) {
  return $x + $y;
}

echo addition(1, "x");

Warnings are not critical errors, but still of significant importance. For example, putting a string into a function that seemingly needs numbers instead. While this will not break the system, it may end up with the wrong results.

 

NOTICES

Notice: Undefined index: foo in D:\http\error-notify.php on line 2
error-notify.php
<?php
if ($_POST['foo']) {
  echo "YES!";
}

An annoying kind of “error”. Notices are often of little importance, and they are just here to remind you of stuff like “you have not defined this variable before”, or “this function has been deprecated, not recommended”.

 

 

SILENT ERRORS

error-silent.php
<?php
function add ($x, $y) {
  // Original intention
  // return $x + $y;
  // Someone did a *small* typo mistake
  return $x - $y;
}

echo add(88, 22); 
// Should be 110, but result is 66

There are the deadly ones. These errors do not throw any messages, are hard to spot, and the script continues to run “as usual”. You will only realize that there is an error when the scripts do not produce the correct results.

 

3) ERROR TRACING & TIPS

Some errors are easy to spot. Just go to the script and line that the error message indicates, eyeball a few lines of code. But how do we deal with complicated scripts? Here are a few troubleshooting tips.

 

DUMP THE VARIABLES

var-dump.php
<?php
// (A) START SESSION
session_start();

// (B) LET'S SAY WE HAVE A SHOPPING
$_SESSION['cart'] = [
  "123" => [
    "name" => "Foo bar",
    "qty" => 99
  ],
  "234" => [
    "name" => "Doge",
    "qty" => 88
  ]
];

// (C) WHAT'S IN THE CART?
print_r($_SESSION);
var_dump($_SESSION);

So, what is in an array? What is in the session that may be causing problems? print_r() and var_dump() are your best friends.

 

STACK TRACE

first.php
<?php
require "second.php";
$testObj = new Test();
$testObj->foo();
second.php
<?php
class Test {
  function foo () {
    var_dump(debug_backtrace());
    debug_print_backtrace();
  }
}

In big projects, it is common to have multiple scripts sharing many library files. So which scripts and functions were previously called? Use debug_backtrace() and debug_print_backtrace() to find out.

 

 

MANUAL BREAKPOINT

halt-section.php
<?php
// (A) INIT
$varA = ["Hello", "World", "Foo", "Bar"];
$varB = "";

// (B) CONCAT
foreach ($varA as $txt) { $varB .= $txt; }

// (C) DISPLAY & STOP HERE
print_r($varA);
echo $varB;
exit();

// (D) MORE PROCESSING
$varA[] = "Doge";
$varB .= "Last";

With debugging tools, we can set “breakpoints” to pause and check what is in which variables at that point. But no worries, we don’t actually need debugging tools to do that – Just output the variables that you want to check and use die() or exit() to manually stop the script at a specific point.

 

CUSTOM ERROR LOG

custom-error-log.php
<?php
// (A) CURL INIT
$curl = curl_init();
curl_setopt_array($curl, [
  CURLOPT_URL => "https://DOES-NOT-EXIST.com/dummy.php",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HEADER => false
]);

// (B) CURL FETCH
$result = curl_exec($curl);
if ($result === false) {
  error_log("Failed connecting to https://DOES-NOT-EXIST.com", 0);
}
curl_close($curl);

Remember the error log from earlier? Code ninjas can’t be sitting at the desk, monitoring, and waiting for errors to happen 24/7. So utilize the error_log() function to capture your own custom error messages.

 

 

USE A GOOD EDITOR OR IDE

Captain Obvious to the rescue! If you have not installed a good code editor, do so now. It helps to automatically indent your code, and highlight all the silly mistakes.

 

USEFUL BITS & LINKS

That’s all for this guide, and here is a small section on some extras and links that may be useful to you.

 

LINKS & REFERENCES

 

THE END

Thank you for reading, and we have come to the end. I hope that it has helped you to better understand, and if you want to share anything with this guide, please feel free to comment below. Good luck and happy coding!

Leave a Comment

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