Includere Tipi di Post Personalizzati nel Widget "Post Recenti"
Riesco facilmente a includere i miei tipi di post personalizzati nel loop principale apportando piccole modifiche con query_posts()
, ma non sono sicuro di come fare per includere i tipi di post personalizzati nel widget "Post Recenti" nella sidebar (o in qualsiasi altro widget, del resto).
Come posso espandere l'ambito del widget "Post Recenti" per includere più del solo tipo di post nativo?

Dovrai modificare il codice del widget Articoli Recenti o creare la tua versione basata su quella predefinita. Il codice si trova nel file wp-includes/default-widgets.php
intorno alla riga 513. Ma poiché non dovresti mai apportare modifiche al core, la mia raccomandazione è di copiare il codice per creare il tuo widget I Miei Articoli Recenti Personalizzati e utilizzarlo sul tuo sito. Basta inserire la nuova classe del widget nel file functions.php
del tuo tema o utilizzarlo in un plugin.
L'unica modifica reale che devi fare riguarda il nome della classe del widget e le funzioni e le opzioni incapsulate (in modo che non ci siano conflitti di nomi con il widget originale Articoli Recenti). Successivamente, dovrai modificare la chiamata a WP_Query
nel costruttore widget()
in modo che includa il tuo tipo di post personalizzato.
Per questo esempio, ho impostato post_type
uguale a array('post', 'page', 'custom-post-type')
... dovrai modificarlo in base al tuo caso d'uso specifico.
Ecco il codice completo del widget per riferimento:
/**
* Classe 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' => __( "Gli articoli più recenti del tuo sito") );
$this->WP_Widget('my-custom-recent-posts', __('I Miei Articoli Recenti Personalizzati'), $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']) ? __('I Miei Articoli Recenti Personalizzati') : $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
// Ripristina il globale $the_post poiché questa query lo avrà sovrascritto
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('Titolo:'); ?></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('Numero di articoli da mostrare:'); ?></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
}
}

Invece di rinominare il widget, penso che fare unregister_widget
al widget predefinito prima di registrarne uno nuovo sarebbe meglio (meno confuso nell'admin).

Sì, potresti usare unregister_widget
, ma questo metodo ti dà accesso a entrambi nel caso volessi usarli entrambi (ad esempio avere un widget Post Recenti per mostrare i post recenti del blog e un widget Recensioni Film Recenti per mostrare solo i post recenti di un tipo di post personalizzato specifico).

solo una nota per chi prova il codice sopra: Non dimenticare di aggiungere questo: register_widget('WP_Widget_My_Custom_Recent_Posts');

Grazie per aver fornito il codice per la classe del widget personalizzato e per le spiegazioni. Mi è stato molto utile. Tuttavia, mi chiedevo se ci fosse un modo per modificarlo per consentire l'HTML incorporato nel campo del titolo? In sostanza, ho bisogno di trasformare il titolo del widget in un link cliccabile, ma per impostazione predefinita l'HTML incorporato viene rimosso dai titoli dei widget. Qualsiasi aiuto sarebbe molto apprezzato.

Ian, per favore fai questa domanda come una domanda separata in modo da poter avere una discussione completa...

Non so nulla di PHP, ma non sarebbe possibile semplicemente Extend
la classe predefinita e aggiornare le variabili richieste? Invece di un copia-incolla completo?

A partire almeno dalla versione 3.6, puoi utilizzare il seguente codice per modificare la query utilizzata:
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;
}
Basta aggiungere i tipi che desideri nell'array per post_type e dovrebbero apparire.
Aggiornamento: Secondo http://core.trac.wordpress.org/ticket/16159, questa funzionalità è disponibile dalla versione 3.4

Mi sono appena imbattuto in un fantastico plugin dove il lavoro pesante è già fatto, e ha un'ottima documentazione e supporto dall'autore. Sono rimasto davvero colpito.
Permette override di WP_Query (consentendoti di filtrare per custom post types e qualsiasi altra cosa tu voglia) e alcune chiare istruzioni su come usarlo.
Documentazione http://www.pjgalbraith.com/2011/08/recent-posts-plus/
URL del Plugin Wordpress http://wordpress.org/extend/plugins/recent-posts-plus/
Ha reso il mio lavoro solo quel po' più breve!

Ho anche creato un widget plugin per questo che è più personalizzabile del widget Articoli Recenti. Se sei interessato puoi scaricarlo qui http://new2wp.com/pro/latest-custom-post-type-posts-sidebar-widget/

Questo codice crea un nuovo widget per i post recenti che include i tuoi CPT
Ci sono 2 passaggi coinvolti nell'estensione del widget nativo dei post recenti:
i. Creare una nuova classe per il tuo widget personalizzato dei post recenti, che puoi fare copiando e rinominando il codice del widget dei post recenti dal file defaults-widgets.php nella cartella wp-includes.
ii. Poi dovrai registrare il nuovo widget e potrai scegliere se deregistrare il widget nativo dei post recenti o utilizzarli entrambi.
Tutto il codice può essere semplicemente copiato nel tuo file functions usando un child theme oppure creare un altro file e includerlo nel file functions del tuo child theme.
<?php
class WPSites_Recent_Posts extends WP_Widget {
public function __construct() {
$widget_ops = array('classname' => 'wpsites_recent_posts', 'description' => __( "Ultimi CPT e Post.") );
parent::__construct('wpsites-recent-posts', __('Post Recenti di 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'] : __( 'Post Recenti' );
/** Questo filtro è documentato in 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( 'Titolo:' ); ?></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( 'Numero di post da mostrare:' ); ?></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( 'Mostrare la data del post?' ); ?></label></p>
<?php
}
}
Registra il nuovo widget personalizzato per i post recenti
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 );
Il codice include una modifica a WP_Query che include un array per i tipi di post incluso il CPT portfolio che puoi rinominare per adattarlo al tuo custom post type.
Ecco la riga di codice che deve essere modificata:
'post_type' => array('post', 'portfolio',

È il 2020 e sono qui per trovare una soluzione ai "10 articoli più recenti del tipo di post personalizzato XYZ". Ho trovato il plugin che fa proprio questo, e molto altro.
Custom Post Type Widgets estende le funzionalità standard dei widget per i post tradizionali (più recenti, archivi mensili, categorie utilizzate, commenti recenti, ricerca, calendario) ai tipi di post personalizzati.
Selezioni il widget di cui hai bisogno (nel mio caso "più recenti") e ti viene presentata prima una selezione in cui specifichi il tipo di post personalizzato a cui il widget deve fare riferimento. La scelta predefinita è il buon vecchio 'post', quindi questo plugin è un sostituto dei widget predefiniti di WP relativi ai post.
