Lets use the build in features WordPress has to offer. It is almost always not adviced to use custom SQL whenever WordPress offers native functions to perform the specific duty.
To query our posts, we will make use of WP_Query
. The only problem is, WP_Query
does not support the feature where we look for posts with certain post titles. Luckily, we can filter the build SQL query just before it queries the db. For this, we will use the posts_where
filter to introduce our own custom parameter, wpse_title_match
(and no, this has nothing to do with wrestling).
We need to add the following in a plugin (recommended) or in your themes functions file
add_filter( 'posts_where', function ( $where, $q ) use ( &$wpdb )
{
// Get the value from our new wpse_title_match query var
$title_match = $q->get( 'wpse_title_match' );
// Make sure we have a value, if not, bail
if ( !$title_match )
return $where;
/**
* Lets alter the SQL WHERE clause
*
* Note, this will be an exact 1 to 1 match, adjust as necessary
*/
$where .= $wpdb->prepare(
" AND {$wpdb->posts}.post_title = %s ",
$title_match
);
return $where;
}, 10, 2 );
At this point, it will be better to build yourself a proper widget than to drop everything inside a php widget
Here is a modified widget plugin I recently done here
class WPSE_Get_Duplicate_Post_titles extends WP_Widget
{
public function __construct()
{
parent::__construct(
'widget_get_duplicate_post_titles',
_x( 'Post Title duplicates', 'Post Title duplicates' ),
[ 'description' => __( 'Displays posts which share the same post title.' ) ]
);
$this->alt_option_name="widget_get_duplicate_post_titles";
add_action( 'save_post', [$this, 'flush_widget_cache'] );
add_action( 'deleted_post', [$this, 'flush_widget_cache'] );
add_action( 'switch_theme', [$this, 'flush_widget_cache'] );
}
public function widget( $args, $instance )
{
$cache = [];
if ( ! $this->is_preview() ) {
$cache = wp_cache_get( 'widget_bpfi', 'widget' );
}
if ( ! is_array( $cache ) ) {
$cache = [];
}
if ( ! isset( $args['widget_id'] ) ) {
$args['widget_id'] = $this->id;
}
if ( isset( $cache[ $args['widget_id'] ] ) ) {
echo $cache[ $args['widget_id'] ];
return;
}
ob_start();
$title = ( ! empty( $instance['title'] ) ) ? $instance['title'] : __( 'Post Title Duplicates' );
/** This filter is documented in wp-includes/default-widgets.php */
$title = apply_filters( 'widget_title', $title, $instance, $this->id_base );
// ADD YOUR CUSTOM PHP CODE HERE FOR EXECUTION TO DISPLAY ON FRONT END
// First make sure this a single post page
if ( is_single() ) { // We are on a single page
// Get the current post object
$post_object = $GLOBALS['wp_the_query']->get_queried_object();
// Run our query to get the posts with duplicate titles
$args = [
'posts_per_page' => -1, // Get all posts
'post_type' => 'post',
'wpse_title_match' => $post_object->post_title,
'post__not_in' => [$post_object->ID], // Exclude current post
'tax_query' => [
[
'taxonomy' => 'category',
'field' => 'slug',
'terms' => 'chroniques'
]
],
// Any other arguments
];
$loop = new WP_Query( $args );
// Run the loop
if ( $loop->have_posts() ) {
while ( $loop->have_posts() ) {
$loop->the_post();
// Display your posts
the_title() . "\n";
}
wp_reset_postdata();
}
}
echo $args['after_widget'];
if ( ! $this->is_preview() ) {
$cache[ $args['widget_id'] ] = ob_get_flush();
wp_cache_set( 'widget_bpfi', $cache, 'widget' );
} else {
ob_end_flush();
}
}
public function update( $new_instance, $old_instance )
{
$instance = $old_instance;
$instance['title'] = strip_tags( $new_instance['title'] );
$this->flush_widget_cache();
$alloptions = wp_cache_get( 'alloptions', 'options' );
if ( isset($alloptions['widget_get_duplicate_post_titles']) )
delete_option('widget_get_duplicate_post_titles');
return $instance;
}
public function flush_widget_cache()
{
wp_cache_delete('widget_bpfi', 'widget');
}
public function form( $instance )
{
$title = isset( $instance['title'] ) ? esc_attr( $instance['title'] ) : '';
?>
<p>
<label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e( 'Title:' ); ?></label>
<input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo $title; ?>" />
</p>
<?php
}
}
add_action( 'widgets_init', function ()
{
register_widget( 'WPSE_Get_Duplicate_Post_titles' );
});
What I also like to do is to always completely remove a widget when it is is totally out of context to avoid the sidebar from rendering a blank space when no other widgets are displayed
We can try the same approach as I have described here. You can just add this at the bottom of the plugin
add_filter( 'sidebars_widgets', function ( $sidebars_widgets )
{
// Return our filter when we are on admin screen
if ( is_admin() )
return $sidebars_widgets;
// Make sure we are not on the blog page, if we are, bail
if ( is_single() )
return $sidebars_widgets;
/**
* Widget we need to target. This should be the name/id we used to register it
*
* EXAMPLE
* parent::__construct(
'widget_get_duplicate_post_titles',
_x( 'Blog Page Featured Image', 'Blog page featured image' ),
[ 'description' => __( 'Displays the featured image for the page set as blog page.' ) ]
);
*
*/
$custom_widget="widget_get_duplicate_post_titles";
// See if our custom widget exists is any sidebar, if so, get the array index
foreach ( $sidebars_widgets as $sidebars_key=>$sidebars_widget ) {
// Skip the wp_inactive_widgets set, we do not need them
if ( $sidebars_key == 'wp_inactive_widgets' )
continue;
// Only continue our operation if $sidebars_widget are not an empty array
if ( $sidebars_widget ) {
foreach ( $sidebars_widget as $k=>$v ) {
/**
* Look for our custom widget, if found, unset it from the $sidebars_widgets array
* @see stripos()
*/
if ( stripos( $v, $custom_widget ) !== false )
unset( $sidebars_widgets[$sidebars_key][$k] );
} // endforeach $sidebars_widget
} // endif $sidebars_widget
} // endforeach $sidebars_widgets
return $sidebars_widgets;
});
FEW NOTES
-
All the above code
is untested andrequires PHP 5.4+ -
You should adjust the
WP_Query
arguments in the widget to suit your needs. Everywhere where I added values in capital letters, you should fill in appropriate values -
Both of the filter functions can be added in the same plugin, so the complete plugin will look like this
FINAL CODE
<?php
/*
Plugin Name: WPSE Get Duplicate Post Titles
Plugin URI: https://wordpress.stackexchange.com/q/220279/31545
Description: Displays posts with the same title in the sidear
Version: 1.0.0
Author: Pieter Goosen
Author URI: https://wordpress.stackexchange.com/users/31545/pieter-goosen
License: GPL2
License URI: https://www.gnu.org/licenses/gpl-2.0.html
*/
add_filter( 'posts_where', function ( $where, $q ) use ( &$wpdb )
{
// Get the value from our new wpse_title_match query var
$title_match = $q->get( 'wpse_title_match' );
// Make sure we have a value, if not, bail
if ( !$title_match )
return $where;
/**
* Lets alter the SQL WHERE clause
*
* Note, this will be an exact 1 to 1 match, adjust as necessary
*/
$where .= $wpdb->prepare(
" AND {$wpdb->posts}.post_title = %s ",
$title_match
);
return $where;
}, 10, 2 );
class WPSE_Get_Duplicate_Post_titles extends WP_Widget
{
public function __construct()
{
parent::__construct(
'widget_get_duplicate_post_titles',
_x( 'Post Title duplicates', 'Post Title duplicates' ),
[ 'description' => __( 'Displays posts which share the same post title.' ) ]
);
$this->alt_option_name="widget_get_duplicate_post_titles";
add_action( 'save_post', [$this, 'flush_widget_cache'] );
add_action( 'deleted_post', [$this, 'flush_widget_cache'] );
add_action( 'switch_theme', [$this, 'flush_widget_cache'] );
}
public function widget( $args, $instance )
{
$cache = [];
if ( ! $this->is_preview() ) {
$cache = wp_cache_get( 'widget_bpfi', 'widget' );
}
if ( ! is_array( $cache ) ) {
$cache = [];
}
if ( ! isset( $args['widget_id'] ) ) {
$args['widget_id'] = $this->id;
}
if ( isset( $cache[ $args['widget_id'] ] ) ) {
echo $cache[ $args['widget_id'] ];
return;
}
ob_start();
$title = ( ! empty( $instance['title'] ) ) ? $instance['title'] : __( 'Post Title Duplicates' );
/** This filter is documented in wp-includes/default-widgets.php */
$title = apply_filters( 'widget_title', $title, $instance, $this->id_base );
// ADD YOUR CUSTOM PHP CODE HERE FOR EXECUTION TO DISPLAY ON FRONT END
// First make sure this a single post page
if ( is_single() ) { // We are on a single page
// Get the current post object
$post_object = $GLOBALS['wp_the_query']->get_queried_object();
// Run our query to get the posts with duplicate titles
$args = [
'posts_per_page' => -1, // Get all posts
'post_type' => 'post',
'wpse_title_match' => $post_object->post_title,
'post__not_in' => [$post_object->ID], // Exclude current post
'tax_query' => [
[
'taxonomy' => 'category',
'field' => 'slug',
'terms' => 'chroniques'
]
],
// Any other arguments
];
$loop = new WP_Query( $args );
// Run the loop
if ( $loop->have_posts() ) {
while ( $loop->have_posts() ) {
$loop->the_post();
// Display your posts
the_title() . "\n";
}
wp_reset_postdata();
}
}
echo $args['after_widget'];
if ( ! $this->is_preview() ) {
$cache[ $args['widget_id'] ] = ob_get_flush();
wp_cache_set( 'widget_bpfi', $cache, 'widget' );
} else {
ob_end_flush();
}
}
public function update( $new_instance, $old_instance )
{
$instance = $old_instance;
$instance['title'] = strip_tags( $new_instance['title'] );
$this->flush_widget_cache();
$alloptions = wp_cache_get( 'alloptions', 'options' );
if ( isset($alloptions['widget_get_duplicate_post_titles']) )
delete_option('widget_get_duplicate_post_titles');
return $instance;
}
public function flush_widget_cache()
{
wp_cache_delete('widget_bpfi', 'widget');
}
public function form( $instance )
{
$title = isset( $instance['title'] ) ? esc_attr( $instance['title'] ) : '';
?>
<p>
<label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e( 'Title:' ); ?></label>
<input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo $title; ?>" />
</p>
<?php
}
}
add_action( 'widgets_init', function ()
{
register_widget( 'WPSE_Get_Duplicate_Post_titles' );
});
add_filter( 'sidebars_widgets', function ( $sidebars_widgets )
{
// Return our filter when we are on admin screen
if ( is_admin() )
return $sidebars_widgets;
// Make sure we are not on the blog page, if we are, bail
if ( is_single() )
return $sidebars_widgets;
/**
* Widget we need to target. This should be the name/id we used to register it
*
* EXAMPLE
* parent::__construct(
'widget_get_duplicate_post_titles',
_x( 'Blog Page Featured Image', 'Blog page featured image' ),
[ 'description' => __( 'Displays the featured image for the pge set as blog page.' ) ]
);
*
*/
$custom_widget="widget_get_duplicate_post_titles";
// See if our custom widget exists is any sidebar, if so, get the array index
foreach ( $sidebars_widgets as $sidebars_key=>$sidebars_widget ) {
// Skip the wp_inactive_widgets set, we do not need them
if ( $sidebars_key == 'wp_inactive_widgets' )
continue;
// Only continue our operation if $sidebars_widget are not an empty array
if ( $sidebars_widget ) {
foreach ( $sidebars_widget as $k=>$v ) {
/**
* Look for our custom widget, if found, unset it from the $sidebars_widgets array
* @see stripos()
*/
if ( stripos( $v, $custom_widget ) !== false )
unset( $sidebars_widgets[$sidebars_key][$k] );
} // endforeach $sidebars_widget
} // endif $sidebars_widget
} // endforeach $sidebars_widgets
return $sidebars_widgets;
});
EDIT
You can extend the code inside the loop by looking at the source code of the content.php
template parts in one of the bundled themes.