5

I've been messing around with custom comments this week and I'm trying to figure out when I'd want to use a walker and when I'd use a callback...

There's some things I can't quite figure out how to change, but the one that's been driving me mad is how to add classes to the children <ul> tag:

<ul class="children">

Are there certain things a comment walker can do that a comment callback can't?... or vice-versa? And is one of these "better" to use as a theme developer? For example, I know that a lot of menu plugins don't work when a theme is using a custom menu walker.

Anyway, here's an example of the exact same comments, but one is being output using a walker and one is using a callback... What am I missing here? Why the need for both of these?

Comment Callback

wp_list_comments( array(
    'callback'      => 'bootstrap_comment_callback',
 ));

function bootstrap_comment_callback( $comment, $args, $depth ){
        $GLOBALS['comment'] = $comment; ?>
    <li id="comment-<?php comment_ID(); ?>" <?php comment_class( empty( $args['has_children'] ) ? '' : 'parent' ); ?>>

    <?php if ( 0 != $args['avatar_size'] ): ?>
    <div class="media-left">
        <a href="<?php echo get_comment_author_url(); ?>" class="media-object"><?php echo get_avatar( $comment, $args['avatar_size'] ); ?></a>
    </div>
    <?php endif; ?>

    <div class="media-body">
    <?php printf( '<h4 class="media-heading">%s</h4>', get_comment_author_link() ); ?>
    <div class="comment-metadata">
        <a href="<?php echo esc_url( get_comment_link( $comment->comment_ID, $args ) ); ?>">
            <time datetime="<?php comment_time( 'c' ); ?>">
                <?php printf( _x( '%1$s at %2$s', '1: date, 2: time' ), get_comment_date(), get_comment_time() ); ?>
            </time>
        </a>
    </div><!-- .comment-metadata -->

    <?php if ( '0' == $comment->comment_approved ) : ?>
    <p class="comment-awaiting-moderation label label-info"><?php _e( 'Your comment is awaiting moderation.' ); ?></p>
    <?php endif; ?>             

    <div class="comment-content">
         <?php comment_text(); ?>
    </div>

    <ul class="list-inline">
        <?php edit_comment_link( __( 'Edit' ), '<li class="edit-link">', '</li>' ); ?>

    <?php
        comment_reply_link( array_merge( $args, array(
            'add_below' => 'div-comment',
            'depth'     => $depth,
            'max_depth' => $args['max_depth'],
            'before'    => '<li class="reply-link">',
            'after'     => '</li>'
        ) ) );  
    ?>
    </ul>
    </div>  
<?php
}

Comment Walker

wp_list_comments( array(
    'walker'        => new Bootstrap_Comment_Walker(),
 ));

class Bootstrap_Comment_Walker extends Walker_Comment {
    protected function html5_comment( $comment, $depth, $args ) {

?><li id="comment-<?php comment_ID(); ?>" <?php comment_class( empty( $args['has_children'] ) ? '' : 'parent' ); ?>>

    <?php if ( 0 != $args['avatar_size'] ): ?>
    <div class="media-left">
        <a href="<?php echo get_comment_author_url(); ?>" class="media-object"><?php echo get_avatar( $comment, $args['avatar_size'] ); ?></a>
    </div>
    <?php endif; ?>

    <div class="media-body">
    <?php printf( '<h4 class="media-heading">%s</h4>', get_comment_author_link() ); ?>
    <div class="comment-metadata">
        <a href="<?php echo esc_url( get_comment_link( $comment->comment_ID, $args ) ); ?>">
            <time datetime="<?php comment_time( 'c' ); ?>">
                <?php printf( _x( '%1$s at %2$s', '1: date, 2: time' ), get_comment_date(), get_comment_time() ); ?>
            </time>
        </a>
    </div><!-- .comment-metadata -->

    <?php if ( '0' == $comment->comment_approved ) : ?>
    <p class="comment-awaiting-moderation label label-info"><?php _e( 'Your comment is awaiting moderation.' ); ?></p>
    <?php endif; ?>             

    <div class="comment-content">
         <?php comment_text(); ?>
    </div>

    <ul class="list-inline">
        <?php edit_comment_link( __( 'Edit' ), '<li class="edit-link">', '</li>' ); ?>

    <?php
        comment_reply_link( array_merge( $args, array(
            'add_below' => 'div-comment',
            'depth'     => $depth,
            'max_depth' => $args['max_depth'],
            'before'    => '<li class="reply-link">',
            'after'     => '</li>'
        ) ) );  
    ?>
    </ul>
    </div>      
<?php
    }   
}
3

We could rewrite:

wp_list_comments( array(
    'callback'      => 'bootstrap_comment_callback',
 ));

with the null walker parameter:

 wp_list_comments( array(
    'walker'        => null,
    'callback'      => 'bootstrap_comment_callback',
 ));

which means we are using the default Walker_Comment class:

  wp_list_comments( array(
    'walker'        => new Walker_Comment,
    'callback'      => 'bootstrap_comment_callback',
 ));

The Walker_Comment::start_el() method is just a wrapper for one of these protected methods:

Walker_Comment::comment()
Walker_Comment::html5_comment()
Walker_Comment::ping()

that, depending on the context, append each comment to the output string when walking along the comment tree.

Using a custom walker class, that extends the Walker_Comment class, gives us the ability to override these public methods:

Walker_Comment::start_el()
Walker_Comment::end_el()
Walker_Comment::start_lvl()
Walker_Comment::end_lvl()
Walker_Comment::display_element()

in addition to the protected ones above.

If we only need to modify the output of the start_el() method, we would only need to use the callback parameter in wp_list_comments().

1

In the simplest of explanations, the callback argument for wp_list_comments() is used to reference a function that will build the beginning of an individual comment. (The end-callback argument references a function that will close an individual comment.)

So, you can use your own custom function to output an individual comment while still using the core Walker_Comment class to build the entire comment list.

Conversely, you could also use your own class to override either all, or parts of, the core Walker_Comment class.

In your example above, you defined a custom walker class with one method defined: html5_comment(). Since you're extending the core Walker_Comment class, but only overriding one method (html_comment()), WP will use the rest of the methods defined in Walker_Comment to build out the remainder of the comment list.

Essentially, use callback/end-callback to build out an individual comment, and use a custom Walker class to build out the entire comment list. You don't need both, it's one or the other.

Incidentally I just wrote an article outlining this in greater detail based on a plugin I released relating to Bootstrap comments for WordPress. You can find it here: http://darrinb.com/wp-bootstrap-comments/

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.