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)∞が見つかり、そこで解決方法の糸口を見つけることが出来ました。


参考サイトでは、

  1. PCREライブラリの設定を変えるか、
  2. 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);
}


既に報告されているバグなので、本線で修正が入るかもしれません。