Jeżeli programujesz w WordPressie i ustawisz opcję pokazywania błędów i debugowanie 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 compression (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 ustawienia są pomocne na etapie deweloperskim.
Przyczyna błędu – ob_end_flush()
Dzieje się tak, gdy motyw lub wtyczka z których korzystamy korzysta z buforowania zlib, ale w sposób nieprawidłowy go opróżnia. Może się też zdarzyć, że wadliwy jest sam moduł zlib. Za wyświetlenie błędu odpowiada funkcja wp_ob_end_flush_all() uruchamiana za pomocą haka 'shutdown'. Do niedawna jedynym znanym mi rozwiązaniem było wyłączenie akcji 'shutdown'. Robiłem to do czasu, aż przeczytał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łączenie go spowoduje coś niedobrego. Lepiej naprawić niż wyłączyć! Przyczyny niepowodzenia to pierwsze wywołanie funkcji bez aktywnego bufora lub to, że z jakiegoś powodu bufor nie mógł zostać usunięty (możliwe w przypadku specjalnego 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 oryginalny kod funkcji. Za błąd odpowiada funkcja ob_end_flush(). Jest to funkcja języka PHP, której wynikiem jest true albo false, a wszelkie błędy są zwracane jako E_NOTICE.
ob_end_flush — Opróżnij (wyślij) bufor wyjściowy i wyłącz buforowanie wyjściowe.
Ta funkcja wyśle zawartość najwyższego bufora wyjściowego (jeśli istnieje) i wyłączy ten bufor wyjściowy. Jeśli chcesz dalej przetwarzać zawartość bufora, musisz wywołać ob_get_contents() przed ob_end_flush(), ponieważ zawartość bufora jest odrzucana po wywołaniu ob_end_flush() .
Bufor wyjściowy musi być uruchomiony przez ob_start() z flagami PHP_OUTPUT_HANDLER_FLUSHABLE i PHP_OUTPUT_HANDLER_REMOVABLE. W przeciwnym razie ob_end_flush() nie zadziała.
Rozwiązanie
Zamiast wyłączyć funkcję, można ją zmodyfikować tak by nie wyświetlał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 usuwamy hak (hook) z wadliwą funkcją, po czym dodajemy go ponownie z poprawionym kodem. Kluczem do sukcesu jest zastosowanie znaku '@' (Operator kontroli błędu) przed nazwą funkcji ob_end_flush(). Z podręczników do PHP wiadomo, że takie rozwiązanie wyłącza pokazywanie błędu. Kod należy umieścić w pliku functions.php WordPressa.
Błąd to błąd. Skoro WordPress informuje, że coś nie działa, to trzeba to sprawdzić i naprawić. Nie zabija się posłańca złych wieści. W tym przypadku istnieje problem z kompresją zlib. Nie zalecam jej wyłączenia, ani usuwania akcji 'shutdown'. Użycie operatora '@' jest w tym konkretnym przypadku jest w porządku.