FuelPHPのORMのメソッド利用時に、データ取得の結果が想定通りにならない時の対処法

  • 0
    いいね
  • 0
    コメント
    この記事は最終更新日から1年以上が経過しています。

    fuelphpのORMが提供するメソッドを利用していてハマりました。

    はまった内容としては
    ORMのfindメソッドを利用して指定したidが一致するレコードを取得する際、検索結果をfuelがキャッシュし、次回以降同じidのレコード検索を行った時、SQLクエリが実行されず、キャッシュしたデータが返されるということ。
    このせいでユニットテストが思うように動作してくれず、どハマりしました。

    結論

    fuelphpのORMにはデータのキャッシュ機能があるようで、テスト実行によるデータのキャッシュ履歴が、次のテストケースに影響を与えてしまっていました。

    動作確認(ORMメソッド利用)

    例えば次の処理を実行させます。

    $user = Model_Users::find(1);
    $user->name = 'name';
    $user->save();
    $user = Model_Users::find(1);
    

    この処理を実行させた時にMySQLでは実際にどのようなクエリが実行されているかを確認してみます。

    MySQLの実行クエリログを見る方法は
    my.cnfのgeneral_logのフラグを1にしてやればOK
    general_log_fileに指定されたファイルに実行クエリのログが吐き出されます。

    では実際の結果を確認してみましょう。

    Connect root@localhost on fuel_dev
    Query   SET NAMES 'utf8'
    Query   SELECT `t0`.`id` AS `t0_c0`, `t0`.`name` AS `t0_c1` FROM `users` AS `t0` WHERE `t0`.`id` = 1 LIMIT 1
    Query   UPDATE `users` SET `name` = 'hoge' WHERE `id` = '1'
    Quit
    

    ログを見てみると最後のfind文がクエリとして実行されていないことがわかります。

    動作確認(クエリビルダ利用)

    次にORMのメソッドではなく、クエリビルダを利用して実行してみます。

    $user = Model_Users::find(1);
    $user->name = 'name';
    $user->save();
    DB::select()->from('users')->where('id', '=', 1)->execute();
    

    この場合のクエリ実行結果は以下の通りです。

    Connect root@localhost on fuel_dev
    Query   SET NAMES 'utf8'
    Query   SELECT `t0`.`id` AS `t0_c0`, `t0`.`name` AS `t0_c1` FROM `users` AS `t0` WHERE `t0`.`id` = 1 LIMIT 1
    Query   UPDATE `users` SET `name` = 'hoge' WHERE `id` = '1'
    Query   SELECT * FROM `users` WHERE `id` = 1
    Quit
    

    クエリビルダを利用して実行すると、クエリがちゃんと実行されるようです。
    よってクエリビルダを利用することで、キャッシュを使わず、DBにアクセスしデータを取得してくるようにできます。

    まとめ

    fuelphpのORMにはデータのキャッシュ機能があるので気を付けましょう。