If a WordPress site has no blog, comments only attract spam. To disable comments in WordPress completely without a plugin, you have to switch them off in several places: post type support, the open/closed check, existing comments, block theme templates and the admin screens. This snippet covers all of them in one code block.
The snippet
<?php
/**
* Disable comments everywhere: front end, block themes, REST, XML-RPC and wp-admin.
*/
// Remove comment and trackback support from every post type.
add_action( 'init', 'dpc_remove_comment_support', 100 );
function dpc_remove_comment_support(): void {
foreach ( get_post_types() as $post_type ) {
if ( post_type_supports( $post_type, 'comments' ) ) {
remove_post_type_support( $post_type, 'comments' );
remove_post_type_support( $post_type, 'trackbacks' );
}
}
}
// Close comments and pings. Forms, wp-comments-post.php, REST and pingbacks all check these.
add_filter( 'comments_open', '__return_false', 20 );
add_filter( 'pings_open', '__return_false', 20 );
// Hide existing comments and counts.
add_filter( 'comments_array', '__return_empty_array', 20 );
add_filter( 'get_comments_number', '__return_zero', 20 );
// Block themes query comments directly, so empty the comment blocks.
foreach ( array( 'core/comments', 'core/post-comments-form', 'core/post-comments-count', 'core/post-comments-link', 'core/latest-comments' ) as $dpc_block ) {
add_filter( "render_block_{$dpc_block}", '__return_empty_string' );
}
unset( $dpc_block );
// No comments feed link, no Recent Comments widget.
add_filter( 'feed_links_show_comments_feed', '__return_false' );
add_action( 'widgets_init', 'dpc_unregister_comments_widget' );
function dpc_unregister_comments_widget(): void {
unregister_widget( 'WP_Widget_Recent_Comments' );
}
// wp-admin: menu, screens and admin bar.
add_action( 'admin_menu', 'dpc_remove_comments_menu' );
function dpc_remove_comments_menu(): void {
remove_menu_page( 'edit-comments.php' );
}
add_action( 'load-edit-comments.php', 'dpc_redirect_comments_screen' );
add_action( 'load-comment.php', 'dpc_redirect_comments_screen' );
function dpc_redirect_comments_screen(): void {
wp_safe_redirect( admin_url() );
exit;
}
add_action( 'admin_bar_menu', 'dpc_remove_comments_admin_bar', 999 );
function dpc_remove_comments_admin_bar( WP_Admin_Bar $admin_bar ): void {
$admin_bar->remove_node( 'comments' );
}
How it works
- Post types: on
initat priority 100, after themes and plugins have registered their post types, comment and trackback support is removed, so the Discussion panel disappears from the editor. - Open or closed:
comments_openandpings_openreturnfalse. WordPress checks these before it shows a form, before it accepts a comment through wp-comments-post.php or the REST API, and before it accepts a pingback. - Existing comments:
comments_arrayis emptied for classic themes, andget_comments_numberreturns 0, so “3 Comments” links and counts disappear. - Block themes: the Comments, Comments Form, Comments Count, Comments Link and Latest Comments blocks render as empty strings, because block themes query comments directly instead of going through
comments_array. - wp-admin: the Comments menu is removed, direct visits to
edit-comments.phpandcomment.phpredirect to the Dashboard, and the admin bar bubble, the Recent Comments widget and the comments feed link are gone.
Compared with the older One-Click Import version: support is removed on init instead of admin_init, so it also applies on the front end; the redirect uses load-{page} hooks and wp_safe_redirect(); block themes are covered; every function has the dpc_ prefix; and the removal of dashboard_recent_comments, a widget WordPress no longer has, is dropped.
Add it with Scripts Organizer
In Scripts Organizer go to Code Blocks → Add New and give the block a name. Set Trigger location to Everywhere, tick PHP under Script location, paste the code into the PHP editor and publish. Leave Action/Hook empty. Everywhere matters here: the code must run in wp-admin for the menus, on the front end for the templates, and in REST and wp-comments-post.php requests, which neither Admin only nor Conditions code reaches.
The same code also works unchanged in a small plugin or an mu-plugin.
Customise it
- Keep WooCommerce reviews (they are comments of type
review): indpc_remove_comment_support()skip'product', and replace the two__return_falsefilters with a function that returnsfalseunlessget_post_type( $post_id )is'product'. - Delete old comments for good: empty them in Comments before you enable the snippet, or run
wp comment delete $(wp comment list --format=ids) --forcewith WP-CLI.
Gotchas
- Comments are hidden, not deleted. Disable the code block and they come back.
- The Activity box on the Dashboard can still list comments that already exist.
- WooCommerce product reviews are comments too, so they are closed and hidden unless you apply the customisation above.
- Don’t expect a measurable speed gain; the benefit is no spam and a cleaner admin.
In the Scripts Organizer library Import it with one click from Scripts Organizer.