Disable Comments Snippet Generator
Turn WordPress comments off properly: close them on old posts, hide existing ones, drop the admin menu, and close the REST and XML-RPC routes.
<?php
/**
* Comments off.
*
* Nothing here deletes a comment. Every part is a filter, so removing this
* file brings the comments back exactly as they were.
*/
/**
* Closes the comment form.
*
* @param bool $open Whether comments are open.
* @param int $post_id The post.
* @return bool
*/
function my_site_comments_open( $open, $post_id ) {
return false;
}
// Priority 20 so it runs after anything that opened them.
add_filter( 'comments_open', 'my_site_comments_open', 20, 2 );
add_filter( 'pings_open', 'my_site_comments_open', 20, 2 );
/**
* Hides comments that were already published.
*
* They stay in the database; this only stops them being rendered.
*
* @param array $comments The comments.
* @return array
*/
function my_site_hide_comments( $comments ) {
return array();
}
add_filter( 'comments_array', 'my_site_hide_comments', 20 );
/**
* Takes comment support off the post types, which removes the Discussion
* panel from the editor as well.
*/
function my_site_remove_comment_support() {
foreach ( get_post_types() as $type ) {
remove_post_type_support( $type, 'comments' );
remove_post_type_support( $type, 'trackbacks' );
}
}
add_action( 'init', 'my_site_remove_comment_support', 100 );
/**
* Removes the Comments menu.
*/
function my_site_remove_comments_menu() {
remove_menu_page( 'edit-comments.php' );
}
add_action( 'admin_menu', 'my_site_remove_comments_menu' );
/**
* Redirects anyone who reaches the screen by URL.
*/
function my_site_block_comments_screen() {
global $pagenow;
if ( 'edit-comments.php' === $pagenow ) {
wp_safe_redirect( admin_url() );
exit;
}
}
add_action( 'admin_init', 'my_site_block_comments_screen' );
/**
* Removes the toolbar comments icon.
*/
function my_site_remove_comments_toolbar() {
if ( is_admin_bar_showing() ) {
remove_action( 'admin_bar_menu', 'wp_admin_bar_comments_menu', 60 );
}
}
add_action( 'init', 'my_site_remove_comments_toolbar' );
/**
* Closes the REST comments route.
*
* The form being gone from the theme does not stop a POST to
* /wp-json/wp/v2/comments.
*
* @param array $endpoints REST endpoints.
* @return array
*/
function my_site_remove_comment_endpoints( $endpoints ) {
unset( $endpoints['/wp/v2/comments'] );
unset( $endpoints['/wp/v2/comments/(?P<id>[\d]+)'] );
return $endpoints;
}
add_filter( 'rest_endpoints', 'my_site_remove_comment_endpoints' );
/**
* Removes the XML-RPC comment methods.
*
* @param array $methods XML-RPC methods.
* @return array
*/
function my_site_remove_xmlrpc_comments( $methods ) {
unset( $methods['wp.newComment'] );
unset( $methods['wp.getComments'] );
unset( $methods['wp.getComment'] );
unset( $methods['wp.editComment'] );
unset( $methods['wp.deleteComment'] );
return $methods;
}
add_filter( 'xmlrpc_methods', 'my_site_remove_xmlrpc_comments' );
Output is valid and updates as you type.
Fix the highlighted fields to update the output.
Turn comments off in the four places they actually live: the front end, the editor, the admin and the API. Nothing here deletes a comment, so removing the file brings everything back.
How to use
- Decide the scope. Off everywhere is the common case; one post type is for a site where the blog keeps its comments and the rest does not.
- Keep “close the REST route” on. Removing the form from the theme does nothing to
/wp-json/wp/v2/comments, which is where automated spam arrives. - Leave “hide existing” on if the site has old comments you do not want shown. They stay in the database, so it is reversible.
- Removing comment support takes the Discussion panel out of the editor, which stops someone turning comments back on for one post and wondering why nothing appears.
- Put the snippet in a site specific plugin, not the theme. Comment settings should survive a redesign.
Example
The front end part, which is the piece most snippets get wrong:
function acme_comments_open( $open, $post_id ) {
return false;
}
// Priority 20 so it runs after anything that opened them.
add_filter( 'comments_open', 'acme_comments_open', 20, 2 );
add_filter( 'pings_open', 'acme_comments_open', 20, 2 );
pings_open matters as much as comments_open: pingbacks are comments, and a snippet that only closes one leaves the site accepting trackback spam.
Pitfalls
- Closing the form does not close the endpoint. Spam bots POST to
wp-comments-post.phpand to the REST route directly, and neither cares what the theme renders. comments_openat the default priority can be re-opened by a plugin that runs later. Priority 20 puts you after most of them.- Removing the admin menu hides the screen but leaves the URL reachable. The generated code redirects it too.
- Removing comment support on
inittoo early misses post types registered later. Priority 100 is late enough for most plugins. - Hiding comments is not deleting them. They still count in the database and still show in exports, which is usually what you want.
- Turning off comments does not remove comment markup from the theme’s templates, so an empty container can remain in the markup.
- XML-RPC comment methods stay available unless you remove them, even with comments closed everywhere else.
- Setting
default_comment_statusto closed only affects new posts. Existing ones keep whatever they had, which is why the filter matters.
Compatibility
comments_open, pings_open and comments_array have been stable since WordPress 2.x. rest_endpoints needs WordPress 4.7, and xmlrpc_methods has been available since 3.5. remove_post_type_support() works on any post type, including ones plugins register. The generated code targets PHP 7.0 and up, and the tool runs entirely in your browser.
Frequently asked questions
Does this delete my existing comments?
Why are bots still posting comments?
Should I use a plugin instead?
How do I keep comments on the blog only?
post. Everything else is closed.Will this affect WooCommerce reviews?
product post type, or choose the scope carefully.