skip to content

In PHP, how do var_dump(), print_r() and var_export() differ, and when would you use each one?

level: middleimportance: should knowfreq 48%

answer

  1. types and lengths vs readable vs code
  2. var_dump has no return option
  3. print_r shows false and null as empty
  4. var_export output is valid PHP
  5. recursion: marker vs warning

basics

~20 s

var_dump() prints types, lengths and values and cannot return a string. print_r() prints a readable view, hides types, and can return a string. var_export() prints valid PHP code, can return it, and rejects circular references.

solid answer

~40 s

`var_dump()` prints **type and value** for each argument, such as `string(4) "Soup"`, `bool(false)`, `NULL`, `float(9.5)`; it takes several values and returns nothing, so capturing it needs output buffering. `print_r()` prints a **human-readable** structure without types: `false` and `null` both appear as an empty string and `true` as `1`, so it hides exactly the bugs you debug. Its second argument `true` makes it **return** the string. `var_export()` prints **valid PHP code** (`false`, `NULL`, `'Soup'`, `array (...)`), can also return it, and exports objects as `\Class::__set_state(array(...))` and enums as `\Menu::Starter`. On a circular reference `var_dump()` and `print_r()` print `*RECURSION*`, while `var_export()` emits `NULL` and a warning. Use `var_dump()` for debugging, `print_r(..., true)` for quick logs, `var_export()` when you need code.

code

php · 13 lines
php
<?php
declare(strict_types=1);

enum Menu { case Starter; case Main; }

$dish = ['name' => 'Soup', 'price' => 9.5, 'vegan' => false, 'note' => null, 'course' => Menu::Starter];

var_dump($dish['vegan'], $dish['note']);  // bool(false) NULL
print_r($dish);                           // [vegan] => , [note] => , [course] => Menu Enum ( ... )
var_export($dish['course']);             // \Menu::Starter
echo PHP_EOL, var_export(1.0, true);     // 1.0

$log = print_r($dish, true);              // captured as a string

go deeper

for a junior

Recall that var_dump shows types, print_r is the readable view, and var_export prints PHP code.

for a middle

Explain which ones can return a string, why print_r hides false and null, and how each handles objects, enums and recursion.

for a senior

Choose the right dump for logs and fixtures, and keep dumps of objects with credentials out of logs and responses.

for a principal

Replace ad-hoc dumps in production code with structured logging and a debugger, and keep dump calls out of committed code with a static-analysis rule.

## Three dump functions, three purposes PHP ships three functions that turn a value into text. They look alike but answer different questions: | | `var_dump()` | `print_r()` | `var_export()` | |---|---|---|---| | Signature | `var_dump(mixed $value, mixed ...$values): void` | `print_r(mixed $value, bool $return = false): string\|true` | `var_export(mixed $value, bool $return = false): ?string` | | Shows types | yes | no | implicitly, as PHP literals | | Can return a string | no | yes, with `true` | yes, with `true` | | Several values per call | yes | no | no | | Output is valid PHP | no | no | yes | | Circular reference | prints `*RECURSION*` | prints `*RECURSION*` | prints `NULL`, raises `E_WARNING` | All three show protected and private properties of objects; none shows static properties. ## var_dump(): the debugging view `var_dump()` prints the type of every value, the length of every string and the count of every array: - `bool(false)`, `NULL`, `int(12)`, `float(9.5)`, `string(4) "Soup"` - `array(2) { ... }`, `object(Dish)#3 (2) { ... }` - enums as `enum(Menu::Starter)` That is why it is the default debugging tool: it distinguishes `""`, `null`, `false` and `"0"`, which all look the same elsewhere. Floats are printed with `serialize_precision` (default `-1`, the shortest representation that round-trips). It returns nothing, so to capture the text you wrap it in output buffering. ## print_r(): the readable view `print_r()` is meant for humans reading nested arrays: ``` Array ( [starter] => Soup [vegetarian] => 1 ) ``` For scalars it prints the string conversion of the value. That is its weakness: 1. `true` prints as `1`. 2. `false` and `null` print as **nothing**. 3. `"1"` and `1` look identical. Its strength is the `$return` parameter: `error_log(print_r($order, true))` writes a readable structure to the log. Without `true` it prints and returns `true`. ## var_export(): the code view `var_export()` produces text that PHP can parse back: - scalars as literals: `false`, `true`, `NULL`, `12`, `9.5`, `'Soup'` (floats keep a fraction, so `1.0` stays `1.0`); - arrays in the `array ( 0 => 'a', )` form; - `stdClass` as `(object) array( ... )`; - enums as `\Menu::Starter`; - other objects as `\Dish::__set_state(array( ... ))`, which only works when the class defines a static `__set_state()` method. Since PHP 8.2 class names are fully qualified with a leading backslash. It cannot represent circular structures: it prints `NULL` in their place and raises the warning "var_export does not handle circular references". Resources are exported as `NULL`. ## Reading var_dump() output A few details of the format are worth knowing: - `string(5) "Café"`: the number is the length in **bytes**, not characters. `é` is two bytes in UTF-8, so the count exposes encoding problems. - `object(Dish)#3 (2)`: the class, the object handle number and the number of properties. Two variables showing the same handle refer to the same object. - `["price":protected]` and `["secret":"Dish":private]`: visibility is shown per property. - Several arguments are dumped one after another: `var_dump($a, $b)`. ## Choosing - **Debugging a value's type**: `var_dump()`, because `print_r()` hides `false`, `null` and the difference between `1` and `"1"`. - **Logging a readable structure**: `print_r($value, true)` or `var_export($value, true)`. - **Writing a value as PHP source**, for a fixture or a generated config file: `var_export()`. - **Never in production responses**: all three can print private properties and secrets. Customising what they show for an object is done with a magic method, a topic of its own.

  • How do you capture var_dump() output in a string?
    `var_dump()` has no return parameter, so wrap it in output buffering: `ob_start(); var_dump($x); $text = ob_get_clean();`. For many cases `var_export($x, true)` or `print_r($x, true)` is simpler, but only `var_dump()` shows string lengths and distinguishes every type.
  • What does print_r() print for false and for null, and why does that matter?
    An empty string for both, because `print_r()` prints the string conversion of scalars; `true` prints as `1`. When you are debugging why a condition failed, that output cannot tell `false`, `null` and `""` apart, which is why `var_dump()` is the tool for type questions.

saying these in an interview costs you the question

  • print_r() shows the type of every value.
  • var_dump() has a second parameter that returns the output as a string.
  • var_export() handles circular references like serialize() does.
  • print_r(false) prints the word false.
  • Dump output is safe to show to users because private properties are hidden.