Help us understand the problem. What is going on with this article?

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

More than 3 years have passed since last update.

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にはデータのキャッシュ機能があるので気を付けましょう。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away