Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

We've moved the forum!

Please use forum.silverstripe.org for any new questions (announcement).
The forum archive will stick around, but will be read only.

You can also use our Slack channel or StackOverflow to ask for help.
Check out our community overview for more options to contribute.

General Questions /

General questions about getting started with SilverStripe that don't fit in any of the categories above.

Moderators: martimiz, Sean, Ed, biapar, Willr, Ingo, swaiba

Partial Caching - Understanding the Concepts


Go to End


19 Posts   8041 Views

Avatar
edk

Community Member, 39 Posts

25 June 2010 at 3:16pm

Edited: 25/06/2010 3:17pm

This page [url=http://doc.silverstripe.org/partial-caching?s[]=partial&s[]=caching]http://doc.silverstripe.org/partial-caching?s[]=partial&s[]=caching does a great job at trying to explain this concept. I am looking for some more concrete example, especially as it woudl relate to a method called in a Page Class and used in a control block.

I would appreciate anyone taking a stab a dumbing this down for me, on more level. :-)

Some Sample Code:
Let's say we have a method in the Page Class that is getting the latest blog posts...

         function LatestBlogPosts($num=5) {
 		$blogs = DataObject::get_one("BlogHolder");
  		return ($blogs) ? DataObject::get("BlogEntry", "ParentID = $blogs->ID", "Date DESC", "", $num) : false;
	}

and then without any caching I would call this in a page template like so...

        <% if LatestBlogPosts %>
	    <ul>
	     <% control LatestBlogPosts %>
	        <li><a href="$Link" title="Read more on &quot;{$Title}&quot;">$Title</a></li>
	      <% end_control %>
	    </ul>
	<% end_if %>

Can someone tell me what the cache call would be for this to check if there was an updated post and then get the new result if there was.

is this even close?

    <% cached 'LatestBlogPosts', Aggregate(BlogEntry).Max(LastEdited) %>

Thanks in advance. I think this feature looks awesome. Another hidden gem in SIlverstripe.

- Ed

Avatar
Willr

Forum Moderator, 5523 Posts

26 June 2010 at 3:41pm

Edited: 26/06/2010 3:42pm

Yes, that is in fact one of the examples on the page

<% cached 'navigation', Aggregate(Page).Max(LastEdited) %>

Its in the format

<% cached 'uniquename', function %>

Where unique name is a reference for that cache block and function to return a string to build the unique cache store. For example latest blog...

<% cached 'blogposts', Aggregate(BlogEntry).Max(LastEdited) %>

<% end_cached %>

If you edited the blog entry at 9am your cache key would be like "blogposts-0900". If you visited that page again and you hadn't edited the page and came back to the site at 2pm then the cache key still would be blogposts-0900, that key exists in the store so it would pull from the cached version. So the function (or functions) are used to decide whether to update that block. You can pass an unlimited amount of functions to a cached control.

Your probably asking yourself "Well hang on then it still needs to do a database query for the last edited date, so the 'cache' still hits that database!!" You are correct but doing a DB::query() for a single value is a heck of a lot faster than a DataObject::get().

Documentation is really quite good on this http://doc.silverstripe.org/partial-caching

* note my date example is simplified.

Avatar
edk

Community Member, 39 Posts

30 June 2010 at 8:01am

Thanks for the extended explanation. The 'uniquename' declaration was what a little ambiguous in the guide in the site. I would even suggest added this part of the explanation in the guide. Your simple explanation here, added that missing part that I was looking for to understand completely how the partial caching works.

Thanks again Willr.

Avatar
edk

Community Member, 39 Posts

1 July 2010 at 4:20pm

Okay, so I am struggling with how to achieve the following...I have a control Structure for a navigation item that uses ChildrenOf...

<% if ChildrenOf(portfolio) %> 
    <ul>
         <% control ChildrenOf(portfolio) %>
	     <li><a class="$LinkingMode" href="$Link" title="Go to the {$Title} page">$MenuTitle</a></li>
	<% end_control %>
    </ul>
<% end_if %>

I have tried to use the ChildrenOf(portfolio) in the Aggregrate call but am getting errors

<% cached 'navigation_portfolio', Aggregate(ChildrenOf(portfolio)).Max(LastEdited) %>

I am probably going about this the wrong way. Any help would be appreciated.

- Ed

Avatar
Willr

Forum Moderator, 5523 Posts

1 July 2010 at 4:36pm

AFAIK Aggregate is a specific ClassName (eg SiteTree) not a function.

Avatar
Dramew

Community Member, 9 Posts

29 July 2010 at 2:19am

I really do not understand one thing in partial caching. To what is "cached part of website" connected to? It is said in documentation that each cache block has a unique cache key. So, for example (taken from documentation):

From a block that updates every time the Page subclass it's the template for updates
<% cached 'database', LastEdited %>

Let's assume I put that into Page.ss layout template. I have several pages on my website, who use this layout template (Page.ss).
What will be cached? Every page which uses Page.ss will have the same cached content (for example, if wrap the whole template Page.ss with the "cached")? Or it will take LastEdited for every page I open in my browser and content will be different for each page?

I hope that I explained my problem clearly. And thanks in advance!

Avatar
Willr

Forum Moderator, 5523 Posts

29 July 2010 at 11:03pm

Let's assume I put that into Page.ss layout template. I have several pages on my website, who use this layout template (Page.ss).
What will be cached? Every page which uses Page.ss will have the same cached content (for example, if wrap the whole template Page.ss with the "cached")? Or it will take LastEdited for every page I open in my browser and content will be different for each page

It will use a cache key of the last edited date for that page and if you put that on Page.ss then it will be on a per page basis. So the Last Edited date of each page. I'm 90% sure this works on a per page. Even the Aggregate functions may cache on a per page url basis but I will need to check.

Avatar
Tonyair

Community Member, 81 Posts

20 September 2010 at 3:12am

Edited: 20/09/2010 3:59am

Here's example with paginator:

class StaffPage_Controller extends Page_Controller {
	private $start;
	public function init() {
		parent::init();
		if(!isset($_GET['start']) || !is_numeric($_GET['start']) || (int)$_GET['start'] < 1) $_GET['start'] = 0;
		$this->start = (int)$_GET['start'];
	}

	public function StaffItems() {
		$doSet = DataObject::get(
			$callerClass = "StaffItem",
			$filter = "`StaffPageID` = '".$this->ID."'",
			$sort = "SortOrder",
			$join = "",
			$limit = "{$this->start},10"
		);
		return $doSet ? $doSet : false;
	}
	
	public function CacheKey() {
	    return implode('_', array(
    	    'StaffItems',
        	$this->ID,
	        $this->RelationshipAggregate('StaffItems')->Max('LastEdited'),
			$this->start
    	));
	}
}

StaffPage.ss
<% cached CacheKey %>

And the question: if i add <% cached LastEdited %> $Layout <% end_cached %> to Page.ss why StaffPage isn't update when i change StaffItem?

Go to Top