ob_​end_​flush(): failed to send buffer of zlib – jak to naprawić? [WordPress]

Jeżeli progra­mu­jesz w WordPres­sie i ustawisz opcję pokazy­wa­nia błędów i debugo­wa­nie ich na 'true', to częstym błędem jaki będzie cię nękał jest ten poniżej:

Notice: ob_​end_​flush(): failed to send buffer of zlib output compres­sion (0) in…

define( 'WP_DEBUG', true );
// Disable display of errors and warnings
define( 'WP_DEBUG_DISPLAY', true );
@ini_set( 'display_errors', 1 );
define( 'WP_DEBUG_LOG', true );

Ciężko kodować i ciągle domyślać się co wywró­ci­ło stronę gdy widać tylko biały ekran. Powyż­sze ustawie­nia są pomoc­ne na etapie deweloperskim.

Przyczyna błędu – ob_end_flush()

Dzieje się tak, gdy motyw lub wtycz­ka z których korzy­sta­my korzy­sta z buforo­wa­nia zlib, ale w sposób niepra­wi­dło­wy go opróż­nia. Może się też zdarzyć, że wadli­wy jest sam moduł zlib. Za wyświe­tle­nie błędu odpowia­da funkcja wp_​ob_​end_​flush_​all() urucha­mia­na za pomocą haka 'shutdown'. Do niedaw­na jedynym znanym mi rozwią­za­niem było wyłącze­nie akcji 'shutdown'. Robiłem to do czasu, aż przeczy­ta­łem wpis na blogu Kevina Leary: Quick Fix for WordPress ob_​end_​flush() Error.

Lepiej naprawić niż wyłączyć

Autor doszedł do wniosku, że po coś jest hak 'shutdown' i prędzej czy później wyłącze­nie go spowo­du­je coś niedo­bre­go. Lepiej napra­wić niż wyłączyć! Przyczy­ny niepo­wo­dze­nia to pierw­sze wywoła­nie funkcji bez aktyw­ne­go bufora lub to, że z jakie­goś powodu bufor nie mógł zostać usunię­ty (możli­we w przypad­ku specjal­ne­go bufora).

/**
 * Flush all output buffers for PHP 5.2.
 *
 * Make sure all output buffers are flushed before our singletons are destroyed.
 *
 * @since 2.2.0
 */
function wp_ob_end_flush_all() {
  $levels = ob_get_level();
  for ( $i = 0; $i < $levels; $i++ ) {
    ob_end_flush();
  }
}

Powyżej jest orygi­nal­ny kod funkcji. Za błąd odpowia­da funkcja ob_​end_​flush(). Jest to funkcja języka PHP, której wynikiem jest true albo false, a wszel­kie błędy są zwraca­ne jako E_NOTICE.

ob_​end_​flush — Opróż­nij (wyślij) bufor wyjścio­wy i wyłącz buforo­wa­nie wyjściowe.

Ta funkcja wyśle ​​zawar­tość najwyż­sze­go bufora wyjścio­we­go (jeśli istnie­je) i wyłączy ten bufor wyjścio­wy. Jeśli chcesz dalej przetwa­rzać zawar­tość bufora, musisz wywołać ob_​get_​contents() przed ob_​end_​flush(), ponie­waż zawar­tość bufora jest odrzu­ca­na po wywoła­niu ob_end_flush() .

Bufor wyjścio­wy musi być urucho­mio­ny przez ob_​start() z flaga­mi PHP_​OUTPUT_​HANDLER_​FLUSHABLE i PHP_​OUTPUT_​HANDLER_​REMOVABLE. W przeciw­nym razie ob_​end_​flush() nie zadziała.

Rozwiązanie

Zamiast wyłączyć funkcję, można ją zmody­fi­ko­wać tak by nie wyświe­tla­ła błędu i działa­ła dalej.

/**
 * Proper ob_end_flush() for all levels
 *
 * This replaces the WordPress `wp_ob_end_flush_all()` function
 * with a replacement that doesn't cause PHP notices.
 */
remove_action( 'shutdown', 'wp_ob_end_flush_all', 1 );
add_action( 'shutdown', function() {
   while ( @ob_end_flush() );
} );

Najpierw usuwa­my hak (hook) z wadli­wą funkcją, po czym dodaje­my go ponow­nie z popra­wio­nym kodem. Kluczem do sukce­su jest zasto­so­wa­nie znaku '@' (Opera­tor kontro­li błędu) przed nazwą funkcji ob_​end_​flush(). Z podręcz­ni­ków do PHP wiado­mo, że takie rozwią­za­nie wyłącza pokazy­wa­nie błędu. Kod należy umieścić w pliku functions.php WordPressa. 

Błąd to błąd. Skoro WordPress infor­mu­je, że coś nie działa, to trzeba to spraw­dzić i napra­wić. Nie zabija się posłań­ca złych wieści. W tym przypad­ku istnie­je problem z kompre­sją zlib. Nie zalecam jej wyłącze­nia, ani usuwa­nia akcji 'shutdown'. Użycie opera­to­ra '@' jest w tym konkret­nym przypad­ku jest w porządku.

Dodaj komentarz

This site uses Akismet to reduce spam. Learn how your comment data is processed.