Как добавить несколько таксономий в URL?

8

Несколько таксономий в URL

Как добавить несколько таксономий к URL-адресу, имеющему следующее:

  • Тип сообщения: продукты
  • Таксономия: product_type
  • Таксономия: товарный бренд


Добавление нового продукта и выбор типа и бренда для этого продукта:

При добавлении нового продукта есть два поля таксономии (product_type и product_brand). Давайте назовем этот новый пост Test Product 1 . Первое, что мы хотим сделать, это отметить, с каким типом продукта я имею дело, скажем, с мобильными телефонами . Далее я хочу отметить, к какому бренду относится продукт, скажем, samsung.

Теперь « Тестовый продукт 1 » ассоциируется с типом «сотовые телефоны» и брендом «Samsung» .

Желаемый конечный результат:

/ продукты
»Просмотреть все пользовательские сообщения

/ продукты / мобильные телефоны
»Просмотреть все пользовательские сообщения с мобильными телефонами таксономии

/ product / cell-phone / samsung /
»Просмотреть все пользовательские сообщения, где таксономия - мобильные телефоны и samsung

/ продукты / мобильные телефоны / samsung / test-product-1
»Просмотреть товар (один пользовательский пост)


Вопрос

Как сделать это возможным? Моя первоначальная мысль заключалась в том, чтобы использовать одну таксономию, имея «мобильные телефоны» в качестве родительского термина «samsung» . На самом деле добавление таксономии и ее условий было не так сложно. Но это привело к множеству других проблем, некоторые из которых хорошо известны, некоторые не так много. В любом случае, это не работает так, как дает 404 проблемы, а WP не разрешит некоторые вещи.
WP.org »таксономия-архив-шаблон

Это привело меня к переосмыслению структуры, необходимости покинуть таксономии и ее термины, и я подумал; почему бы не создать 2-ю таксономию, связать с ней тип сообщения и добавить его к URL-адресу?

Хороший вопрос, но как?

ДРСК
источник
Можете ли вы проверить эту ссылку у меня есть проблема с той же вещи stackoverflow.com/questions/34351477/…
Санджай Накате

Ответы:

7

Это, безусловно, возможно, если использовать некоторые собственные правила переписывания. В WP_Rewrite API подвергает функции , которые позволяют добавлять правила перезаписи (или «карты») , чтобы преобразовать запрос на запрос.

Есть предпосылки для написания хороших правил переписывания, и наиболее важным из них является базовое понимание регулярных выражений. Движок WordPress Rewrite использует регулярные выражения для перевода частей URL-адресов в запросы для получения сообщений.

Это краткое и хорошее руководство по PHP PCRE (Perl-совместимые регулярные выражения).

Итак, вы добавили две таксономии, давайте предположим, что их имена:

  • Тип продукта
  • product_brand

Мы можем использовать их в запросах так:

get_posts( array(
    'product_type' => 'cell-phones',
    'product_brand' => 'samsung'
) );

Запрос будет ?product_type=cell-phones&product_brand=samsung. Если вы введете это в качестве запроса, вы получите список телефонов Samsung. Чтобы переписать /cell-phones/samsungэтот запрос, необходимо добавить правило перезаписи.

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

add_rewrite_rule( '^products/([^/]*)/([^/]*)/?',
    'index.php?product_type=$matches[1]&product_brand=$matches[2]',
    'top' );

Вам нужно будет это сделать, flush_rewrite_rules()как только вы добавите правило перезаписи, чтобы сохранить его в базе данных. Это делается только один раз, нет необходимости делать это с каждым запросом, как только правило сбрасывается туда. Чтобы удалить его, просто сбросьте без добавления правила перезаписи.

Если вы хотите добавить нумерацию страниц, вы можете сделать это следующим образом:

add_rewrite_rule( '^products/([^/]*)/([^/]*)/(\d*)?',
    'index.php?product_type=$matches[1]&product_brand=$matches[2]&p=$matches[3]',
    'top' );
soulseekah
источник
1
Одна самая простая статья, которую я видел относительно правил переписывания WordPress. Много читал, но после прочтения, наконец, все заработало. Спасибо! +1
евр
3

Конечный результат

Вот то, что я придумал, частично используя кусочки из всех ответов, которые я получил:

/**
 * Changes the permalink setting <:> post_type_link
 * Functions by looking for %product-type% and %product-brands% in the URL
 * 
  * products_type_link(): returns the converted url after inserting tags
  *
  * products_add_rewrite_rules(): creates the post type, taxonomies and applies the rewrites rules to the url
 *
 *
 * Setting:         [ produkter / %product-type%  / %product-brand% / %postname% ]
 * Is actually:     [ post-type / taxonomy        /  taxonomy       / postname   ]
 *                   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
 * Desired result:  [ products  / cellphones      / apple           / iphone-4   ]
 */

    // Add the actual filter    
    add_filter('post_type_link', 'products_type_link', 1, 3);

    function products_type_link($url, $post = null, $leavename = false)
    {
        // products only
        if ($post->post_type != 'products') {
            return $url;
        }

        // Post ID
        $post_id = $post->ID;

        /**
         * URL tag <:> %product-type%
         */
            $taxonomy = 'product-type';
            $taxonomy_tag = '%' . $taxonomy . '%';

            // Check if taxonomy exists in the url
            if (strpos($taxonomy_tag, $url) <= 0) {

                // Get the terms
                $terms = wp_get_post_terms($post_id, $taxonomy);

                if (is_array($terms) && sizeof($terms) > 0) {
                    $category = $terms[0];
                }

                // replace taxonomy tag with the term slug » /products/%product-type%/productname
                $url = str_replace($taxonomy_tag, $category->slug, $url);
            }

        /** 
         * URL tag <:> %product-brand%
         */
        $brand = 'product-brand';
        $brand_tag = '%' . $brand . '%';

        // Check if taxonomy exists in the url
        if (strpos($brand_tag, $url) < 0) {
            return $url;
        } else { $brand_terms = wp_get_post_terms($post_id, $brand); }

        if (is_array($brand_terms) && sizeof($brand_terms) > 0) {
            $brand_category = $brand_terms[0];
        }

        // replace brand tag with the term slug and return complete url » /products/%product-type%/%product-brand%/productname
        return str_replace($brand_tag, $brand_category->slug, $url);

    }

    function products_add_rewrite_rules() 
    {
        global $wp_rewrite;
        global $wp_query;

        /**
         * Post Type <:> products
         */

            // Product labels
            $product_labels = array (
                'name'                  => 'Products',
                'singular_name'         => 'product',
                'menu_name'             => 'Products',
                'add_new'               => 'Add product',
                'add_new_item'          => 'Add New product',
                'edit'                  => 'Edit',
                'edit_item'             => 'Edit product',
                'new_item'              => 'New product',
                'view'                  => 'View product',
                'view_item'             => 'View product',
                'search_items'          => 'Search Products',
                'not_found'             => 'No Products Found',
                'not_found_in_trash'    => 'No Products Found in Trash',
                'parent'                => 'Parent product'
            );

            // Register the post type
            register_post_type('products', array(
                'label'                 => 'Products',
                'labels'                => $product_labels,
                'description'           => '',
                'public'                => true,
                'show_ui'               => true,
                'show_in_menu'          => true,
                'capability_type'       => 'post',
                'hierarchical'          => true,
                'rewrite'               => array('slug' => 'products'),
                'query_var'             => true,
                'has_archive'           => true,
                'menu_position'         => 5,
                'supports'              => array(
                                            'title',
                                            'editor',
                                            'excerpt',
                                            'trackbacks',
                                            'revisions',
                                            'thumbnail',
                                            'author'
                                        )
                )
            );

        /**
         * Taxonomy <:> product-type
         */
            register_taxonomy('product-type', 'products', array(
                'hierarchical' => true, 
                'label' => 'Product Types', 
                'show_ui' => true, 
                'query_var' => true, 
                'rewrite' => array('slug' => 'products/types'),
                'singular_label' => 'Product Types') 
            );

        /**
         * Taxonomy <:> product-type
         */
            register_taxonomy('product-brand', 'products', array(
                'hierarchical' => true, 
                'label' => 'Product Brands', 
                'show_ui' => true, 
                'query_var' => true, 
                'rewrite' => array('slug' => 'product/brands'),
                'singular_label' => 'Product Brands') 
            );

            $wp_rewrite->extra_permastructs['products'][0] = "/products/%product-type%/%product-brand%/%products%";

            // flush the rules
            flush_rewrite_rules();
    }

    // rewrite at init
    add_action('init', 'products_add_rewrite_rules');


Некоторые мысли:

Это работает. Хотя вы «обязаны» назначать обе таксономии каждому сообщению, иначе у URL будет трейлинг '/'» '/products/taxonomy//postname'. Поскольку я собираюсь назначить обе таксономии для всех моих протоколов, имеющих тип и марку, этот код, кажется, работает для моих нужд. Если у кого-то есть предложения или улучшения, не стесняйтесь отвечать!

ДРСК
источник
Отлично. Спасибо за размещение вашего решения. Пожалуйста, выберите его как ответ, как только прошло достаточно времени. Кроме того, рекомендуется проголосовать за любые полезные ответы.
Марфарма
Мне трудно заставить это работать, не знаю почему. Даже копирование / вставка в мои функции вместо того, чтобы пытаться перенести ваши изменения, дает мне массу ошибок. Я думаю, что-то в ядре WordPress должно было измениться между тем, когда это было написано (более 3 лет назад), и сегодняшним днем. Я пытаюсь понять то же самое: wordpress.stackexchange.com/questions/180994/…
JacobTheDev
flush_rewrite_rules()на init? не к этому. в основном вы сбрасываете свои правила перезаписи при каждой загрузке страницы.
honk31
1

Проверьте этот способ, все еще есть ошибки с архивом бренда

http://pastebin.com/t8SxbDJy

add_filter('post_type_link', 'products_type_link', 1, 3);

function products_type_link($url, $post = null, $leavename = false)
{
// products only
    if ($post->post_type != self::CUSTOM_TYPE_NAME) {
        return $url;
    }

    $post_id = $post->ID;

    $taxonomy = 'product_type';
    $taxonomy_tag = '%' . $taxonomy . '%';

    // Check if exists the product type tag
    if (strpos($taxonomy_tag, $url) < 0) {
        // replace taxonomy tag with the term slug: /products/%product_type%/samsumng/productname
        $url = str_replace($taxonomy_tag, '', $url);
    } else {
        // Get the terms
        $terms = wp_get_post_terms($post_id, $taxonomy);

        if (is_array($terms) && sizeof($terms) > 0) {
            $category = $terms[0];
            // replace taxonomy tag with the term slug: /products/%product_type%/samsumng/productname
            $url = str_replace($taxonomy_tag, $category->slug, $url);
        }
        }

    /* 
     * Brand tags 
     */
    $brand = 'product_brand';
    $brand_tag = '%' . $brand . '%';

    // Check if exists the brand tag 
    if (strpos($brand_tag, $url) < 0) {
        return str_replace($brand_tag, '', $url);
    }

    $brand_terms = wp_get_post_terms($post_id, $brand);

    if (is_array($brand_terms) && sizeof($brand_terms) > 0) {
        $brand_category = $brand_terms[0];
    }

    // replace brand tag with the term slug: /products/cell-phone/%product_brand%/productname 
    return str_replace($brand_tag, $brand_category->slug, $url);
}

function products_add_rewrite_rules() 
{
global $wp_rewrite;
global $wp_query;

register_post_type('products', array(
    'label' => 'Products',
    'description' => 'GVS products and services.',
    'public' => true,
    'show_ui' => true,
    'show_in_menu' => true,
    'capability_type' => 'post',
    'hierarchical' => true,
    'rewrite' => array('slug' => 'products'),
    'query_var' => true,
    'has_archive' => true,
    'menu_position' => 6,
    'supports' => array(
        'title',
        'editor',
        'excerpt',
        'trackbacks',
        'revisions',
        'thumbnail',
        'author'),
    'labels' => array (
        'name' => 'Products',
        'singular_name' => 'product',
        'menu_name' => 'Products',
        'add_new' => 'Add product',
        'add_new_item' => 'Add New product',
        'edit' => 'Edit',
        'edit_item' => 'Edit product',
        'new_item' => 'New product',
        'view' => 'View product',
        'view_item' => 'View product',
        'search_items' => 'Search Products',
        'not_found' => 'No Products Found',
        'not_found_in_trash' => 'No Products Found in Trash',
        'parent' => 'Parent product'),
    ) 
);

register_taxonomy('product-categories', 'products', array(
    'hierarchical' => true, 
    'label' => 'Product Categories', 
    'show_ui' => true, 
    'query_var' => true, 
    'rewrite' => array('slug' => 'products'),
    'singular_label' => 'Product Category') 
);

$wp_rewrite->extra_permastructs['products'][0] = "/products/%product_type%/%product_brand%/%products%";

    // product archive
    add_rewrite_rule("products/?$", 'index.php?post_type=products', 'top');

    /* 
     * Product brands
     */
    add_rewrite_rule("products/([^/]+)/([^/]+)/?$", 'index.php?post_type=products&product_brand=$matches[2]', 'top');
    add_rewrite_rule("products/([^/]+)/([^/]+)/page/([0-9]{1,})/?$", 'index.php?post_type=products&product_brand=$matches[2]&paged=$matches[3]', 'top');

    /*
     * Product type archive
     */
    add_rewrite_rule("products/([^/]+)/?$", 'index.php?post_type=products&product_type=$matches[1]', 'top');    
    add_rewrite_rule("products/([^/]+)/page/([0-9]{1,})/?$", 'index.php?post_type=products&product_type=$matches[1]&paged=$matches[1]', 'bottom'); // product type pagination

    // single product
    add_rewrite_rule("products/([^/]+)/([^/]+)/([^/]+)/?$", 'index.php?post_type=products&product_type=$matches[1]&product_brand=$matches[2]&products=$matches[3]', 'top');



flush_rewrite_rules();

}

add_action('init', 'products_add_rewrite_rules');
Луис Абарка
источник
1

Несмотря на то, что вы не имеете желаемой структуры URL, вы можете получить:

/ продукты
»Просмотреть все пользовательские сообщения

/ продукты / тип / мобильные телефоны
»Просмотреть все пользовательские сообщения с мобильными телефонами таксономии

/ продукты / тип / мобильные телефоны / бренд / Samsung
»Просмотреть все пользовательские сообщения, где таксономия мобильных телефонов и Samsung

/ brand / samsung
»Просмотреть все пользовательские сообщения, где таксономия samsung

/ product / test-product-1
»Просмотреть товар (один пользовательский пост)

без указания пользовательских правил перезаписи.

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

product_type taxonomy slug               = products/type
product custom_post_type slug            = product
product custom_post_type archive slug    = products
product_brand taxonomy slug              = brand

Тогда вы можете зарегистрировать их в следующем порядке:

register_taxonomy( 
    'products_type', 
    'products', 
        array( 
            'label' => 'Product Type', 
            'labels' => $product_type_labels,
            'public' => true, 
            'show_ui' => true, 
            'show_in_nav_menus' => true, 
            'args' => array( 'orderby' => 'term_order' ),
            'rewrite' => array( 'slug' => 'products/type', 'with_front' => false  ),
            'has_archive' => true,
            'query_var' => true, 
        ) 
);

register_post_type('products', array(
    'labels' =>$products_labels,
    'singular_label' => __('Product'),
    'public' => true,
    'show_ui' => true,
    'capability_type' => 'post',
    'hierarchical' => false,
    'rewrite' => array('slug' => 'product', 'with_front' => false ),
    'has_archive' => 'products',
    'supports' => array('title', 'editor', 'thumbnail', 'revisions','comments','excerpt'),
 ));

register_taxonomy( 
    'products_brand', 
    'products', 
        array( 
            'label' => 'Brand', 
            'labels' => $products_brand_labels,
            'public' => true, 
            'show_ui' => true, 
            'show_in_nav_menus' => true, 
            'args' => array( 'orderby' => 'term_order' ),
            'rewrite' => array( 'slug' => 'brand', 'with_front' => false  ),
            'has_archive' => true,
            'query_var' => true, 
        ) 
);

Если вам абсолютно необходим URL-адрес, например:

/ продукты / тип / мобильные телефоны / бренд / Samsung / тест-продукт-1
»Просмотреть продукт (один пользовательский пост)

Тогда вам потребуется правило переписывания примерно так:

    add_rewrite_rule(
        '/products/type/*/brand/*/([^/]+)/?',
        'index.php?pagename='product/$matches[1]',
        'top' );

ОБНОВЛЕНИЕ /programming/3861291/multiple-custom-permalink-structures-in-wordpress

Вот как правильно переопределить URL-адрес одного сообщения.

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

  'rewrite' => false

   global $wp_rewrite;
   $product_structure = '/%product_type%/%brand%/%product%';
   $wp_rewrite->add_rewrite_tag("%product%", '([^/]+)', "product=");
   $wp_rewrite->add_permastruct('product', $product_structure, false);

Затем отфильтруйте post_type_link, чтобы создать желаемую структуру URL - с учетом неустановленных значений таксономии. Изменив код из связанного поста, вы получите:

function product_permalink($permalink, $post_id, $leavename){
    $post = get_post($post_id);

    if( 'product' != $post->post_type )
         return $permalink;

    $rewritecode = array(
    '%product_type%',
    '%brand%',
    $leavename? '' : '%postname%',
    $leavename? '' : '%pagename%',
    );

    if('' != $permalink && !in_array($post->post_status, array('draft', 'pending', 'auto-draft'))){

        if (strpos($permalink, '%product_type%') !== FALSE){

            $terms = wp_get_object_terms($post->ID, 'product_type'); 

            if (!is_wp_error($terms) && !empty($terms) && is_object($terms[0]))  
               $product_type = $terms[0]->slug;
            else 
               $product_type = 'unassigned-artist';         
        }

        if (strpos($permalink, '%brand%') !== FALSE){
           $terms = wp_get_object_terms($post->ID, 'brand');  
           if (!is_wp_error($terms) && !empty($terms) && is_object($terms[0])) 
               $brand = $terms[0]->slug;
           else 
               $brand = 'unassigned-brand';         
        }           

        $rewritereplace = array(
           $product_type,
           $brand,
           $post->post_name,
           $post->post_name,
        );

        $permalink = str_replace($rewritecode, $rewritereplace, $permalink);
    }
    return $permalink;
}

add_filter('post_type_link', 'product_permalink', 10, 3);

Теперь мне просто нужно выяснить, как переписать URL таксономии бренда без лидирующего тега бренда, и я должен точно соответствовать желаемому URL.

marfarma
источник