ob_get_level

Returns how many output buffers are currently nested, or zero when buffering is not active.

Signature
ob_get_level(): int
  • Added in PHP 4.2.0

Return value

intReturns the number of nested output buffering handlers, or 0 if output buffering is not active.

ob_get_level() answers one question: how deep is the output buffer stack right now? Each ob_start() adds one, each ob_end_clean() or ob_end_flush() removes one, and zero means no buffering at all.

When to reach for it

It is the safety mechanism for any code that opens buffers. Record the level before you start, and in a finally block or shutdown handler loop ob_end_clean() until you are back at it. That guarantees an exception thrown mid-template cannot leave a half-rendered fragment trapped in a buffer, and cannot accidentally close a buffer that belonged to the caller. It is also the correct guard before calling ob_flush() or ob_clean(), both of which emit a notice when no buffer exists.

What trips people up

Do not assume the base level is zero. If output_buffering is enabled in php.ini, or a framework wrapped your handler, a buffer already exists before your first line runs — so while (ob_get_level() > 0) ob_end_clean(); destroys something you did not open. Always unwind to a level you captured yourself.

Also note the off-by-one against ob_get_status(): the first buffer is level 1 here but has a level key of 0 there.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Unwind exactly the buffers your code opened in a finally block, without touching the caller's.
  • Guard ob_flush() or ob_clean() calls so they never emit a notice when no buffer exists.
  • Assert in tests that a template helper left the buffer stack the way it found it.

Frequently asked questions

How do I check if output buffering is on?

Call ob_get_level(); anything greater than 0 means at least one buffer is active. It never returns false, so a plain comparison is safe.

How do I close all output buffers?

Loop while ob_get_level() is above the level you recorded at the start of your code, calling ob_end_clean() or ob_end_flush(). Unwinding to 0 risks closing a buffer opened by php.ini or your framework.

Why do ob_get_level and ob_get_status report different levels?

ob_get_level() counts from 1 for the first buffer, while the level key in ob_get_status() counts from 0. The same buffer therefore shows as 1 and 0 respectively.

More examples

Unwinding safely to the level you started at

The partial page never appears and the dump is bool(true). Unwinding to $base rather than to 0 means a buffer opened by php.ini's output_buffering setting, or by a calling framework, survives untouched.

Example · php
<?php
$base = ob_get_level();
ob_start();
echo "partial page that must not be sent";

// An error occurred: discard everything we opened, nothing else.
while (ob_get_level() > $base) {
    ob_end_clean();
}

echo "clean error page\n";
var_dump(ob_get_level() === $base);

Guarding a helper that may be called with or without buffering

'scratch text' is discarded and the script prints 'buffer cleaned'. The level check means the same helper can run outside a buffer without triggering the E_NOTICE that a bare ob_clean() would produce.

Example · php
<?php
function safeClean(): string {
    if (ob_get_level() === 0) {
        return 'no buffer to clean';
    }
    ob_clean();
    return 'buffer cleaned';
}

ob_start();
echo "scratch text";
$result = safeClean();
ob_end_flush();
echo $result, "\n";

Discussion

  • Be the first to comment on this lesson.