nfil Posted March 9, 2014 Share Posted March 9, 2014 Hello, I'am trying to store the 4 latest visited pages, using sessions and output the first image and title from those pages to the user. Any help is appreciated! Tried $session and PW api variables but couldn't get this to work. This is working but only to get the urls to the page: session_start(); // URL array if (empty($_SESSION['pageurls'])) { $_SESSION['pageurls'] = array_fill(0,4,''); } function trackPage($url) { array_unshift($_SESSION['pageurls'],$url); array_pop($_SESSION['pageurls']); } trackPage($_SERVER['REQUEST_URI']); foreach ($_SESSION['pageurls'] as $page) { echo "<a href='{$page}'>" . $page . "</a>" . "<br/>"; }; Link to comment Share on other sites More sharing options...
teppo Posted March 9, 2014 Share Posted March 9, 2014 Still somewhat ugly, but I'd probably go with something like this: $session->history = is_array($session->history) ? array_slice(array_merge(array($page->id), $session->history), 0, 4) : array($page->id); After that you can output stored data like this: foreach ($session->history as $page_id) { $p = $pages->get($page_id); echo "<a href='{$p->url}'>{$p->title}</a><br />"; } 2 Link to comment Share on other sites More sharing options...
nfil Posted March 10, 2014 Author Share Posted March 10, 2014 Thanks for the help teppo! Tried to output pages from a specific PW template but it outputs all the pages, maybe there is something wrong with this: <?php $session->history = is_array($session->history) ? array_slice(array_merge(array($page->id), $session->history), 0, 4) : array($page->id); foreach ($session->history as $page_id) { $p = $pages->get($page_id)->find("template=basic-page"); echo "<a href='{$p->url}'>{$p->title}</a><br />"; } ?> Link to comment Share on other sites More sharing options...
teppo Posted March 10, 2014 Share Posted March 10, 2014 @nfil: $pages->get($page_id) returns one page and you can't "find" from one page Try adding new row after $p = $pages->get($pages_id) with something like this: if ($p->template != "basic-page") continue; 1 Link to comment Share on other sites More sharing options...
nfil Posted March 10, 2014 Author Share Posted March 10, 2014 @nfil: $pages->get($page_id) returns one page and you can't "find" from one page Try adding new row after $p = $pages->get($pages_id) with something like this: if ($p->template != "basic-page") continue; oops, You are right! I added the first image from those pages too. $resized_imageWidth = 120; $resized_imageHeight = 0; $session->history = is_array($session->history) ? array_slice(array_merge(array($page->id), $session->history), 0, 4) : array($page->id); foreach ($session->history as $page_id) { $p = $pages->get($page_id); if ($p->template != "basic-page") continue; echo "<img src='{$p->images->first->url}' width='{$resized_imageWidth}' heigth='{$resized_imageHeight}'>" . "<a href='{$p->url}'>{$p->title}</a><br />"; } Thanks again teppo for all the help! 2 Link to comment Share on other sites More sharing options...
teppo Posted March 10, 2014 Share Posted March 10, 2014 I'm glad I could help.. and this actually looks quite interesting, might have use for similar snippet somewhere Link to comment Share on other sites More sharing options...
adrian Posted March 10, 2014 Share Posted March 10, 2014 @nfil: $pages->get($page_id) returns one page and you can't "find" from one page Try adding new row after $p = $pages->get($pages_id) with something like this: if ($p->template != "basic-page") continue; Hey teppo, Possibly I am missing something so wanted to clarify with you: I often chain get and find for finding all the children/grandchildren of a particular single parent. Compare this to "->get->children(selector)" which of course only returns first level children. I know that it doesn't work for what @nfil is after, but wanted to clarify how they can actually work together for those that are new to PW. Also, curious what you think of: $p = $pages->get($page_id); if ($p->template != "basic-page") continue; echo .... vs $ps = $pages->find("id=$page_id, template=basic-page"); foreach($ps as $p){ echo ......; } The first option (your suggestion) is likely more efficient, but just wanted to point out the second option to others and make the note that, in this case, you need a find rather than a get, because with a get, the id= selector overrides anything else after it. 1 Link to comment Share on other sites More sharing options...
teppo Posted March 11, 2014 Share Posted March 11, 2014 Possibly I am missing something so wanted to clarify with you: I often chain get and find for finding all the children/grandchildren of a particular single parent. Compare this to "->get->children(selector)" which of course only returns first level children. I know that it doesn't work for what @nfil is after, but wanted to clarify how they can actually work together for those that are new to PW. Very good clarification. My explanation earlier was way too vague What I meant was that you can't find from a single page, i.e. use find like a filter for one page. You can find from children of given page, though: $pages->get(123)->find("template=basic-page") would return children of page 123 with template "basic-page" recursively, while $pages->get(123)->children("template=basic-page") would only return matching direct children. Also, curious what you think of: $p = $pages->get($page_id); if ($p->template != "basic-page") continue; echo .... vs $ps = $pages->find("id=$page_id, template=basic-page"); foreach($ps as $p){ echo ......; } The first option (your suggestion) is likely more efficient, but just wanted to point out the second option to others and make the note that, in this case, you need a find rather than a get, because with a get, the id= selector overrides anything else after it. That's another way to do it. With find() you could also do something like this to, perhaps, simplify it a bit: $p = $pages->find("id=$page_id, template=basic-page")->first(); if (!$p) continue; echo .... Quick look at the SQL generated by get() vs. find(): SELECT id, templates_id FROM pages WHERE id=1001 SELECT pages.id,pages.parent_id,pages.templates_id FROM `pages` WHERE (pages.id=1001) AND (pages.templates_id=29) AND (pages.status<1024) GROUP BY pages.id /* Selector id=1001, template=basic-page, status<1024 */ I would assume first one (get) to be slightly faster, but this is micro-optimisation at it's best and doesn't usually matter at all in real world use. I prefer get() for getting single pages as it's the straightforward way 2 Link to comment Share on other sites More sharing options...
teppo Posted March 11, 2014 Share Posted March 11, 2014 Another clarification. (I seem to need these a lot these days.) As is (probably) made quite obvious by the SQL statements above, get() with a Page ID doesn't care about the status of the page at all. It returns hidden and unpublished pages too, making it somewhat equal to find() with "include=all". This is important to keep in mind in case that those pages you're "getting" could've been unpublished in the meantime; if that's possible, you really should add another check for $p->viewable() before displaying content. With this addition, nfil's final code could look like this: $resized_imageWidth = 120; $resized_imageHeight = 0; $session->history = is_array($session->history) ? array_slice(array_merge(array($page->id), $session->history), 0, 4) : array($page->id); foreach ($session->history as $page_id) { $p = $pages->get($page_id); if (!$p->viewable() || $p->template != "basic-page") continue; echo "<img src='{$p->images->first->url}' width='{$resized_imageWidth}' height='{$resized_imageHeight}'>" . "<a href='{$p->url}'>{$p->title}</a><br />"; } 2 Link to comment Share on other sites More sharing options...
adrian Posted March 11, 2014 Share Posted March 11, 2014 Since we're in a clarifying mood , the catch with $p->viewable is that there must be a template php file for the page, so this isn't a complete fix for using ->get and making sure it is not hidden/unpublished. Maybe this instead of viewable? !$p->status>=1024 I know it won't matter for this script because we are looping through pages that were at some point viewable (even if the status was changed in the meantime), so they must have had a template file at some point and likely still do. Sorry, I know I am getting too pedantic and off-topic now - time to sleep 2 Link to comment Share on other sites More sharing options...
horst Posted March 11, 2014 Share Posted March 11, 2014 Since we're in a clarifying mood , the catch with $p->viewable is that there must be a template php file for the page, so this isn't a complete fix for using ->get and making sure it is not hidden/unpublished. in this case you only have to change the order in this line: if (!$p->viewable() || $p->template != "basic-page" ) continue; // old if ($p->template != "basic-page" || !$p->viewable()) continue; // new PHP will return after the first conditional if it does not match and in these cases the code of the second condition (or any following) never get executed. Changing this, Teppos code is a complete fix. 1 Link to comment Share on other sites More sharing options...
teppo Posted March 11, 2014 Share Posted March 11, 2014 Good clarifications from both of you This is getting a bit out of hand, but one more addition: in current code image isn't actually resized -- it's just forced to specific dimensions with HTML attributes. This could be intentional, but I'm wondering if this might make even more sense here: ... echo "<img src='{$p->images->first->size($resized_imageWidth, $resized_imageHeight)->url}' width='{$resized_imageWidth}' height='{$resized_imageHeight}'>" . "<a href='{$p->url}'>{$p->title}</a><br />"; ... This way end-user doesn't have to download excessively large images, if what you really want here is a thumb. It should also be noted that simply defining width and height with HTML attributes forces image to those exact dimensions without considering actual aspect ratio, which can easily result in distorted images. (More about various options that size() accepts here.) 2 Link to comment Share on other sites More sharing options...
pideluxe Posted March 11, 2014 Share Posted March 11, 2014 I often chain get and find for finding all the children/grandchildren of a particular single parent. Compare this to "->get->children(selector)" which of course only returns first level children. Another way to return all children including grand-children is to use has_parent: $all_children = $pages->find("has_parent=$parent, ..."); 1 Link to comment Share on other sites More sharing options...
adrian Posted March 11, 2014 Share Posted March 11, 2014 in this case you only have to change the order in this line: if (!$p->viewable() || $p->template != "basic-page" ) continue; // old if ($p->template != "basic-page" || !$p->viewable()) continue; // new PHP will return after the first conditional if it does not match and in these cases the code of the second condition (or any following) never get executed. Changing this, Teppos code is a complete fix. Actually I don't think that makes any difference in this hypothetical case. The $p->template check doesn't look to see if the template file exists, just the name of the template assigned to the page. So assume it hits a page with that template - it will then move to the "viewable" check. Assuming there is no template file, this will force the "continue". So this means that you still can't check just the assigned template and page status (not hidden or unpublished). I think that makes sense. But, yes, now we are really getting silly - sorry for starting it Link to comment Share on other sites More sharing options...
nfil Posted March 12, 2014 Author Share Posted March 12, 2014 Good clarifications from both of you This is getting a bit out of hand, but one more addition: in current code image isn't actually resized -- it's just forced to specific dimensions with HTML attributes. This could be intentional, but I'm wondering if this might make even more sense here: ... echo "<img src='{$p->images->first->size($resized_imageWidth, $resized_imageHeight)->url}' width='{$resized_imageWidth}' height='{$resized_imageHeight}'>" . "<a href='{$p->url}'>{$p->title}</a><br />"; ... This way end-user doesn't have to download excessively large images, if what you really want here is a thumb. It should also be noted that simply defining width and height with HTML attributes forces image to those exact dimensions without considering actual aspect ratio, which can easily result in distorted images. (More about various options that size() accepts here.) Thanks Teppo for the reminder! The uploaded image will always have the dimensions attributes. Also great contributions from all the forum's members! Link to comment Share on other sites More sharing options...
francis Posted January 4, 2020 Share Posted January 4, 2020 On 3/9/2014 at 7:36 PM, teppo said: Still somewhat ugly, but I'd probably go with something like this: $session->history = is_array($session->history) ? array_slice(array_merge(array($page->id), $session->history), 0, 4) : array($page->id); After that you can output stored data like this: foreach ($session->history as $page_id) { $p = $pages->get($page_id); echo "<a href='{$p->url}'>{$p->title}</a><br />"; } Sorry to resurrect this topic several years later. This works well but I am trying to a) prevent the displayed list of pages from showing the current page as well and b) also to only show each visited page once in the list. My attempts with array_unique have failed so far. Any tips? Link to comment Share on other sites More sharing options...
teppo Posted January 4, 2020 Share Posted January 4, 2020 24 minutes ago, francis said: Sorry to resurrect this topic several years later. This works well but I am trying to a) prevent the displayed list of pages from showing the current page as well and b) also to only show each visited page once in the list. My attempts with array_unique have failed so far. Any tips? Perhaps something like this? $session->history = is_array($session->history) ? array_slice(array_unique(array_merge([$page->id], $session->history)), 0, 4) : [$page->id]; And when you're displaying the history, just skip over current page: foreach ($session->history as $page_id) { if ($page_id == $page->id) continue; $p = $pages->get($page_id); echo "<a href='{$p->url}'>{$p->title}</a><br />"; } 2 Link to comment Share on other sites More sharing options...
francis Posted January 4, 2020 Share Posted January 4, 2020 Fantastic, thank you, much obliged. That works perfectly! I was putting the array_unique in the wrong place and just couldn't work out how to leave out the current page. 1 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