How to display the comments_template with a shortcode, in WordPress?

I managed to display the comment_form with a shortcode (while removing it from the default location) using the code below:

`add_shortcode( 'wpse_comment_form', function( $atts = array(), $content = '' )
{
    if( is_singular() && post_type_supports( get_post_type(), 'comments' ) )
    {
        ob_start();
        comment_form();
        print(  '<style>.no-comments { display: none; }</style>' );
        add_filter( 'comments_open', '__return_false' );
        return ob_get_clean();
    }
    return '';
}, 10, 2 );

Code suggested by birgire in this answer: https://wordpress.stackexchange.com/a/177289/26350

Read More

For more clarity, here is where I want to get: I need to display both the comments form and the comments list through shortcodes and in different locations. I managed to mimic the same code above to display the comments_template (and later editing the comments.php to remove the comment_form from it, since what I really need to display is the comments list) but the comments list displays 2x, one in the shortcode location and also at the bottom of the post (default location). I tried to use the same code to display the wp_list_comments independently but without success.

Related posts

Leave a Reply

3 comments

  1. If you do not provide an array of comments wo wp_list_comments, then it expects to find that a query has already been done (i.e. in the loop).

    If you want to display comments for a post independent of the loop, you can use something like:

        $comments = get_comments( array( 'post_id' => $id ) );
        wp_list_comments( array( 'per_page' => how many to show ), $comments);
    

    So to put it in a shortcode you would do something like (not tested):

    add_shortcode( 'wpse_comment_list', function( $atts = array(), $content = '' )
    {
        if( isset($atts['id']) && post_type_supports( $atts['id'], 'comments' ) )
        {
            ob_start();
            $comments = get_comments( array( 'post_id' => $atts['id'] ) );
            wp_list_comments( array( 'per_page' => how many to show ), $comments);
            return ob_get_clean();
        }
        return '';
    }, 10, 2 );
    

    and you would invoke it with [wpse_comment_list id="33"] (or whatever the id is).

  2. I managed to arrive at the result that I needed but partly through deleting on my child-theme the parts that I couldn’t remove through code.
    I mimicked the code used to shortcode-display the comment_form (above in the question) to shortcode-display the comments_template (here below). It displayed it where I needed but it didn’t remove it’s “ghost” from the bottom of the post like the previous code did for the comment_form. So I copied single.php to my child-theme and deleted all this:

    <?php
    `// If comments are open or we have at least one, load up
        the comment template
        if ( comments_open() || '0' != get_comments_number() )
        comments_template( '', true );
    ?>
    

    It worked. Not sure it’s the best way though and I’m curious about it. I won’t need comments at the bottom of posts anymore; my comment form is a different form now and has different locations too, in case that is the only issue.

    Here is the code I used to shortcode-display the comments_template. I needed it to display only the comments and not the form, so I removed the comments_form call from the comments.php in my child-theme.

    add_shortcode( 'wpse_comments_template', function( $atts = array(), $content = '' )
    {
        if( is_singular() && post_type_supports( get_post_type(), 'comments' ) )
        {
            ob_start();
            comments_template();
            print(  '<style>#comments-title { display: none; }</style>' );
            return ob_get_clean();
        }
        return '';
    }, 10, 2 ); 
    
  3. If you are running the [wpse_comments_template] shortcode before this part in your theme:

    <?php
        if ( comments_open() || '0' != get_comments_number() )
            comments_template( '', true );
    ?>
    

    then it’s attempting to use:

    add_shortcode( 'wpse_comments_template', function( $atts = array(), $content = '' )
    {
        if( is_singular() && post_type_supports( get_post_type(), 'comments' ) )
        {
            ob_start();
            comments_template();
            add_filter( 'comments_open',         '__return_false'             );
            add_filter( 'get_comments_number',   '__return_zero'              );
            return ob_get_clean();
        }
        return '';
    }, 10, 2 );
    

    but this might interfere with comment related stuff that comes later, for example in the sidebar.

    So it would be more accurate to use:

    /**     
     * Display the comment template with the [wpse_comments_template] 
     * shortcode on singular pages. 
     *
     * @see http://stackoverflow.com/a/28644134/2078474
     */
     add_shortcode( 'wpse_comments_template', function( $atts = array(), $content = '' )
     {
        if( is_singular() && post_type_supports( get_post_type(), 'comments' ) )
        {
            ob_start();
            comments_template();
            add_filter( 'comments_open',       'wpse_comments_open'   );
            add_filter( 'get_comments_number', 'wpse_comments_number' );
            return ob_get_clean();
        }
        return '';
    }, 10, 2 );
    
    function wpse_comments_open( $open )
    {
        remove_filter( current_filter(), __FUNCTION__ );
        return false;
    }
    
    function wpse_comments_number( $open )
    {
        remove_filter( current_filter(), __FUNCTION__ );
        return 0;
    }
    

    and you wouldn’t have to remove any code from your theme.

    I tested this on the Twenty Fifteen theme and it seemed to work as expected.