How to test if latte cache is valid?

Notice: This thread is very old.
Čamo
Member | 726
+
0
-

Hello,
Today I wrote some caching for my menu component which looks like:

{cache 'menu_key', tags => [ 'menu_tag' ] }

{block menu}
	<ul>
		{foreach $section as $item}
		<li>
			{if $item->url_params}
				<a href="{plink $item->url (expand)explode(' ', $item->url_params)}">{$item->title}</a>
			{else}
				<a href="{plink $item->url}">{$item->title}</a>
			{/if}

			{ifset $menuArr[$item->id] }
				{include menu, section => $menuArr[$item->id]} {* RECURSION *}
			{/ifset}
		</li>
		{/foreach}
	</ul>
{/block}

{/cache}

Everything works fine. But I would like to skip some code in component render method which loads data from database. I tried this:

if( ! $this->cache->load( 'menu_key' ) )
{
	$arr = $this->categories->getArray();
}

but it does not work of course.

Question is how to check if template cache is not null? Probably the problem is in cache namespaces but how to solve it?

Thanks.

Last edited by Čamo (2016-02-06 22:52)

petr.jirous
Member | 128
+
0
-

Why do you need that?

Čamo
Member | 726
+
0
-

Why not? Aren't generating links and db queries expensive?

Last edited by Čamo (2016-02-07 00:11)

petr.jirous
Member | 128
+
0
-

Čamo wrote:

Why not? Aren't generating links and db queries expensive?

Of course, they are. But what DB layer do you use? If you have your db queries lazy and your view is cached, it does not execute the query even not generate links.

Čamo
Member | 726
+
0
-

Hmm quite interesting idea. But my solution is based on one query which generates array so does not use lazy loading.
There is no way to find out if key from {cache} macro is valid?

petr.jirous
Member | 128
+
0
-

I don't think so. It's conceptually wrong idea. Why don't you cache the query result then?

Čamo
Member | 726
+
0
-

Cause it throws me an exception “You cannot serialize or unserialize PDO instances”.

But I don't want to instantiate all that rows. I want to skip that. As I see one query can't be the best idea.

Last edited by Čamo (2016-02-07 01:08)

petr.jirous
Member | 128
+
0
-

Give me the piece of code I can look at. You did something wrong.

Čamo
Member | 726
+
0
-

But which part?
This is what throws me an exception.

$this->cache->save( 'categories', $arr = $this->categories->getArray() );

This is method which generates $arr

/**
 * @return array
 * @desc returns array of arrays
 * like $a[0][5] $a[0][6] where [0] is parent_id which is array of his children
 */
public function getArray($admin = false)
{
    $selection = $this->findAll($admin);
    $arr = array();
    while($row = $selection->fetch())
    {
        $arr[$row['parent_id']][$row['id']] = $row;
    }
    return $arr;
}
Čamo
Member | 726
+
0
-

Now I have this

if( $arr = $this->cache->load( 'categories_key' ) )
{
	$this->cache->save( 'categories_key',  $this->categories->getArray(), [ Cache::TAGS => [ 'categories_tag' ] ] );
	$arr = $this->cache->load( 'categories_key' );
}

but latte throws me “Invalid argument passed to foreach; array or Traversable expected, NULL given.”

Last edited by Čamo (2016-02-07 01:41)

petr.jirous
Member | 128
+
0
-

Čamo wrote:

Now I have this

if( $arr = $this->cache->load( 'categories_key' ) )
{
	$this->cache->save( 'categories_key',  $this->categories->getArray(), [ Cache::TAGS => [ 'categories_tag' ] ] );
	$arr = $this->cache->load( 'categories_array' );
}

but latte throws me “Invalid argument passed to foreach; array or Traversable expected, NULL given.”

You should cache the result if it was not successful to load it. So if (!($arr = $this->cache->load('categories_key')))

Čamo
Member | 726
+
0
-

Of course 1:30AM … Now there is “You cannot serialize or unserialize PDO instances” exception again.

It creates folder _categories but it is empty.

Last edited by Čamo (2016-02-07 01:49)

petr.jirous
Member | 128
+
0
-

Because you're trying to cache ActiveRow objects. When you do $selection->fetch() it returns IRow (most probably ActiveRow, which couldn't be serialized). Think about using Selection::fetchAssoc() or ActiveRow::toArray()

Čamo
Member | 726
+
0
-

Yes it could work. But I have done it this way:

if( ! $this->cache->load( 'is_in_cache' ) )
{
	$arr = $this->categories->getArray();
	$this->cache->save( 'is_in_cache', true, [ Cache::TAGS => [ 'is_in_cache' ] ] );
}

Last edited by Čamo (2016-02-07 02:15)

petr.jirous
Member | 128
+
0
-

Oh, I really don't understand this. You cache indicator if the query result was in the cache? It's fundamental misunderstanding how cache works.

Čamo
Member | 726
+
0
-

Can you explain what you mean? what it means “It's fundamental misunderstanding”?
What is wrong if I want to avoid serializing and unserializing this way?