Incluir Custom Post Types en el Widget "Publicaciones Recientes"
Puedo incluir fácilmente mis custom post types en el loop principal haciendo pequeños ajustes con query_posts()
, pero no estoy seguro de cómo incluir custom post types en el widget "Publicaciones Recientes" de la barra lateral (o en cualquiera de los otros widgets).
¿Cómo debería proceder para expandir el alcance de "Publicaciones Recientes" para incluir más que solo el tipo de publicación nativo?

Tendrás que editar el código del widget Entradas recientes o crear tu propia versión basada en el predeterminado. El código está en el archivo wp-includes/default-widgets.php
alrededor de la línea 513. Pero como nunca deberías modificar el núcleo, mi recomendación sería copiar el código para crear tu propio widget Mis Entradas Recientes Personalizadas y usarlo en tu sitio. Simplemente coloca la nueva clase del widget en el archivo functions.php
de tu tema o utilízalo en un plugin.
La única modificación real que necesitas hacer son al nombre de la clase del widget y a las funciones y opciones encapsuladas (para que no haya conflictos de nombres con el widget original Entradas Recientes). Después de eso, necesitarás editar la llamada a WP_Query
en el constructor widget()
para que incluya tu tipo de entrada personalizado.
Para este ejemplo, he configurado post_type
igual a array('post, 'page', 'custom-post-type')
... necesitarás modificar esto para que se ajuste a tu caso de uso específico.
Aquí está el código completo del widget como referencia:
/**
* Clase del widget My_Custom_Recent_Posts
*
*/
class WP_Widget_My_Custom_Recent_Posts extends WP_Widget {
function __construct() {
$widget_ops = array('classname' => 'widget_my_custom_recent_entries', 'description' => __( "Las entradas más recientes en tu sitio") );
$this->WP_Widget('my-custom-recent-posts', __('Mis Entradas Recientes Personalizadas'), $widget_ops);
$this->alt_option_name = 'widget_my_custom_recent_entries';
add_action( 'save_post', array(&$this, 'flush_widget_cache') );
add_action( 'deleted_post', array(&$this, 'flush_widget_cache') );
add_action( 'switch_theme', array(&$this, 'flush_widget_cache') );
}
function widget($args, $instance) {
$cache = wp_cache_get('widget_my_custom_recent_posts', 'widget');
if ( !is_array($cache) )
$cache = array();
if ( isset($cache[$args['widget_id']]) ) {
echo $cache[$args['widget_id']];
return;
}
ob_start();
extract($args);
$title = apply_filters('widget_title', empty($instance['title']) ? __('Mis Entradas Recientes Personalizadas') : $instance['title'], $instance, $this->id_base);
if ( !$number = (int) $instance['number'] )
$number = 10;
else if ( $number < 1 )
$number = 1;
else if ( $number > 15 )
$number = 15;
$r = new WP_Query(array('showposts' => $number, 'nopaging' => 0, 'post_status' => 'publish', 'ignore_sticky_posts' => true, 'post_type' => array('post', 'page', 'custom-post-type')));
if ($r->have_posts()) :
?>
<?php echo $before_widget; ?>
<?php if ( $title ) echo $before_title . $title . $after_title; ?>
<ul>
<?php while ($r->have_posts()) : $r->the_post(); ?>
<li><a href="<?php the_permalink() ?>" title="<?php echo esc_attr(get_the_title() ? get_the_title() : get_the_ID()); ?>"><?php if ( get_the_title() ) the_title(); else the_ID(); ?></a></li>
<?php endwhile; ?>
</ul>
<?php echo $after_widget; ?>
<?php
// Restablece la variable global $the_post ya que esta consulta la habrá sobrescrito
wp_reset_postdata();
endif;
$cache[$args['widget_id']] = ob_get_flush();
wp_cache_set('widget_my_custom_recent_posts', $cache, 'widget');
}
function update( $new_instance, $old_instance ) {
$instance = $old_instance;
$instance['title'] = strip_tags($new_instance['title']);
$instance['number'] = (int) $new_instance['number'];
$this->flush_widget_cache();
$alloptions = wp_cache_get( 'alloptions', 'options' );
if ( isset($alloptions['widget_my_custom_recent_entries']) )
delete_option('widget_my_custom_recent_entries');
return $instance;
}
function flush_widget_cache() {
wp_cache_delete('widget_my_custom_recent_posts', 'widget');
}
function form( $instance ) {
$title = isset($instance['title']) ? esc_attr($instance['title']) : '';
if ( !isset($instance['number']) || !$number = (int) $instance['number'] )
$number = 5;
?>
<p><label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Título:'); ?></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>
<p><label for="<?php echo $this->get_field_id('number'); ?>"><?php _e('Número de entradas a mostrar:'); ?></label>
<input id="<?php echo $this->get_field_id('number'); ?>" name="<?php echo $this->get_field_name('number'); ?>" type="text" value="<?php echo $number; ?>" size="3" /></p>
<?php
}
}

En lugar de cambiar el nombre del widget, creo que sería mejor usar unregister_widget
en el widget predeterminado antes de registrar el nuevo (menos confuso en el administrador).

Sí, podrías usar unregister_widget
, pero este método te da acceso a ambos por si quieres usar los dos (es decir, tener un widget de Publicaciones Recientes para mostrar las entradas recientes del blog y un widget de Reseñas de Películas Recientes para mostrar solo las entradas recientes de un tipo de contenido personalizado específico).

solo una nota para cualquiera que pruebe el código anterior: No olvides agregar esto: register_widget('WP_Widget_My_Custom_Recent_Posts');

Gracias por proporcionar el código para la clase de widget personalizado y por las explicaciones. Ha sido muy útil. Sin embargo, me preguntaba si habría alguna manera de modificarlo para permitir HTML incrustado en el campo del título. Básicamente necesito convertir el título del widget en un enlace clickable, pero por defecto el HTML incrustado es eliminado de los títulos de los widgets. Cualquier ayuda sería muy apreciada.

Ian, por favor pregunta eso como una pregunta separada para que podamos tener una discusión completa...

No sé nada de PHP pero ¿no se podría simplemente Extend
la clase por defecto y actualizar las variables requeridas? ¿En lugar de un copiar y pegar completo?

A partir de al menos la versión 3.6, puedes usar el siguiente código para modificar la consulta utilizada:
add_filter('widget_posts_args', 'widget_posts_args_add_custom_type');
function widget_posts_args_add_custom_type($params) {
$params['post_type'] = array('post','custom_type');
return $params;
}
Solo añade los tipos que quieras en el array para post_type y deberían aparecer.
Actualización: Según http://core.trac.wordpress.org/ticket/16159, esto ha estado disponible desde la versión 3.4

Acabo de encontrar un plugin genial donde el trabajo pesado ya está hecho, tiene una documentación excelente y buen soporte del autor. Realmente me ha impresionado.
Permite anulaciones de WP_Query (lo que te permite filtrar por tipos de entrada personalizados y cualquier otra cosa que desees) e incluye instrucciones claras sobre cómo usarlo.
Documentación http://www.pjgalbraith.com/2011/08/recent-posts-plus/
URL del plugin de WordPress http://wordpress.org/extend/plugins/recent-posts-plus/
¡Hizo que mi trabajo fuera mucho más corto!

También he creado un widget plugin para esto que es más personalizable que el widget de Publicaciones Recientes. Si estás interesado, puedes descargarlo aquí http://new2wp.com/pro/latest-custom-post-type-posts-sidebar-widget/

Este código crea un nuevo widget de publicaciones recientes que incluye tus CPT's
Hay 2 pasos involucrados al extender el widget nativo de publicaciones recientes:
i. Crear una nueva clase para tu widget personalizado de publicaciones recientes, lo cual puedes hacer copiando y renombrando el código del widget de publicaciones recientes del archivo defaults-widgets.php en la carpeta wp-includes.
ii. Luego necesitarás registrar el nuevo widget y puedes elegir desregistrar el widget nativo de publicaciones recientes o usar ambos.
Todo el código puede copiarse directamente en tu archivo functions.php usando un tema hijo o crear otro archivo e incluirlo en el archivo functions.php de tu tema hijo.
<?php
class WPSites_Recent_Posts extends WP_Widget {
public function __construct() {
$widget_ops = array('classname' => 'wpsites_recent_posts', 'description' => __( "Últimos CPT's & Publicaciones.") );
parent::__construct('wpsites-recent-posts', __('Publicaciones Recientes de WP Sites'), $widget_ops);
$this->alt_option_name = 'wpsites_recent_posts';
add_action( 'save_post', array($this, 'flush_widget_cache') );
add_action( 'deleted_post', array($this, 'flush_widget_cache') );
add_action( 'switch_theme', array($this, 'flush_widget_cache') );
}
public function widget($args, $instance) {
$cache = array();
if ( ! $this->is_preview() ) {
$cache = wp_cache_get( 'wpsites_widget_recent_posts', 'widget' );
}
if ( ! is_array( $cache ) ) {
$cache = array();
}
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'] : __( 'Publicaciones Recientes' );
/** Este filtro está documentado en wp-includes/default-widgets.php */
$title = apply_filters( 'widget_title', $title, $instance, $this->id_base );
$number = ( ! empty( $instance['number'] ) ) ? absint( $instance['number'] ) : 5;
if ( ! $number )
$number = 5;
$show_date = isset( $instance['show_date'] ) ? $instance['show_date'] : false;
$r = new WP_Query( apply_filters( 'widget_posts_args', array(
'posts_per_page' => $number,
'no_found_rows' => true,
'post_status' => 'publish',
'post_type' => array('post', 'portfolio',
'ignore_sticky_posts' => true
) ) ) );
if ($r->have_posts()) :
?>
<?php echo $args['before_widget']; ?>
<?php if ( $title ) {
echo $args['before_title'] . $title . $args['after_title'];
} ?>
<ul>
<?php while ( $r->have_posts() ) : $r->the_post(); ?>
<li>
<a href="<?php the_permalink(); ?>"><?php get_the_title() ? the_title() : the_ID(); ?></a>
<?php if ( $show_date ) : ?>
<span class="post-date"><?php echo get_the_date(); ?></span>
<?php endif; ?>
</li>
<?php endwhile; ?>
</ul>
<?php echo $args['after_widget']; ?>
<?php
wp_reset_postdata();
endif;
if ( ! $this->is_preview() ) {
$cache[ $args['widget_id'] ] = ob_get_flush();
wp_cache_set( 'wpsites_widget_recent_posts', $cache, 'widget' );
} else {
ob_end_flush();
}
}
public function update( $new_instance, $old_instance ) {
$instance = $old_instance;
$instance['title'] = strip_tags($new_instance['title']);
$instance['number'] = (int) $new_instance['number'];
$instance['show_date'] = isset( $new_instance['show_date'] ) ? (bool) $new_instance['show_date'] : false;
$this->flush_widget_cache();
$alloptions = wp_cache_get( 'alloptions', 'options' );
if ( isset($alloptions['wpsites_recent_posts']) )
delete_option('wpsites_recent_posts');
return $instance;
}
public function flush_widget_cache() {
wp_cache_delete('wpsites_widget_recent_posts', 'widget');
}
public function form( $instance ) {
$title = isset( $instance['title'] ) ? esc_attr( $instance['title'] ) : '';
$number = isset( $instance['number'] ) ? absint( $instance['number'] ) : 5;
$show_date = isset( $instance['show_date'] ) ? (bool) $instance['show_date'] : false;
?>
<p><label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e( 'Título:' ); ?></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>
<p><label for="<?php echo $this->get_field_id( 'number' ); ?>"><?php _e( 'Número de publicaciones a mostrar:' ); ?></label>
<input id="<?php echo $this->get_field_id( 'number' ); ?>" name="<?php echo $this->get_field_name( 'number' ); ?>" type="text" value="<?php echo $number; ?>" size="3" /></p>
<p><input class="checkbox" type="checkbox" <?php checked( $show_date ); ?> id="<?php echo $this->get_field_id( 'show_date' ); ?>" name="<?php echo $this->get_field_name( 'show_date' ); ?>" />
<label for="<?php echo $this->get_field_id( 'show_date' ); ?>"><?php _e( '¿Mostrar fecha de publicación?' ); ?></label></p>
<?php
}
}
Registrar el nuevo widget personalizado de publicaciones recientes
function wpsites_widgets_init() {
if ( !is_blog_installed() )
return;
register_widget('WPSites_Recent_Posts');
do_action( 'widgets_init' );
}
add_action( 'init', 'wpsites_widgets_init', 2 );
El código incluye una WP_Query modificada que incluye un array para tipos de publicación incluyendo el CPT portfolio que puedes renombrar para que coincida con tu tipo de publicación personalizado.
Esta es la línea de código que necesita ser modificada:
'post_type' => array('post', 'portfolio',

Es 2020 y vine aquí buscando una solución para los "10 artículos más recientes del tipo de entrada personalizada XYZ". Encontré el plugin que hace eso y más.
Widgets para Tipos de Entradas Personalizadas extiende las funcionalidades estándar de los widgets para entradas habituales (más recientes, archivos mensuales, categorías utilizadas, comentarios recientes, búsqueda, calendario) a tipos de entradas personalizadas.
Seleccionas el widget que necesitas (en mi caso "más recientes") y primero obtienes un selector donde especificas el tipo de entrada personalizada al que debe dirigirse el widget. La opción predeterminada es el clásico 'post', por lo que este plugin es un sustituto de los widgets estándar de WordPress relacionados con entradas.
