How to set up Xdebug 3 and Webgrind for PHP 8

Steve HamSteve Ham
8 min read

Debugging and profiling apps is something that's often overlooked in a developer workflow, especially since it's one of the more tedious and less exciting things to do, but it can be a crucial step to understanding a bug or performance issue. Xdebug in particular is the quintessential tool for debugging in PHP, and Webgrind provides an additional layer on top of it that allows you to view the results from Xdebug in your favorite browser.

Setting up the latest version of Xdebug (3 as of this writing) with the latest version of PHP (8.3 as of this writing) is relatively simple to do, and is already documented in various places online, but since it's possible to run into some installation quirks (in particular with Apache on Ubuntu Linux), this setup guide is provided here to cover those quirks with workarounds that I found.

Prerequisites: since this guide is completely focused on installing & setting up Xdebug 3 with PHP 8 (8.3.10 to be specific), I assume that you have enough familiarity with PHP to be able to follow along (and ideally will have it already installed, but if you don't, some info on that is provided in the next section below). I've verified that all of the steps in this guide will work on both Windows (with WSL) and a native Linux install of Ubuntu 22.04; there may or may not be any differences on macOS that I'm not aware of, since I don't use macOS.

Prerequisite: Installing PHP (and Apache if needed)

If you use Windows, I highly recommend using WSL for development. While it's possible to use WAMP or XAMPP, configuring these can be complicated for a beginner and adds unnecessary complexity. Using WSL instead is very straightforward, and is what this guide covers.

If you don't already have either PHP or Apache installed, both should be installed prior to installing Xdebug and Webgrind. You can check whether you have PHP already installed with the command "php -v", which will show the version of PHP that's installed (assuming that it is installed).

For PHP, LiquidWeb provides an excellent installation guide that's available here: https://www.liquidweb.com/help-docs/install-php-on-ubuntu/. Note that if you follow their guide, make sure to substitute "php8.3" for "php8.2" to make sure that you install the newer version.

For Apache, DigitalOcean provides an installation guide that covers the basics of what you need to know (although written for Ubuntu 22.04, it's applicable to any recent version of Ubuntu, and includes a drop-down to select a different Linux distribution if you don't have Ubuntu): https://www.digitalocean.com/community/tutorials/how-to-install-the-apache-web-server-on-ubuntu-22-04

Note that depending on your Linux installation, the "systemctl" command may not work, in which case you can use "service apache2 [status/start/stop/restart]".

Installing PHP Composer

Composer is PHP's dependency manager (comparable to npm or yarn for Node.js) which is a prerequisite for using Webgrind. Installation instructions for Composer can be found on its offical website here: https://getcomposer.org/doc/00-intro.md

Create a sample PHP file to verify PHP

Before configuring Xdebug, the first thing we should do is setting up a sample PHP file to verify that PHP is installed & working. We can do this using the below steps:

  1. Let's create the new file PHP first:

    $ sudo touch /var/www/html/index.php

  2. Then we'll need to edit the new file. On most Linux systems, you can use "nano" as an editor, which is much easier to use than alternatives like vim. If you don't have "nano" installed, it can be installed with "apt install nano". Once "nano" is installed, then we can do this command next, to edit the new file:

    $ sudo nano /var/www/html/index.php

  3. Once in nano, add the below code, which just calls php's built-in phpinfo() function, which displays detailed info about your PHP installation:

     <?php
     phpinfo();
    
  4. To save your changes and close the file, press Ctrl-X on the keyboard, followed by Y to confirm.

  5. In your Web browser, go to http://localhost:80, where you'll see the result of the phpinfo() statement.

Xdebug Wizard

Xdebug happens to conveniently provide an installation wizard available here, which will give you customized installation & configuration instructions for your particular environment: https://xdebug.org/wizard

You'll have to give it the source output from phpinfo() in your browser (i.e. "View page source" in Chrome) that we just saw in the previous step, to get its customized instructions. Give it a try if you'd like, but it won't be needed for this guide.

Installing Xdebug

In the off chance that you might have xdebug already installed, we can find that out using the below command, which displays all of the PHP modules that are installed:

$ php --ini

Look carefully at the displayed list for anything that shows 20-xdebug.ini or 99-xdebug.ini. If you don't find either of these files, that means Xdebug is not currently installed, and we can install it with this simple command:

$ sudo apt install php-xdebug

After installation completes, you can run this command to verify that Xdebug got installed:

$ php --version

The results of this command should show Xdebug mentioned at the bottom, as it is here:

PHP 8.3.10 (cli) (built: Aug  2 2024 15:31:15) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.3.10, Copyright (c) Zend Technologies
    with Zend OPcache v8.3.10, Copyright (c), by Zend Technologies
    with Xdebug v3.3.2, Copyright (c) 2002-2024, by Derick Rethans

Configuring Xdebug with an xdebug.ini

The next step is to create a new blank configuration file for Xdebug with this command:

$ sudo touch /etc/php/8.3/cli/conf.d/99-xdebug.ini

Or if you already had this file (whether it was 20-xdebug.ini or 99-xdebug.ini), you can skip the preceding step to create the file. We'll then need to edit the file in either case, which we can do with:

$ sudo nano /etc/php/8.3/cli/conf.d/99-xdebug.ini

In nano, paste the below contents exactly as-is. Remember to Ctrl-X to save & close after pasting, then Y to confirm. Many of the configuration options are documented on the Xdebug website here: https://xdebug.org/docs/profiler

zend_extension = xdebug
xdebug.client_host = 127.0.0.1
xdebug.log = /tmp/xdebug_remote.log
xdebug.remote_handler = dbgp
xdebug.mode = profile
xdebug.output_dir = /tmp/cachegrind
xdebug.profiler_output_name = cachegrind.out.%t.%R
xdebug.start_with_request = trigger
xdebug.trigger_value=StartProfile

The directory "/tmp/cachegrind" shown above is our intended profiling output directory, but won't exist yet. The four commands below will: (1) create it, (2) set full read-write-execute permissions on it, (3) allow the Apache server to write to it (Apache has a user known as "www-data"), and (4) restart Apache (can alternately use "sudo systemctl restart apache2.service" if "sudo service apache2 restart" doesn't work).

