Jump to content

detect how often a category is used


totoff
 Share

Recommended Posts

hello forum,

after a bit a humble start i think i've wrapped my head around pw a little better... that's why i'm now in the general support forum and not any longer in getting started ;-)

however, i'm working on a portfolio site for an engineering company and i've set up categories to organize the way their work is presented on the site. setting up the categories was easy and works good thanks to the tutorials in the forum here.

but now i would like to present the categories as a tag cloud and therefore need to get the number, how often each category has been chosen for a portfolio item (aka page).

this is a bit over my head in php. could someone point me in the right direction?

thanks pretty much in advance!

  • Like 1
Link to comment
Share on other sites

Something like this should work:

// First iterate through all of your categories (I'm assuming they all have a template called "category", but this could be changed to suit

$categorycount = array();
foreach ($pages->find("template=category") as $category) {
   // Now I'm assuming that the portfolio pages have a template called "portfolio" and are tagged against a category using a field called "category"
   $categorycount[$category->title] = $pages->find("template=portolio, category=$category")->getTotal();
}

And that should be it - an array of category titles and their corresponding portfolio page counts.

In the above code, we're first iterating through the categories, then finding all pages in the portfolio with a category that matches the current category we're looping through.

Note that it seems like you would have to use $category->id, but if you omit the field you are outputting for a given page object it will default to ID anyway :)

Oh, and the above is untested but should hopefully work ;)

EDIT: It's also worth noting that I had to refer to the cheatsheet as I couldn't remember the correct method to get a total - turns out it was getTotal() :rolleyes: The cheatsheet is an invaluable resource even to those of us who have been here a while so if you've not seen it yet then check it out.

  • Like 2
Link to comment
Share on other sites

In terms of efficiency, I remember Ryan mentioned that it's better to use count instead of find when you only need a total number of items.

So the the aggregating line above can be improved a little:

$categorycount[$category->title] = $pages->count("template=portolio, category=$category");

or use limit:

$categorycount[$category->title] = $pages->find("template=portolio, category=$category, limit=2")->getTotal();

But the first is way cooler.

Probably, you won't feel any difference, but it's always nice to know your code is optimized ;) and works. Even when they have a gazillion items in their portfolio...

  • Like 2
Link to comment
Share on other sites

hello,

thanks again and sorry that it took a while for me to get back to this project.

the good news is that i figured it out to make this work on my project - or almost work.

this is my php code:

<?php
// First iterate through all categories defined by pages with template kom_catlanding
$categorycount = array();
foreach ($pages->find("template=kom_catlanding") as $category) {
       // fill the array $categorycount where the key is defined by title and the value by pages with template kom_project and field project_services containing a page from $category
       $categorycount[$category->title] = $pages->count("template=kom_project, project_services=$category");
 }
?>

this returns an array with the desired key/value pairs. the bad new is, that i'm still uncertain if i fully understand what the script is doing. therefore i commented what i understood it is doing and would greatly appreciate if you could do me the favor to confirm wether i'm right or wrong.

but, even worse, i've not yet managed to link back to my category "landing pages" from my tag cloud. here is my code

<ul id="catcloud">
<?php foreach ($categorycount as $category => $number) {
 echo "<li><a href='/leistungen/kategorien/{$pages->get("title=$category")}' class='$number'>$category</a></li>";
}
?>
</ul> <!-- /catcloud -->

this code doesn't work because it returns the ID of the page instead of the title. obviously it could never work because what would be required is the name instead of the title. but if i change from title=$category to name="$category" i get error messages:

Error Exception: Illegal mix of collations (ascii_general_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation '=' (in /www/htdocs/w00cb333/KOM/wire/core/Database.php line 118)

i've gone through the documentation and the cheat sheet but am quite lost. so i need to ask for your help again. could you give me a clue?

thanks

Link to comment
Share on other sites

hi,

good news. i've found the mistake i made and have a working code now:

<?php
// First iterate through all categories defined by pages with template kom_catlanding
$categorycount = array();
foreach ($pages->find("template=kom_catlanding") as $category) {
 // fill the array $categorycount where the key is defined by title and the value by pages with template kom_project and field project_services containing a page from $category
 $categorycount[$category->name] = $pages->count("template=kom_project, project_services=$category");
}
?>
<ul id="catcloud">
<?php foreach ($categorycount as $category => $number) {
echo "<li><a href='/leistungen/kategorien/$category' class='$number'>{$pages->get("/leistungen/kategorien/$category")->title}</a></li>";
}
?>
</ul> <!-- /catcloud -->

that fills the bill :-)

only thing i'm wondering is, if the code could be optimised somehow. is there a better way for the page url than

"/leistungen/kategorien/$category"

if so, i would greatly appreciate your hints.

Link to comment
Share on other sites

Not sure this is what you need, but maybe this post of Soma can help. I didn't use this approach and not sure it makes exactly what you want, but it seems like using it or something similar you could have both category landing pages and service items right under your /leistlungen/ page using urlSegments.

You will need a code in your /leistlungen/ page's template that would check if the value of your urlSegment maps to category page (make sure it uses kom_catlanding category template). If so then serve the output for category's landing page. If then urlSegment maps to service item page then serve it. If your service item pages are direct children of /leistlungen/ then, I think, PW should serve them automatically without additional check for it on your part.

Wrote it off the top of my head. The wise part of community, please, tell me it's not gibberish :huh:

  • Like 1
Link to comment
Share on other sites

Using your existing example, you could do it this way, which is a little simpler and less code. Basically you'd just add your own 'totalPages' temporary variable to each category… and use that in your output. That way you don't have to retrieve those categories any more than once (it would execute faster too).

$categories = $pages->find("template=kom_catlanding"); 
foreach($categories as $category) {
 // populate your own made-up variable: totalPages
 $category->totalPages = $pages->count("template=kom_project, project_services=$category"); 
}

echo "<ul id='catcloud'>";
foreach($categories as $category) {
 echo "<li><a href='$category->url' class='$category->totalPages'>$category->title</a></li>
}
echo "</ul>";

If you wanted to sort them by count or something, you could do this:

$categories->sort('-totalPages'); // sort most to least
  • Like 3
Link to comment
Share on other sites

thank you very much ryan for joining this thread and contributing code. it works out-of-the-box like a charm! this is indeed, as far as my understanding reaches, a more elegant solution because of it's simplicity.

i make progress in php while working with processwire and it means fun for me. i know, this is not the php-forum :rolleyes: but may i nevertheless ask why we are able to use the arrow operator here?

$category->totalPages

from what i've read it is used to access methods and properties of a class, but do we have defined a class here (maybe because we work with the $pages object)? this confuses me a little.

thanks again for taking time to support your user. this is much appreciated.

Link to comment
Share on other sites

$category in this code is a Page object (of Page class) so you can add and populate a property on the fly to the objects and use that on runtime. Like a virtual field that isn't saved to page.

  • 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...