最近Symfonyのプラグインの中で個人的に気になっているのがsfSuperCacheです。Symfonyには元々cacheのメカニズムが組み込まれていますが、sfSuperCache別のアプローチでキャッシュします。Symfonyに組み込まれたcacheの仕組みは、myproject/cache等のディレクトリにアクションやコンポネントの実行結果を保存しておき、次回のリクエストの時アクションやビューの処理を飛ばす事で実行速度を上げています。sfSuperCacheでは、キャッシュの結果をmyproject/cacheではなくmyproject/web/cache以下に保存し、Apacheのmod_rewriteを利用してPHPを仲介せず直接静的なコンテンツを呼びにいきます。つまり、sfSuperCacheはSymfonyの巨大なフロントコントローラを介さない事で一桁違う処理スピードを実現するのです。
ちょうどディノのホームページをウェブプロダクションに制作依頼していますが、このウェブをSymfonyベースのCMS(コンテンツ管理システム)にしようと思っています。企業のホームページは静的な部分が多いのでsfSuperCacheは是非多用したいプラグインです。
本家tracにある文章に注釈を加えながら説明してきます。(というか、1.0.0-betaではこの通りやったのではさっぱり動きません)
インストール
プロジェクトディレクトリにてプラグインをインストールします。sfSuperCacheに限った事ではないのですが、1.0.0-betaでプラグインをインストールする時に、
symfony plugin-install http://plugins.symfony-project.com/sfSuperCachePlugin
本家tracでは上のコマンドでプラグインをインストールしていますが、私のMacOSXではうまく行きません。sudoとするとなぜかうまく行きます。
sudo symfony plugin-install http://plugins.symfony-project.com/sfSuperCachePlugin
web/cacheディレクトリの作成
次にキャッシュを保存するweb/cacheディレクトリを作成します。ついでに、Subversionの管理から除外するためにsvn-addignoreをしておきます。
mkdir web/cache chmod 777 web/cache svn-addignore web/cache
余談になりますが、私はSubversionからチェックアウトした後、実行環境をセットアップするスクリプトをmyproject/bootstrapというファイル名でおいています。bootstrapにもweb/cacheの作成作業を追加しておきます。bootstrapファイルの中身は以下のようになっています。
#!/usr/bin/env bash mkdir -p cache log web/uploads/assets web/cache symfony fix-perms chmod 777 web/cache
filters.ymlに追加する
以下のようにfilters.ymlに追加します。追加というは嘘です(ごめんなさい)上に足してください。
supercache:
class: sfSuperCacheFilter
param:
cache_dir: cache
rendering: ~
web_debug: ~
security: ~
cache: ~
common: ~
flash: ~
execution: ~sfSuperCacheは、PostFilterですので下に足したのでは他のフィルターの実行結果が反映されません。SymfonyではcommonフィルタでStyleSheetが追加されるのですが、filters.ymlの最下部にsfSuperCacheを記述するとStyleSheetが適用され無い状態でキャッシュされてしまいます。
.htaccessの修正
RewriteRule ^$ index.html [QSA] RewriteRule ^([^.]+)$ $1.html [QSA]
の部分を以下のように修正します。
# if the request starts with /cache
RewriteCond %{REQUEST_URI} ^/cache
# and it's not the user that requested this in his browser
RewriteCond %{THE_REQUEST} !/cache/
# go
RewriteRule .* - [L]
# check the page in the "super" cache
RewriteRule ^$ index.html
RewriteRule ^(.+)/$ $1/index.html
RewriteRule ^(.*)$ cache/%{HTTP_HOST}/$1prod環境のフロントコントローラを作成
sfSuperCacheには以下のような発動条件があります。
- デバッグモードが無効であること
- レイアウトを含んだキャッシュ 有効であること
- GET/POSTのパラメータないこと
- no_script_name であること
- HTTPのレスポンスが成功(200)であること
つまり、prod環境にしろということですのでprod環境のcontrollerをつくります。init-controllerについては以前のエントリに説明がありますので参考にしてください。
symfony init-controller frontend prod index false
cacheを有効にする
発動条件を合わせるためmyproject/apps/frontend/config/cache.ymlを以下のように変えます。
default: enabled: on with_layout: true lifetime: 86400
myproject/apps/frontend/config/settings.ymlも以下のように変更します。
prod: .settings: no_script_name: on cache: on suffix: .html
clear-cache
フロントコントローラと設定ファイルを替えたのでキャッシュをクリアします。
symfony ccお疲れさまでした
ここまでの作業でsfSuperCacheが動くはずですのでブラウザから試してみます。http://localhost/ をリクエストしてみます。myprojecct/web/cache/localhost/index.htmlが生成されていればとりあえず成功です。
次にもう一回http://localhost/にアクセスしてください。同じ画面が出ましたか?これでは本当に動いているか不安ですね。ちゃんと動いているか確かめる為に思い切ってフロントコントローラを叩き消してしまいましょう。
rm web/index.php
この状態で動けばきちんと動いていると信じられますね。
制限事項と補足説明
sfSuperCacheで生成されたキャッシュはsymfon ccコマンドではクリアされません。手動でweb/cacheを消して上で紹介したbootstrapで再生成するといいでしょう。また、キャッシュはWebサーバからは完全に静的なファイルとしてあつかわれるのでContent-Typeを決定する上で拡張子(.html)が必ず必要です。
sfSuperCacheは非常に簡単な仕組みですがうまく適用できれば効果は絶大です。機会があったら是非どうぞ。

