Conversation
Template::parse(), template() and combine() open an output buffer, include the template and close the buffer only on success. When the template throws (e.g. a PHP 8.x deprecation turned into an ErrorException), the buffer stays open and swallows everything the caller prints afterwards. Under PHPUnit 9 this snowballs. stopOutputBuffering() sees the unbalanced level and throws "risky" before clearing outputBufferingActive, so the printer re-prints the whole enclosing buffer as the test's output. In the accounts integration suite on PHP 8.5 that doubled the output with every failing page until PHPUnit ran out of memory. Catch \Throwable around the include, close the buffer and rethrow. The new variable follows the file's $ctlbtmplt... naming, because it lives in the template's scope. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Template::parse(),template()andcombine()doob_start(); include …; ob_get_contents(); ob_end_clean();with nothing around the include. If the template throws, the buffer stays open and swallows whatever the caller outputs afterwards.On PHP 8.x this happens a lot more, because deprecations in templates (
trim(null)and the like) becomeErrorExceptions in apps that fail on them. Under PHPUnit 9 it snowballs.stopOutputBuffering()sees the unbalanced level, cleans down, and throws "risky" before clearingoutputBufferingActive, sogetActualOutput()returns the whole enclosing buffer and the printer writes it back into that buffer. In the accounts integration suite on PHP 8.5, the output doubled with every failing page until PHPUnit ran out of memory (4.7 GB allocation), so the 8.5 suite couldn't report anything.Change
Wrap the include in
try { … } catch (\Throwable $ctlbtmplterror) { ob_end_clean(); throw $ctlbtmplterror; }in all three methods. The success path is unchanged. The variable follows the file's$ctlbtmplt…convention because it lives in the template's variable scope. It stays within the PHP 7.4 minimum (php -lon 7.4).Tests
TemplateOutputBufferTest: a throwing template reached viaparse(), via$this->template()and via$this->combine()leavesob_get_level()unchanged, and normal rendering still returns its output.Template.php: 3 failures (and PHPUnit flags them risky for unclosed buffers).--exclude-group=database: 203 OK on PHP 8.5.Effect on accounts (PHP 8.5, this file mounted over
vendor/)Before: the integration run died with an out-of-memory error. After: 776 tests run, 617 pass. The 159 failures are real 8.5 findings in the app and vendors.
Release as v3.3.1 (patch).
🤖 Generated with Claude Code