smarty icon indicating copy to clipboard operation
smarty copied to clipboard

Smarty creates cache for includes with cache_id even when it's null and cache disabled

Open Razunter opened this issue 1 year ago • 19 comments

I have Smarty cache globally disabled, cache_lifetime set to 0, but include with any cache_id still creates cache files.

{include file='example.tpl' cache_id=NULL}

Any way to disable this behavior?


v5.4.1

Razunter avatar Sep 02 '24 15:09 Razunter

Hello,

  1. To disable caching for a specific code snippet or include file, wrap the include tag or code snippet with {nocache}{/nocache} and remove the cache_id attribute from the include tag.

Example: {nocache}{include file='example.tpl'}{/nocache}

devthisath avatar Sep 03 '24 10:09 devthisath

But I need to cache it when cache is enabled or cache_id is not null.

Razunter avatar Sep 03 '24 10:09 Razunter

Then you should use a statement behaviour {if} {/else} like {if $cache_enabled} {include file='example.tpl'} {else} {nocache} {include file='example.tpl'} {/nocache} {/if}

devthisath avatar Sep 03 '24 10:09 devthisath

I thought about it, but it's too verbose. The main problem is with cache_id - if set to NULL in PHP, Smarty stops caching, if set to NULL in the Smarty template, it still caches. And it shouldn't ignore the fact that caching is actually disabled.

Razunter avatar Sep 03 '24 10:09 Razunter

It would be better if you provide the proper code snippet that addresses your issue, so I can help you more effectively. We can also optimize the code by understanding its functionality once you provide it

devthisath avatar Sep 03 '24 11:09 devthisath

  1. Normally, cache is enabled globally and Smarty is called with Smarty->fetch($template, $cache_id)
  2. cache_id is generated with special function:
public function generateCacheKey(string|null $prefix = null, array|null $options = null): string|null
    {
        if (!$this->design->cachingEnabled) {
            return null;
        }

        $defaultOptions = [
            'useHost' => true,
            'usePath' => true,
            'useQuery' => true,
            'cachedQueryParams' => ['page'],
            'ignoredQueryParams' => []
        ];
        
        ...
  1. Same function is used in .tpl for parts that require different caching policy: {include file='components/page--catalog/footer/brands-and-categories.tpl' cache_id=generateCacheKey('brands-and-categories', ['useHost' => false, 'useQuery' => false])}

Works fine usually, but in .tpl Smarty still creates cache files even when function returns null and when caching is disabled in Smarty... I think this is a bug.

UPD... Actually, ->fetch is used via custom function that has if ($cache_id === null) { $this->smarty->setCaching(0); }. That explains the difference in behavior, but doesn't solve the issue.

Razunter avatar Sep 03 '24 11:09 Razunter

Hey,

Sorry for taking so long. This could be a bug. But here is a solution for you :

  1. Edit : /smarty/smarty/src/Compile/Tag/IncludeTag.php
  2. Line 137 change from if (isset($_attr['cache_id']){ to if (isset($_attr['cache_id']) && $_attr['cache_id'] != 'null') {

devthisath avatar Sep 03 '24 12:09 devthisath

This is because assigning the cache_id seems to be set as a string and not as a null type

devthisath avatar Sep 03 '24 12:09 devthisath

Could you please let me know if it works or not?

devthisath avatar Sep 03 '24 12:09 devthisath

Huh, turns out, it's not that simple... Tried printing $_attr['cache_id'], it is not processed at this point: $_smarty_tpl->getSmarty()->getModifierCallback('generateCacheKey')('head-analytics--google',array('usePath'=>false,'useQuery'=>false))

Razunter avatar Sep 03 '24 12:09 Razunter

Verbose syntax it is, I guess...

Razunter avatar Sep 03 '24 12:09 Razunter

Huh, turns out, it's not that simple... Tried printing $_attr['cache_id'], it is not processed at this point: $_smarty_tpl->getSmarty()->getModifierCallback('generateCacheKey')('head-analytics--google',array('usePath'=>false,'useQuery'=>false))

Mmm🤔

devthisath avatar Sep 03 '24 12:09 devthisath

Well, $_smarty_tpl->getSmarty()->getModifierCallback('generateCacheKey')('head-analytics--google', array('usePath' => false, 'useQuery' => false)) is not directly related to the include tag class that I asked you to modify and is only processed if the .tpl file contains any include tags.

devthisath avatar Sep 03 '24 12:09 devthisath

I thought about it, but it's too verbose. The main problem is with cache_id - if set to NULL in PHP, Smarty stops caching, if set to NULL in the Smarty template, it still caches. And it shouldn't ignore the fact that caching is actually disabled.

Have you tried passing the value for cache_id from a template variable (populated from PHP) instead of literally using NULL in the template? NULL is not a reserved word in Smarty in the way it is in PHP. It is interpreted as a string 'NULL'.

wisskid avatar Sep 04 '24 07:09 wisskid

I thought about it, but it's too verbose. The main problem is with cache_id - if set to NULL in PHP, Smarty stops caching, if set to NULL in the Smarty template, it still caches. And it shouldn't ignore the fact that caching is actually disabled.

Have you tried passing the value for cache_id from a template variable (populated from PHP) instead of literally using NULL in the template? NULL is not a reserved word in Smarty in the way it is in PHP. It is interpreted as a string 'NULL'.

I created a structure identical to the code snippet he provided, keeping if (isset($_attr['cache_id']) && strtolower($_attr['cache_id']) != 'null') {, so cache_id works even when it's assigned the string 'NULL', and it works fine for me.

devthisath avatar Sep 04 '24 09:09 devthisath

I created a structure identical to the code snippet he provided, keeping if (isset($_attr['cache_id']) && strtolower($_attr['cache_id']) != 'null') {, so cache_id works even when it's assigned the string 'NULL', and it works fine for me.

With function call?

Razunter avatar Sep 04 '24 09:09 Razunter

I created a structure identical to the code snippet he provided, keeping if (isset($_attr['cache_id']) && strtolower($_attr['cache_id']) != 'null') {, so cache_id works even when it's assigned the string 'NULL', and it works fine for me.

With function call?

No, $_smarty_tpl->getSmarty()->getModifierCallback(...) doesn't affect the cache_id value. What if you consider assigning a value in PHP and setting it as the cache_id instead of calling the function?

devthisath avatar Sep 04 '24 10:09 devthisath

No, $_smarty_tpl->getSmarty()->getModifierCallback(...) doesn't affect the cache_id value. What if you consider assigning a value in PHP and setting it as the cache_id instead of calling the function?

But then cache_id will be $_smarty_tpl->getValue('cache_id'), not calculated value. That's not really relevant. The more important issue is that with any cache_id present, Smarty will create a cache, even though caching is disabled by default in init.

Razunter avatar Sep 04 '24 10:09 Razunter

Then we should try adding another statement to check whether the cache is disabled by default in the initialization or not, and proceed accordingly.

devthisath avatar Sep 04 '24 10:09 devthisath