PHP 5.6.0 has been released last month by the PHP Development Team. This new version includes some major changes and many improvements. See the release note.

"phpdbg, Interactive PHP debugger"

Main features added:

  • Constant scalar expressions.
  • Variadic functions and argument unpacking using the … operator.
  • Exponentiation using the ** operator.
  • Function and constant importing with the use keyword.
  • phpdbg as an interactive integrated debugger SAPI.
  • php://input is now reusable, and $HTTP_RAW_POST_DATA is deprecated.
  • GMP objects now support operator overloading.
  • File uploads larger than 2 gigabytes in size are now accepted.

You can find the complete features list on the PHP Website.

One of the new features is the integrated phpdbg debugger which provides an interactive environment to debug your PHP code. phpdbg is implemented and distributed as an SAPI module. The phpdbg website has some good documentation, I recommend the Getting started with phpdbg section. This is not a replacement for XDebug.

Let’s cover how to get started with PHP 5.6.0 and phpdbg on Mac OS X.

On Mac OS you can easily install the latest PHP 5.6 with Homebrew. You may hit some errors while trying to enable phpdbg, see Compilation Error.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
$ brew options php56
--disable-opcache
    Build without Opcache extension
--disable-zend-multibyte
    Disable auto-detection of Unicode encoded scripts (PHP 5.2 and 5.3 only)
--homebrew-apxs
    Build against apxs in Homebrew prefix
--with-apache
    Enable building of shared Apache 2.0 Handler module, overriding any options which disable apache
--with-cgi
    Enable building of the CGI executable (implies --without-apache)
--with-debug
    Compile with debugging symbols
--with-fpm
    Enable building of the fpm SAPI executable (implies --without-apache)
--with-gmp
    Build with gmp support
--with-homebrew-curl
    Include Curl support via Homebrew
--with-homebrew-libxslt
    Include LibXSLT support via Homebrew
--with-homebrew-openssl
    Include OpenSSL support via Homebrew
--with-imap
    Include IMAP extension
--with-libmysql
    Include (old-style) libmysql support instead of mysqlnd
--with-mssql
    Include MSSQL-DB support
--with-pdo-oci
    Include Oracle databases (requries ORACLE_HOME be set)
--with-pgsql
    Include PostgreSQL support
--with-phpdbg
    Enable building of the phpdbg SAPI executable (PHP 5.4 and above)
--with-thread-safety
    Build with thread safety
--with-tidy
    Include Tidy support
--without-bz2
    Build without bz2 support
--without-mysql
    Remove MySQL/MariaDB support
--without-pcntl
    Build without Process Control support
--without-pear
    Build without PEAR
--without-snmp
    Build without SNMP support
--HEAD
    install HEAD version

Compilation Error

