How to implement a recursive search in Laravel 4? - recursion

I am trying to create a posts <-> comments relationship tables and display the results.
I think I can create all the relationships properly, but I am missing the recursive function in the View to display them correctly. Here is my code:
my posts table is:
id | subject | content |
my comments table is:
id | content | post_id | parent_id
As you can see, I relate the comments table with the posts ones with the "post_id", and relate the comments table to itself with de "parent_id" for those comments that are children of others.
Now, these are my models. For the Post I have:
<?php
class Post extends Eloquent{
public function comments(){//Me captura el primer bloque de replies
return $this->hasMany('Comment')->where('parent_id',0);
}
}
?>
and my Comment Model is:
<?php
class Comment extends Eloquent{
public function posts(){
return $this->belongsTo('Post');
}
public function nestedComment(){
return $this->hasMany('Comment','parent_id');
}
}
?>
I think those relationships should be enough to create the view (which I have no idea how to build using a recursive function), so far I have this:
#if($posts)
#foreach($posts as $post) {{-- for posts --}}
<strong>{{$post->subject}}</strong><br />
#foreach($post->comments as $comment) {{-- for 1st reply --}}
<p id="reply1">{{$comment->content}}</p>
#if($comment->nestedComment->count() >0) {{-- for reply reply --}}
#foreach($comment->nestedComment as $nestedComment)
<p id="reply2">{{$nestedComment->content}}</p>
#endforeach
#endif
#endforeach
#endforeach
#else
#endif
Of course with this type of view I can just get to show the first reply of a reply, but cannot go any deeper...
Any idea about how I can build this View and get to display as deep as the replies are?
Thanks in advanced from Costa Rica.

This is what I am going to try:
function display_comment($comment, $indent) {
echo $indent, $comment, PHP_EOL;
if ( $comment->nestedComment )
display_comment($comment->nestedComment, $indent + INDENT);
}
I haven't been able to implement it though

Related

How to wrap HTML/PHP concatenation in Wordpress Function

