Skip to end of metadata
Go to start of metadata

Redirection Notice

Icon
This page will redirect to https://www.jetbrains.com/help/phpstorm/debugging-code.html in about 2 seconds.

 

In this tutorial, we'll explore how to use the PhpStorm Debugger to step through our source code while it's running. We'll see how the debugger tool window works, what types of breakpoints exist, how we can watch variables and edit them at runtime, and more. It's assumed either Xdebug or Zend Debugger is already installed and configured.

This tutorial does not cover installing and configuring PhpStorm for debugging. Check out the other tutorials on debugging PHP code with PhpStorm if you want to learn more about how to configure the debugger and get started with several scenarios such as Zero-configuration Web Application Debugging with Xdebug and PhpStorm.

Icon

While this tutorial focuses on using the debugger with PHP code, debugging JavaScript code is very similar. After you finish this tutorial, why not try debugging JavaScript using PhpStorm?

Prerequisites

To make it easier to go through this tutorial, there are some prerequisites we should have in place.

1. Xdebug / Zend Debugger are installed

Make sure either Xdebug or Zend Debugger is installed and configured with PhpStorm.

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.

Icon

If PhpStorm does not detect the debugger with our PHP interpreter, refer to the Troubleshooting PhpStorm debugging tutorial to fix this issue.

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:

 Manually creating a Run/Debug configuration for a PHP script

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.

 Generating a Run/Debug configuration for a PHP script

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.

Icon

We're explicitly creating the Run/Debug configuration in this tutorial, as we are using a PHP CLI script as the example. While we're not using zero-configuration debugging in this tutorial, the interface is the same regardless of the type of debugging we are doing.

Hello, Debugger

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.

Icon

Please note that breakpoints can be set only on lines with code.

Icon

Sometimes we just want to pause execution right at the start of the script. We can do this by checking the Run | Break at first line in PHP scripts menu.

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:

  1. The debugger toolbars, which let us pause, continue or step through script execution.
  2. The Frames pane, which shows us the call stack or execution stack of a script.
  3. The Variables pane, which displays all variables that are available in the current scope where execution is paused.
  4. The Watches pane, where we can watch expressions that we are interested in. Consider them "bookmarks" for data shown in the Variables pane.
  5. The Console tab, which displays the output of our PHP script.
Icon

The tool window layout can be customized at will. For example, when multiple monitors are used, the console tab can be made floating by dragging it out. Or we could make the Watches pane float, again by dragging it out of the debug tool window.

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)

Icon

PHP's superglobals such as _$SERVER, _$GET and _$POST will be visible depending on the type of script being debugged, and whether GET/POST data is available and so on.

Icon

Execution halted on line 16. Even though it initializes a variable named $hundred, that variable is nowhere to be seen. Remember what a breakpoint is? Exactly: the line of code in blue is yet to be executed, and thus in this case we have not yet assigned $hundred. Try pressing F8 (Step Over, see #Stepping through Source Code) once and see the line of code is executed and the variable is now assigned.

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.

Icon

The Watches pane also supports watching expressions. For example, we can use it to view the results of a specific function call that depends on the execution context. We could, for example, monitor PHP's error_get_last() function by adding it to Watches. Keep in mind that executing functions may change script behavior if they perform actions that influence variables, etc.

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.

Icon

Updating variables is really useful in many scenarios. For example, changing an object's property value to test a condition in code. Or changing the current value of $i to a different number while executing a for loop to advance the loop's counter.

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);).

Step Over

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.

Step Out

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.

Step Filters

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)

Breakpoints

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.

Setting 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.

Viewing Breakpoints

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.

The Run | View Breakpoints... menu (or Ctrl+Shift+F8 / CMD-Shift-F8) lets us view, edit and add breakpoints for PHP and JavaScript code. It shows options for all breakpoints we have created in our current project.

Disabling and Enabling Breakpoints

We can enable/disable breakpoints by right-clicking them and selecting/deselecting the Line <...> in <...> enabled option.

Icon

Why enable/disable breakpoints? Isn't this the same as adding/removing a breakpoint? Well, yes and no. Yes, in that disabling a breakpoint has the same effect as removing the breakpoint: it makes PhpStorm not pause script execution at the specific position. However, we can still see the breakpoint and re-enable it if needed. No need to search that specific location and add a breakpoint if it's needed again: simply enable it from the view breakpoints window.

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.

Icon

The expression field has code completion. Try pressing Ctrl+Space to have PhpStorm provide suggestions.

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:

Icon

The expression field has code completion. Try pressing Ctrl+Space to have PhpStorm provide suggestions.

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!

Icon

Exception breakpoints only work when using Xdebug. Zend Debugger currently does not support this feature.

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.

Icon

It's also possible to work with just-in-time (JIT) debugging where Xdebug will only launch the debugger when an error occurs.

 

  • No labels