This section describes on how to install Xdebug.
How you install Xdebug depends on your system. There are the following possibilities:
- Linux with a package manager such
asapt
,yum
, or something else. - Linux without an Xdebug package with PECL.
- macOSX with homebrew, through PECL.
- Windows, with help from a wizard.
- Unix-like operating systems, from source.
Installing on Linux #
Installing Xdebug with a package manager is often the fastest way. Depending on your distribution, run the following command:
- Alpinelinux:
sudo apk add php7-pecl-xdebug
, or
sudo apk add php8-pecl-xdebug
- Arch Linux:
sudo pacman -S xdebug
- CentOS:
sudo yum install php-xdebug
- CentOS (Remi Repo):
sudo yum install php74-php-xdebug3
, or
sudo yum install php80-php-xdebug3
, or
sudo yum install php81-php-xdebug3
- Debian (9/stretch, testing/buster/bullseye/sid):
sudo apt-get install php-xdebug
- Fedora (32):
sudo yum install php-xdebug
- Fedora (Remi Repo):
sudo yum install php74-php-xdebug3
- Gentoo:
emerge dev-php/xdebug
- Manjaro (20.1/Mikah):
sudo pacman -S xdebug
- RHEL:
sudo yum install php-xdebug
- RHEL (Remi Repo):
sudo yum install php74-php-xdebug3
- SUSE (openSUSE, Enterprise):
sudo zypper in php7-xdebug
, or
sudo zypper in php8-xdebug
- Ubuntu (18.04 LTS/Bionic, 20.04 LTS/Focal):
sudo apt-get install php-xdebug
- Ubuntu (Ondřej Surý’s PPA):
sudo apt-get install php7.4-xdebug
, or
sudo apt-get install php8.0-xdebug
, or
sudo apt-get install php8.1-xdebug
Xdebug’s latest version is 3.2.0.
For packages that have the PHP version in the package name, such as in
php81-php-xdebug3
, you can substitute the PHP
version with the one that matches the PHP version that you are running.
Linux distributions might be providing an old and/or outdated version.
If the package manager
installs a version that is no longer supported (see Supported Versions), please install
Xdebug with PECL, or from source
instead.
Installing with PECL #
You can install Xdebug through PECL on Linux & macOS with Homebrew.
Prerequisites:
- macOS:
- Xcode’s command line tools (run:
xcode-select
).
--install - PHP installed through Homebrew.
- Xcode’s command line tools (run:
- Linux:
- GCC and associated libraries.
- PHP development headers (see Compile below).
Run:
pecl install xdebug
On Apple M1 hardware, programs can either be compiled for the native M1/ARM64
architecture, or for the emulated x86_64 architecure. Sometimes there is a
mismatch with the default and PECL will fail, or Xdebug won’t load with a
message such as:
PHP Warning: Failed loading Zend extension 'xdebug.so' (tried: /opt/homebrew/lib/php/pecl/20190902/xdebug.so (dlopen(/opt/homebrew/lib/php/pecl/20190902/xdebug.so, 9): no suitable image found. Did find: /opt/homebrew/lib/php/pecl/20190902/xdebug.so: mach-o, but wrong architecture /opt/homebrew/lib/php/pecl/20190902/xdebug.so: stat() failed with errno=22), /opt/homebrew/lib/php/pecl/20190902/xdebug.so.so (dlopen(/opt/homebrew/lib/php/pecl/20190902/xdebug.so.so, 9): image not found)) in Unknown on line 0
You can verify what your PHP’s architecture is with:
file `which php`
If that says arm64e
, then you need to run:
arch -arm64 sudo pecl install xdebug
And if it’s x86_64
, then you need to run:
arch -x86_64 sudo pecl install xdebug
You should ignore any prompts to add
"extension=xdebug.so"
to
php.ini
— this will cause problems.
In some cases pecl
will change the php.ini
file to
add a configuration line to load Xdebug. You can check whether it did by
running php -v
. If Xdebug shows up with a version number, than
you’re all set and you can configure Xdebug’s other functions, such as
Step Debugging, or Profiling.
If pecl
did not add the right line, skip to the Configure PHP section.
1 On macOS, you should have PHP installed with Homebrew.
Installing on Windows #
There are a few precompiled modules for Windows, they are all for the non-debug
version of PHP. You can get those at the download
page. Follow these instructions to get Xdebug
installed.
Installation From Source #
Obtain #
You can download the source of the latest stable release 3.2.0.
Alternatively you can obtain Xdebug from GIT:
git clone git://github.com/xdebug/xdebug.git
This will checkout the latest development version which is currently
3.2.0dev. This development branch might not always work as
expected, and may have bugs.
You can also browse the source on GitHub at https://github.com/xdebug/xdebug.
Compile #
There is a wizard available that provides you
with the correct file to download, and which paths to use.
You compile Xdebug separately from the rest of PHP. You need access to the
scripts phpize
and php-config
. If your system
does not have phpize
and php-config
, you will
need to install the PHP development headers.
Debian users can do that with:
apt-get install php-dev
And RedHat and Fedora users with:
yum install php-devel
It is important that the source version matches the installed version as there
are slight, but important, differences between PHP versions. Once you have
access to phpize
and php-config
, take the
following steps:
-
Unpack the tarball:
tar -xzf xdebug-3.2.0.tgz
You should not
unpack the tarball inside the PHP source code tree.
Xdebug is compiled separately, all by itself, as stated above. -
cd xdebug-3.2.0
-
phpize
If phpize is not in your path, please make sure
that it is by expanding thePATH
environment variable. Make sure
you use the phpize that belongs to the PHP version that you want to use Xdebug
with. See this FAQ entry if you’re having some
issues with finding which phpize to use. -
./configure --enable-xdebug
-
make
-
make install
Configure PHP #
-
Find out which PHP ini file to modify.
Run a script with the following to find all configuration files that PHP has
loaded:<?php var_dump(php_ini_loaded_file(), php_ini_scanned_files());
Alternatively, you can run
php --ini
on the command line.If there is a file with
xdebug
in the name, such as
/etc/php/7.4/cli/conf.d/99-xdebug.ini
, then this is the
file to use.If that file does not exist, but there are other files in a
conf.d
or similar directory, you can create a new file there too.
Please name it99-xdebug.ini
in that case.Otherwise, modify the
php.ini
file that is displayed through
the script, orphp --ini
command.There could be more than one
php.ini
file. In many set-ups there is a different one for the
command line (oftencli/php.ini
) and the web server (often
fpm/php.ini
).If you want to use Xdebug and
OPCache together, you must have thezend_extension
line for Xdebug
below the line for OPCache, or in a file starting with a higher number (ie.
99-xdebug.ini
vs20-opcache.ini
), otherwise they
won’t work properly together. -
Add the following line to this PHP ini file:
zend_extension=xdebug
-
Restart your webserver, or PHP-FPM, depending on what you are
using. -
Verify that Xdebug is now loaded.
Create a PHP page that calls xdebug_info(). If you request the
page through the browser, it should show you an overview of Xdebug’s settings
and log messages.On the command line, you can also run
php -v
. Xdebug and its
version number should be present as in:PHP 7.4.10 (cli) (built: Aug 18 2020 09:37:14) ( NTS DEBUG ) Copyright (c) The PHP Group Zend Engine v3.4.0, Copyright (c) Zend Technologies with Zend OPcache v7.4.10-dev, Copyright (c), by Zend Technologies with Xdebug v3.0.0-dev, Copyright (c) 2002-2020, by Derick Rethans
If Xdebug does not show up, or you get a warning from PHP that an
xdebug.so
file or similar was not found, you might need to use the
full path instead of justzend_extension=xdebug
, such as
zend_extension=/usr/lib/php/20190902/xdebug.so
.On Windows, you should place the
php_xdebug.dll
in the
ext/
directory, which is a child directory in your PHP
installation tree.
If you have trouble with this, please refer to the installation wizard to help you guide through this
process.
With Xdebug loaded, you can now enable individual features, such as
Step Debugging, or Profiling.
Related Content #
- Activation and Triggers
This video explains how to activate, through triggers and other method’s Xdebug’s step debugger, profiler, and tracer.
- Xdebug 3: Diagnostics
This video teaches you how to troubleshoot your Xdebug setup. It explains how to find out how Xdebug is configured, which settings have been made, and what it is attempting to do regarding its different features.
- Xdebug 3: Modes
This video introduces Xdebug 3’s modes — the new way to configure which parts of Xdebug you have enabled.
Related Settings and Functions #
- string xdebug.log =
- integer xdebug.log_level = 7
- string xdebug.mode = develop
- xdebug_info() : mixed
Settings #
string xdebug.log = #
Configures Xdebug’s log file.
Xdebug will log to this file all file creations issues, Step Debugging
connection attempts, failures, and debug communication.
Enable this functionality by setting the value to a absolute path. Make sure
that the system user that PHP runs at (such as www-data
if you are
running with Apache) can create and write to the file.
The file is opened in append-mode,
and will therefore not be overwritten by default. There is no concurrency
protection available.
The log file will include any attempt that Xdebug
makes to connect to an IDE:
[2693358] Log opened at 2020-09-02 07:19:09.616195 [2693358] [Step Debug] INFO: Connecting to configured address/port: localhost:9003. [2693358] [Step Debug] ERR: Could not connect to debugging client. Tried: localhost:9003 (through xdebug.client_host/xdebug.client_port). [2693358] [Profiler] ERR: File '/foo/cachegrind.out.2693358' could not be opened. [2693358] [Profiler] WARN: /foo: No such file or directory [2693358] [Tracing] ERR: File '/foo/trace.1485761369' could not be opened. [2693358] [Tracing] WARN: /foo: No such file or directory [2693358] Log closed at 2020-09-02 07:19:09.617510
It includes the opening time (2020-09-02 07:19:09.616195
), the
IP/Hostname and port Xdebug is trying to connect to
(localhost:9003
), and whether it succeeded (Connected to
). The number in brackets (
client[2693358]
) is the
Process ID.
It includes:
[2693358]
- process ID in brackets
2020-09-02 07:19:09.616195
- opening time
For Step Debugging:
INFO: Connecting to configured address/port: localhost:9003. ERR: Could not connect to debugging client. Tried: localhost:9003 (through xdebug.client_host/xdebug.client_port).
For Profiling:
ERR: File '/foo/cachegrind.out.2693358' could not be opened. WARN: /foo: No such file or directory
For Function Trace:
ERR: File '/foo/trace.1485761369' could not be opened. WARN: /foo: No such file or directory
All warnings and errors are described on the Description of errors page, with
detailed instructions on how to resolve the problem, if possible. All errors are always logged through
PHP’s internal logging mechanism (configured with error_log
in php.ini
). All warnings and errors also show up in the
diagnostics log that you can view by calling xdebug_info().
Step Debugger Communication
The debugging log can also log the communication between Xdebug and an IDE.
This communication is in XML, and starts with the <init
XML
element:
<init xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug" fileuri="file:///home/httpd/www.xdebug.org/html/router.php" language="PHP" xdebug:language_version="7.4.11-dev" protocol_version="1.0" appid="2693358" idekey="XDEBUG_ECLIPSE"> <engine version="3.0.0-dev"><![CDATA[Xdebug]]></engine> <author><![CDATA[Derick Rethans]]></author> <url><![CDATA[https://xdebug.org]]></url> <copyright><![CDATA[Copyright (c) 2002-2020 by Derick Rethans]]></copyright> </init>
The fileuri
attribute lists the entry point of your
application, which can be useful to compare to breakpoint_set
commands to see if path mappings are set-up correctly.
Beyond the <init
element, you will find the configuration of
features:
<- feature_set -i 4 -n extended_properties -v 1 -> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug" command="feature_set" transaction_id="4" feature="extended_properties" success="1"> </response>
And continuation commands:
<- step_into -i 9 -> <response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug" command="step_into" transaction_id="9" status="break" reason="ok"> <xdebug:message filename="file:///home/httpd/www.xdebug.org/html/router.php" lineno="3"> </xdebug:message> </response>
You can read about DBGP — A common debugger protocol specification at its dedicated documation page.
The xdebug.log_level setting controls how much information is
logged.
Many Linux distributions now use systemd, which
implements private tmp directories. This means that when PHP
is run through a web server or as PHP-FPM, the /tmp
directory is
prefixed with something akin to:
/tmp/systemd-private-ea3cfa882b4e478993e1994033fc5feb-apache.service-FfWZRg
This setting can additionally be configured through the
XDEBUG_CONFIG
environment variable.
integer xdebug.log_level = 7 #
Configures which logging messages should be added to the log file.
The log file is configured with the xdebug.log setting.
The following levels are supported:
Level | Name | Example |
---|---|---|
0 | Criticals | Errors in the configuration |
1 | Errors | Connection errors |
3 | Warnings | Connection warnings |
5 | Communication | Protocol messages |
7 | Information | Information while connecting |
10 | Debug | Breakpoint resolving information |
Criticals, errors, and warnings always show up in the
diagnostics log that you can view by calling xdebug_info().
Criticals and errors are additionally logged through
PHP’s internal logging mechanism (configured with error_log
in php.ini
).
This setting can additionally be configured through the
XDEBUG_CONFIG
environment variable.
string xdebug.mode = develop #
This setting controls which Xdebug features are enabled.
This setting can only be set in php.ini
or
files like 99-xdebug.ini
that are read when a PHP process starts
(directly, or through php-fpm), but not in .htaccess
and
.user.ini
files, which are read per-request.
The following values are accepted:
off
- Nothing is enabled. Xdebug does no work besides checking whether
functionality is enabled. Use this setting if you want close to 0
overhead. develop
- Enables Development Helpers including the overloaded var_dump().
coverage
- Enables Code Coverage Analysis to generate code coverage reports, mainly in
combination with
PHPUnit. debug
- Enables Step Debugging. This can be used to step through your code while it
is running, and analyse values of variables. gcstats
- Enables Garbage Collection Statistics to collect statistics about PHP’s Garbage
Collection Mechanism. profile
- Enables Profiling, with which you can analyse performance bottlenecks
with tools like KCacheGrind. trace
- Enables the Function Trace feature, which allows you record every function
call, including arguments, variable assignment, and return value that is made
during a request to a file.
You can enable multiple modes at the same time by comma separating their
identifiers as value to xdebug.mode: xdebug.mode=develop,trace
.
XDEBUG_MODE environment variable
You can also set Xdebug’s mode by setting the XDEBUG_MODE
environment variable on the command-line; this will take precedence over the
xdebug.mode setting, but will not change the value of the xdebug.mode
setting.
Some web servers have a configuration option to
prevent environment variables from being propagated to PHP and Xdebug.
For example, PHP-FPM has a clear_env
configuration setting that is on
by default, which you will
need to turn off
if you want to use XDEBUG_MODE
.
Make sure that your web server does not clean the environment, or specifically
allows the XDEBUG_MODE
environment variable to be passed on.
Functions #
xdebug_info( string $category = null )
: mixed
#
Show and retrieve diagnostic information
This function presents APIs to retrieve information about Xdebug itself. Which
information gets returned, or displayed, depends on which arguments, or none at
all, are given.
$category
=
Without arguments, this function returns an HTML page which shows diagnostic
information. It is analogous to PHP’s phpinfo() function.
The HTML output includes which mode is active, what the settings are, and
diagnostic information in case there are problems with debugging connections,
opening of files, etc.
Each warning and error in the diagnostics log also links through to the
Description of errors documentation page.
$category
= 'mode'
(New in Xdebug 3.1)
The function returns an array of all the
enabled modes, whether through xdebug.mode or the
XDEBUG_MODE
environment variable.
Example:
<?php
var_dump( xdebug_info( 'mode' ) );
?>
Returns:
array(3) { [0] => string(5) "debug" [1] => string(7) "develop" [2] => string(5) "trace" }
$category
= 'extension-flags'
(New in Xdebug 3.1)
The function returns an array of all the compile flags that were enabled when
running ./configure
as part of Xdebug’s compilation process.
The only flag that is available, is the compression
flag. If this
flag is enabled, then the xdebug.use_compression setting is available, and enabled by default.
Profiling and Function Trace will create GZip compressed files if the
xdebug.use_compression setting is turned on (the default).
Example:
<?php
var_dump( xdebug_info( 'extension-flags' ) );
?>
Returns:
array(1) { [0] => string(11) "compression" }
Setting up Xdebug
Last modified on Fri 01 Jul 2022
Xdebug is an indispensible tool when working on PHP projects. It’s a very powerful debugger which can be used for code coverage when running tests as well.
Assuming you have installed the latest stable PHP version using Homebrew, you should use pecl
to install the Xdebug. Pecl is a repository for PHP extensions. First, make sure you have it installed (even though it comes with the Homebrew PHP version).
which pecl
/usr/local/bin/pecl
Try to install Xdebug:
That can be done in two ways: your installation passes, and you get a message like this:
Successful installation
...
Build process completed successfully
Installing '/usr/local/Cellar/php@7.4/7.4.16/pecl/20200930/xdebug.so'
install ok: channel://pecl.php.net/xdebug-3.0.4
Extension xdebug enabled in php.ini
In this case, all you need to check is whether PHP has linked the module correctly.
php -v
PHP 7.4.16 (cli) (built: Mar 4 2021 20:52:51) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
with Zend OPcache v7.4.16, Copyright (c), by Zend Technologies
with Xdebug v3.0.4, Copyright (c) 2002-2021, by Derick Rethans
If you get an error message, you’ll need to find your php.ini
file.
php --ini
Configuration File (php.ini) Path: /usr/local/etc/php/7.4
Loaded Configuration File: /usr/local/etc/php/7.4/php.ini
Scan for additional .ini files in: /usr/local/etc/php/7.4/conf.d
Additional .ini files parsed: /usr/local/etc/php/7.4/conf.d/error_log.ini,
/usr/local/etc/php/7.4/conf.d/ext-blackfire.ini,
/usr/local/etc/php/7.4/conf.d/ext-opcache.ini,
/usr/local/etc/php/7.4/conf.d/php-memory-limits.ini
Go to /usr/local/etc/php/7.4/php.ini
and edit it by adding
[xdebug]
zend_extension="xdebug.so"
xdebug.mode=debug,develop
xdebug.client_port=9003
at the end of the php.ini
file.
That’s it, you’re ready to go.
Unsuccessful installation
When installing Xdebug, you might get the following error:
Build process completed successfully
Installing '/usr/local/Cellar/php@7.4/7.4.16/pecl/20200930/xdebug.so'
Warning: mkdir(): File exists in System.php on line 294
PHP Warning: mkdir(): File exists in /usr/local/Cellar/php/7.4.16/share/php/pear/System.php on line 294
Warning: mkdir(): File exists in /usr/local/Cellar/php/7.4.16/share/php/pear/System.php on line 294
ERROR: failed to mkdir /usr/local/Cellar/php/7.4.16/pecl/20180731
Go to your PHP installation folder (/usr/local/Cellar/php/7.4.16/
, for instance) and type
ls -all
total 168
-rw-r--r-- 1 infinum-denis staff 3.1K Aug 7 10:10 INSTALL_RECEIPT.json
-rw-r--r-- 1 infinum-denis staff 3.1K Jul 3 13:30 LICENSE
-rw-r--r-- 1 infinum-denis staff 64K Jul 3 13:30 NEWS
-rw-r--r-- 1 infinum-denis staff 1.6K Jul 3 13:30 README.md
drwxr-xr-x 12 infinum-denis staff 384B Aug 7 10:10 bin
-rw-r--r-- 1 infinum-denis staff 628B Aug 7 10:10 homebrew.mxcl.php.plist
drwxr-xr-x 3 infinum-denis staff 96B Jul 3 13:30 include
drwxr-xr-x 4 infinum-denis staff 128B Jul 3 13:30 lib
lrwxr-xr-x 1 infinum-denis staff 23B Aug 7 10:10 pecl -> /usr/local/lib/php/pecl
drwxr-xr-x 3 infinum-denis staff 96B Jul 3 13:30 sbin
drwxr-xr-x 4 infinum-denis staff 128B Jul 3 13:30 share
You can see that pecl
is symlinked to /usr/local/lib/php/pecl
, but which pecl
specified /usr/local/bin/pecl
, which is itself a symlink to /usr/local/Cellar/php/7.4.16/bin/pecl
. Therefore, you need to remove the symlink.
Now you can install Xdebug again, and it should work as described in the previous case (follow the steps described above to add it correctly into your php.ini
).
Possible side effects
A possible side effect of running Xdebug, especially if you enable profiler output in Xdebug settings in php.ini
, is that the file can grow very large. To prevent this, just make sure you delete it every once in a while, or simply don’t enable logging.
Using Xdebug
You can use Xdebug to debug your CLI scripts (tests for instance), or debug your web application.
In order to debug the web application, you’ll need a browser extension. In Chrome it’s Xdebug helper, in FF it’s Xdebug helper for Firefox.
If you are using PhpStorm, setting up Xdebug is straightforward. In VSCode you’ll need to install the PHP Debug extension, configre it, and then you should be able to set breakpoints in your code.
Be sure to enable the helper and listener in your IDE.
Debugging CLI scripts
When you want to debug the CLI scripts, such as automated tests or custom commands, you need to add a manual trigger:
XDEBUG_TRIGGER=yes CLI SCRIPT
This will instruct Xdebug to be triggered on the script run.
WSL2 issues
Windows Subsystem for Linux (WSL) works differently than MacOS system, because you need to set the correct external IP address for Xdebug to be able to ‘listen’ to the requests.
To quickly find the external IP of your WSL you can type
ip route show default | awk '{print }'
in your WSL terminal. Then you need to add this IP address as your xdebug.client_host
in your php.ini
or xdebug.ini
settings.
After that make sure you restart your PHP server. You should be able to use XDebug normally.
In order to debug the CLI scripts, you’ll need to add additional environment variable
XDEBUG_TRIGGER=yes PHP_IDE_CONFIG=serverName=yourprojectname.test CLI SCRIPT
PhpStorm
For webserver script debugging (e.g. integration test debugging), you can add the URL to your server setup, and correct port mappings in the server settings, and it should work.
In the case of running script debugging that isn’t tied to a specific domain (for instance you want to debug a phpcs sniff), the server name can be localhost, but it’s important to correctly set up path mappings. For instance in the image below
The name of the server is WSL
, host is localhost, but the port mappings between the local files and server files are specified (note that the local ones have \wsl$
prefix, while the server ones are the ones you get by typing pwd
inside your terminal, like /home/...
).
Then running the script as
XDEBUG_TRIGGER=yes PHP_IDE_CONFIG=serverName=WSL CLI SCRIPT
Will correctly trigger a breakpoint and you can debug your script as before.
That is because from the PhpStorm’s point of view, the WSL distribution is a server, so it needs to have the correct port mappings available so that it can connect the dots.
Visual Studio Code
Install the PHP Debug extension published by Xdebug. The PHP Debug extension can also be found in VSCode’s Extensions tab by searching for it.
Once installed click on the Run tab and select «Add configuration…». Now, you’ll need to pick the PHP environment. A new launch.json
file will be added to the root directory by VSCode. By default it will contain 3 configurations. The one you need is the «Listen for Xdebug».
Example of the «Listen for Xdebug» configuration:
{
"name": "Listen for Xdebug",
"type": "php",
"request": "launch",
"port": 9003
}
Start debugging by opening the debug mode tab. In the dropdown select «Listen for Xdebug» and click the green debug button next to the dropdown.
If the process started successfully you will now see several options in the window, via which you can pick what logs Xdebugger will show like:
- Notices
- Warnings
- Errors
- Exceptions
- Everything
And you will see a small floating bar where you can Pause/Stop the debugger or step trough the steps when debugging breakpoints.
While the debugger is running you can run unit tests or run your website (chrome php debug extension needed) and debugger will listen for anything you selected and show you the data in the VS Code debug view.
Using Xdebug in Postman
There are some instances where you’d like to debug the logic for your API calls.
In this case you’ll need to add a query parameter to your endpoint URL:
https://yoururl.test/wp-json/wp/v2/posts?XDEBUG_SESSION_START=PHPSTORM
The query parameter value can be changed according to your IDE.
In the last post, I was finally back up and running with my IDE after an update to Serenata. Or maybe not…
Turns out, another update broke something. MacOS Catalina was released recently and introduced a new version of PHP (7.3.8 in my case). This change means XDebug is now referencing outdated Zend API, which throws an error when running pretty much anything. Oops, beause no XDebug egals no PHPUnit code coverage report.
On MacOS Mojave, getting XDebug was a matter of installing Pear, setting up some Xcode SDK Headers file, installing XDebug from source using Pear and enabling XDebug in PHP configuration files. Sounds easy, should be the same for Catalina…
Spoiler alert, Xcode 11 comes with a massive breaking change.
An alternative installation method is to use homebrew to install PHP, Pecl and XDebug. I didn’t test this method, as I prefer the long method which was simple to setup on Mojave. Plus, solving this issue might prove useful for other situations.
Installing XDebug
Assuming Pear, Autoconf, and Xcode is installed on your computer, installing XDebug should be easy as :
sudo pecl install xdebug
But now, I’m getting the following error. This is because the compiler requires some header files, which are provided by the MacOS SDK bundled with Xcode. Not a surprise, as it was the same error with previous version of MacOS, aka Mojave :
/private/tmp/pear/install/xdebug/xdebug.c:25:10: fatal error: 'php.h' file not found
#include "php.h"
^~~~~~~
1 error generated.
make: *** [xdebug.lo] Error 1
ERROR: `make' failed
The Mojave Solution
On Mojave, the following step was necessary to install the missing header files. Don’t actually run this command on Catalina, as it will fail.
sudo installer -pkg /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg -target /
The problem is the SDK headers package was removed starting with Xcode 11.0. And we can’t just change 10.14
to 10.15
to make it work…
The Catalina Issue
After a lot of digging, I’ve found the actual files are actually stored somewhere :
$ sudo find /Library -name php.h
/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/include/php/main/php.h
/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/usr/include/php/main/php.h
And if you look closely,
$ sudo pecl install xdebug
downloading xdebug-2.7.2.tgz ...
Starting to download xdebug-2.7.2.tgz (230,987 bytes)
.................................................done: 230,987 bytes
69 source files, building
running: phpize
grep: /usr/include/php/main/php.h: No such file or directory
grep: /usr/include/php/Zend/zend_modules.h: No such file or directory
grep: /usr/include/php/Zend/zend_extensions.h: No such file or directory
See the error returned by phpize
claiming /usr/include/php/main/php.h
doesn’t exist? Turns out, /usr/include
doesn’t actually exist on my system:
$ ls /usr/include
ls: /usr/include: No such file or directory
If you try to symlink one into the other, even using sudo, that won’t work, thanks to SIP :
$ sudo ln -s /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/usr/include /usr/include
ln: /usr/include: Operation not permitted
The reason is Apple has deprecated having a /usr/include
distinct from the SDK. This has been completely removed in Catalina so different SDK and Xcode version could be run together.
So now the issue is, in order to compile XDebug, we need to either tell the compiler to use the headers from a different location, or actually put the required files in /usr/include
…
Until this issue is resolved, either on Apple side or XDebug side, not much can be done other than use a VM to run tests locally…
References for later
- Can’t compile a C program on a Mac after upgrading to Catalina 10.15
- Where are the C headers in MacOS Mojave?
- Can’t compile C program on a Mac after upgrade to Mojave
- /usr/include missing on macOS Catalina (with Xcode 11)
- Installation of Xdebug on MacOS Catalina 10.15
On 31st March 2018 homebrew’s homebrew-php
tap was archived and formulae were merged back into homebrew-core
or deleted. See https://github.com/Homebrew/homebrew-php#readme. Among the ones deleted are the xdebug extensions, so there is now no easy way to install it.
Let’s do it anyway!
1. Install xdebug
According to xdebug’s site, the best way to install it when using homebrew is to use the pecl
version. So step 1, make sure we have pecl
.
$ which pecl
/usr/local/bin/pecl
Pecl should really come with a homebrew php version, so you should have this. Installing it if you don’t have it falls outside the scope of this article.
$ pecl install xdebug
downloading xdebug-2.6.0.tgz ...
Starting to download xdebug-2.6.0.tgz (283,644 bytes)
.............done: 283,644 bytes
79 source files, building
<a long list of config vars and build script output here>
Build process completed successfully
Installing '/usr/local/Cellar/php/7.2.5/pecl/20170718/xdebug.so'
Warning: mkdir(): File exists in System.php on line 294
Warning: mkdir(): File exists in ↵
/usr/local/Cellar/php/7.2.5/share/php/pear/System.php on line 294
ERROR: failed to mkdir /usr/local/Cellar/php/7.2.5/pecl/20170718
$
I’ve run into this problem the first time I wanted to install this. Here’s how to fix it. If you got the following, skip to part 2.
Build process completed successfully
Installing '/usr/local/Cellar/php/7.2.5/pecl/20170718/xdebug.so'
install ok: channel://pecl.php.net/xdebug-2.6.0
Extension xdebug enabled in php.ini
$
1.1 Fixing xdebug install path
Can’t create a directory. Let’s try this:
$ cd /usr/local/Cellar/php/7.2.5/
$ ls -la
total 208
-rw-r--r-- 1 javorszky admin 2.2K 26 Apr 19:29 INSTALL_RECEIPT.json
-rw-r--r-- 1 javorszky admin 3.1K 24 Apr 16:10 LICENSE
-rw-r--r-- 1 javorszky admin 85K 24 Apr 16:10 NEWS
-rw-r--r-- 1 javorszky admin 1.6K 24 Apr 16:10 README.md
drwxr-xr-x 12 javorszky admin 384B 26 Apr 19:29 bin
-rw-r--r-- 1 javorszky admin 628B 26 Apr 19:29 homebrew.mxcl.php.plist
drwxr-xr-x 3 javorszky admin 96B 24 Apr 16:10 include
drwxr-xr-x 4 javorszky admin 128B 24 Apr 16:10 lib
lrwxr-xr-x 1 javorszky admin 23B 26 Apr 19:29 pecl -> /usr/local/lib/php/pecl
drwxr-xr-x 3 javorszky admin 96B 24 Apr 16:10 sbin
drwxr-xr-x 4 javorszky admin 128B 24 Apr 16:10 share
So pecl
is a symlink to /usr/local/lib/php/pecl
. But which pecl
told us that lived in /usr/local/bin/pecl
, which itself is a symlink to /usr/local/Cellar/php/7.2.5/bin/pecl
.
Which means we can remove the symlink from /usr/local/Cellar/php/7.2.5/
, and try installing xdebug again. That way the mkdir, which failed because you can’t create a directory with the same name as a symlink, should succeed.
2. Configuring xdebug
Let’s start with what php thinks its ini files are:
$ php --ini
PHP Warning: Failed loading Zend extension 'xdebug.so' ↵
(tried: /usr/local/lib/php/pecl/20170718/xdebug.so ↵
(dlopen(/usr/local/lib/php/pecl/20170718/xdebug.so, 9): image not found), ↵
/usr/local/lib/php/pecl/20170718/xdebug.so.so ↵
(dlopen(/usr/local/lib/php/pecl/20170718/xdebug.so.so, 9): image not found)) ↵
in Unknown on line 0
Warning: Failed loading Zend extension 'xdebug.so' ↵
(tried: /usr/local/lib/php/pecl/20170718/xdebug.so ↵
(dlopen(/usr/local/lib/php/pecl/20170718/xdebug.so, 9): image not found), ↵
/usr/local/lib/php/pecl/20170718/xdebug.so.so ↵
(dlopen(/usr/local/lib/php/pecl/20170718/xdebug.so.so, 9): image not found)) ↵
in Unknown on line 0
Configuration File (php.ini) Path: /usr/local/etc/php/7.2
Loaded Configuration File: /usr/local/etc/php/7.2/php.ini
Scan for additional .ini files in: /usr/local/etc/php/7.2/conf.d
Additional .ini files parsed: /usr/local/etc/php/7.2/conf.d/ext-opcache.ini,
/usr/local/etc/php/7.2/conf.d/php-memory-limits.ini
Lovely, so we need to configure everything.
Opening the entire directory of /usr/local/etc/php/7.2
in Sublime provides me quick and easy access to all the ini files that then I can edit.
Two things here.
- the xdebug installer added the
zend_extension="xdebug.so"
line to the top of the actualphp.ini
; it should not be there - and it points to the wrong file;
xdebug.so
should have a full path
To fix them, I created a new file called xdebug.ini
in the conf.d
folder, which php reads and parses and uses all ini
files from, and in that file I’ve added the following configs:
;XDebug
zend_extension="/usr/local/Cellar/php/7.2.5/pecl/20170718/xdebug.so"
xdebug.remote_autostart=1
xdebug.remote_port=9000
xdebug.remote_enable=1
xdebug.profiler_enable=1
xdebug.profiler_output_dir="/Users/javorszky/xdebugtmp/"
Make sure that the xdebugtmp
directory actually exists.
I’ve also removed the xdebug entry from the top of the actual php.ini
file.
NOTE: the config above has
xdebug.profiler_enable=1
on it. This will SIGNIFICANTLY slow down your site. In return you get a lot of awesome data. This is not always needed though, so be sure to turn it off if you don’t need profiling!
After restarting valet, php --ini
should yield you
Configuration File (php.ini) Path: /usr/local/etc/php/7.2
Loaded Configuration File: /usr/local/etc/php/7.2/php.ini
Scan for additional .ini files in: /usr/local/etc/php/7.2/conf.d
Additional .ini files parsed: /usr/local/etc/php/7.2/conf.d/ext-opcache.ini,
/usr/local/etc/php/7.2/conf.d/php-memory-limits.ini,
/usr/local/etc/php/7.2/conf.d/xdebug.ini
With no errors, and xdebug.ini actually showing up.
3. Configure PhpStorm
You need to open Preferences (CMD + ,
on mac), and then find Languages & Frameworks | PHP, and on that look for the CLI interpreter. Click the ...
next to it, and then refresh. Xdebug should show up.
Then we need to configure xdebug itself. Open up Preferences, then find Languages & Frameworks | PHP | Debug (it is just within the PHP option):
Make sure that the port you set here is the same that you set in the xdebug.ini
file above. I set it to xdebug.remote_port=9000
, but truth be told it could be anything above 1024 (not including) as long as the port is not used by anything else.
Thirdly the project needs to have its path mappings set. That setting is in Languages & Frameworks | PHP | Servers.
The only path mapping I set is the one you see in the screenshot.
And finally run the Web Server Debug Validation, which is under the Run option:
That should give you a popup window with a Validate button. Clicking that you want green ticks everywhere:
You might need to add a server here. Click the ...
next to the dropdown for Deployment server, and add a new one.
4. Use xdebug
Finally the proof is in the pudding. Turn on listening:
After you’ve added your break points, and click Debug…, you should see it working:
5. Notes
I’m using Laravel Valet to serve files locally. For that the debug configuration (see 2. Configuring Xdebug) has two options that I need to untick: Force break at first line….
Getting this working is also non-trivial, so it might require fiddling. Your milage may vary.
Hope this helps.
Photo by rawpixel.com on Unsplash
Инструкция по настройке xdebug в PhpStorm на Mac OS.
Все следующее будет справедливо при установленном Homebrew и настроенным веб-сервером на Mac OS.
xdebug настраивать не всегда просто. Надо прописывать и указывать много всего разного. В данном труде будет описан один из возможных вариантов настройки с установленными у меня на тот момент версиями PHP. Соответственно нужно не тупо копировать ссылки на директории, а смотреть где всё находится это у вас и делать под себя. Также описаны ошибки, которые встречались у меня при настройке.
Установка
Заходим в консоль и запускаем команду установки xdebug
Ошибка 1
Если возникла ошибка такого типа: Ошибка ERROR: failed to mkdir /usr/local/Cellar/php/7.3.9_1/pecl/
running: find «/private/tmp/pear/temp/pear-build-DreamjT4nWU/install-xdebug-2.7.2» | xargs ls -dils
8803261274 0 drwxr-xr-x 3 Dream wheel 96 Oct 19 02:56 /private/tmp/pear/temp/pear-build-DreamjT4nWU/install-xdebug-2.7.2
8803261823 0 drwxr-xr-x 3 Dream wheel 96 Oct 19 02:56 /private/tmp/pear/temp/pear-build-DreamjT4nWU/install-xdebug-2.7.2/usr
8803261824 0 drwxr-xr-x 3 Dream wheel 96 Oct 19 02:56 /private/tmp/pear/temp/pear-build-DreamjT4nWU/install-xdebug-2.7.2/usr/local
8803261825 0 drwxr-xr-x 3 Dream wheel 96 Oct 19 02:56 /private/tmp/pear/temp/pear-build-DreamjT4nWU/install-xdebug-2.7.2/usr/local/Cellar
8803261826 0 drwxr-xr-x 3 Dream wheel 96 Oct 19 02:56 /private/tmp/pear/temp/pear-build-DreamjT4nWU/install-xdebug-2.7.2/usr/local/Cellar/php
8803261827 0 drwxr-xr-x 3 Dream wheel 96 Oct 19 02:56 /private/tmp/pear/temp/pear-build-DreamjT4nWU/install-xdebug-2.7.2/usr/local/Cellar/php/7.3.9_1
8803261828 0 drwxr-xr-x 3 Dream wheel 96 Oct 19 02:56 /private/tmp/pear/temp/pear-build-DreamjT4nWU/install-xdebug-2.7.2/usr/local/Cellar/php/7.3.9_1/pecl
8803261829 0 drwxr-xr-x 3 Dream wheel 96 Oct 19 02:56 /private/tmp/pear/temp/pear-build-DreamjT4nWU/install-xdebug-2.7.2/usr/local/Cellar/php/7.3.9_1/pecl/20180731
8803261830 576 -rwxr-xr-x 1 Dream wheel 294068 Oct 19 02:56 /private/tmp/pear/temp/pear-build-DreamjT4nWU/install-xdebug-2.7.2/usr/local/Cellar/php/7.3.9_1/pecl/20180731/xdebug.soBuild process completed successfully
Installing ‘/usr/local/Cellar/php/7.3.9_1/pecl/20180731/xdebug.so’Warning: mkdir(): File exists in System.php on line 294
PHP Warning: mkdir(): File exists in /usr/local/Cellar/php/7.3.9_1/share/php/pear/System.php on line 294Warning: mkdir(): File exists in /usr/local/Cellar/php/7.3.9_1/share/php/pear/System.php on line 294
ERROR: failed to mkdir /usr/local/Cellar/php/7.3.9_1/pecl/20180731
То для решения, нас интересует последняя строка:
ERROR: failed to mkdir /usr/local/Cellar/php/7.3.9_1/pecl/20180731
Заходим и удаляем там файл pecl. После этого снова запускам установку xdebug.
Ошибка 2
Как-то раз возникла такая ошибка:
Notice: Trying to access array offset on value of type bool in REST.php on line 181
PHP Notice: Trying to access array offset on value of type bool in /usr/local/Cellar/php/7.4.2/share/php/pear/PEAR/REST.php on line 181Notice: Trying to access array offset on value of type bool in /usr/local/Cellar/php/7.4.2/share/php/pear/PEAR/REST.php on line 181
No releases available for package «pecl.php.net/xdebug»
install failed
При повторном запуске команды установки, она исчезла сама по себе:
Если всё пройдет успешно, появится сообщение:
Build process completed successfully
Installing ‘/usr/local/Cellar/php/7.3.9_1/pecl/20180731/xdebug.so’
install ok: channel://pecl.php.net/xdebug-2.7.2
Extension xdebug enabled in php.ini
Перезагружаем сервисы PHP
brew services restart php
Если вдруг PHP не перезагружается, смотрим логи:
/usr/local/var/log/php-fpm.log
Например, у меня была такая ошибка:
PHP: syntax error, unexpected BOOL_FALSE in /usr/local/etc/php/7.3/php.ini on line 1053
[19-Oct-2019 03:27:22] NOTICE: PHP message: PHP Warning: Failed loading Zend extension ‘xdebug.so’ (tried: /usr/local/lib/php/pecl/20180731/xdebug.so (dlopen(/usr/local/lib/php/pecl/20180731/xdebug.so, 9): image not found), /usr/local/lib/php/pecl/20180731/xdebug.so.so (dlopen(/usr/local/lib/php/pecl/20180731/xdebug.so.so, 9): image not found)) in Unknown on line 0
Failed loading /usr/local/Cellar/php/7.3.9_1/pecl/20180731/xdebug.so”
Failed loading /usr/local/Cellar/php/7.3.9_1/pecl/20180731/xdebug.so
Как исправить. Заходим в файл
/usr/local/etc/php/7.4/conf.d/xdebug.ini
или в ту версию, которая у вас текущая. Внутри исправляем путь до файла xdebug.so.
Его искать по адресу:
или (версия php может быть другой)
Failed loading /usr/local/Cellar/php/7.4/pecl/
Настраиваем файл php.ini
Создаём файл xdebug.ini по такому пути (ну или к той версии php которая у вас текущая):
/usr/local/etc/php/7.3/conf.d/xdebug.ini
Внутри пишем конфиг такого типа:
[XDebug]
zend_extension=»/usr/local/Cellar/php/7.3.9_1/pecl/20180731/xdebug.so»
xdebug.remote_autostart=1
xdebug.remote_port=9001
xdebug.remote_enable=1
; xdebug.profiler_enable=1
; xdebug.profiler_output_dir=»/Users/Dream/Sites/_xdebug-profiler/»
xdebug.remote_host=localhost
xdebug.idekey=PHPstorm
Сохраняем, перезагружаем PHP:
brew services restart php
Смотрим что показывает команда:
Если всё хорошо, должно показываться так:
Configuration File (php.ini) Path: /usr/local/etc/php/7.3
Loaded Configuration File: /usr/local/etc/php/7.3/php.ini
Scan for additional .ini files in: /usr/local/etc/php/7.3/conf.d
Additional .ini files parsed: /usr/local/etc/php/7.3/conf.d/ext-opcache.ini,
/usr/local/etc/php/7.3/conf.d/xdebug.ini
Настраиваем CLI Interpretator в PhpStorm
Теперь заходим в настройки Шторма и там где CLI Interpreter нажимаем три точки.
Видим, что показывается PHP, которая стоит по умолчанию в системе Mac OS.
В моем случае это не подходит. Кроме стандартного маковского PHP у меня установлен php от Homebrew. А там он находится по иному пути.
Поэтому ставим другой путь (для которого мы указывали настройки).
Зависит от версии, например:
/usr/local/Cellar/php/7.3.9_1/bin
или
/usr/local/Cellar/php/7.4.2/bin
и после этого получаем такую красивую картинку, где все заполнено:
Через терминал можно проверить загруженные модули:
Сочетание xdebug должен встречаться 2 раза в списке. Один из которых под заголовком [Zend Modules].
Настраиваем PHP -> Servers
Прописываем для нашего сайта настройки таким образом:
Изменим порт на 9001
Здесь:
Добавим конфиг для дебага:
Теперь можем запускать дебаг из меню run настроек шторма:
По идее должны увидеть следующее:
Дело в том, что шторм использует php и конфиг тот который существует в системе Mac OS, а не тот что мы указали. Тем не менее он копирует конфиг нашего PHP внутрь текущего в Mac OS. Хоть на этом, спасибо!
Теперь чтобы всё заработало надо перезагрузить обычный апач:
Также перезайдите в проект шторма, иначе может не заработать.
И теперь наконец всё работает!
Кстати, если мы запустим php файл с функцией phpinfo() то рядом с Zend Engine увидим наш дебаг:
В шторме должно быть все зелененькое:
В браузере должно быть установлено расширение для дебага (в хроме Xdebug helper) и тоже включено:
В проекте PhpStorm должны быть проставлены breakpoint. Затем при перезагрузки страницы и с включенными настройками выше, откроется дебаг в шторме.
Теперь включаем трубку. А если она была включена, сначала выключить, потом включить. Перезагрузить страницу, не забыв поставить брейкпоинты. Если при загрузке страницы код попадет в брейкпоинт, то откроется программа phpStorm с такой табличкой:
Выбираем как на скрине выше и нажимаем сохранить. Эта табличка возникает только в первый раз.
На этом все. Наслаждаемся дебаггером.
Профилирование
Профилирование такая штука, которая показывает весь путь и все происходящие события при загрузки страницы.
Одновременно с установленным дебагом, мы также настроили профилирование. Оно жрет очень много памяти и ресурсов и его можно отключить в настройках php.ini.
У меня выше в настройках он был закомментирован, но если хотите запустить его, уберите точки с запятой:
; xdebug.profiler_enable=1
; xdebug.profiler_output_dir=»/Users/Dream/Sites/_xdebug-profiler/»
Во второй строке указан путь куда будут сохраняться файлы профилирования, которые можно посмотреть через шторм, вкладка Tools.
Открываем файл с профилированием:
И потом наслаждаемся переплетением функций, событий и что там у вас будет еще.