cphalcon icon indicating copy to clipboard operation
cphalcon copied to clipboard

model reusable - clear cache

Open zak-wojtek77 opened this issue 3 years ago • 4 comments

Discussed in https://github.com/phalcon/cphalcon/discussions/15931

Originally posted by zak-wojtek77 March 23, 2022 Hello,

if I have such code:

class Invoices extends Model
{
    public $inv_id;
    public $inv_cst_id;
    public $inv_status_flag;
    public $inv_title;
    public $inv_total;
    public $inv_created_at;

    public function initialize()
    {
        $this->hasManyToMany(
            'inv_id',
            InvoicesProducts::class,
            'ixp_inv_id',
            'ixp_prd_id',
            Products::class,
            'prd_id',
            [
                'reusable' => true,
                'alias'    => 'products',
            ]
        );

        $this->hasMany(
            'inv_id',
            InvoicesProducts::class,
            'ixp_inv_id',
            [
                'reusable' => true,
                'alias'    => 'invoicesProducts'
            ]
        );
    }
}

how can I delete cache of reusable?

zak-wojtek77 avatar Apr 08 '22 06:04 zak-wojtek77

You mean you do not want the cached result from the relation? As far as I know, there is currently no official way to do it for only one related record.

According to the code, you can always pass arguments and if there is currently no cache for the result, the results will be collected from the database rather than the cache.

// First call is not cached
$products = $model->getRelated('invoicesProducts');

// This will use the cache because it is reusable
$products = $model->getRelated('invoicesProducts');

// This will pass the cache and execute queries to the db -> fresh results
$products = $model->getRelated('invoicesProducts', ['conditions' => '1=1']); 

// If you would have to do another getRelated call, this would now be cached too. So you need to change the conditions again for a fresh result
$products = $model->getRelated('invoicesProducts', ['conditions' => '1=1']); 

Another way to do it:

        $this->hasMany(
            'inv_id',
            InvoicesProducts::class,
            'ixp_inv_id',
            [
                'reusable' => true,
                'alias'    => 'invoicesProducts'
            ]
        );
        $this->hasMany(
            'inv_id',
            InvoicesProducts::class,
            'ixp_inv_id',
            [
                'reusable' => true,
                'alias'    => 'invoicesProductsFresh'
            ]
        );

And then you would have to call ->getRelated('invoicesProductsFresh')

An approach with the Hammer would be to delete all cached related models:

$manager = $this->getDi()->get('modelsManager');
if ($manager instanceof \Phalcon\Mvc\Models\Manager) {
    $manager->clearReusableObjects();
}

$products = $model->getRelated('invoicesProducts');

noone-silent avatar Jun 10 '22 02:06 noone-silent

This code does not work:

$manager = $this->getDi()->get('modelsManager');
if ($manager instanceof \Phalcon\Mvc\Model\Manager) {
    $manager->clearReusableObjects();
}
// here still use cache
$products = $model->getRelated('invoicesProducts');

And in this code is strange behavior:

// First call is not cached
// is OK
$products = $model->getRelated('invoicesProducts');

// This will use the cache because it is reusable
// is OK
$products = $model->getRelated('invoicesProducts');

// This will not use the cache, why I don't know
// is strange
$products = $model->getRelated('invoicesProducts', ['blabla' => 'blabla']);

zak-wojtek77 avatar Jun 14 '22 08:06 zak-wojtek77

What version do you use? 3? 4? 5? This code below should work in 4.

This code does not work:

$manager = $this->getDi()->get('modelsManager');
if ($manager instanceof \Phalcon\Mvc\Model\Manager) {
    $manager->clearReusableObjects();
}
// here still use cache
$products = $model->getRelated('invoicesProducts');

Not strange. If you pass arguments to getRelated and the arguments have not been executed yet, then there is no cache. If you execute the same arguments again, it will be cached.

And in this code is strange behavior:

// First call is not cached
// is OK
$products = $model->getRelated('invoicesProducts');

// This will use the cache because it is reusable
// is OK
$products = $model->getRelated('invoicesProducts');

// This will not use the cache, why I don't know
// is strange
$products = $model->getRelated('invoicesProducts', ['blabla' => 'blabla']);

noone-silent avatar Jun 15 '22 00:06 noone-silent

I use 4.0.6 version of Phalcon.

Not strange. If you pass arguments to getRelated and the arguments have not been executed yet, then there is no cache. If you execute the same arguments again, it will be cached.

I understand but for me it is still strange, because I have to do workaround to get relationship without cache for reusable.

This code below I used to check if "clearReusableObjects()" work correctly.

$manager = \Service::modelsManager();
// it is entity "parent"
$register = \Register::findFirst("id = '23c3dfe5-8d5a-43e8-91f6-10add34d9740'");
// "register" has many "events"
// and "event" has property "info"
// print "aaa"
var_dump($register->registerEvents[0]->info);
$register->registerEvents[0]->info = 'bbb';
// print "bbb"
var_dump($register->registerEvents[0]->info);
if ($manager instanceof \Phalcon\Mvc\Model\Manager) {
    $manager->clearReusableObjects();
}
// print "bbb"
// should print "aaa" because is called "clearReusableObjects()"
var_dump($register->getRelated('registerEvents')[0]->info);
// print "aaa"
var_dump($register->getRelated('registerEvents', ['reusable' => false])[0]->info);
// print "aaa"
var_dump($register->getRelated('registerEvents', ['blabla' => 'blabla'])[0]->info);

zak-wojtek77 avatar Jun 15 '22 09:06 zak-wojtek77