You may hit a bug while installing PHP 5.6 with phpdbg on Mac OS. While trying to install using brew install -v php56 --with-phpdbg the compilation was failing with some errors:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/bin/sh /private/tmp/php56-SQBxFw/php-5.6.0/libtool --silent --preserve-dup-deps --mode=compile clang -D_GNU_SOURCE -Isapi/phpdbg/ -I/private/tmp/php56-SQBxFw/php-5.6.0/sapi/phpdbg/ -DPHP_ATOM_INC -I/private/tmp/php56-SQBxFw/php-5.6.0/include -I/private/tmp/php56-SQBxFw/php-5.6.0/main -I/private/tmp/php56-SQBxFw/php-5.6.0 -I/private/tmp/php56-SQBxFw/php-5.6.0/ext/date/lib -I/private/tmp/php56-SQBxFw/php-5.6.0/ext/ereg/regex -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/include/libxml2 -I/usr/local/opt/zlib/include -I/usr/local/opt/jpeg/include -I/usr/local/opt/libpng/include -I/usr/local/Cellar/freetype/2.5.3_1/include/freetype2 -I/usr/local/opt/gettext/include -I/usr/local/Cellar/icu4c/53.1/include -I/private/tmp/php56-SQBxFw/php-5.6.0/ext/mbstring/oniguruma -I/private/tmp/php56-SQBxFw/php-5.6.0/ext/mbstring/libmbfl -I/private/tmp/php56-SQBxFw/php-5.6.0/ext/mbstring/libmbfl/mbfl -I/private/tmp/php56-SQBxFw/php-5.6.0/ext/sqlite3/libsqlite -I/usr/include/libxml2 -I/private/tmp/php56-SQBxFw/php-5.6.0/ext/zip/lib -I/private/tmp/php56-SQBxFw/php-5.6.0/TSRM -I/private/tmp/php56-SQBxFw/php-5.6.0/Zend  -no-cpp-precomp  -I/usr/include -g -O2 -fvisibility=hidden -DZEND_SIGNALS  -c /private/tmp/php56-SQBxFw/php-5.6.0/sapi/phpdbg/phpdbg_help.c -o sapi/phpdbg/phpdbg_help.lo
/private/tmp/php56-SQBxFw/php-5.6.0/sapi/phpdbg/phpdbg.c:1498:2: error: expected identifier or '('
        if (cleaning || remote) {
        ^
/private/tmp/php56-SQBxFw/php-5.6.0/sapi/phpdbg/phpdbg.c:1508:2: error: expected identifier or '('
        if (address) {
        ^
/private/tmp/php56-SQBxFw/php-5.6.0/sapi/phpdbg/phpdbg.c:1513:2: error: expected identifier or '('
        if (sapi_name) {
        ^
/private/tmp/php56-SQBxFw/php-5.6.0/sapi/phpdbg/phpdbg.c:1520:9: error: a parameter list without types is only allowed in a function definition
        unlink(bp_tmp_file);
               ^
/private/tmp/php56-SQBxFw/php-5.6.0/sapi/phpdbg/phpdbg.c:1523:2: error: expected identifier or '('
        return 0;
        ^
/private/tmp/php56-SQBxFw/php-5.6.0/sapi/phpdbg/phpdbg.c:1524:1: error: extraneous closing brace ('}')
} /* }}} */
^
6 errors generated.
make: *** [sapi/phpdbg/phpdbg.lo] Error 1
make: *** Waiting for unfinished jobs....
==> Formula
Tap: homebrew/homebrew-php
Path: /usr/local/Library/Taps/homebrew/homebrew-php/Formula/php56.rb
==> Configuration
HOMEBREW_VERSION: 0.9.5
HEAD: 911331708b7e547a143f3e03af06ae1834a03290
CPU: 8-core 64-bit sandybridge
OS X: 10.9.4-x86_64
Xcode: 5.1.1
CLT: 5.1.0.0.1.1396320587
X11: N/A
==> ENV
HOMEBREW_CC: clang
HOMEBREW_CXX: clang++
MAKEFLAGS: -j8
CMAKE_PREFIX_PATH: /usr/local/opt/gettext:/usr/local/opt/icu4c:/usr/local/opt/zlib:/usr/local
CMAKE_INCLUDE_PATH: /usr/include/libxml2:/System/Library/Frameworks/OpenGL.framework/Versions/Current/Headers
CMAKE_LIBRARY_PATH: /System/Library/Frameworks/OpenGL.framework/Versions/Current/Libraries
PKG_CONFIG_PATH: /usr/local/opt/libpng/lib/pkgconfig:/usr/local/opt/freetype/lib/pkgconfig:/usr/local/opt/icu4c/lib/pkgconfig:/usr/local/opt/zlib/lib/pkgconfig
PKG_CONFIG_LIBDIR: /usr/lib/pkgconfig:/usr/local/Library/ENV/pkgconfig/10.9
ACLOCAL_PATH: /usr/local/opt/gettext/share/aclocal:/usr/local/share/aclocal
PATH: /usr/local/Library/ENV/4.3:/usr/local/opt/libpng/bin:/usr/local/opt/freetype/bin:/usr/local/opt/gettext/bin:/usr/local/opt/icu4c/bin:/usr/local/opt/jpeg/bin:/usr/local/opt/unixodbc/bin:/usr/local/opt/libtool/bin:/usr/bin:/bin:/usr/sbin:/sbin

Error: php56 5.6.0 did not build
Logs:
     /Users/nicolas/Library/Logs/Homebrew/php56/01.configure
     /Users/nicolas/Library/Logs/Homebrew/php56/01.configure.cc
     /Users/nicolas/Library/Logs/Homebrew/php56/02.make
     /Users/nicolas/Library/Logs/Homebrew/php56/02.make.cc
     /Users/nicolas/Library/Logs/Homebrew/php56/config.log

To fix it I ended-up decompressing the file locally, patch phpdbg.c, tar again and edit the Homebrew formula to not check the SHA1.

1
2
3
4
5
6
7
8
9
10
11
12
$ diff -u php-5.6.0/sapi/phpdbg/phpdbg.c.orig php-5.6.0/sapi/phpdbg/phpdbg.c
--- php-5.6.0/sapi/phpdbg/phpdbg.c.orig 2014-09-13 17:52:20.000000000 -0700
+++ php-5.6.0/sapi/phpdbg/phpdbg.c  2014-09-13 17:39:58.000000000 -0700
@@ -1493,7 +1493,7 @@

        sapi_shutdown();

-   }
+   //}

    if (cleaning || remote) {
        goto phpdbg_main;

I replaced the initial archive tar zc php-5.6.0 > /Library/Caches/Homebrew/php56-5.6.0, then using brew edit php56 I commented the checksum check.

1
2
3
4
5
6
7
8
9
10
11
12
$ diff -u php56.rb.orig php56.rb
--- php56.rb.orig   2014-09-13 17:56:17.000000000 -0700
+++ php56.rb    2014-09-13 17:43:52.000000000 -0700
@@ -5,7 +5,7 @@
   include AbstractPhpVersion::Php56Defs

   url     PHP_SRC_TARBALL
-  sha256  PHP_CHECKSUM[:sha256]
+  #sha256  PHP_CHECKSUM[:sha256]
   version PHP_VERSION

   head    PHP_GITHUB_URL, :branch => PHP_BRANCH

Passed this issue, I was able to test PHP 5.6.0 with phpdbg.

1
2
3
4
5
6
7
8
$ php -v
PHP 5.6.0 (cli) (built: Sep 13 2014 18:17:01)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2014 Zend Technologies
$ phpdbg -V
phpdbg 0.4.0 (built: Sep 13 2014 18:17:02)
PHP 5.6.0, Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2014 Zend Technologies

update: I opened a bug on GitHub. The issue is now resolved in the master branch of phpdbg: Fix bug #111 (compile error without ZEND_SIGNALS). It is not yet in the master branch of PHP, once it is, you could use brew install php56 --with-phpdbg --head. Also, the fix should be in the next official PHP 5.6 release. update 2: The fix has been merged to the PHP master branch. Using --head option fix the issue.

First steps with phpdbg

You simply need to start the CLI using the command phpdbg. Inside the CLI, simply check the help.

phpdbg> help

To inspect or debug a PHP file, I will make an example using the judy.php example file from Pecl PHP Judy (Official Documentation, GitHub). Judy can be installed with Homebrew using brew install php56-judy.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
$ phpdbg -e examples/judy.php
[Welcome to phpdbg, the interactive PHP debugger, v0.4.0]
To get help using phpdbg type "help" and press enter
[Please report bugs to <http://github.com/krakjoe/phpdbg/issues>]
[Attempting compilation of /Users/nicolas/Documents/php-judy/php-judy-git/examples/judy.php]
[Success]
phpdbg> run
PHP Judy Version: 1.0.2
<br>
Functions available in the judy extension:<br>
    judy_version()<br>
    judy_type()<br>
<br>
Constants available in judy extension:<br>
<br>
Judy class methods:<br>
    Judy::__construct()<br>
    Judy::__destruct()<br>
    Judy::getType()<br>
    Judy::free()<br>
    Judy::memoryUsage()<br>
    Judy::count()<br>
    Judy::byCount()<br>
    Judy::first()<br>
    Judy::next()<br>
    Judy::last()<br>
    Judy::prev()<br>
    Judy::firstEmpty()<br>
    Judy::nextEmpty()<br>
    Judy::lastEmpty()<br>
    Judy::prevEmpty()<br>
    Judy::offsetSet()<br>
    Judy::offsetUnset()<br>
    Judy::offsetGet()<br>
    Judy::offsetExists()<br>
    Judy::size()<br>

To print the opcode of a function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
$ phpdbg -e examples/judy-bench-string_to_int.php
[Welcome to phpdbg, the interactive PHP debugger, v0.4.0]
To get help using phpdbg type "help" and press enter
[Please report bugs to <http://github.com/krakjoe/phpdbg/issues>]
[Attempting compilation of /Users/nicolas/Documents/php-judy/php-judy-git/examples/judy-bench-string_to_int.php]
[Success]
phpdbg> p f __convert
[User Function __convert]
    L5-9 __convert() /Users/nicolas/Documents/php-judy/php-judy-git/examples/judy-bench-string_to_int.php
        L5  0x106c8d3b0 ZEND_RECV                      <unused>             <unused>             $size
        L7  0x106c8d3e0 ZEND_INIT_ARRAY                C0                   <unused>             @0
        L7  0x106c8d410 ZEND_ADD_ARRAY_ELEMENT         C1                   <unused>             @0
        L7  0x106c8d440 ZEND_ADD_ARRAY_ELEMENT         C2                   <unused>             @0
        L7  0x106c8d470 ZEND_ADD_ARRAY_ELEMENT         C3                   <unused>             @0
        L7  0x106c8d4a0 ZEND_ADD_ARRAY_ELEMENT         C4                   <unused>             @0
        L7  0x106c8d4d0 ZEND_ADD_ARRAY_ELEMENT         C5                   <unused>             @0
        L7  0x106c8d500 ZEND_ASSIGN                    $unit                @0                   @1
        L8  0x106c8d530 ZEND_BEGIN_SILENCE             <unused>             <unused>             @2
        L8  0x106c8d560 ZEND_FETCH_R                   C6                   <unused>             @3
        L8  0x106c8d590 ZEND_SEND_VAL                  C7                   <unused>             <unused>
        L8  0x106c8d5c0 ZEND_SEND_VAR                  $size                <unused>             <unused>
        L8  0x106c8d5f0 ZEND_SEND_VAL                  C8                   <unused>             <unused>
        L8  0x106c8d620 ZEND_DO_FCALL                  C9                   <unused>             @4
        L8  0x106c8d650 ZEND_SEND_VAR_NO_REF           @4                   <unused>             <unused>
        L8  0x106c8d680 ZEND_DO_FCALL                  C10                  <unused>             @5
        L8  0x106c8d6b0 ZEND_ASSIGN                    $i                   @5                   @6
        L8  0x106c8d6e0 ZEND_SEND_VAR_NO_REF           @6                   <unused>             <unused>
        L8  0x106c8d710 ZEND_DO_FCALL                  C11                  <unused>             @7
        L8  0x106c8d740 ZEND_DIV                       @3                   @7                   @8
        L8  0x106c8d770 ZEND_SEND_VAL                  @8                   <unused>             <unused>
        L8  0x106c8d7a0 ZEND_SEND_VAL                  C12                  <unused>             <unused>
        L8  0x106c8d7d0 ZEND_DO_FCALL                  C13                  <unused>             @9
        L8  0x106c8d800 ZEND_END_SILENCE               @2                   <unused>             <unused>
        L8  0x106c8d830 ZEND_CONCAT                    @9                   C14                  @10
        L8  0x106c8d860 ZEND_FETCH_DIM_R               $unit                $i                   @11
        L8  0x106c8d890 ZEND_CONCAT                    @10                  @11                  @12
        L8  0x106c8d8c0 ZEND_RETURN                    @12                  <unused>             <unused>
        L9  0x106c8d8f0 ZEND_RETURN                    C15                  <unused>             <unused>

To set a break point:

1
2
3
4
5
6
7
8
9
10
phpdbg> break 0x106c8d53
[Breakpoint #0 added at L8]
phpdbg> run
## Count: 100
-- ARRAY
[Breakpoint #1 in 0x106c8d530 at /Users/nicolas/Documents/php-judy/php-judy-git/examples/judy-bench-string_to_int.php:8, hits: 1]
 00007:     $unit=array('b','kb','mb','gb','tb','pb');
>00008:     return @round($size/pow(1024,($i=floor(log($size,1024)))),2).' '.$unit[$i];
 00009: }
 00010:

To set a break point on a function:

1
2
3
4
5
6
7
8
9
10
11
12
phpdbg> b __convert
[Breakpoint #0 added at __convert]
phpdbg> rum
[The command "rum" could not be found]
phpdbg> run
## Count: 100
-- ARRAY
[Breakpoint #0 in __convert() at /Users/nicolas/Documents/php-judy/php-judy-git/examples/judy-bench-string_to_int.php:5, hits: 1]
 00004:
>00005: function __convert($size)
 00006: {
 00007:     $unit=array('b','kb','mb','gb','tb','pb');

Don’t be afraid to use the help command, all the information you need are there.

More Examples

You should check out the official examples:

Comments