Files
Snippets/xdebug-spickzettel.md

741 lines
22 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Xdebug – Installation, Konfiguration, Nutzung
Stand: Xdebug 3.x (Modus-Konfiguration ab Xdebug 3, Port **9003**)
---
## Die wichtigste Antwort vorweg
**Nein – man trägt nichts in die einzelnen PHP-Dateien ein.**
Xdebug wird **einmal** in der `php.ini` konfiguriert. Danach ist es für *jedes* PHP-Skript
aktiv, das über diesen Webserver bzw. diese CLI läuft. Kein `require`, kein `include`,
keine Zeile im Quellcode.
```
php.ini ändern → Apache neu starten → gilt ab sofort überall
```
Das `ini_set(...)` aus dem Gesprächsverlauf war ausdrücklich der **Notfallweg** für
Systeme, auf denen man keine INI-Datei anfassen darf. Wer Zugriff auf die `php.ini` hat,
braucht es nicht.
Im Code gibt es nur zwei *optionale* Dinge, die man punktuell einsetzen kann:
```php
xdebug_break(); // setzt einen Breakpoint ohne IDE-Klick
xdebug_start_trace('/tmp/xy'); // startet ein Aufrufprotokoll ab hier
```
Beides ist Zusatzkomfort, keine Voraussetzung.
---
## 0. Versionsmatrix
| PHP | Xdebug | Konfigurationsstil |
|---|---|---|
| 7.0 – 7.1 | 2.9.x | `xdebug.remote_*`, Port 9000 |
| 7.2 – 7.4 | 3.1.x | `xdebug.mode`, Port 9003 |
| 8.0 – 8.2 | 3.2.x | `xdebug.mode`, Port 9003 |
| 8.3+ | 3.3+ / 3.5+ | `xdebug.mode`, Port 9003 |
> Xdebug 3.5 setzt mindestens PHP 8.3 voraus. Bei älterem PHP die Version explizit pinnen:
> `pecl install xdebug-3.2.2`
Verzeichnisnamen wie `no-debug-non-zts-20220829` kodieren die PHP-API-Version:
`20220829` = PHP 8.2 · `20230831` = PHP 8.3 · `20240924` = PHP 8.4
---
## 1. Installation unter XAMPP (macOS)
Xdebug wird für macOS **nicht** vorkompiliert ausgeliefert – es muss gebaut werden.
### 1.1 Vorbereitung
```bash
xcode-select --install # Compiler / Command Line Tools
brew install autoconf # phpize benötigt autoconf
```
Auf Apple Silicon zusätzlich:
```bash
softwareupdate --install-rosetta --agree-to-license
```
### 1.2 Architektur-Falle (Apple Silicon)
XAMPP für macOS ist **x86_64** und läuft unter Rosetta 2. Ein nativer Build auf einem
M-Mac erzeugt eine arm64-`.so`, die PHP nicht laden kann:
```
dlopen(...) (mach-o file, but is an incompatible architecture
(have 'arm64', need 'x86_64'))
```
`arch -x86_64` **vor** `pecl` reicht nicht – `pecl` ist ein PHP-Skript, dessen
Kindprozesse (`phpize`, `configure`, `clang`) die Rosetta-Umgebung nicht zuverlässig
erben. Deshalb eine komplette x86_64-Shell öffnen:
```bash
arch -x86_64 /bin/zsh
arch # muss "i386" ausgeben
```
### 1.3 Build via pecl
```bash
# Alte Reste entfernen, sonst wird der falsche Build wiederverwendet
sudo rm -f /Applications/XAMPP/xamppfiles/lib/php/extensions/no-debug-non-zts-*/xdebug.so
rm -rf /tmp/pear
# PEAR-Registry abmelden (sonst: "already installed ... install failed")
sudo /Applications/XAMPP/xamppfiles/bin/pecl uninstall xdebug
# Build (in der Rosetta-Shell!)
sudo CFLAGS="-arch x86_64" LDFLAGS="-arch x86_64" CXXFLAGS="-arch x86_64" \
/Applications/XAMPP/xamppfiles/bin/pecl install xdebug-3.2.2
```
`pecl` gibt am Ende die Zeile `Installing '/Applications/XAMPP/.../xdebug.so'` aus –
**das** ist der Pfad für die `php.ini`.
### 1.4 Ergebnis prüfen
```bash
file /Applications/XAMPP/xamppfiles/lib/php/extensions/no-debug-non-zts-20220829/xdebug.so
# muss "x86_64" enthalten
```
### 1.5 Manueller Build (falls pecl scheitert)
Gibt mehr Kontrolle, weil jeder Schritt einzeln sichtbar ist:
```bash
cd /tmp && curl -O https://xdebug.org/files/xdebug-3.2.2.tgz
tar -xzf xdebug-3.2.2.tgz && cd xdebug-3.2.2
/Applications/XAMPP/xamppfiles/bin/phpize
./configure --with-php-config=/Applications/XAMPP/xamppfiles/bin/php-config \
CFLAGS="-arch x86_64" LDFLAGS="-arch x86_64"
make
file modules/xdebug.so # VOR dem Kopieren prüfen
sudo cp modules/xdebug.so \
/Applications/XAMPP/xamppfiles/lib/php/extensions/no-debug-non-zts-20220829/
```
### 1.6 Alternative ohne Compile-Schmerz
Wer nicht an XAMPP gebunden ist:
```bash
brew install php # natives arm64-PHP
pecl install xdebug # läuft ohne Rosetta durch
php -S localhost:8000 # eingebauter Server statt Apache
```
---
## 2. Installation unter XAMPP (Windows)
Deutlich einfacher – es gibt fertige DLLs.
### 2.1 Passende DLL ermitteln
XAMPP kompiliert PHP als **Thread Safe** (Apache mit mod_php), also wird eine TS-DLL
benötigt. Statt zu raten, den Xdebug-Wizard nutzen:
**https://xdebug.org/wizard**
1. `phpinfo()`-Ausgabe erzeugen – im Browser (`http://localhost/info.php`) oder per
`C:\xampp\php\php.exe -i > info.txt`
2. **Kompletten** Output kopieren (Strg+A / Strg+C), nicht nur die sichtbare Tabelle
3. Ins Textfeld einfügen → *Analyse my phpinfo() output*
4. Der Wizard nennt exakt die passende Datei, z. B.
`php_xdebug-3.4.x-8.2-vs16-x86_64.dll`
> Alternativ manuell unter https://xdebug.org/download – dann Thread Safety und
> VS/VC-Compilerversion selbst aus `phpinfo()` ablesen.
Nach dem Test: **`info.php` wieder löschen.**
### 2.2 Installieren
DLL kopieren nach `C:\xampp\php\ext\php_xdebug.dll`, dann in `C:\xampp\php\php.ini`
(ganz unten steht bereits ein auskommentierter `[XDebug]`-Block):
```ini
[XDebug]
zend_extension = xdebug
xdebug.mode = develop,debug
xdebug.start_with_request = trigger
xdebug.client_port = 9003
xdebug.client_host = 127.0.0.1
```
### 2.3 Prüfen
Apache über das Control Panel **Stop/Start** (nicht nur „Config"), dann:
```
C:\xampp\php\php.exe -v
```
Die Ausgabe muss `with Xdebug v3.x.x` enthalten.
---
## 3. Installation unter Debian
Der bequemste Fall – Paketverwaltung erledigt alles.
### 3.1 Über apt
```bash
sudo apt install php-xdebug
# oder versionsspezifisch, z. B. bei Sury-Repository:
sudo apt install php8.4-xdebug
```
### 3.2 Über pecl (wenn kein Paket verfügbar)
```bash
sudo apt install php-pear php-dev autoconf
sudo pecl install xdebug
```
### 3.3 Konfiguration – hier gilt `conf.d`
Debian nutzt ein Scan-Verzeichnis. **Nicht** die zentrale `php.ini` anfassen, sondern
eine eigene Datei anlegen:
```
/etc/php/8.4/apache2/conf.d/99-xdebug-local.ini
```
```ini
xdebug.mode = develop,debug
xdebug.start_with_request = trigger
xdebug.client_port = 9003
xdebug.discover_client_host = 1
xdebug.var_display_max_depth = 10
xdebug.var_display_max_data = 1024
xdebug.var_display_max_children = 256
```
**Warum `99-`?** Die Dateien werden alphabetisch geladen, die letzte gewinnt. Xdebug
bringt typischerweise `20-xdebug.ini` mit – `99-` läuft danach und überschreibt.
Außerdem überlebt die eigene Datei ein `apt upgrade`, während Änderungen an der
zentralen `php.ini` einen Konfliktdialog auslösen.
### 3.4 SAPI-Trennung beachten
Debian hat getrennte Bäume:
```
/etc/php/8.4/apache2/conf.d/
/etc/php/8.4/fpm/conf.d/
/etc/php/8.4/cli/conf.d/
```
Eine Änderung in `cli/` wirkt **nicht** auf den Webserver. Meist sind es Symlinks nach
`/etc/php/8.4/mods-available/` – dort anlegen und mit `phpenmod` aktivieren, dann gilt
sie für beide.
```bash
sudo systemctl restart apache2
```
---
## 4. Wo wird was eingetragen?
### 4.1 Die entscheidende Frage zuerst
```bash
php -i | grep -E "Loaded Configuration|Scan this dir"
```
| Ergebnis bei *Scan this dir* | Vorgehen |
|---|---|
| ein Verzeichnispfad | eigene Datei mit hoher Nummer, z. B. `99-xdebug-local.ini` |
| `(none)` | direkt in die `php.ini` (Loaded Configuration File) |
**XAMPP → immer `php.ini`** (Windows, macOS, Linux). XAMPP liefert bewusst eine
einzige, selbst verwaltete Datei ohne `conf.d`.
**Debian / RHEL / Sury / Docker-Images → `conf.d` mit `99-…`**
> CLI und Browser können unterschiedliche INIs laden. Was Apache tatsächlich nutzt,
> zeigt nur `phpinfo()` im Browser.
### 4.2 Referenz-Konfiguration
```ini
zend_extension = xdebug.so ; NICHT "extension="!
; Was Xdebug tut
xdebug.mode = develop,debug ; develop = schöneres var_dump + Stack-Traces
; debug = Breakpoints
; trace = Aufrufprotokoll in Datei
; profile = Performance-Analyse
; Wann Xdebug aktiv wird
xdebug.start_with_request = trigger ; nur bei ?XDEBUG_TRIGGER=1 – hält Overhead klein
; Verbindung zur IDE
xdebug.client_port = 9003
xdebug.client_host = 127.0.0.1
xdebug.discover_client_host = 1 ; praktisch bei Remote / Lima / Docker
; Anzeige-Limits (Defaults sind zu knapp!)
xdebug.var_display_max_depth = 10 ; Default 3
xdebug.var_display_max_children = 256 ; Default 128
xdebug.var_display_max_data = 1024 ; Default 512
```
Die drei Anzeige-Limits sind der Grund, warum `var_dump` oft `...` statt der
eigentlichen Daten zeigt.
### 4.3 Nur wenn keine INI-Datei erreichbar ist
**`.htaccess`** (nur bei mod_php, nicht FPM; erfordert `AllowOverride Options`):
```apache
php_value xdebug.var_display_max_depth 10
php_flag xdebug.collect_return 1
```
**Im Skript** – funktioniert nur für `PHP_INI_ALL`-Direktiven:
```php
ini_set('xdebug.var_display_max_depth', '10');
ini_set('xdebug.var_display_max_data', '1024');
```
Sinnvoll dann **einmal zentral** im Bootstrap, nicht in jeder Datei:
```php
require __DIR__ . '/vendor/autoload.php';
if (($_ENV['APP_ENV'] ?? 'prod') === 'dev') {
ini_set('xdebug.var_display_max_depth', '10');
ini_set('xdebug.var_display_max_data', '1024');
}
```
Zwei Fallstricke:
- Die Werte wirken erst auf `var_dump`-Aufrufe **nach** dem `ini_set()`
- Gilt nur für den einen Request (nicht für separate Ajax-/Cron-Skripte)
`xdebug.mode` ist `PHP_INI_SYSTEM` und lässt sich zur Laufzeit **nicht** setzen.
**Auf der CLI ganz ohne Datei:**
```bash
php -d xdebug.mode=develop,trace -d xdebug.start_with_request=yes script.php
```
---
## 5. Schritt für Schritt: Debuggen unter XAMPP (macOS/Windows)
Ausgangslage: Xdebug ist installiert, `php -v` zeigt „with Xdebug".
### Schritt 1 – Konfiguration eintragen (einmalig)
`php.ini` öffnen. Pfad zur *richtigen* Datei ermitteln:
```bash
# macOS
/Applications/XAMPP/xamppfiles/bin/php -i | grep "Loaded Configuration"
```
```
:: Windows
C:\xampp\php\php.exe -i | findstr "Loaded Configuration"
```
Am Ende der Datei eintragen (jede Direktive auf einer **eigenen Zeile**):
```ini
[XDebug]
zend_extension = /Applications/XAMPP/xamppfiles/lib/php/extensions/no-debug-non-zts-20220829/xdebug.so
xdebug.mode = develop,debug
xdebug.start_with_request = trigger
xdebug.client_port = 9003
xdebug.client_host = 127.0.0.1
xdebug.var_display_max_depth = 10
xdebug.var_display_max_data = 1024
xdebug.var_display_max_children = 256
```
Unter Windows genügt `zend_extension = xdebug`, weil die DLL in `ext\` liegt.
### Schritt 2 – Apache neu starten
```bash
sudo /Applications/XAMPP/xamppfiles/xampp restart
```
Windows: XAMPP Control Panel → Apache **Stop**, dann **Start**.
### Schritt 3 – Kontrollieren
Datei `htdocs/info.php` mit `<?php phpinfo();` anlegen, `http://localhost/info.php`
aufrufen. Es muss ein eigener **Xdebug-Abschnitt** erscheinen. Danach Datei löschen.
Ab hier ist Xdebug für **alle** Skripte unter `htdocs/` aktiv – ohne weitere Eintragung.
### Schritt 4 – Erster Test ohne IDE
Beliebige Datei, z. B. `htdocs/test.php`:
```php
<?php
$daten = ['id' => 7, 'name' => 'Müller', 'rollen' => ['admin', 'user']];
var_dump($daten);
```
Aufrufen. Erwartetes Ergebnis: farbige, eingerückte Ausgabe mit Datei- und
Zeilenangabe – **ohne** dass `<pre>` nötig wäre. Das ist der `develop`-Modus.
Ebenso: einen absichtlichen Fehler einbauen (`$x->foo();`) – statt der nackten
PHP-Meldung kommt ein tabellarischer Stack-Trace mit allen Aufrufen und Parametern.
### Schritt 5 – Breakpoint-Debugging vorbereiten
**Grundprinzip verstehen:** PHP verbindet sich **zur IDE**, nicht umgekehrt. Die IDE
lauscht auf Port 9003, PHP klopft an. Der Listener muss also **vor** dem Seitenaufruf
laufen – sonst passiert schlicht nichts.
VS Code: Extension „PHP Debug" (xdebug.php-debug) installieren, dann im Projektordner
`.vscode/launch.json` anlegen:
```json
{
"version": "0.2.0",
"configurations": [
{ "name": "Listen for Xdebug", "type": "php", "request": "launch", "port": 9003 }
]
}
```
`pathMappings` ist **nicht** nötig, weil Code und IDE auf derselben Maschine liegen.
### Schritt 6 – Breakpoint setzen und Session starten
1. In `test.php` links neben die Zeilennummer klicken → roter Punkt erscheint
2. **F5** drücken → unten wird die Statusleiste orange, VS Code lauscht jetzt
3. Im Browser aufrufen: `http://localhost/test.php?XDEBUG_TRIGGER=1`
4. Die Seite bleibt hängen, VS Code springt in den Vordergrund und markiert die Zeile
### Schritt 7 – Was man jetzt sieht
| Bereich in VS Code | Inhalt |
|---|---|
| **Variables** (links oben) | alle Variablen im aktuellen Scope, aufklappbar |
| **Watch** | eigene Ausdrücke: `$daten['name']`, `count($items)`, Methodenaufrufe |
| **Call Stack** | wer diese Funktion aufgerufen hat, mit Parametern – Klick springt dorthin |
| **Breakpoints** | Liste aller gesetzten Haltepunkte |
| **Debug Console** | beliebigen PHP-Code im aktuellen Kontext ausführen |
Steuerung: **F10** Step Over (nächste Zeile) · **F11** Step Into (in Funktion hinein) ·
**Shift+F11** Step Out · **F5** Continue (bis zum nächsten Breakpoint)
### Schritt 8 – Trigger bequemer machen
Der Query-Parameter `?XDEBUG_TRIGGER=1` funktioniert nicht bei POST-Formularen oder
Ajax. Lösung: Browser-Extension **Xdebug Helper** (Chrome/Firefox) – ein Klick auf den
Käfer setzt ein Cookie, danach ist jeder Request auf der Domain getriggert.
CLI-Äquivalent:
```bash
XDEBUG_TRIGGER=1 /Applications/XAMPP/xamppfiles/bin/php script.php
```
### Schritt 9 – Session beenden
**Shift+F5** in VS Code stoppt den Listener. Die Seite im Browser läuft dann normal
weiter. Ohne laufenden Listener werden Breakpoints einfach ignoriert – es entsteht kein
Fehler.
---
## 6. Schritt für Schritt: Debuggen unter Debian
Zwei Fälle: Code liegt lokal auf demselben Rechner, oder auf einem entfernten Server.
### Schritt 1 – Installieren und konfigurieren
```bash
sudo apt install php-xdebug
sudo nano /etc/php/8.4/apache2/conf.d/99-xdebug-local.ini
```
```ini
xdebug.mode = develop,debug
xdebug.start_with_request = trigger
xdebug.client_port = 9003
xdebug.discover_client_host = 1
xdebug.var_display_max_depth = 10
xdebug.var_display_max_data = 1024
xdebug.var_display_max_children = 256
```
```bash
sudo systemctl restart apache2
```
Für CLI-Skripte dieselbe Datei zusätzlich unter `/etc/php/8.4/cli/conf.d/` ablegen –
oder einmal in `mods-available/` und mit `phpenmod xdebug-local` für beide aktivieren.
### Schritt 2 – Kontrollieren
```bash
php -v # CLI: "with Xdebug v3.x.x"
php -i | grep xdebug.mode
```
Für den Webserver: `phpinfo()` im Browser aufrufen – nur das zeigt, was Apache lädt.
Danach die Datei löschen.
### Schritt 3 – Client-Position klären
Der Debug-Client läuft auf **deiner** Maschine, nicht auf dem Server.
| Situation | Vorgehen |
|---|---|
| Code liegt lokal | nichts weiter nötig, Listener einfach starten |
| Code auf entferntem Server | SSH-Reverse-Tunnel |
```bash
ssh -R 9003:localhost:9003 user@server
```
Damit verbindet sich Xdebug auf dem Server nach `localhost:9003` – und landet über den
Tunnel bei dir. Der Tunnel muss offen bleiben, solange du debuggst.
### Schritt 4 – Pfade zuordnen (nur bei Remote)
Die IDE muss wissen, welche lokale Datei welchem Serverpfad entspricht.
VS Code, `.vscode/launch.json`:
```json
{
"version": "0.2.0",
"configurations": [
{
"name": "Listen for Xdebug",
"type": "php",
"request": "launch",
"port": 9003,
"pathMappings": {
"/var/www/projekt": "${workspaceFolder}"
}
}
]
}
```
Links steht immer der **Serverpfad**, rechts der lokale. Stimmt das nicht, hält der
Debugger zwar an, öffnet aber keine Datei – der häufigste Frustpunkt bei Remote-Setups.
### Schritt 5 – Ohne VS Code: vdebug in Vim/Neovim
Spricht DBGp direkt, braucht nur Vim mit `+python3` – keine Node-Abhängigkeit.
`.vimrc`:
```vim
let g:vdebug_options = {
\ 'port': 9003,
\ 'break_on_open': 0,
\ 'path_maps': {'/var/www/projekt': '/home/sven/projekt'},
\}
```
Bedienung: **F5** Listener starten · **F10** Breakpoint setzen/entfernen ·
**F2** Step Over · **F3** Step Into · **F4** Step Out · **F6** beenden
Sobald die Session steht, teilt sich das Fenster: Quellcode, Variablen im aktuellen
Scope, Call-Stack und ein Watch-Bereich, in dem sich beliebige Ausdrücke auswerten
lassen.
Alternativen: **nvim-dap** (moderneres UI, braucht Node + `vscode-php-debug`) und
**dbgp-tools** von Derick Rethans (reiner CLI-Client, via Composer).
### Schritt 6 – Request triggern
```bash
# Webseite
http://server/projekt/index.php?XDEBUG_TRIGGER=1
# CLI-Skript auf dem Server
XDEBUG_TRIGGER=1 php artisan irgendwas
```
### Schritt 7 – Wenn keine IDE möglich ist: Trace-Dateien
Auf gesperrten Systemen oft der stärkste Hebel – ein Step-Debugger im Nachhinein.
```ini
xdebug.mode = develop,trace
xdebug.start_with_request = trigger
xdebug.output_dir = /tmp
xdebug.trace_format = 0
xdebug.collect_params = 4 ; volle Argumentwerte
xdebug.collect_return = 1
```
Ein Request mit `?XDEBUG_TRIGGER=1` schreibt `/tmp/trace.*.xt` – eine vollständige,
eingerückte Aufrufliste mit allen Parametern und Rückgabewerten:
```bash
ls -t /tmp/trace.*.xt | head -1 | xargs less
```
Gezielt nur einen Abschnitt protokollieren:
```php
xdebug_start_trace('/tmp/meintrace');
// verdächtiger Abschnitt
xdebug_stop_trace();
```
Für die Frage „wer ruft das mit welchen Werten auf" meist schneller als ein Breakpoint.
---
## 7. Was man wo sieht – Überblick
| Modus | Ausgabeort | Zeigt |
|---|---|---|
| `develop` | Browser / STDOUT | farbiges `var_dump`, Stack-Traces bei Fehlern |
| `trace` | Datei in `xdebug.output_dir` | kompletter Aufrufbaum mit Parametern |
| `debug` | IDE / Vim | Variablen, Call-Stack, Watch, schrittweise Ausführung |
| `profile` | `cachegrind.out.*` in `output_dir` | Laufzeit pro Funktion (qcachegrind) |
Zusätzlich im Code nutzbar (alle Modi):
```php
xdebug_info(); // Konfigurations-Übersicht im Browser
xdebug_break(); // Breakpoint aus dem Code heraus
var_dump(xdebug_get_function_stack()); // Wer hat mich aufgerufen?
error_log(xdebug_print_function_stack()); // Stack ins Logfile
echo xdebug_call_line();
```
### Conditional Breakpoints
Rechtsklick auf den Breakpoint → Bedingung eintragen, z. B. `$id === 4711`. Damit hält
man gezielt bei einem Datensatz in einer Schleife über 10.000 Zeilen an. Einer der
größten praktischen Vorteile gegenüber `var_dump`.
### Profiling
```ini
xdebug.mode = profile
xdebug.output_dir = /tmp
```
Auswertung mit **qcachegrind** (`brew install qcachegrind`, `apt install kcachegrind`).
> Nicht dauerhaft anlassen: bremst massiv und füllt `/tmp`.
---
## 8. Alternative & Ergänzung: Symfony VarDumper
Unabhängig von Xdebug, rein per Composer – nützlich auf Systemen, wo keine Extension
installiert werden darf.
```bash
composer require --dev symfony/var-dumper
```
```php
dump($row); // weiter im Code
dd($row, $other); // dump and die
```
Ausgabe im Browser aufklappbar, auf der CLI eingefärbt, kürzt rekursive Strukturen.
**Dump-Server** – fängt Ausgaben in einem separaten Terminal ab, statt sie in die
Response zu schreiben. Praktisch bei API-Endpunkten, wo HTML im Output stört:
```bash
vendor/bin/var-dump-server
# dazu: VAR_DUMPER_FORMAT=server
```
| PHP | symfony/var-dumper |
|---|---|
| 7.1 | `^4.4` |
| 7.2 – 7.4 | `^5.4` |
| 8.0 – 8.1 | `^6.4` |
| 8.2+ | `^7` |
**Absolutes Minimum**, wenn gar nichts geht (Ajax, Redirects, Cronjobs):
```php
error_log(var_export($row, true));
```
```bash
tail -f /var/log/apache2/error.log
```
### Ohne Xdebug: `<pre>` nicht vergessen
`var_dump()` gibt Plaintext aus, der Browser kollabiert Whitespace. Deshalb:
```php
function dbg(...$vars): void {
echo '<pre style="text-align:left">';
var_dump(...$vars);
echo '</pre>';
}
```
`var_dump()` ist variadisch – mehrere Werte auf einmal sind erlaubt. Praktischer Trick
zur Orientierung: `var_dump(__LINE__, $row);`
---
## 9. Stolperfallen-Kurzliste
| Symptom | Ursache / Lösung |
|---|---|
| Extension wird ignoriert, keine Meldung | `extension=` statt `zend_extension=` |
| `incompatible architecture (have 'arm64', need 'x86_64')` | Build ohne Rosetta-Shell – `arch -x86_64 /bin/zsh`, dann neu bauen |
| `already installed ... install failed` | `pecl uninstall xdebug` oder `pecl install -f` |
| `Failed loading ... (no such file)` beim `pecl`-Aufruf | harmlos: PHP liest die INI, die `.so` wurde gerade gelöscht |
| `pecl` schreibt in falsche PHP-Installation | XAMPP-eigenes `pecl` aus `.../xamppfiles/bin/` verwenden |
| CLI zeigt Xdebug, Browser nicht | Apache lädt eine andere `php.ini` → Pfad aus `phpinfo()` nehmen |
| Direktiven wirken nicht | alles in einer Zeile statt untereinander |
| `<datum>` im Pfad | Platzhalter! echten Namen per `php -i \| grep extension_dir` ermitteln |
| `var_dump` zeigt `...` statt Daten | `var_display_max_depth` / `_data` / `_children` erhöhen |
| Breakpoint wird nie erreicht | Listener nicht gestartet, oder Trigger fehlt |
| Debugger hält an, öffnet aber keine Datei | `pathMappings` / `path_maps` falsch (Serverpfad links) |
| Port-Verbindung schlägt fehl | Xdebug 2 nutzt 9000, Xdebug 3 nutzt 9003 |
| `autoconf: command not found` | `brew install autoconf` |
| `Cannot find php-config` | falsches `phpize`/`php-config` – das aus dem Ziel-PHP nehmen |
---
## 10. Randnotiz: `var_dump` mit Barewords
```php
var_dump("Test", ffff); // ohne $
```
| PHP | Verhalten |
|---|---|
| ≤ 7.1 | `Notice: Use of undefined constant ffff` → gibt `string(4) "ffff"` aus |
| 7.2 – 7.4 | `Deprecated`, sonst wie oben |
| 8.0+ | **fataler** `Error: Undefined constant "ffff"` |