Включение пользовательских типов записей в виджет "Последние записи"

30 сент. 2010 г., 17:36:06
Просмотры: 22.8K
Голосов: 7

Я могу легко включить свои пользовательские типы записей в основной цикл, внося небольшие изменения с помощью query_posts(), но я не уверен, как включить пользовательские типы записей в виджет "Последние записи" в сайдбаре (или в любые другие виджеты).

Как я могу расширить область действия виджета "Последние записи", чтобы он включал не только стандартный тип записей?

1
Комментарии

Никогда не используйте query_posts()

Brad Dalton Brad Dalton
25 июл. 2014 г. 01:17:31
Все ответы на вопрос 7
7

Вам придется отредактировать код виджета Недавние записи или создать собственную версию на основе стандартной. Код находится в файле wp-includes/default-widgets.php примерно на строке 513. Но так как вносить изменения в ядро не рекомендуется, лучше всего скопировать код и создать собственный виджет Мои пользовательские недавние записи, который затем можно будет использовать на сайте. Просто добавьте новый класс виджета в файл темы functions.php или используйте его в плагине.

Основное изменение, которое нужно внести, — это имя класса виджета и его инкапсулированных функций и опций (чтобы избежать конфликтов имен с оригинальным виджетом Недавние записи). После этого необходимо отредактировать вызов WP_Query в конструкторе widget(), чтобы он включал ваш пользовательский тип записи.

