Comment Walker vs. Comment Callback

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
    }   
}

Topic comments-template walker comment-form comments Wordpress

Category Web


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 class="children"> ...

Beside using Walkers and Callbacks, a straight to the point fix would be to do a preg_replace before echoing-it-out.

<?php

$buffer = wp_list_comments(
    array (
        //...
        'echo' => false,
    ),
    //...
);

$buffer = preg_replace( '/class="children"/', 'class="list-unstyled"', $buffer );

echo $buffer;

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/


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().

About

Geeks Mental is a community that publishes articles and tutorials about Web, Android, Data Science, new techniques and Linux security.