Как вы используете CPT в качестве домашней страницы по умолчанию?

20

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

В действительности, домашняя страница будет стеком определенных «страниц» в WordPress. В основном, будут страницы для: вступления , блога , о нас , портфолио и контактов . Все они будут накладываться друг на друга, чтобы вы могли перемещаться с одной страницы на другую.

Моим первым инстинктом было просто использовать страницу (называемую « Домой» ) и вставлять шорткод, который принимает слагы страницы и выводит правильный порядок (то есть [pageOrder]intro, blog, about-us, portfolio, contact-us[/pageOrder]). Страница будет использовать пользовательский шаблон страницы для разметки, управления циклом и добавления навигации в левую часть страницы. Но это все кажется клунки.

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

Проблема с моим идеальным решением - настройки. WordPress позволяет выбрать страницу для домашней страницы сайта по умолчанию. Но это привязанный к сообщению типа страницы , и я не уверен , где крюк , чтобы изменить то , чтобы пользователи могли также выбрать Stack в качестве домашней страницы по умолчанию.

Итак, к чему мне подключиться, чтобы добавить CPT в выпадающий список доступных страниц для домашней страницы по умолчанию?

EAMann
источник

Ответы:

11

Спасибо @toscho за полезный ответ, но он показался мне немного хакерским, поэтому я немного покопался и решил, что вместо этого могу добавить фильтр:

function wpa18013_add_pages_to_dropdown( $pages, $r ){
    if('page_on_front' == $r['name']){
        $args = array(
            'post_type' => 'stack'
        );
        $stacks = get_posts($args);
        $pages = array_merge($pages, $stacks);
    }

    return $pages;
}
add_filter( 'get_pages', 'wpa18013_add_pages_to_dropdown', 10, 2 );

Обновить

После добавления приведенного выше кода я действительно смог использовать собственный тип записи в качестве домашней страницы, но WordPress перенаправлял постоянные ссылки, потому что это не был тип записи "страница". Так http://localhost/testчто перенаправил бы http://localhost/test/stacks/home-stack, что было не то, что я хотел.

Добавление этого действия, однако, исправило это и запросило мой пользовательский тип записи наряду со страницами для домашней страницы:

function enable_front_page_stacks( $query ){
    if('' == $query->query_vars['post_type'] && 0 != $query->query_vars['page_id'])
        $query->query_vars['post_type'] = array( 'page', 'stack' );
}
add_action( 'pre_get_posts', 'enable_front_page_stacks' );
EAMann
источник
Я тоже играл с таким фильтром, но он должен быть ограничен запросом на первой странице. А потом я был побежден каким-то странным поведением / ошибками: я получил только 404. В любом случае +1. :)
fuxia
Хороший улов. Дополнительное условие внутри функции (убедитесь, что post_typeоно еще не установлено и page_idне равно 0) предотвращает все 404 с. Теперь я могу выполнять запросы для всех своих пользовательских сообщений, всех своих сообщений и всех своих страниц без какого-либо вмешательства.
EAMann
@EAmann Спасибо за код! Он работает как надо, хотя меняет заголовок главной страницы на Заголовок сообщения | Название домашней страницы, можно ли это как-то изменить, чтобы оно было просто именем домашней страницы?
INT
Это не работает вообще ... предупреждения / ошибки сервера: отсутствует аргумент 2 для wpa18013_add_pages_to_dropdown () и неопределенная переменная: r
Dameer
8

Может быть и так? Уточненная версия моего более раннего решения .

add_filter( 'wp_dropdown_pages', 'add_cpt_to_front_page_dropdown', 10, 1 );


/**
 * Adds CPTs to the list of available pages for a static front page.
 *
 * @param  string $select Existing select list.
 * @return string
 */
