interitty / output-buffer-manager

输出缓冲区管理器提供了一种安全的方式来处理输出。

v1.0.4 2024-09-01 12:05 UTC

This package is auto-updated.

Last update: 2024-09-01 10:09:12 UTC


README

输出缓冲区管理器提供了一种安全的方式来处理输出。

要求

安装

安装 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_cleanob_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('...');