В этом примере я установил параметр post_type равным array('post, 'page', 'custom-post-type') ... вам нужно изменить его в соответствии с вашими потребностями.

Вот полный код виджета для справки:

/**
  * Класс виджета 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' => __( "Последние записи на вашем сайте") );
        $this->WP_Widget('my-custom-recent-posts', __('Мои пользовательские недавние записи'), $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']) ? __('Мои пользовательские недавние записи') : $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
        // Сброс глобальной переменной $the_post, так как запрос мог ее изменить
        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('Заголовок:'); ?></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('Количество записей для отображения:'); ?></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
    }
}
30 сент. 2010 г. 18:13:10
Комментарии

Вместо переименования виджета, я думаю, что лучше сначала сделать unregister_widget для виджета по умолчанию перед регистрацией нового (это будет менее запутанно в админке).

sorich87 sorich87
30 сент. 2010 г. 18:25:33

Да, вы можете использовать unregister_widget, но этот метод дает вам доступ к обоим, если вы хотите использовать оба (например, иметь виджет Недавние записи для отображения недавних записей блога и виджет Недавние обзоры фильмов для отображения только записей определенного пользовательского типа).

EAMann EAMann
30 сент. 2010 г. 18:31:55

небольшое замечание для тех, кто пробует код выше: Не забудьте добавить это: register_widget('WP_Widget_My_Custom_Recent_Posts');

Fredrik Holm Fredrik Holm
24 февр. 2011 г. 15:28:11

Спасибо за предоставление кода для пользовательского класса виджета и за объяснения. Это очень пригодилось. Однако мне интересно, есть ли способ изменить его, чтобы разрешить встроенный HTML в поле заголовка? По сути, мне нужно превратить заголовок виджета в кликабельную ссылку, но по умолчанию встроенный HTML удаляется из заголовков виджетов. Любая помощь будет очень ценной.

Ian Young Ian Young
29 апр. 2011 г. 12:57:21

Иэн, пожалуйста, задайте это как отдельный вопрос, чтобы мы могли обсудить его полностью...

EAMann EAMann
29 апр. 2011 г. 16:51:07

Я ничего не знаю о PHP, но разве нельзя просто Extend стандартный класс и обновить необходимые переменные? Вместо полного копирования и вставки?

thornomad thornomad
10 мар. 2012 г. 23:02:18

К сожалению, класс WP_Widget_Recent_Posts не очень подходит для расширения и изменения всего нескольких свойств - элементы, которые вам нужно изменить, находятся в середине довольно больших методов.

Phil Gyford Phil Gyford
16 февр. 2017 г. 20:27:34
Показать остальные 2 комментариев
0

Начиная с версии 3.6 (как минимум), вы можете использовать следующий код для изменения запроса:

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;
}

Просто добавьте нужные типы записей в массив post_type, и они должны отображаться.

Обновление: Согласно http://core.trac.wordpress.org/ticket/16159, эта возможность доступна начиная с версии 3.4

30 сент. 2013 г. 00:30:12
0

Я только что нашел отличный плагин, где вся сложная работа уже сделана, и у него отличная документация и поддержка автора. Я действительно впечатлен.

Он позволяет переопределять WP_Query (что дает возможность фильтровать по пользовательским типам записей и всему, что вам может понадобиться), а также содержит четкие инструкции по его использованию.

Документация http://www.pjgalbraith.com/2011/08/recent-posts-plus/

Ссылка на плагин WordPress http://wordpress.org/extend/plugins/recent-posts-plus/

Это значительно упростило мою работу!

27 июл. 2012 г. 17:32:18
2

Вы можете скопировать код виджета (см. /wp-includes/default-widgets.php) и изменить строку запроса.

30 сент. 2010 г. 18:03:00
Комментарии

Именно мои мысли... но я уже наполовину закончил писать ответ, когда ты это опубликовал...

EAMann EAMann
30 сент. 2010 г. 18:13:48

Твой ответ очень полный! +1

sorich87 sorich87
30 сент. 2010 г. 18:26:19
0

Я также создал виджет-плагин для этого, который более настраиваемый, чем стандартный виджет "Последние записи". Если вам интересно, вы можете скачать его здесь http://new2wp.com/pro/latest-custom-post-type-posts-sidebar-widget/

30 янв. 2011 г. 13:20:28
0

Этот код создает новый виджет "Последние записи", включающий ваши пользовательские типы записей (CPT)

Для расширения стандартного виджета "Последние записи" необходимо выполнить 2 шага:

i. Создать новый класс для вашего пользовательского виджета последних записей, скопировав и переименовав код виджета из файла defaults-widgets.php в папке wp-includes.

ii. Затем нужно зарегистрировать новый виджет, при этом вы можете выбрать - отменить регистрацию стандартного виджета или использовать оба.

Весь код можно просто скопировать в файл functions вашей дочерней темы или создать отдельный файл и подключить его в functions.php дочерней темы.

<?php

class WPSites_Recent_Posts extends WP_Widget {

    public function __construct() {
        $widget_ops = array('classname' => 'wpsites_recent_posts', 'description' => __( "Последние CPT и записи.") );
        parent::__construct('wpsites-recent-posts', __('Последние записи 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'] : __( 'Последние записи' );

        /** Этот фильтр документирован в 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( 'Заголовок:' ); ?></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( 'Количество записей для показа:' ); ?></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( 'Показывать дату записи?' ); ?></label></p>
<?php
    }
}

Регистрация нового пользовательского виджета последних записей

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 );

Код включает модифицированный WP_Query с массивом для типов записей, включая CPT portfolio, который вы можете переименовать в соответствии с вашим пользовательским типом записей.

Вот строка кода, которую нужно изменить:

'post_type'           => array('post', 'portfolio'),
26 июл. 2014 г. 02:15:27
0

2020 год, и я пришел сюда найти решение для "10 самых последних записей пользовательского типа XYZ". Я нашел тот самый плагин, который делает это и даже больше.

Custom Post Type Widgets расширяет стандартные функции виджетов для обычных записей (последние записи, архивы по месяцам, используемые категории, последние комментарии, поиск, календарь) на пользовательские типы записей.

Вы выбираете нужный виджет (в моем случае "последние записи") и сначала получаете выпадающий список, где указываете пользовательский тип записей, на который должен ориентироваться виджет. По умолчанию выбран старый добрый 'post', так что этот плагин может заменять стандартные виджеты WordPress, связанные с записями.

24 февр. 2020 г. 07:28:09