interitty / output-buffer-manager
输出缓冲区管理器提供了一种安全的方式来处理输出。
Requires
- php: ~8.3
- dg/composer-cleaner: ~2.2
- interitty/di: ~1.0
- interitty/utils: ~1.0
Requires (Dev)
- interitty/application: ~1.0
- interitty/code-checker: ~1.0
- interitty/phpunit: ~1.0
README
输出缓冲区管理器提供了一种安全的方式来处理输出。
要求
- PHP >= 8.3
安装
安装 interitty/output-buffer-manager 的最佳方式是使用 Composer
composer require interitty/output-buffer-manager
然后在 Nette 配置文件 中注册扩展
# app/config/config.neon
extensions:
outputBufferManager: Interitty\OutputBufferManager\Nette\DI\OutputBufferManagerExtension
功能
对于需要使用输出缓冲区的更复杂的应用程序,此包有助于组织单个处理器。每个处理器的命名是必需的,因为这有助于防止难以察觉和不必要的问题。它还允许在同一时刻轻松地处理多个并发处理器。输出缓冲区管理器在请求之前不做任何事情。因此,它可以注册为依赖注入容器或服务定位器中的服务,并在需要的地方使用。以下示例中,为了简化,创建了新的 OutputBufferManager
类实例。管理器使用所谓的“处理器”,这些是匿名函数或回调。这些“处理器”封装在代表内部使用的 HandlerInterface
的简单实现的 Handler
类对象中。此机制提供了在某些情况下可能有用的额外事件。
示例:将内容捕获到变量中
以下示例捕获发送到输出的任何内容,并将其追加到指定的 $output
变量中。它还显示,“处理器”可以定义为一个匿名函数。因为处理器没有返回值,所以将不会向输出或另一个已注册的处理器发送任何内容。
$output = null;
$outputBufferManager = new OutputBufferManager();
$outputBufferManager->begin('…', function(string $bufferOutput) use(&$output): string {
$output .= $bufferOutput;
return '';
});
// Any content that was sent to the output
echo 'testContent';
$outputBufferManager->end('…');
示例:将内容捕获到属性中
以下示例捕获发送到输出的任何内容,并将其追加到 Example::$output
属性中。它还显示,“处理器”可以定义为一个回调。
class Example
{
public $output;
public function __construct(): void
{
$outputBufferManager = new OutputBufferManager();
$outputBufferManager->begin('…', [$this, 'handleCatchContent']);
// Any content that was sent to the output
echo 'testContent';
$outputBufferManager->end('…');
}
public function handleCatchContent(string $bufferOutput): string
{
$this->output .= $bufferOutput;
return '';
}
}
示例:将内容代理到变量中
以下示例将发送到输出的任何内容代理到指定的 $output
变量中。因为处理器有返回值,所以也将向输出或另一个已注册的处理器发送所有内容。
$output = null;
$outputBufferManager = new OutputBufferManager();
$outputBufferManager->begin('…', function(string $bufferOutput) use(&$output): string {
$output .= $bufferOutput;
return $bufferOutput;
});
// Any content that was sent to the output
echo 'testContent';
$outputBufferManager->end('…');
示例:刷新输出缓冲区的内容
在某些情况下,手动将输出缓冲区的内容刷新到处理器中可能很有用。为此目的,在 OutputBufferManager
对象上有一个 flush
方法。与其他方法一样,它也期望当前处理器的名称,以防止出现令人不快的问题。
$outputBufferManager = new OutputBufferManager();
// in some cases like in the foreach cycle …
$outputBufferManager->flush('…');
$outputBufferManager->end('…');
当出错时
在某些情况下,可能会看到以下异常。
LogicException: 输出缓冲区处理器 "…" 已经注册
如异常消息所述,之前已注册了具有相同名称的另一个处理器。问题的核心类似于以下代码。
$outputBufferManager = new OutputBufferManager();
$outputBufferManager->begin('…', function(): string {return '';});
$outputBufferManager->begin('…', function(): string {return '';});
同一时间只能有一个同名的处理器。
解决方案
解决方案是使用不同的(唯一的)名称或停止使用最后一个名称,并开始使用新的名称工作。
$outputBufferManager = new OutputBufferManager();
$outputBufferManager->begin('…', function(): string {return '';});
// warning: calling end flush unflushed data
$outputBufferManager->end('…');
$outputBufferManager->begin('…', function(): string {return '';});
逻辑异常:当前输出缓冲区管理器不是 OutputBufferManager
问题的核心是,OutputBufferManager
不是一个当前的输出缓冲区处理器。这可能会发生在 OutputBufferManager
尚未启动时。
$outputBufferManager = new OutputBufferManager();
// Forgotten call of $outputBufferManager->begin('…', function(): string {return '';});
$outputBufferManager->end('…');
另一种可能性是已注册了一个不同的处理器而不是 OutputBufferManager
。
$outputBufferManager = new OutputBufferManager();
$outputBufferManager->begin('…', function(): string {return '';});
// Maybe the old mechanism of the Output buffer was forgotten in the code
ob_start(function(): string {return '';});
$outputBufferManager->end('…');
解决方案
可能的解决方案取决于具体的使用场景。
- 用
OutputBufferManager
替换旧处理器。 - 刷新旧处理器(
ob_end_clean
或ob_end_flush
),以便回退到OutputBufferManager
。 - 通过
OutputBufferManager::begin
注册新的OutputBufferManager
。
逻辑异常:预期的输出缓冲区处理器 "…" 未注册
问题的核心大多在于处理器名称的拼写错误。
$outputBufferManager = new OutputBufferManager();
$outputBufferManager->begin('...', function(): string {return '';});
$outputBufferManager->end('…');
解决方案
修复预期处理器的名称。最好使用 常量 作为处理器名称以防止此类问题。
define('OUTPUT_BUFFER_MAIN', '…');
$outputBufferManager = new OutputBufferManager();
$outputBufferManager->begin(OUTPUT_BUFFER_MAIN, function(): string {return '';});
$outputBufferManager->end(OUTPUT_BUFFER_MAIN);
逻辑异常:当前输出缓冲区处理器 "..." 不是预期的 "…"
问题的核心大多在于忘记终止最后使用的处理器或调用错误。
$outputBufferManager = new OutputBufferManager();
$outputBufferManager->begin('…', function(): string {return '';});
$outputBufferManager->begin('...', function(): string {return '';});
// Somebody forgot call $outputBufferManager->end('...');
$outputBufferManager->end('…');
解决方案
添加先前处理器的忘记终止或纠正调用处理器位置。
$outputBufferManager = new OutputBufferManager();
$outputBufferManager->begin('…', function(): string {return '';});
$outputBufferManager->end('…');
$outputBufferManager->begin('...', function(): string {return '';});
$outputBufferManager->end('...');