Zend Frameworkでob_gzhandlerを使用する。

Firebug用YSlowプラグインが出たことにより、またhttpレスポンス圧縮の話題が再燃しているような気がします。(参考
Apache側でmod_gzip,mod_deflateが設定できれば良いのですが、レンタルサーバなどでは設定できないことが多いです。そういった場合にはPHPでアウトプットを圧縮して送信することができます。方法としては主に

  • php.iniの設定でzlib.output_compression を有効にする。
  • ob_start()のコールバック関数 ob_gzhandler を使用する。

があります。

zlib.output_compressionに関してはとても簡単で、php.iniに

zlib.output_compression = On

の行を入れるだけです。おそらくコメントアウト状態で入っているので、

#zlib.output_compression = Off

コメントアウトを外し、OffをOnに変更するのが簡単です。
これで通常のPHP出力は、圧縮されてクライアントに送信されます。
#この設定はzlib 拡張モジュールがPHPに組み込まれている必要があります
また、zlib.output_compression_level というものがあり、これで圧縮率を変更できるようです。

zlib.output_compression_level = 1

ただ、この設定は(マニュアルを確認すると)変更の可否がPHP_INI_ALLとなっているものの、スクリプト上から変更できない場合があります。
(php.iniで zlib.output_compression = On にされているものをスクリプトでOffにすることはほとんどの場合で可能なようですが・・・)
その場合は ob_gzhandlerを使うしかありません。

Zend Frameworkの出力はob_start()で制御されています。
ob_gzhandlerを使用するには、
[php]
ob_start(“ob_gzhandler”);
[/php]
と、ob_startの引数としてコールバック関数名(ob_gzhandler)を渡すのですが、Zend Frameworkのどこに埋め込みましょう?
使用している箇所はディスパッチャの中ですが、しかし、Zend Framework本体に手を入れるのはあまり好ましくありません。(まだまだバージョン更新が激しいですから:-) 。仕様もいつガラっと変えてくるかわかりません)
じゃあ、ob_startまわりを継承、委譲して作る、というのもよいのですが、ob_start()のマニュアルを見てみると、

出力バッファはスタッカブルであり、このため、他の ob_start() がアクティブの間に ob_start() をコールすることが可能です。この場合、 ob_end_flush() を適切な回数コールするようにしてください。 複数の出力コールバック関数がアクティブの場合、 ネストした順番で逐次連続的に出力がフィルタ処理されます。

とありますので、起動ファイルでDispatchに渡す前にob_startしてしまいましょう。
[php]
ob_start(“ob_gzhandler”);
Zend_Controller_Front::run(‘/path/to/app/controllers’);
[/php]

無事、圧縮されましたでしょうか。