読者です 読者をやめる 読者になる 読者になる

【CakePHP】afterFind時にUndefined indexで苦しんだ話

CakePHPでfindした値をリフォーマットして出力したかったため、CakeのafterFindを利用したんだけれども、Viewに謎のエラーが発生して結構困ったためメモ。

自分の環境では、ComponentのPagenatorを利用したfind時($this->paginate()的なやつ)のみしかエラーの発生は確認していないけど、通常のfindでも恐らく発生するのではないかと思う。

ソースコードのafterFind部分抜粋。
ほぼ公式のドキュメントのコピペです。

<?php
//find後のデータ整形
public function afterFind($results, $primary = false) {
    foreach ($results as &$result) {
        $result['Test']['datetime'] = date("Y/m/d H:i:s", strtotime($result['Test']['datetime']));
    }
    return $results;
}

$result['Test']['datetime']には、'2013-04-15 19.20.39'のような日時データが格納されているとします。

Viewに表示されるエラーメッセージはこんな感じ。

Notice (8): Undefined index: 【index名】 [APP/Model/【モデル名】.php, line **]

うーむ、何が悪いんだろうとdebugメソッドを使って$resultsの値を調べてみたところ、find結果のデータの他に、取得データ数の格納がされている配列も同時に送られていることが分かりました。
恐らく、配列のindexが存在しない部分にアクセスしようとしていたため、エラーが出ていたんだと思われます。エラーメッセージそのままですね。
イマイチこの値がどういう形式や理由で送られているのかは不明ですが、ともかく、配列に希望するキーがない場合は値の取得および更新をしない方針で実装し直しました。

<?php
//find後のデータ整形
public function afterFind($results, $primary = false) {
    foreach ($results as &$result) {
        if (isset($result['Test']['datetime']) && is_array($result['Test']['datetime'])) {
            $result['Test']['datetime'] = date("Y/m/d H:i:s", strtotime($result['Test']['datetime']));
        }
    }
    return $results;
}

無事エラーが消えてめでたしめでたし。
エラーが出ていても、実際の値自体は適切にリフォーマットされているため、原因を見つけるのが難しかったように思います。
というか勝手に末尾にゴミつけるの止めて下さい……。


参考
コールバックメソッド — CakePHP Cookbook 2.x ドキュメント