Wordpress 3.3 пользовательский тип записи с /% postname% / permastruct?


9

Существует более ранняя публикация с похожим названием, но она не подходит для WordPress 3.3, и это важно, так как 3.3 интересно рекламирует: «Используйте структуру постоянных ссылок для имени без потери производительности»

Проблема с Wordpress 3.2 и более ранними версиями заключалась в том, что сначала он просматривал имена страниц, а затем 404. Сначала он не проверял произвольные типы записей. 3.3, с другой стороны, должен смотреть типы сообщений, затем страницы и, наконец, 404 (как он рекламирует эту функцию). Это подразумевает, что пользовательские типы записей без слагов должны быть простыми , если они не post_type=postгде-то жестко кодируют .

Я пока не могу найти конкретное решение 3.3.

Вопрос : Как я могу определить постоянную ссылку struct "/% postname% /" для любого заданного пользовательского типа записи "xyz"?

Спасибо.


Я не вижу вопроса - что вы на самом деле спрашиваете?
Трэвис Норткатт

Для ясности вы хотите определить новый пользовательский тип записи, который использует постоянную структуру /% postname% /? Планируете ли вы, чтобы посты также использовали ту же самую permastructure, или они будут иметь префикс?
prettyboymp

После этого, чтобы увидеть, если кто-нибудь придет с ответом. Я также попробовал описанные выше подходы, просто установив параметр перезаписи в '/', что также нарушает постоянные ссылки на страницы. Вздох ...

Ответы:


2

Это нелегко сделать в WP 3.3, если вы не обманываете правила перезаписи, чтобы быть в правильном месте, и заставляете wp_rewrite думать, что подробные правила используются во внешнем интерфейсе. Класс ниже работает.

class Test_Post_Type {
    const POST_TYPE = 'test';

    public static function init() {
        global $wp_rewrite;

        $post_type_obj = register_post_type( self::POST_TYPE, array(
            'labels' => array(
                'name' => __( 'Tests' ),
                'singular_name' => __( 'Test' ),
                'add_new' => __( 'Add New' ),
                'add_new_item' => __( 'Add New Test' ),
                'edit_item' => __( 'Edit Test' ),
                'new_item' => __( 'New Test' ),
                'all_items' => __( 'All Tests' ),
                'view_item' => __( 'View Test' ),
                'search_items' => __( 'Search Tests' ),
                'not_found' => __( 'No Tests found' ),
                'not_found_in_trash' => __( 'No Tests found in Trash' ),
                'menu_name' => __( 'Tests' )
            ),
            'publicly_queryable' => true,
            'exclude_from_search' => true,
            'hierarchical' => false,
            'public' => true,
            'rewrite' => false,
            'has_archive' => true,
            'supports' => array( 'title', 'editor', 'thumbnail', 'test_source' ),
            'taxonomies' => array( 'category', 'post_tag' ),
        ) );

        $post_type_obj = get_post_type_object(self::POST_TYPE);

        //register the rewrite tag for permalink building
        $wp_rewrite->add_rewrite_tag( '%' . $post_type_obj->query_var . '%', '([^/]+)', $post_type_obj->query_var . '=' );

        //we have to add the permastruct here in order to build the permalink, otherwise we'll need to filter the post_type link
        add_permastruct(self::POST_TYPE, '%' . $post_type_obj->query_var . '%/', false );

        //add a filter to remove the permastructs generated above
        add_filter(self::POST_TYPE . '_rewrite_rules', array(__CLASS__, '_remove_default_rules')); 

        //now we add a filter to put the generated rewrite rules in the correct spot
        add_action('generate_rewrite_rules', array(__CLASS__, '_filter_rewrite_rules'));

        if(!is_admin()) {
            //we need verbose_page_rules to be on on the front end in order for pages to be process properly
            $wp_rewrite->use_verbose_page_rules = true;
        }
    }

    /**
     * Filter to remove the rules for this post type when they're automatically generated due to the permastruct registration
     * @param type $rules
     * @return type 
     */
    public static function _remove_default_rules($rules) {
        return array();
    }

    /**
     * Filters the rules at the end to add back the ones for this post type at the bottom
     * @param WP_Rewrite $wp_rewrite 
     */
    public static function _filter_rewrite_rules($wp_rewrite) {
        $post_type_obj = get_post_type_object(self::POST_TYPE);
        $my_rules = $wp_rewrite->generate_rewrite_rules('%' . $post_type_obj->query_var . '%', EP_NONE);
        $wp_rewrite->rules += $my_rules;
    }

}

