CakePHP1.3のキャッシュ不具合
CakePHPのバージョンを1.2.5から1.3.6に上げたところ、一部のページで、指定と異なる内容が表示されたりするようになりました。
原因は、キャッシュの不具合。
ファイル名の正規化などを行うInflector::slugの不具合のため、異なるページのキャッシュが同一名で作成されてるなどしていました。
参考サイト
http://dxd8.com/archives/209/
Inflector::slugを一箇所変更することで、CakePHP ver1.2時と同じファイル名でキャッシュできるようになりました。
本線コード改修なので、バージョンアップ時要注意です。
現象
キャッシュを消すと直るので、原因はキャッシュと推測。
app/tmp/cache以下を確認したところ、ver1.2時点とはまったく異なる、
element__t_p_tu_t_l
t_d.php
と言ったようなファイル名でキャッシュされていました。
ver1.2時点では
chara_shee_characters_index.php
element_thp7gomvp09pup20q79l9dcdu7_home_left
などの様に出力されていたものです。
Cache処理をたどると、 キャッシュ生成時、キャッシュファイル名をInflector::slug('ファイルパス')で決めている過程で、変わっていました。
cake/libs/views/helpers/cache.phpの __writeFile()
function __writeFile($content, $timestamp, $useCallbacks = false) { (中略) $cache = strtolower(Inflector::slug($path)); // ここ
解決方法
CakePHP, 1.3, slugをキーワードに探すと、上記参考サイト CakePHP 1.3のキャッシュやスラッグ(Inflector::slug)に要注意 - (DxD)∞が見つかり、そこで解決方法の糸口を見つけることが出来ました。
参考サイトでは、
- PCREライブラリの設定を変えるか、
- CakePHP1.2のInflector::slug()で置換して直す、
とありましたが、
CakePHPのマイナーバージョンの違いか、CakePHP1.2.5のソースで1.3.6を置換すると、最後の preg_replaceでエラーになって、上手くいきませんでした。
参考サイト内で紹介されている記事 のコメント*1によると、
'/[^\s\p{Ll}\p{Lm}\p{Lo}\p{Lt}\p{Lu}\p{Nd}]/mu'
による正規化が原因のようです。
この部分のみ、ver1.2時点の処理に戻すと、1.2時点と同様にキャッシュファイルが出力されるようになりました。
cake/libs/inflector.php
function slug($string, $replacement = '_', $map = array()) { (中略) $merge = array( - '/[^\s\p{Ll}\p{Lm}\p{Lo}\p{Lt}\p{Lu}\p{Nd}]/mu' => ' ', +// '/[^\s\p{Ll}\p{Lm}\p{Lo}\p{Lt}\p{Lu}\p{Nd}]/mu' => ' ', + '/[^\w\s]/' => ' ', '/\\s+/' => $replacement, sprintf('/^[%s]+|[%s]+$/', $quotedReplacement, $quotedReplacement) => '', ); $map = $map + $_this->_transliteration + $merge; return preg_replace(array_keys($map), array_values($map), $string); }
既に報告されているバグなので、本線で修正が入るかもしれません。