$ sudo mkdir /tmp/cachegrind

$ sudo chmod 777 /tmp/cachegrind

$ sudo chown www-data:www-data /tmp/cachegrind

$ sudo service apache2 restart

Configuring Apache for Ubuntu 20-24

One of Apache's less-documented quirks on Ubuntu Linux is that it will try to write temporary files directly to the /tmp directory, rather than our intended /tmp/cachegrind directory. To fix this issue, we just need to override Apache's PrivateTmp parameter by running this command:

$ sudo systemctl edit apache2

This command will bring up the file /etc/systemd/system/apache2.service.d, which we'll edit by adding these lines between the comments:

[Service]
PrivateTmp=false

Save and close the file, and then restart Apache with these commands:

$ sudo service apache2 restart

$ systemctl daemon-reload

Verifying our Xdebug installation

At this point, we can go back to our test PHP file and make sure that Xdebug is installed & working. We'll need to edit our previously-created PHP file:

$ sudo nano /var/www/html/index.php

And overwrite the previous code with a call to the xdebug_info() statement:

<?php
xdebug_info();

Refresh your browser on http://localhost:80 to see the new output. Any errors will be highlighted on the page - but there shouldn't be any.

Generating demo PHP code

We should change our test PHP file again to add some code that we can actually profile, before we try to profile anything. We can do that with something as simple as this to overwrite the current index.php file:

<!DOCTYPE html>
<html class="js" lang="en-US">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="profile" href="https://gmpg.org/xfn/11">
  <title>Test Site</title>
</head>
<body>
  <h1>Home</h1>
  <a href="about.php?XDEBUG_TRIGGER=StartProfile"><?= 'to About page'; ?></a>
</body>
</html>

Then we'll create & edit an about.php with the following HTML:

$ sudo touch /var/www/html/about.php

$ sudo nano /var/www/html/about.php

<!DOCTYPE html>
<html class="js" lang="en-US">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="profile" href="https://gmpg.org/xfn/11">
  <title>Test Site</title>
</head>
<body>
  <h1>About</h1>
  <a href="index.php?XDEBUG_TRIGGER=StartProfile"><?= 'to Home page'; ?></a>
</body>
</html>

Installing Webgrind

Webgrind is available directly from a GitHub repo, which allows you to install it with Git clone (or you can alternately visit https://github.com/jokkedk/webgrind, download the ZIP, and unzip the file with tar). You can install Webgrind into any directory, including your home directory (which I did on my own personal system):

$ cd ~

$ git clone https://github.com/jokkedk/webgrind.git

Running Webgrind

With Xdebug installed & working, we just need to 'cd' back over to the webgrind directory and start the server using Composer, which will run on port 8080 by default:

$ cd ~/webgrind

$ composer serve

Then in our browser, we'll just need to add a URL parameter for Xdebug to trigger by visiting http://localhost:80/index.php?XDEBUG_TRIGGER=StartProfile. Click between the About and Index pages a couple of times to generate a handful of profiler files.

In another browser tab, open http://localhost:8080 (which should still be running). You may need to click the "Update" button on this screen for it to see the profiler files, which are listed in the drop-down at the top-right.

At this point we're done and you can view the results from all the files that are generated!

Errors you might run into

  1. If you see the error "[Log Files] File '/tmp/xdebug_remote.log' could not be opened" on the Xdebug info page, it just means that your Linux user is trying to write to a directory that it doesn't have permissions on, which can be fixed with the below two commands. You might need to alternate between Apache and your user, because Apache will also be trying to write to this file.

    $ sudo chown www-data:www-data /tmp/xdebug_remote.log

    $ sudo chown [user]:[user] /tmp/xdebug_remote.log

  2. If you see the error "Trigger value for 'XDEBUG_TRIGGER' not found, falling back to 'XDEBUG_PROFILE'", a workaround is use to the GET parameter in the browser, as shown before:

    http://localhost:80/index.php?XDEBUG_TRIGGER=StartProfile

0
Subscribe to my newsletter

Read articles from Steve Ham directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Steve Ham
Steve Ham