CakePHP 1.3のキャッシュやスラッグ(Inflector::slug)に要注意
CakePHPの最新版1.3を導入してみたところ、キャッシュがおかしな挙動をすることに気づきました。CakePHP 1.3を利用する場合には、Cacheヘルパーや(Cacheヘルパーなどが利用する)Inflector::slug()に注意が必要なようです。
事例
例えば、以下のような場面を想定してみます。
- ビューから「element」というエレメントを複数箇所で呼び出す(あるいは、複数のビューから同じエレメントを呼び出す)。
- 一方では「$vars1」を渡し、もう一方では「$vars2」を渡す(呼び出し箇所ごとに異なる値を渡す)。
- エレメントの出力をそれぞれ別々にキャッシュする。
このような場合、エレメントの呼び出し時に、キャッシュのキーとしてそれぞれにユニークな文字列を指定することになっています。
<?php e($this->element('element', array('cache' => array('time' => '+1 hour', 'key' => 'element_1', 'vars' => $vars1))); ?>
<?php e($this->element('element', array('cache' => array('time' => '+1 hour', 'key' => 'element_2', 'vars' => $vars2))); ?>
ところが、CakePHP1.3では、どちらのエレメントも同じ内容が出力されてしまいます。
原因
キャッシュファイルのファイル名を調べたところ、キャッシュファイル名がどちらも「element_l_m_t」と同じものになっていました。さらに調べてみると、文字列からいわゆるスラッグを生成するInflector::slug()が正しく機能していないことがわかりました。
本来、Inflector::slug()に「CakePHP 1.3」という文字列を与えた場合、「CakePHP_1_3」のように英数字と区切り文字のみで構成された文字列が返されます。ところが、CakePHP 1.3ではスラッグが正しく返されなかったり、空文字が返されてしまいます。
同様の現象が#582 function slug in inflector.php - CakePHPで報告されていました。これによると、正規表現ライブラリであるPCREライブラリをコンパイルする際に、「--enable-utf8」オプションが指定されている場合で「--enable-unicode-properties」オプションが指定されていない場合に発生するようです。
CakePHP 1.3からは、マルチバイト文字を含む文字列からスラッグを生成できるようになりましたが、この変更とPCREライブラリの問題が原因で、環境によっては正しくスラッグが生成できないようです。
解決策
PCREライブラリをコンパイルする際に、「--enable-utf8」オプションと「--enable-unicode-properties」オプションの両方を指定すれば解決するようです。
今回は、Inflector::slug()をCakePHP 1.2のものに置き換えることで解決しました(CakePHP 1.2.7のInflector::slug()はgithubなどから参照できます)。
Inflector::slug()を1.2.7のものに置き換えた場合、生成されるスラッグからはマルチバイト文字が削除されてしまいますが、CakePHPを1.2から利用してきたのであれば手軽な解決策かと思います。
一見正しく動作しているようでも問題が発生する可能性もあるので、CakePHP 1.3を利用する場合には、<?php echo Inflector::slug('CakePHP 1.3'); ?>
の出力内容を確認しておいたほうがよいでしょう。
コメント (1)
トラックバック (3)
[…] CakePHP 1.3のキャッシュやスラッグ(Inflector::slug)に要注意 – (DxD)∞ […]
[…] 原因の関数が分かったので早速検索。 CakePHP 1.3のキャッシュやスラッグ(Inflector::slug)に要注意をみつけた。 このへんには文字列にアンダーバーとかついて変みたいなことも書いてある。 […]
CakePHP1.3のelementキャッシュがうまくいかなかった件
いつもどおり、開発しているWebサイトで、
同じようなレイアウトを何個も出力する際に、
CakePHPでこんな感じのヘルパーを作成して、
ユニーク
私もちょうど、同様の現象で困っておりました。まさかInflector::slug()とは・・ 有益な情報ありがとうございました。