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.