add_action( 'init', array( 'Test_Post_Type', 'init' ) );

Копия вставила этот код в мою тему, мела переписать правила. Добавил новый пост, просмотрел пост (правильный URL), получил 404 ... На WP 3.3.1. Есть идеи, почему это не сработает? (Спасибо за код, кстати!)
Роб Вермеер

EP_NONE -> EP_PERMALINK для работы страниц комментариев, а затем для получения нескольких типов записей, работающих с /% postname% /, вы также должны использовать фильтр parse_query. Смотрите мой ответ выше.
Ciantic

Роб, ты добавил новый пост или новый тестовый пост? В первоначальном вопросе о том, должны ли посты также иметь структуру permastructure /% post_name% /, было непонятно. Если это так, зачем вообще создавать новый тип поста? Кроме того, у вас могут возникнуть проблемы с конфликтами имен, если несколько типов постов имеют одинаковую структуру.
prettyboymp

1

Святые ключи от машины!

Я думаю, что это работает . Это почти работает, это очень просто, только одна строка:

global $wp_rewrite;
$args = array(
    'public' => true,
    'publicly_queryable' => true,
    'show_ui' => true,
    'show_in_menu' => true,
    'query_var' => true,
    'rewrite' => array('slug' => 'anything'),
    'capability_type' => 'post',
    'has_archive' => true,
    'hierarchical' => false,
    'menu_position' => null,
    'supports' => array('title','editor','thumbnail')
);
register_post_type('my_custom_post_type', $args);

$wp_rewrite->add_permastruct('my_custom_post_type', "%my_custom_post_type%");

PS Если вы попробуете это дома, после добавления этой одной строки перейдите в «Настройки» -> «Постоянные ссылки» и «Сохранить изменения», она обновит постоянные ссылки.

Я читал register_post_type()исходный код WP и нашел строку:

$wp_rewrite->add_permastruct($post_type, "{$args->rewrite['slug']}/%$post_type%", $args->rewrite['with_front'], $args->permalink_epmask);

Само собой разумеется, но без пули я решил, что это должно работать, и это сделало . Даже редактирование постоянной ссылки под заголовком в редакторе работает правильно!

Обновление: это разрывает постоянные ссылки на страницы, обратно на чертежную доску ...


Я также попробовал этот, с похожим результатом. Было бы очень круто, если бы это сработало. Может быть, кто-то еще с идеей?
Роб Вермеер

@RobVermeer Заметил, что без строки (просто слаг по умолчанию) WordPress уже способен перенаправлять на URL. Например, «some-post» перенаправляет на «что-нибудь / some-post». В codepeak, где-то в коде есть поддержка CPT без slug, он просто по умолчанию перенаправляет. лицо ладони
Ciantic

1

Ответ prettyboymp - почти то же самое, что я получил вчера, но я не доволен этим. Ответ prettyboymp имеет один недостаток, он не работает, когда /% postname% / используется одновременно для нескольких типов записей.

Вот мой ответ, который также смотрит на текущую структуру и создает массив типов записей для отката. В этом тоже есть один недостаток: если два типа записей имеют одинаковый слаг и оба имеют /% postname% /, то это показывает оба.

class MyCustomPostType {
    /**
     * Register post type
     **/
    public static function register_post_type() {
        global $wp_rewrite;

        $args = array(
            'public' => true,
            'publicly_queryable' => true,
            'show_ui' => true,
            'show_in_menu' => true,
            'query_var' => true,
            'rewrite' => false,
            'capability_type' => 'post',
            'has_archive' => true,
            'hierarchical' => false,
            'menu_position' => null,
            'supports' => array('title','editor','thumbnail')
        );

        register_post_type('my_custom_post_type', $args);

        // Enables the pages to work simultaneously
        $wp_rewrite->use_verbose_page_rules = true;
        add_filter("rewrite_rules_array", array(__CLASS__, 'rewrite_rules_array'));
        add_action("parse_query", array(__CLASS__, 'parse_query'));
        add_filter("post_type_link", array(__CLASS__, 'post_type_link'), 1, 4);
    }