I'm making my first basic Wordpress Theme, and trying to create a function to retrieve and display the first 6 posts, which I could use in various areas depending on the page you're on. It is very similar to this tutorial, that I found... after facing the fact it doesn't work in my theme.
Here is a simplified piece of the code (I tried several versions) :
function show_last_items() {
while ( have_posts() && $count < 6) :
the_post();
$count++;
print '<article id="post-'.the_ID().'" class="post-link-display">
<a href="'.the_permalink().'" title="'.the_title_attribute().'">
<div class="date">
<p>'.the_time( 'd/m' ).'</p>
</div>
<div class="title">
<h6>'.the_title().'</h6>
</div>
</a>
</article>';
endwhile;
}
For some reason, while the code inside the function works just fine if I use it directly on a template part (for example sidebar.php), all the HTML seems to be wiped off when used as a function... Or more exactly, it still exists, but in-between the data. So I get something like this displayed :
55http://localhost/myTheme/posts/55/my-post-title/My post title19/03My
post title
56http://localhost/myTheme/posts/56/my-other-post-title/My other post
title19/03My other post title
Yet the <article> tag and every markup in it is still there, empty, after each line that displays the retrieved information. I'd really like to understand why the concatenation doesn't work properly in this case. Is it something about the theme support ? It doesn't seem to me the WP_Widget class would change anything to this issue, but maybe I'm wrong ?
Try this
function show_last_items() {
while ( have_posts() && $count < 6) :
the_post();
$count++;
sprintf('<article id="post-%s" class="post-link-display">
<a href="%s" title="%s">
<div class="date">
<p>%s</p>
</div>
<div class="title">
<h6>%s</h6>
</div>
</a>
</article>', the_ID(), the_permalink(), the_title_attribute(), the_time( 'd/m' ), the_title());
}
Have you tried building a string and then returning it?
$return_string = '';
// while loop
$return_string .= '<article .....';
// end while
return $return_string;

KNP Pagination links stucked on page 1

Good evening everybody,
I'm actually pushing my symfony2 website online and I have some issues. I have set the knp paginator bundle and have followed their intructions regarding the installation. But the fact is that my pagination is not working and therefore it only shows the items that are appearing on page one. When I click next/page2, the url seems to be behaving correctls but the page is still "freezed" the first display.
Here is my code (and I have all the config set up for the different bundles in the autoloader and the kernel):
// Controller/HomeController.php (used for the homepage)
<?php
namespace Pf\Bundle\BlogBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class HomeController extends Controller
{
public function indexAction()
{
$em = $this->get('doctrine.orm.entity_manager');
$dql = "SELECT a FROM PfBlogBundle:Projects a ORDER by a.id DESC";
$query = $em->createQuery($dql);
$paginator = $this->get('knp_paginator');
$pagination = $paginator->paginate(
$query,
$this->get('request')->query->get('page', 1)/*page number*/,
8/*limit per page*/
);
return $this->render('PfBlogBundle:Default:home.html.twig', array('pagination'=>$pagination));
}
}
and the twig
// Default/home.html.twig
{% extends '::home.html.twig'%}
{% block body %}
<div id="works">
<div class="container">
<div class="row-fluid">
<div class="span12">
{% for project in pagination %}
<div class="span3">
<div class="workBlocks">
<img src="{{ project.thumbnail }}" />
<div class="workCaption">
<h3>{{ project.title }}</h3>
See
</div><!-- end workCaption -->
</div><!-- end workBlocks -->
</div><!-- end span3 -->
{% endfor %}
</div>
{# display navigation #}
{{ knp_pagination_render(pagination) }}
</div><!-- end row -->
</div>
</div><!-- end works -->
{% endblock %}
I can't see where I'm wrong. All the help is much appreciated ;)
EDIT:
// this is the route I want to use...
pf_blog_index:
path: /
defaults: { _controller: PfBlogBundle:Home:index }
(EDIT) Well here I will continue by providing more details as I can't figure out what's wrong:
So in my vendors I have the following folder structure:
knplabs:
knp-components
knp-menu
knp-menu-bundle
knp-paginator-bundle
After having checked my autoload and my AppKernel, I have what I need to have regarding the doc..
In my composer.json :
"require": {
"knplabs/knp-components": "1.2.*#dev",
"knplabs/knp-menu-bundle": "2.0.*#dev",
"knplabs/knp-paginator-bundle": "dev-master"
},
In app/autoload.php I have
$loader->registerNamespaces(array(
'Knp\\Component' => __DIR__.'/../vendor/knp-components/src',
'Knp\\Bundle' => __DIR__.'/../vendor/bundles',
));
And finally, in my AppKernel.php
$bundles = array(
new Knp\Bundle\MenuBundle\KnpMenuBundle(),
new Knp\Bundle\PaginatorBundle\KnpPaginatorBundle(),
);
EDIT:
Also here are my settingy in the app/config.yml
knp_paginator:
page_range: 3 # default page range used in pagination control
default_options:
page_name: page # page query parameter name
sort_field_name: sort # sort field query parameter name
sort_direction_name: direction # sort direction query parameter name
distinct: true # ensure distinct results, useful when ORM queries are using GROUP BY statements
template:
pagination: KnpPaginatorBundle:Pagination:twitter_bootstrap_pagination.html.twig # sliding pagination controls template
sortable: KnpPaginatorBundle:Pagination:sortable_link.html.twig # sort link template
Ok so I found THE or ONE solution to my problem. In fact as I said in my previous comments, the issue seemed to come from the routing. Knp bundle did effectively not appreciate the index route. Therefore, I have modified my controller in order to make a redirection with my indexAction(). Here is what works for me:
// Controller\HomeController.php
<?php
namespace Pf\Bundle\BlogBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class HomeController extends Controller
{
public function indexAction()
{
return $this->redirect($this->generateUrl('pf_blog_index2'));
}
public function listAction()
{
$em = $this->get('doctrine.orm.entity_manager');
$dql = "SELECT a FROM PfBlogBundle:Projects a ORDER by a.id DESC";
$query = $em->createQuery($dql);
$paginator = $this->get('knp_paginator');
$pagination = $paginator->paginate(
$query,
$this->get('request')->query->get('page', 1)/*page number*/,
8 /*limit per page */
);
// Puis modifiez la ligne du render comme ceci, pour prendre en compte l'article :
return $this->render('PfBlogBundle:Default:home.html.twig', array('pagination'=>$pagination));
}
}
// src/..../.../.../config/routing.php
pf_blog_index:
path: /
defaults: { _controller: PfBlogBundle:Home:index }
pf_blog_index2:
path: /home
defaults: { _controller: PfBlogBundle:Home:list }
I don't know if that's the best way to solve this issue but it works and in my case, I don't mind having such a url for the time being.
I hope that would help a beginner like me!
Pay attention on this code
$this->get('request')->query->get('page', 1)/*page number*/
You get the 'page' value of _GET parameter of request,by this code , but you have to get your 'page' as Request Attribute, not as value of _GET.
In other words the right code is
$this->get('request')->get('page')
The example in KnpPaginatorBundle repo shows that you need to pass Request $request as a parameter to the controller method that creates $pagination, which is indexAction in your case. I noticed that you don't have this parameter. This is probably why the paginator is not paginating. I've had exactly the same problem and solved it by including the $request parameter in the controller, as the example in KnpPaginatorBundle repo shows. Also, you need to remember to include use Symfony\Component\HttpFoundation\Request in the controller class.
I have the same problem, after many hour of search, I finaly find the solution, we just have to put
$request = Request::createFromGlobals();
before and after get the variable you need, in my case a get it from "GET" by doing
$request->query->get('variable')

Advanced Custom Fields/PHP issue

I apologize if this is answered elsewhere, but I'm having an issue with this ACF code here: http://goo.gl/9onrFN I want the client to be able to add a portfolio site link (if applicable) to the artist page and the link would say "View Artist's Website" and the link would take the user to the artist's site in a new window. How would I go about not making this text not visible, unless there was a url entered into the custom field on the post? Here's the code:
<p><?php the_field('contact_phone_number'); ?><br />
or <?php the_field('contact_email'); ?><br />
View Artist's Website</p>
Thanks in advance!
You can check if a ACF field is set with:
if(get_field('artist_website')) {
the_field('artist_website');
}
Using the_field will simple echo the contents of your field, whereas get_field will return the value which is a lot more helpful. For example you could write the above code as:
Note: get_field simple returns the value of the field, if you want to check if a valid url has been entered you will have to use a regular expression.
Below is your code with an if statement performing an empty field check:
<p>
<?php the_field('contact_phone_number'); ?><br />
or <?php the_field('contact_email'); ?>
<?php if(get_field('artist_website')) { ?>
<br />View Artist's Website
You may find your code easier to read by pre-setting your variables and including HTML in the echo:
<p>
<?php
$contact_phone_number = get_field('contact_phone_number');
$contact_email = get_field('contact_email');
$artist_website = get_field('artist_website');
echo "{$contact_phone_number}<br />";
echo "or <a href='mailto:{$contact_email}'>{$contact_email}</a><br/ >;
if($artist_website) {
echo "View <a href='{$artist_website}' target='_blank'>Artist's website</a>";
}
?>
</p>

Wordpress - let post author pick best comment (frontend)

From the front end, I want to allow the author to pick up the best comment/answer of his post. I am close, but not there yet. Every time I click the button, all comments of that post are selected as best (this is wrong). It should only select one comment per post.
In function.php I have the following:
add_action ('comment_post', 'add_comment_field', 1);
function add_comment_field($comment_id) {
add_comment_meta($comment_id, 'bestanswer', 'no', false);
}
In comment.php I have the following:
<?php
$current_author = get_the_author_meta('nickname');
global $current_user; get_currentuserinfo();
if ($current_user->nickname == $current_author) {
?>
<?php
$my_post_meta = get_comment_meta($comment->comment_ID, 'bestanswer', true);
if ( $my_post_meta == 'yes' ) {
echo '<h4>Best answer</h4>';
} else {
?>
<form method="post" action="" id="bestanswer-<?php comment_ID() ?>">
<input type="submit" name="confirm" value="Best Answer" />
</form>
<?php
if (isset($_POST['confirm'])) {
update_comment_meta($comment->comment_ID, 'bestanswer', 'yes');
}
}
?>
Thoughts? Suggestions? Any help will be appreciated.
I solved this by adding a link to each comment. The link goes to a page that displays that comment. On this page, the author then selects the comment as best answer. Now the comment meta is only saved for that particular comment. I know is an extra step, but I prefer this method since the author has to make sure that that is the comment he wants to pick. Once the comment is selected as best, author cannot change it.

Wordpress if else requirements for comments

I am not sure where to start, but I want to add in a symbol or change the css for the comments for registered users. Show a difference between non registered user comments and registered user comments.
How would I go about adding this to my wordpress website?
<div class="commentdetails">
<p class="commentauthor"><?php comment_author_link() ?></p>
<?php if ($comment->comment_approved == '0') : ?>
<em>Your review is pending approval by gsprating staff.</em>
<?php endif; ?>
<p class="commentdate"><?php comment_date('F jS, Y') ?>
IP/Hostname: <small>(coming soon)</small>
<?php edit_comment_link('Edit Comment','',''); ?>
</p>
I want to add make it so that the entire class is a different color if the user is a registered logged in user.
Here's an all php version of Saladin's code using the standard if/else sysntax:
<?php
if ($comment->user_ID) {
echo "<div class='comment_registeredUser'>";
}
else { // The user is not logged in
echo "<div class='commentdetails'>";
}
?>
Putting all the code in php has fixed execution errors for me. Of course, that may have been because I was doing something else wrong.
As comments are displayed in the wp_list_comments() function, you will need to edit the code there. The easiest way to achieve this is to use a simple if/else statement checking whether or not the comment has a user ID associated with it. If it does, that means the comment was made by a registered user.
Of course, as well as this, you will need to create a new CSS class to give the distinction. Here is some example code:
<?php if($comment->user_ID) : ?>
<div class="comment_registeredUser"> <!-- Or whatever you decide to call the CSS class -->
<?php else : ?> <!-- The commenter isn't a registered user -->
<div class="commentdetails">
<?php endif; ?>
// Then include the rest of the code as is
The $comment->user_ID variable will return a true if the comment poster is a registered user and was logged in when they posted the comment. The code above will assign your custom CSS class to the div if it does indeed return true. If not, it will simply apply the standard class and styling.
There is also a really good tutorial for developing themes over at the Wordpress Codex. Definitely worth having a read through if you are unsure on what you need to do to create/edit your WordPress theme.
Edit: Cleaned up the answer and better explained the correct logic.

Resources