antknight Posted March 18, 2014 Share Posted March 18, 2014 Sorry I probably wasn't clear, I would like to limit to the top 4 related pages. If I use your suggestion won't it limit before sorting? Link to comment Share on other sites More sharing options...
DaveP Posted March 18, 2014 Share Posted March 18, 2014 Aahh, now I understand. Apologies. I think array_slice might be what you need. arsort($related_id); $related_id = array_slice($related_id, 0, 4); foreach($related_id as $key => $val){ $rp = $pages->get($key); ?> <a href="<?=$rp->url;?>"><?=$rp->title;?><br><? } That should limit the array $related_id to just the first 4 entries, which I think are the highest scoring after the arsort(). Link to comment Share on other sites More sharing options...
antknight Posted March 18, 2014 Share Posted March 18, 2014 Hmmm Before I added the array_slice I got all the related pages correctly, when I add the array_slice I get 4 results but they are the current page, the home page, /processwire/ and /processwire/page/ foreach ($page->tags as $tags) { $tag = $sanitizer->selectorValue($tags->title); $related_pages = $pages->get("/products/")->find("tags.title=$tag"); foreach ($related_pages as $related) { if ($related->id != $page->id) $related_id[$related->id]++; } } arsort($related_id); foreach ($related_id as $key => $val) { $rp = $pages->get($key); foreach ($page->tags as $tags) { $tag = $sanitizer->selectorValue($tags->title); $related_pages = $pages->get("/products/")->find("tags.title=$tag"); foreach ($related_pages as $related) { if ($related->id != $page->id) $related_id[$related->id]++; } } arsort($related_id); $related_id = array_slice($related_id, 0, 4); foreach ($related_id as $key => $val) { $rp = $pages->get($key); Link to comment Share on other sites More sharing options...
Pete Posted March 18, 2014 Share Posted March 18, 2014 I think the whole example from further up the thread could just be shortened as there are errors in it. Well, unnecessary sanitisation anyway. For one, you don't have to sanitise $tags->title as $pages->find("tags=$page->tags") is sufficient as it matches page IDs stored in the tags field across the site with the tags in the current page. Here's my shortened version of your latest post: foreach ($pages->get("/products/")->children("tags=$page->tags, id!=$page->id, sort=-sort, limit=4") as $related) { // In one line I think we've done it all echo "<a href='$related->url'>$related->title</a><br />"; } It may not work because I've not tested it, but it's worth a go I assumed the products were manually sorted and you wanted the last 4 not the first 4, hence the -sort, but if you want the latest you could to -id as newer pages will have higher IDs. I think if you do the sort before limiting the number it returns it will do the query in that order. id != $page->id will exclude the current page from the results. If the $page is a product though, you might have simply been able to do something like foreach ($page->siblings(<selector goes here>)... and so on, like this: foreach ($page->siblings("tags=$page->tags, sort=-sort, limit=4") as $related) { echo "<a href='$related->url'>$related->title</a><br />"; } Link to comment Share on other sites More sharing options...
antknight Posted March 18, 2014 Share Posted March 18, 2014 Thanks for that Pete, I agree that approach is simpler but it is not a simple sort I am after. To quote an earlier post I want it to look for pages with the same tags and the more tags are shared, the more "related" the other page is, thus getting it further up on the list. So I tried the snippet apeisa posted and it works! I adapted it for my needs obviously. Thanks everybody for your help. The answer I was looking for was here all along foreach($page->tags as $tag) { $related_pages = $pages->find("template=article, tags=$tag"); foreach($related_pages as $related) { if($related->id != $page->id) $related_id[$related->id]++; } } arsort($related_id); // We limit it to three related pages at max $related_id = array_slice($related_id, 0, 3, true); foreach($related_id as $key => $val){ $rp = $pages->get($key); 2 Link to comment Share on other sites More sharing options...
Pete Posted March 18, 2014 Share Posted March 18, 2014 Ah, sorry - I completely misunderstood that bit. Glad it's sorted though. Link to comment Share on other sites More sharing options...
antknight Posted March 21, 2014 Share Posted March 21, 2014 Actually there is one more thing, how can I make it conditional so it only outputs content if there are in fact related pages? foreach($page->tags as $tag) { $related_pages = $pages->find("template=article, tags=$tag"); foreach($related_pages as $related) { if($related->id != $page->id) $related_id[$related->id]++; } } arsort($related_id); // We limit it to three related pages at max $related_id = array_slice($related_id, 0, 3, true); foreach($related_id as $key => $val){ $rp = $pages->get($key); echo //Conditional stuff here... Link to comment Share on other sites More sharing options...
adrian Posted March 21, 2014 Share Posted March 21, 2014 If I understand correctly, would counting related_id work? if(count($related_id)>0){ 1 Link to comment Share on other sites More sharing options...
antknight Posted March 21, 2014 Share Posted March 21, 2014 I have tried that but I am not sure where to put it, I still get the conditional content regardless. Here is my code snippet, I know it's messy with all those unnecessary echos... <?php foreach ($page->tags as $tag) { $related_pages = $pages->find("template=product|product-2, tags=$tag"); foreach ($related_pages as $related) { if ($related->id != $page->id) $related_id[$related->id]++; } } arsort($related_id); // We limit it to 4 related pages at max $related_id = array_slice($related_id, 0, 4, true); foreach ($related_id as $key => $val) { $rp = $pages->get($key); $first = $rp->gallery->first(); $thumb = $first->gallery_image->size(780, 600); echo "<div class='col-27"; foreach ($rp->tags as $tag) { echo " {$tag->name}"; } echo "'>"; echo "<article class='project'>"; echo "<figure class='project-thumb'>"; echo "<img src='{$thumb->url}' alt='project-1'>"; echo "<figcaption class='middle'>"; echo "<div>"; echo "<a href='{$rp->url}' class='icon circle medium'><i class='fa fa-link'></i></a>"; echo "<p style='color:white'>{$rp->page_heading}</p>"; echo "</div>"; echo "</figcaption>"; echo "</figure>"; echo "<header class='project-header'>"; echo "<h4 class='project-title'><a href='{$rp->url}'>{$rp->title}</a></h4>"; echo "</header>"; echo "</article>"; echo "</div>"; } ?> Link to comment Share on other sites More sharing options...
adrian Posted March 21, 2014 Share Posted March 21, 2014 Well I am not sure I understand - the stuff inside the foreach ($related_id as $key => $val) { will only get displayed if the $related_id array has entries in it so perhaps you need to figure out why there are page ids in that array in the first place if there are no related pages. EDIT: I had some code here that I thought made sense, but then realized it didn't 1 Link to comment Share on other sites More sharing options...
antknight Posted March 21, 2014 Share Posted March 21, 2014 Arrrrr, it was my own stupidity. The content was outside the conditional. You were exactly right there was nothing in the array so why should it get displayed? Thanks! Link to comment Share on other sites More sharing options...
MilenKo Posted April 21, 2017 Share Posted April 21, 2017 Hello. I found this topic looking for some ideas about similar pages. Presently I am working on a cooking website and am looking at how to organize a block of similar recipes in the recipe view. What I have so far is a parent page Categories in which I am creating the child pages for every category. Then in the recipe template I have a field (recipe_category) to select one or multiple categories the recipe belongs to. If the recipe had only one category assigned, it would have been easy to get the result checking if there are others within the selected category however what would be the approach if a recipe belongs to multiple cats? I know I could use the recipe tags too for the sorting and in this case I could implement the tags weight solution provided in earlier posts however how would you suggest to find similar pages which would basically hold an array of recipe_category? Link to comment Share on other sites More sharing options...
Zeka Posted April 21, 2017 Share Posted April 21, 2017 Hi @MilenKo Maybe you can rely on some additional field like "ingredients" when a recipe belongs to multiple categories? Link to comment Share on other sites More sharing options...
MilenKo Posted April 21, 2017 Share Posted April 21, 2017 @Zeka I thought about that too, however with similar products you can make completely different results sometimes so it won't be a match. Example would be using almonds/almond flour and coconut oil to pan-fry meat or make a cake Link to comment Share on other sites More sharing options...
Zeka Posted April 21, 2017 Share Posted April 21, 2017 @MilenKo $recipesCategoriesSelector = $page->recipe_categories->implode("|"); $related = $pages->find("template=recipe, recipe_categories={$recipesCategoriesSelector}, sort=random, limit=4); 1 Link to comment Share on other sites More sharing options...
nfil Posted April 21, 2017 Share Posted April 21, 2017 Hello. I have 3 templates: category sub-category partner I can output the template "partner" from a sub-category! But if there arent't 3 partners in that sub-catgory I want to get the others from the parent category template. Thank you $morep = $page->parent->children("template=partner, id!=$page->id, limit=3, sort=random"); foreach($morep as $a) { $firstimage = $a->images->first(); $thumb = $firstimage->size(400, 200); echo "<li class='item'> <div class='img_box'> <a href='$a->url' title='$a->title'> <img src='$thumb->url' alt='$a->title' width="400" height="200"> </a> </div> <div class='featured_title_postcustom'> <div class='caption_inner'> <a href='$a->url'><h4>$a->title</h4></a> <div class='post_date {$a->parent->parent->style_color}'><em> <a href='$a->url' title='$a->title'> {$a->parent->parent->title} {$a->parent->title} </a></em></div> </div> </div> </li>"; } -- My sitemap Pages Templates -- Category -sub-category -partner Category -sub-category -partner Link to comment Share on other sites More sharing options...
Zeka Posted April 21, 2017 Share Posted April 21, 2017 $morep = $featured = $page->siblings("template=partner, limit=3, sort=random", false); if($morep->count() < 3) { $morep->import($page->closest("template=category)->children("template=partner, id!=$page->id, limit=3, sort=random") } 1 Link to comment Share on other sites More sharing options...
MilenKo Posted April 21, 2017 Share Posted April 21, 2017 @Zeka Will try your suggestion later on today and share if that works fine. Because I was thinking of another way to organize what is needed, but I don't want to flood the topic. Basically instead of finding matching pages I thought to add a field with PageSelect and pick up manually recipes that would have similarities. Doing so is not an automated process but in my case would allow to be used for drinks matching the recipe or other recipes that you would prefer to suggest (versus the automated). It is always good to have options so I appreciate your suggestion. Now I have an option to provide similar pages by tags, by "category" and manually select so it could even be set in the admin as a drop down box to choose which way to go 1 Link to comment Share on other sites More sharing options...
MilenKo Posted April 22, 2017 Share Posted April 22, 2017 @Zeka I tried your suggestion and I am closer but the result of the query is not what is needed: Here is the code I used with a tiny modification to match the correct field names: $recipesCategoriesSelector = $page->recipe_category->implode("|"); $related = $pages->find("template=recipes-inner, recipe_category={$recipesCategoriesSelector}, limit=3"); foreach($related as $similar_recipes) { echo $similar_recipes->title; } The result I see instead of having the title of the recipe is the text Categories which is the name of the parent that I used to add child pages as categories. Any ideas what is wrong? Link to comment Share on other sites More sharing options...
Zeka Posted April 22, 2017 Share Posted April 22, 2017 Could you please share your tree view for these pages. Link to comment Share on other sites More sharing options...
MilenKo Posted April 22, 2017 Share Posted April 22, 2017 (edited) == Home == Categories (template=categories) == == Category 1 (template=categories) == == Category 2 (template=categories) == Recipes (template=recipes) == == Recipe 1 (template=recipes-inner) == == Recipe 2 (template=recipes-inner) == Tags (template=tags) == == Tag 1 (template=tags) == == Tag 2 (template=tags) So each recipe could have multiple categories or a single if needed. With the earlier provided code, $related is equal to the id of Categories page but not to the recipes containing the selected categories, hence $related->title shows "Categories" Edited April 22, 2017 by MilenKo Added template names after the corrections Link to comment Share on other sites More sharing options...
MilenKo Posted April 22, 2017 Share Posted April 22, 2017 @Zeka I think I found the issue as the query seemed perfectly right but was showing strange results. So I went back to check every template and found out that Categories page had assigned recipe-inner as template instead of categories. This would explain the strange result. Edit: After applying the proper templates as per the tree above, the query returns no results. I even deleted all the categories child pages and added them back to every recipe to make sure that at least a few of them would match with others, but still nothing. Link to comment Share on other sites More sharing options...
nfil Posted April 15, 2018 Share Posted April 15, 2018 This is my Tree View: == Home == List ----- blog-post (has two page reference fields "categories" and "categories_a") ----- blog-post 1 == categories (List categories and latest blog-post title *) ----- category ----- my other category == categories-a ----- category-a ----- my other category a $categories = $page->children; foreach($categories as $category) { $posts = $pages->find("template=blog-post, categories=$category, limit=1, sort=-date"); foreach($posts as $post) { echo $category->title; echo $post->title; } } * Want to show the latest post for each category in the categories page. Not sure what I am doing wrong to retrieve latest posts. I changed it to this and its working now! $posts = $pages->find("template=blog-post, categories_select=$category, limit=1, sort=-date"); foreach($posts as $post) { $fimg = $post->featured_image; $thumb = $fimg->width(200); echo "<h4>Latest entry</h4>"; echo "<img width='200' src='$thumb->url' alt='$post->title'/>"; echo "<p>$post->title</p>"; } Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now