    public static function post_type_link($link, $post, $leavename=false, $sample=false) {
        if ($sample && ($begin = strpos($link, "?my_custom_post_type=")) !== false) {
            return substr($link, 0, $begin-1) . "/%my_custom_post_type%/";
        }
        return str_replace("?my_custom_post_type=", "", $link) . "/";
    }

    public static function parse_query($query) {
        global $wp, $wp_rewrite;

        // Is this query for /%post_name%/? Is it main request query?
        if (isset($query->query['name'])
            && substr($wp->matched_rule, 0, 7) == "([^/]+)"
            && isset($query->query)
            && isset($wp->query_vars)
            && $query->query == $wp->query_vars)
        {
            //echo '<p><h1>hit!</h1></p>';
            if (!($post_types = get_query_var("post_type"))) {
                if ($wp_rewrite->permalink_structure == "/%postname%/")
                    $post_types = array("post");
                else
                    $post_types = array();
            }

            if (is_array($post_types))
                $post_types[] = "my_custom_post_type";

            set_query_var("post_type", $post_types);
            //set_query_var("posts_per_page", 1);
        }
    }

    public static function rewrite_rules_array($array) {
        global $wp_rewrite;
        // Same rules as in /%post_name%/
        return array_merge($array, $wp_rewrite->generate_rewrite_rules("/%postname%/", EP_PERMALINK));
    }
}


add_action('init', array("MyCustomPostType", "register_post_type"));

Возможно ли, что некоторые пост-типы становятся иерархическими. Я попробовал это сам, но, похоже, ничего не работает ... Он думает, что сообщение является вложением с родителем / ребенком / ... И если я делаю родитель / ребенок / внук / получит 404.
Роб Вермеер

1

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

add_action('init', 'firmasite_resimlitarif_cpt', 0);
function firmasite_resimlitarif_cpt() 
{

// Yemek Tarifi

  $args = array(
    'public' => true,
    'show_in_menu' => true, 
    'permalink_epmask' => EP_NONE,
    'rewrite' => array('slug'=>'/','with_front'=>false),
    'has_archive' => false,
    'supports' => array('title','editor','thumbnail')
  ); 
  register_post_type('yemek',$args);

}


// http://wordpress.stackexchange.com/questions/37650/wordpress-3-3-custom-post-type-with-postname-permastruct
add_action("parse_query", 'firmasite_resimlitarif_parse_query');
function firmasite_resimlitarif_parse_query($query) {
    global $wp, $wp_rewrite;


    // Is this query for /%post_name%/? Is it main request query?
    if (isset($query->query['name'])
        && substr($wp->matched_rule, 0, 7) == "([^/]+)"
        && isset($query->query)
        && isset($wp->query_vars)
        && $query->query == $wp->query_vars)
    {
        if (!($post_types = get_query_var("post_type"))) {
            if ($wp_rewrite->permalink_structure == "/%postname%/")
                $post_types = array("post");
            else
                $post_types = array();
        }

        if (is_array($post_types)){ 
            $post_types[] = 'yemek';
            $post_types[] = 'page';
        }


        set_query_var("post_type", $post_types);
    } 
}

Измените «yemek» с вашим именем типа сообщения.



0

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

Таким образом, ваш «пользовательский тип записи» может иметь URL-адреса, такие как / что угодно, не беспокоясь о переходе на страницу или постоянные ссылки на пост.

Чтобы сделать это, я сделал следующее:

  • Добавление собственного шаблона страницы внутри моего плагина
  • Настройка шаблона страницы, чтобы его можно было выбрать в редакторе страниц
  • Создание пользовательских мета-блоков, которые отображаются только для моего шаблона страницы

Это позволило мне:

  • Вытащите список страниц, которые используют шаблон страницы, используя WP_Query

  • Добавить специальную обработку, подключив add_meta_boxes для хранения моих пользовательских данных

  • Добавьте мой пользовательский шаблон к отображаемым, отфильтровав page_attributes_dropdown_pages_args, theme_page_templates, wp_insert_post_data и template_include. См. Этот пост о добавлении шаблонов страниц в плагин

Вниз стороны

Конечно, хотя это не топает ссылки на страницы и не публикует ссылки, у него есть несколько очевидных недостатков.

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

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

Это может быть частично решено добавлением фильтра в список страниц (чтобы можно было фильтровать по используемому шаблону страницы), показом любого шаблона страницы, используемого в новом столбце, и т. Д.


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

Я знаю, что это не настоящее решение, но это альтернатива, которая отлично подходит для моих нужд.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.