- Hello, Debugger
- The Debug Tool Window
- Stepping through Source Code
- Setting Breakpoints
- Viewing Breakpoints
- Disabling and Enabling Breakpoints
- Breaking when a Condition is True - Conditional Breakpoints
- Breaking just Once - Temporary Breakpoints
- Breaking after Another Breakpoint is Hit
- Knowing when a Line of Code is Executed
- Breaking when Things Break - Exception Breakpoints
To make it easier to go through this tutorial, there are some prerequisites we should have in place.
1. Xdebug / Zend Debugger are installed
2. Create a New Project with Sample Code
In PhpStorm, create a new Empty project. In it, create a file named debugger.php and paste the following code:
3. Set the PHP Interpreter
Make sure the project has a PHP Interpreter set that is enabled for debugging. To verify this, open the settings / preferences and expand Languages & Frameworks | PHP. From the Interpreters drop-down, pick a PHP interpreter that has Xdebug or Zend Debugger enabled.
If no interpreters are present, use the ... button to add one. PhpStorm will verify the configuration and tell us which debugger and which version of the debugger are configured.
4. Create a Run/Debug Configuration
Run/debug configurations define how a script or application can be executed and launched from the IDE. To be able to launch the debugger, we'll need a Run/Debug Configuration in place. There are two ways of creating a Run/Debug configuration:
We create a new Run/Debug configuration using the Run | Edit Configurations menu. Next, we add a new configuration of the type PHP Script.
We'll have to provide some parameters:
- The name of the Run/Debug configuration, which is something we will use to identify the configuration.
- The path to the script we want to run/debug.
Once finished, click Save and note the Run/Debug configuration appears in the PhpStorm toolbar.
PhpStorm can generate a Run/Debug configuration for a script for us. From the Project tool window, use the Debug | debugging.php context menu (make sure to pick the one with the PHP icon).
Alternatively, we can press Alt+Shift+F9 (Ctrl-Alt-D on Mac OS X) to generate the Run/Debug configuration.
The IDE will launch the script with the debugger enabled, and open the debugger tool window. Note that the PhpStorm toolbar now displays the generated Run/Debug configuration.
Let's do a "Hello World" of debugging by executing a few steps.
1. Set a Breakpoint
Debugging typically consists of pausing the execution of our application at a specific line of code. Such a line of code is called a breakpoint (more about breakpoints later in this tutorial). Breakpoints can be set from the editor window, by clicking in the left-hand gutter. A breakpoint will have a red dot next to it.
Removing breakpoints can be done by clicking the red dot again. Alternatively, we can use the Ctrl+F8 keyboard shortcut (CMD-F8 on Mac OS X) to toggle the breakpoint.
2. Launch the Debugger
From the toolbar, click the "bug" icon to start the debugger. We can also use the Run | Debug menu or the Shift+F9 keyboard shortcut (CMD-F9 on Mac OS X). This will launch our script with the debugger attached, and then pause execution at the first breakpoint.
The line is marked in blue, which means that all lines before it have been executed, and the PHP interpreter is about to execute the marked line if we let it.
Near the bottom, we can also see the debug tool window. It can be used to look at the execution stack, variables currently in scope, watched expressions and more. Since we now have the debugger launched, let's explore it.
The Debug Tool Window
Once the debugger is launched, PhpStorm shows us the debug tool window. It consists of:
- The debugger toolbars, which let us pause, continue or step through script execution.
- The Frames pane, which shows us the call stack or execution stack of a script.
- The Variables pane, which displays all variables that are available in the current scope where execution is paused.
- The Watches pane, where we can watch expressions that we are interested in. Consider them "bookmarks" for data shown in the Variables pane.
- The Console tab, which displays the output of our PHP script.
Now let's see what we can do here.
The Frames pane
In the Frames pane, we can see the call stack at the current breakpoint. For example when we place a breakpoint on the last line of our sum function, the Frames window will tell us that:
- The top frame is on line 11 of debugging.php, in the sum function
- That call originated from line 16 of debugging.php, in the script's main function
By using frames, we can see exactly how we ended up at our breakpoint. Clicking a frame will open the editor at the exact location of that frame. Note that when clicking a frame, the Variables pane is also updated to display the variables that are in scope at that position of our script's execution.
The Variables pane
In the Variables pane, we can see the variables that are in scope at the current breakpoint. For example for a breakpoint inside a function body, the variables created within that function will be visible. When a breakpoint outside that function is hit, those variables will not be available. Here's an example: (note I dragged the Variables pane out into a separate window to make it easier to see the amount of data presented)
The Watches pane
Using the Watches pane, we can explore how the values of certain variables (or expressions) change during script execution. Click the green + in the watches pane and type the name of the variable to watch. Another option is to use the Add to Watches context menu when selecting a variable in the Variables pane.
Running an Expression while Debugging
Sometimes it can be useful to run an expression during debugging. For example, we may want to verify if the add() function does what it's supposed to do. Clicking the Evaluate Arbitrary Expression button in the debug tool window toolbar lets us do exactly this: run some code and inspect the result. Here's an example comparing the
$five variable which was created from calling add against a simple sum.
Updating a Variable
Imagine having to debug a situation where we know which value we want to test, but reproducing it takes time. What we can do is place a breakpoint and simply change a variable's value using the debugger. How about we change the value of
$b to a thousand? We can do this by using the Set Value... context menu on a variable, or by pressing F2.
Stepping through Source Code
Let's explore how we can step through code. Remove all breakpoints and place a new breakpoint on line 14 (
$five = add(2, 3);).
The simplest way of stepping through source code is using Step Over (F8). It executes the current line of code and then pauses execution on the next line of code (even when there is no breakpoint defined). Try it out by starting a new debugging session and stepping over each line of code until the script is finished.
Step Into (and Smart Step Into)
We may want to pause execution at a breakpoint, but then may want to step into a function call that is being made. We can do this with Step Into (F7).
Now what if we want to step into only the inner add function on line 17 (
$thousand = sum(array(100, 200, 300, add(399, 1)));)? We can do this with Smart Step Into (Shift+F7) and select the function to step into.
When we've stepped into a function, we may want to return to the parent frame in the call stack, effectively executing the function and returning its value and pausing right after. Using Step Out (Shift+F8), this is what will happen. PhpStorm will execute the function we're in and pause execution right after it.
Run to Cursor
We may want to just run code until we reach the position where our cursor is located. After we place the cursor somewhere in our code and press Alt+F9, PhpStorm will run code until execution hits that spot. Of course, if the location of the cursor is not in the execution path of our code (e.g. dead code or an if statement where we select a different code path), the IDE will not be able to pause execution at the cursor location.
Rerun, Resume and Stop
From the toolbar, we can restart the current debugging session by pressing the Rerun button (Ctrl+F5 or CMD-F5). We can also Resume execution (F9) and run the script to the next breakpoint (or the end, if none are present). Finally, Stop (Ctrl+F2 or CMD-F2) will halt the current script and stop the debugger.
With step filters, you can specify some methods for which stepping into is suppressed. This will save a lot of time and resources during debugging.
Step filters can be defined in Settings/Preferences | Languages & Frameworks | PHP | Debug | Step Filters, and the following items can be specified:
- Skip magic methods (stepping into all PHP magic methods and any other methods or functions with names starting with a double underscore __ will be suppressed)
- Skip constructors (stepping into all constructors will be suppressed)
- List of specific Skipped Methods (create a list of methods that you do not want PhpStorm to step into. Just type the name of the required function or the fully qualified name of the required method in the format \namespace\class->method)
While debugging, we typically use breakpoints to pause the execution of our application at a specific line of code. PhpStorm provides different types of breakpoints, such as line breakpoints, temporary breakpoints, and more. Let's go over them and see what else is possible making clever use of breakpoints.
To set a breakpoint, all we have to do is open the code in the editor and either:
- Click the left gutter to enable/disable the breakpoint
- Press Ctrl+F8 (CMD-F8 on Mac OS X) to toggle it
Please note that breakpoints can be set only on lines with code.
To view details of a single breakpoint, we can right-click it. This will show us some basic details about the breakpoint and also allows making it a conditional breakpoint.
Disabling and Enabling Breakpoints
We can enable/disable breakpoints by right-clicking them and selecting/deselecting the Line <...> in <...> enabled option.
Breaking when a Condition is True - Conditional Breakpoints
Suppose we're only interested in pausing execution at a breakpoint when a given condition is met. For example, we may only want to pause execution at a breakpoint in a loop when we're working with a specific value. After right-clicking the breakpoint, we can set such a condition. Once saved, PhpStorm will only pause execution when the result of the condition is true.
Breaking just Once - Temporary Breakpoints
Suppose we want to delete a breakpoint after it has been hit. After we right-click a breakpoint and select the Remove once hit check-box, PhpStorm ensures the breakpoint will only be hit once and removes it afterwards.
Temporary breakpoints can also be created by pressing Ctrl+Alt+Shift+F8 (CMD-Alt-Shift-F8 on Mac OS X).
Breaking after Another Breakpoint is Hit
We may want to disable a breakpoint until another breakpoint has been hit. For example, we could add a breakpoint in the add function which is only enabled once another breakpoint in the sum function is hit. From the Breakpoints window we can tell PhpStorm to keep the add breakpoint disabled until the sum one is hit.
Knowing when a Line of Code is Executed
Sometimes we don't want to pause execution, but we still want to know when a line of code has been executed. Or we may want to write a log message when a line of code is executed. When we right-click a breakpoint and uncheck the Suspend box, PhpStorm shows us some additional options for the breakpoint.
We can enable:
- Log message to console to have PhpStorm write some info about the breakpoint to the console when it's hit.
- Log evaluated expression to have PhpStorm evaluate an expression and log the result to the console when hit.
After enabling Log evaluated expression and giving PhpStorm an expression, here's the console output for a debugging session:
Breaking when Things Break - Exception Breakpoints
What if we want to pause execution when an error or Exception occurs during execution? That's what Exception Breakpoints are for!
From the Breakpoints window (Run | View Breakpoints...), we can create a new Exception breakpoint (use the green +) and specify the errors or Exception types to break on.
Custom Exception types are supported, as well as PHP's Warning, Notice or Deprecated error conditions instead. E_ERROR, E_PARSE and E_COMPILE_ERROR can’t be handled, as they halt execution of the PHP engine.
If we now add
$infinity = 1 / 0; somewhere in our script and launch the debugger, PhpStorm will pause execution on this line of code even if we did not explicitly add a breakpoint. To see the type of error or Exception, hover over the breakpoint which PhpStorm adds in the gutter. Also note I added a watch for the error_get_last() function to get some additional information.