function add_cpt_to_front_page_dropdown( $select )
{
    if ( FALSE === strpos( $select, '<select name="page_on_front"' ) )
    {
        return $select;
    }

    $cpt_posts = get_posts(
        array(
            'post_type'      => 'YOUR_POST_TYPE'
        ,   'nopaging'       => TRUE
        ,   'numberposts'    => -1
        ,   'order'          => 'ASC'
        ,   'orderby'        => 'title'
        ,   'posts_per_page' => -1
        )
    );

    if ( ! $cpt_posts ) // no posts found.
    {
        return $select;
    }

    $current = get_option( 'page_on_front', 0 );

    $options = walk_page_dropdown_tree(
        $cpt_posts
    ,   0
    ,    array(
            'depth'                 => 0
         ,  'child_of'              => 0
         ,  'selected'              => $current
         ,  'echo'                  => 0
         ,  'name'                  => 'page_on_front'
         ,  'id'                    => ''
         ,  'show_option_none'      => ''
         ,  'show_option_no_change' => ''
         ,  'option_none_value'     => ''
        )
    );

    return str_replace( '</select>', $options . '</select>', $select );
}
Фуксия
источник
Это только для того, чтобы выбрать пользовательский тип сообщения, но это не заставляет его отображать этот пользовательский тип сообщения в качестве главной страницы? или я что-то упустил?
Хамидулла Хан
@Hameedullah - Как только вы выберете его, WordPress обновит опцию, которая помечает, какая страница должна использоваться для главной страницы. Затем, когда пользователь заходит на первую страницу, WordPress читает ту же опцию обратно из базы данных.
EAMann
@Hameedullah Khan Вы правы. Это работало до 3.1, теперь я перенаправлен на постоянную ссылку поста - и я получаю 404. Странно. Хотел бы я иметь время для этого. :(
fuxia
5

Почему бы просто не создать front-page.phpфайл шаблона, который использует либо обычный запрос / цикл, либо (если для пользовательской опции «Темы» установлено отображение CPT на главной странице), выводит пользовательский запрос / цикл на основе CPT?

Проблема в том, что вам придется создать отдельную опцию Theme для управления выводом Front Page, и в то же время инструктировать пользователей для установки Front Page на статическую страницу.

Чтобы упростить задачу, вы можете подключить опцию «Тема» к чтению настроек, используя группу опций «Чтение» при вызове register_settingчерез API настроек, чтобы она отображалась с существующими опциями на передней странице.

Чип Беннетт
источник
Мне нравятся простые решения, и Чип, я думаю, ваш лучший. Wordpress позволяет создавать собственные шаблоны для главной страницы codex.wordpress.org/Template_Hierarchy#Home_Page_display, а затем внутри можно делать все, что угодно.
Анмари
Это наиболее приемлемое и простое решение. front-page.phpВыбирается автоматически , поскольку является частью иерархии шаблонов WordPress. Не нужно помнить, почему это происходит (или нужно пометить это для следующего человека).
Одис
2

Я думаю, что что-то могло измениться с тех пор, как EAMann написал свое обновление в 2011 году, и функция wpa18013_add_pages_to_dropdown (), которую он предоставляет, больше не работает. Как упоминается в комментарии Dameer, эта функция в настоящее время (декабрь 2013 г.) выдает ошибку «Отсутствует аргумент 2 для wpa18013_add_pages_to_dropdown ()»

В любом случае, для меня решение состояло в том, чтобы переписать функцию без второго параметра или проверить ее содержимое. Полный блок кода становится:

function add_unbox_tabs_to_dropdown( $pages ){
    $args = array(
        'post_type' => 'unbox_tabs'
    );
    $items = get_posts($args);
    $pages = array_merge($pages, $items);

    return $pages;
}
add_filter( 'get_pages', 'add_unbox_tabs_to_dropdown' );

function enable_front_page_unbox_tabs( $query ){
    if('' == $query->query_vars['post_type'] && 0 != $query->query_vars['page_id'])
        $query->query_vars['post_type'] = array( 'page', 'unbox_tabs' );
}
add_action( 'pre_get_posts', 'enable_front_page_unbox_tabs' );

Обратите внимание, что в приведенном выше примере добавляемый мной тип поста «unbox_tabs», а не «stack».

Мэтью Бернхардт
источник
1

Я использую эту технику, чтобы включить шаблон из плагина. Таким образом, решение @ ChipBennett не применяется.

Чтобы добавить CPT ( ) из плагина в список статических страниц, я изменил решение @ EAMann следующим образом: 'hierarchical' => 'false'

add_action( 'admin_head-options-reading.php', 'wpse_18013_modify_front_pages_dropdown' );
add_action( 'pre_get_posts', 'wpse_18013_enable_front_page_stacks' );

function wpse_18013_modify_front_pages_dropdown()
{
    // Filtering /wp-includes/post-templates.php#L780
    add_filter( 'get_pages', 'wpse_18013_add_cpt_to_pages_on_front' );
}

function wpse_18013_add_cpt_to_pages_on_front( $r )
{
    $args = array(
        'post_type' => 'stack'
    );
    $stacks = get_posts( $args );
    $r = array_merge( $r, $stacks );

    return $r;
}

function wpse_18013_enable_front_page_stacks( $query )
{
    if( '' == $query->query_vars['post_type'] && 0 != $query->query_vars['page_id'] )
        $query->query_vars['post_type'] = array( 'page', 'stack' );
}

Базовая ссылка v3.4.2:
небольшая разница в номерах строк в 3.5 RC3, но код остается тем же

/**
 * wp-admin/options-reading.php#L96
 * Happens inside a <li><label>-</label></li>
 */
    wp_dropdown_pages( array( 
                'name' => 'page_on_front'
            ,   'echo' => 0
            ,   'show_option_none' => __( '&mdash; Select &mdash;' )
            ,   'option_none_value' => '0'
            ,   'selected' => get_option( 'page_on_front' ) 
        ) 
    )

/**
  * wp-includes/post-template.php#L768
  */
function wp_dropdown_pages($args = '') {
    $defaults = array( /* defaults array */ );    
    $r = wp_parse_args( $args, $defaults );
    extract( $r, EXTR_SKIP );  
    $pages = get_pages( $r );
brasofilo
источник