Jump to content

Small performance question


mr-fan
 Share

Recommended Posts

Just a small question on selector performance and room for improvments...

i use a little function that renders me all archiv links like /2015/   /2014/ and so on...all years that are _used_ in the article system...

This cause a selector without limit...and there will be many posts/articles in future now there are about 40 - it will scale up to 100 fast and more will follow...so here is the question about caching the find query or using other code...?

Basic information i work with a URL segment approach that show me /year/ and /category/ overview pages.

(Category or not the problem while here limit works and pagination is used)

Code from the year archive:

function renderArchive() {
	//check for url segments
	$seg1 = wire('sanitizer')->pageName(wire('input')->urlSegment1);
	//get all posts to check for years
	$posts = wire('pages')->find("template=artikel");
	//get homepage url for the links
	$homepageurl = wire('pages')->get('/')->httpUrl;
	//get article root page for links
	$artikel_root = wire('pages')->get(1068);
	//get year list
	$out = '<h4 class="subtitle">Archiv</h4>';
	$out .= '<div class="listbox1"><ul>';
	//Setup for the year sidemenu
	$years = array();
	// find the array of years for all events
	foreach ($posts as $y) {
		$dateY = $y->getUnformatted("publish_from");
		$years[]= date('Y',(int)$dateY);
	}
	$years = array_unique($years);
	arsort($years);
	$year = "";
	foreach($years as $key => $year) {
		// Output the year
		$class = $year === $seg1 ? " active" : '';
		$out .= '<li class="'.$class.'"><a href="'.$homepageurl.$artikel_root->name.'/'.$year.'/">'.$year.'</a></li>';
	}
	//close list
	$out .= '</ul></div>';
	return $out;
}

Could this done better - or cached somehow (I'm not really experienced with caching such things)

regards mr-fan

Link to comment
Share on other sites

Might be faster to just do a simple for loop from 2010 (depending on how far back your archive goes) to 2100 (or, say, the current year) and just check the page count for each year. That way you’re not loading any pages at all, and you don’t have to do any date magic. It would also probably result in shorter code.

for ($i = 2010; $i <= date('Y'); $i++) {
    $c = $pages->count("template=artikel, publish_from>={$i}, publish_from<" . ($i+1));
    if ($c > 0) $out += "<a href='/{$i}'>{$i}</a>";
}

Maybe even throw limit=1 into the selector, or display the count for free.

  • Like 1
Link to comment
Share on other sites

I'd additionally "paginate" the archive to something reasonable. E.g. only the first (or most interesting) 30, 50 or something articles per year and, if necessary, a link to show all articles of a single year (paginated as well). This will scale even as archive. 

  • Like 1
Link to comment
Share on other sites

Just a update to present the whole function - may useful for others.

No more ->find just some ->count 's are running in a preset scope of years...much better now.

Thank you very much Jan for your example!

It renders a archive navigation like

  2015 (12)

  2014 (4)

  2013 (10)

  ....

i changed Jan's example to sort the years in descending order. It's great a great example about the for loop (most ignored by me) ;)

function renderArchive() {
	//check for url segments (using URL segments for the years like /2000/ 
	$seg1 = wire('sanitizer')->pageName(wire('input')->urlSegment1);
	//get homepage url for the links to build them absolut since relative wont work with URL segments
	$homepageurl = wire('pages')->get('/')->httpUrl;
	//get article root page for links
	$artikel_root = wire('pages')->get(1068);
	//get year list
	$out = '<h4 class="subtitle">Archiv</h4>';
	$out .= '<div class="listbox1"><ul>';
	//loop trow years and count pages
	for ($i = date('Y'); $i >= 2007; $i--) {
		//get start and enddate
		$start = "$i-01-01";
		$end = "$i-12-31";
		//count pages from the year
		$c = wire('pages')->count("template=artikel, publish_from>=$start, publish_from<=$end");
		if ($c > 0) {
			//check if year was active
			$class = $i === $seg1 ? " active" : '';
			//output listitem
			$out .= '<li class="'.$class.'"><a href="'.$homepageurl.$artikel_root->name.'/'.$i.'/">'.$i.' ('.$c.')</a></li>';
		}
	}
	//close list
	$out .= '</ul></div>';
	return $out;
}

Best regards mr-fan

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...