alan Posted June 14, 2012 Share Posted June 14, 2012 I've written the chunk of code below to retrieve then display the three most recent comments from blogpost Pages. I am worried that in places I may be failing to use the power of the PW API (overusing generic PHP instead). Do you see a 'tighter' / more powerful PW-API-way of doing this? Also I don't see how to retrieve the URL of the blogpost that a comments belongs to, in pseudo code I feel I want to do: $comment->parent()->url; Here's the code: $blogposts = $pages->get( "/blog/" )->children; $comments = array(); foreach($blogposts as $blogpost) { foreach($blogpost->comment as $comment) { if($comment->isApproved()) { array_push($comments, $comment); // Build an array of comments } } } if($comments) { $out = "<h2>Last three blog comments</h2>"; $out .= "<dl>"; arsort($comments); $num_comments = 0; foreach($comments as $comment) { $cite = htmlentities($comment->cite); $text = htmlentities($comment->text); $date = date("j M 'y ", $comment->created); $out .= "<dt>{$date}</dt>"; $out .= "<dd>{$cite}</dd>"; $out .= "<dd>{$text}</dd>"; $num_comments++; if($num_comments == 3) break; } $out .= "</dl>"; echo $out; } else { echo "<p>No comments.</p>"; } Any comments gratefully received, cheers, -Alan Link to comment Share on other sites More sharing options...
interrobang Posted June 14, 2012 Share Posted June 14, 2012 I did not test it, but I looked around in Ryans BlogProfile and saw some interesting methods in BlogTools.php: /** * Find comments from the given selector string * * @param string $selector * @return CommentArray * */ public function findComments($selector) { $comments = FieldtypeComments::findComments($this->commentsField, $selector); foreach($comments as $comment) { if(!$comment->page->viewable()) $comments->remove($comment); } return $comments; } /** * Find $limit recent comments * * @param int $limit Number of recent comments to find * @param int $start Where to start, like 0 (default: null = automatic, based on page number) * @param bool $admin Include non-approved and spam comments? (default: null = determine automatically) * @return CommentArray * */ public function findRecentComments($limit = 3, $start = null, $admin = null) { $limit = (int) $limit; $_limit = is_null($start) ? $limit : $limit+1; $out = ''; $pageNum = $this->input->pageNum; // auto-determine $start if not specified if(is_null($start)) { if($pageNum > 1) $start = $pageNum * $limit; else $start = 0; } // we show pending and spam comments when page is editable if(is_null($admin)) $admin = $this->page->editable(); // build selector to locate comments $selector = "limit=$_limit, start=$start, sort=-created, "; if($admin) $selector .= "status>=" . Comment::statusSpam . ", "; else $selector .= "status>=" . Comment::statusApproved . ", "; // find the comments we want to output $comments = $this->findComments($selector); return $comments; } I think FieldtypeComments::findComments is a new addition to PW, so you might need the lastet version from github. It looks like instead of $comment->parent()->url; you can use $comment->page; 2 Link to comment Share on other sites More sharing options...
alan Posted June 14, 2012 Author Share Posted June 14, 2012 (edited) Thanks @interrobang, I've not even seen that resource For the dev work I'm doing here I keep up-to-date with github so I'll go test. Cheers! Update: $comment->page; appears to be showing the ID of the page where the comment list is being viewed rather than the pages the comments belonged to. But thanks this looks promising. Edited June 14, 2012 by alan Link to comment Share on other sites More sharing options...
ryan Posted June 14, 2012 Share Posted June 14, 2012 Alan the $comment->page will only point to the actual comment's page if the comment was retrieved with FieldtypeComments::findComments. Part of what that function does is populate the appropriate $page variable to all the comments it finds. However, you can still get it even if you don't have the latest PW or aren't using that findComments function: $page = wire('pages')->get($comment->pages_id); 1 Link to comment Share on other sites More sharing options...
alan Posted June 14, 2012 Author Share Posted June 14, 2012 Thanks Ryan, I was off in the kitchen making Tea and suddenly did a mental forehead-slap when I realized I probably needed to use the fn rather than my own code. Thanks also for extremely useful reminder how the API can be used, pearls of wisdom I keep pumping into pinboard.in Link to comment Share on other sites More sharing options...
alan Posted June 14, 2012 Author Share Posted June 14, 2012 Drat, I am managing to fail to solve this even with the help. I modified my first foreach to include the $page = wire(... line: foreach( $blogposts as $blogpost ) { foreach($blogpost->comment as $comment) { if($comment->isApproved()) { array_push($comments, $comment); // Build an array of comments $page = wire('pages')->get($comment->pages_id); } } } ...and then later to check I am seeing the ID of each comments parent page I added the $comment_parent code: foreach($comments as $comment) { $cite = htmlentities($comment->cite); $text = htmlentities($comment->text); $date = date("j M 'y ", $comment->created); $comment_parent_id = $comment->page; $out .= "<dt>{$date}</dt>"; $out .= "<dd>{$cite}</dd>"; $out .= "<dd>{$text}</dd>"; $out .= "<dd>{$comment_parent_id}</dd>"; $num_comments++; if($num_comments == 3) break; } But the ID returned is the same each time and is the ID of the page where the list is being shown—if I understood you rightly Ryan the edit $page = wire('pages')->get($comment->pages_id); in the first foreach should have stopped that—did I do something wrong? PS: If the use of FieldtypeComments::findComments is documented I'll try that also, I tried adding and using these functions but got errors and don't want to cloud this post so I'll ignore for now. Thanks in advance for any more pointers. Link to comment Share on other sites More sharing options...
interrobang Posted June 14, 2012 Share Posted June 14, 2012 I think you have to store the $page in your $comment. $comment->page should now be the actual page, and not only the page_id. foreach( $blogposts as $blogpost ) { foreach($blogpost->comment as $comment) { if($comment->isApproved()) { $page = $pages->get($comment->pages_id); $comment->page = $page; array_push($comments, $comment); // Build an array of comments } } } Link to comment Share on other sites More sharing options...
alan Posted June 14, 2012 Author Share Posted June 14, 2012 Thanks @interrobang. I tried it but it seems to produce no output (no errors but no output). This is what I had: foreach( $blogposts as $blogpost ) { foreach($blogpost->comment as $comment) { if($comment->isApproved()) { array_push($comments, $comment); // Build an array of comments $page = $pages->get($comment->pages_id); $comment->page = $page; // $page = wire('pages')->get($comment->pages_id); // tried with this line in and out but same result } } } PS: I'm using echo $comment->page; to see the ID of each comments page. Link to comment Share on other sites More sharing options...
interrobang Posted June 14, 2012 Share Posted June 14, 2012 I think you have to change the line order like in my example. Otherwise the $comment you push into your array doesnt't have the page variable set. Maybe there are other and better ways to do this, I am still new to php. Btw, echo $comment->page shows the ID, but nevertheless $comment->page should be the real page, so things like $comment->page->url should work. Link to comment Share on other sites More sharing options...
alan Posted June 14, 2012 Author Share Posted June 14, 2012 Thanks again @interrobang for your patience, I should have spotted that the line order mattered, but I'm not so good at PHP But sadly I've changed the order to match your order and it still produces nothing. Link to comment Share on other sites More sharing options...
interrobang Posted June 14, 2012 Share Posted June 14, 2012 Sorry, I have no idea whats wrong. But maybe this works better, instead of storing the $page in the $comment: foreach($comments as $comment) { $cite = htmlentities($comment->cite); $text = htmlentities($comment->text); $date = date("j M 'y ", $comment->created); $comment_parent_id = $comment->pages_id; // Get the page_id $out .= "<dt>{$date}</dt>"; $out .= "<dd>{$cite}</dd>"; $out .= "<dd>{$text}</dd>"; $out .= "<dd>{$comment_parent_id}</dd>"; $num_comments++; if($num_comments == 3) break; } Link to comment Share on other sites More sharing options...
diogo Posted June 14, 2012 Share Posted June 14, 2012 (edited) Alan, maybe this is not the best way of doing it, but at least it works $blogposts = $pages->get( "/blog/" )->children; $comments = array(); foreach( $blogposts as $blogpost ) { foreach ($blogpost->article_comments as $comment) { if($comment->isApproved()) { array_push($comments, array("comment"=>$comment, "post"=>$blogpost)); } } } foreach ($comments as $c) { echo $c["comment"]->text . "<br>"; echo $c["post"]->url . "<br>"; } Edited June 14, 2012 by diogo Link to comment Share on other sites More sharing options...
alan Posted June 14, 2012 Author Share Posted June 14, 2012 Thanks again for trying so much to help me @interrobang, I can't seem to find the answer this way either. And thanks @diogo, I wondered about a two dimension array but I was already getting PHP-lost so I bailed on that. Your code does indeed work, thanks, and I'll edit my code to use it. Thanks everyone, I'll post back the final version. I'd love to know where/when the use of FieldtypeComments::findComments is documented for future projects though in case anyone finds this thread and knows. Cheers! Link to comment Share on other sites More sharing options...
alan Posted June 14, 2012 Author Share Posted June 14, 2012 (edited) This is the code I ended up using, thanks again to interrobang, diogo and Ryan: $blogposts = $pages->get( "/blog/" )->children; $comments = array(); foreach( $blogposts as $blogpost ) { foreach($blogpost->comment as $comment) { if($comment->isApproved()) { array_push($comments, array("comment"=>$comment, "post"=>$blogpost)); } } } if($comments) { $out = "<h2>Last three blog comments</h2>"; $out .= "<dl>"; arsort($comments); $num_comments = 0; foreach($comments as $comment) { $cite = htmlentities($comment["comment"]->cite); $text = htmlentities($comment["comment"]->text); $date = date("j M 'y ", $comment["comment"]->created); $comment_parent_url = $comment["post"]->url . "#Comment" . $comment["comment"]; $out .= "<dt><a href='{$comment_parent_url}'>{$date}</a></dt>"; $out .= "<dd>{$cite}</dd>"; $out .= "<dd>{$text}</dd>"; $num_comments++; if($num_comments == 3) break; } $out .= "</dl>"; echo $out; } else { echo "<p>No comments.</p>"; } Brilliant. Thanks guys! Updated 2012-06-14-1329 to use named arrays, much better, thanks to diogo for suggesting this Edited June 14, 2012 by alan 1 Link to comment Share on other sites More sharing options...
diogo Posted June 14, 2012 Share Posted June 14, 2012 You used the numeric array I will revert my code back to it, so it's not confusing to anyone that sees this later. Link to comment Share on other sites More sharing options...
alan Posted June 14, 2012 Author Share Posted June 14, 2012 No! I prefer your non-numeric version I'll change my code and check it and then post back her! Thanks! Link to comment Share on other sites More sharing options...
diogo Posted June 14, 2012 Share Posted June 14, 2012 changed back Link to comment Share on other sites More sharing options...
alan Posted June 14, 2012 Author Share Posted June 14, 2012 High Five! Link to comment Share on other sites More sharing options...
encho Posted April 4, 2013 Share Posted April 4, 2013 Thank you, exactly what I was looking for. Only problem I encountered is on 4th line foreach($blogpost->comment as $comment) { where it should be $blogpost->comments (as that is the name of field I am using). Great example. 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