Caddy/Nginx + PHP XDebug Cookie Switch

Wenn man PHP mit XDebug Extension startet bringt dies trotz der Verbesserungen von Version 3 immer noch einen gewissen Overhead mit sich, welcher sich auf jeden Request auswirkt, der an PHP-FPM gesendet wird.

Zum aktivieren von XDebug über den Browser wird üblicherweise das Cookie XDEBUG_SESSION verwendet, auf welches man in der Konfiguration prüfen und die Requests an die jeweiligen PHP-FPM Ports, Sockets oder Docker-Container umleiten kann.

Im Beispiel verwende ich zwei unterschiedliche Docker-Container. Dies es einmal der Container php ohne XDebug und der Container php_debug mit geladener XDebug Erweiterung.

Beispiel Caddy

Im Caddyfile werden bei einem normalen Setup alle Anfragen direkt an PHP-FPM weiterleitet:

route {
    # ... your config
    php_fastcgi php:9000
}

Dies wird nun ergänzt durch einen so genannten Matcher welcher prüft, ob das Cookie XDEBUG_SESSION vorhanden ist.
Somit wird daraus:

route {
    # ... your config
    @xdebug {
        header_regexp xdebug_cookie Cookie XDEBUG_SESSION
    }

    php_fastcgi @xdebug php_debug:9000
    php_fastcgi php:9000
}

Beispiel Nginx

Bei Nginx funktioniert das Wechsel über map und die Prüfung auf genaue Übereinstimmung auf den Wert des Cookies. Überlicherweise steht in dem Cookie der Wert PHPSTORM.

server {
    # ... your config
    fastcgi_pass  php:9000;
}

Das Mapping kann nach belieben irgendwo in der Nginx Config eingebunden werden z.B. in /etc/nginx/conf.d/xdebug.conf in sieht folgendermaßen aus:

map $cookie_XDEBUG_SESSION $php_fastcgi_pass {
    default php:9000;
    PHPSTORM php_debug:9000;
}

Die Konfiguration vom vHost wird dann entsprechend angepasst:

server {
    # ... your config
    fastcgi_pass  $php_fastcgi_pass;
}

Howto: Debian 6 (Squeeze) mit nginx + FastCGI + Zend Framework

Falls noch nicht geschehen installieren wir zuerst mal nginx und php5-cgi PHP-FPM.

aptitude install nginx php5-cgi php5-fpm

Jetzt legen wir uns eine neue Konfigurationsdatei für nginx mit folgendem Inhalt an.

server {
	server_name  example.com;
	access_log  /var/log/nginx/com.example.access.log;
	if (!-e $request_filename) {
    		rewrite ^.*$ /index.php last;
	}
	root   /var/www/vhosts/example.com/public;
	index  index.php index.html;
	location ~ \.php$ {
		include /etc/nginx/fastcgi_params;
                keepalive_timeout 0;
                fastcgi_param  APPLICATION_ENV  'development';
                fastcgi_param   SCRIPT_FILENAME  $document_root$fastcgi_script_name;
                fastcgi_pass    127.0.0.1:9000;
	}
}

Die Rewrite Regel leitet wie beim Zend-Framework üblich alle Dateien die nicht existieren auf die index.php um.

Die Datei wird anschließend als “/etc/nginx/sites-available/example.com” gespeichert und zum aktivieren verlinkt.

ln –s “/etc/nginx/sites-available/example.com “/etc/nginx/sites-enabled/example.com

Nun muss noch nginx neu startet werden.

/etc/init.d/nginx restart

Dateien mit der Endung .php werden also an localhost auf den Port 9000 weiter gereicht. An der Stelle wartet jetzt noch kein PHP auf die Anfrage. Man könnte jetzt also einfach php-cgi starten, das hält aber nur bis nächsten Neustart.

php-cgi -b 127.0.0.1 &

Oder aber man richtet sich ein entsprechendes Init Script ein.