Love Fuel?    Donate

FuelPHP Forums

Ask your question about FuelPHP in the appropriate forum, or help others by answering their questions.
How set default value for from_cache ?
  • Hi. I have a project with an old FuelPHP version (v 1.5). After updating it to 1.8 version I got a lot of errors in business logic associated with ORM object cache. 
    I found only one way to change a default value from_cache to "True".

    \Orm\Query::$from_cache = true 

    Is it a right way?
  • What errors exactly if I may ask?

    The ORM always had an object cache, which is there to make sure that if you select the same record twice, the same model object will be returned. This is to make sure a model object for a particular record only exists once, and it's state is consistent with what is in the database.

    1.8+ only introduces the capability to switch this cache off, which you would want to do if for example you want to do batch operations. You wouldn't want to store 1000's of objects in memory. This is controlled by the flag you mention, and this is why the default is TRUE, so it's function is backwards compatible.

    You can switch the cache off in a query by using ->from_cache(false)-> , or as part of the options array in a Model::find() call. 

    You can not overload the Query class to change the default, and you can also not access the propery from the outside, as it is protected.
  • For example, If in one part of code is used a code like this
    $product = \Model\Orm\Product::find('first', [
    'select' => [
    'description'
    ],
    'where' => [
    ['sku', '=', 'PRODUCT1']
    ]
    ]);
    and in another part is executed the same code, only without select option
    $product = \Model\Orm\Product::find('first', [
    'where' => [
    ['sku', '=', 'PRODUCT1']
    ]
    ]);
    I got object from cache only with two items (id, description).
    This is an old code and has more then 900 calling of 'find' method and more then 400 calling of query' method. And therefore it will be hard to add a function call ->from_cache (false) to all the places where it's needed
  • Understand. 

    I think the only way to disable it globally is to edit query.php, and change the default from true to false.

    More work is to extend \Orm\Model in your app, overload the methods that call the Query class, and overload them to inject the cache flag. For example:

    public static function query($options = array())
    {
    $options['from_cache'] = false;
    return parent::query($options);
    }

    There are 3 more, which are more complex I'm afraid. And you'll need to change all your models to extend your base Model, instead of \Orm\Model. So not entirely easy either.

    Looking at the code, what might also work:

    Extend \Orm\Model in your app, and overload the constructor. The last parameter of the constructor is $cache, which is true if the object need to be cached. So you to do this:

    class Model_Base extends \Orm\Model
    {
        public function __construct($data = array(), $new = true, $view = null, $cache = true)
        {
            parent::__construct($data, $new, $view, false); 
        }
    }

    and then have all your models extend this instead of \Orm\Model. This should also work.
  • You might want to switch the ORM to 1.9/develop:


    Probably a quicker fix... ;-)
  • HarroHarro
    Accepted Answer
  • Thank you, Harro. I think that having an ability to change this param in config is the best decision =)
  • I can't disable caching globally, because it creates a new problem with searching object with many relations described in another post.

    I think this code
    if ( ! isset($obj->{$f}))
    {
    $obj->{$f} = $row[$s[1]];
    }
    in file fuel/packages/orm/classes/query.php:1446 works incorrectly. 
    In the code we have a comment

    // add fields not present in the already cached version

    But, if we found the object once and fill properties then this condition always will be false 
     if ( ! isset($obj->{$f}))
    because the model has properties
    fuel/packages/orm/classes/model.php:1039
    public function __isset($property)
    {
    if (array_key_exists($property, static::properties()))
    {
    return true;
    } ...

  • Hmm... You might have a point. I'll have a look.
  • Thank you. It helps for me.
  • Cool, thanks for the feedback.
  • since i upgraded my fuel project from 1.7 to 1.8.2 and ORM to 1.9/develop:

    i have a problem caching model below:
    ===========================================
    // update "last_login" and "login_hash"
    \DB::update(\Config::get('myauth.table_name'))
    ->set(array('last_login' => $last_login, 'login_hash' => $login_hash))
    ->where('username', '=', $this->user['username'])
    ->execute(\Config::get('myauth.db_connection'));

    // this wont give me new "last_login" and "login_hash"
    $thisIsCached1 = DB::select()->from('m_users')
            ->where('username', $this->user['username'])->execute();

    // this wont give me new "last_login" and "login_hash" too
    $thisIsCached2 = MUsers::find(13);
    ===========================================

    if i want to get new "last_login" and "login_hash" i need to set 
    orm.php#caching to false

    is it safe to do that ? will it broke my project ?

  • ORM cache has nothing to do with DB operations?

    So if

    $thisIsCached2 = MUsers::find(13);

    doesn't give you a full record, you've done an ORM query on this record before with a select (which as you see is a bad thing when using the ORM).

    In general, because of the caching, it is not a good idea to mix ORM and DB operations. Why not use the Auth package for those updates, or an ORM model update?

    p.s. query cache can be bypassed per query, so this should work too:

    $thisIsCached2 = MUsers::query()->where('id', '=', 13)->from_cache(false)->get_one();

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion