Como anexar várias taxonomias ao URL?

8

Várias taxonomias no URL

Como anexar várias taxonomias à URL, com o seguinte:

  • Tipo de postagem: produtos
  • Taxonomia: product_type
  • Taxonomia: product_brand


Adicionando novo produto e selecionando o tipo e a marca para este produto:

Ao adicionar um novo produto , há duas caixas de taxonomia (product_type e product_brand). Vamos chamar esse novo post Produto de Teste 1 . A primeira coisa que queremos fazer é marcar com que tipo de produto estou lidando, digamos, telefones celulares . Em seguida, quero marcar a que marca o produto pertence, digamos samsung.

Agora, o " Produto de teste 1 " está associado ao tipo "telefones celulares" e à marca "samsung" .

O resultado final desejado é:

/ produtos
»Ver todas as postagens personalizadas

/ products / cell-phones
»Veja todas as postagens personalizadas com os celulares de taxonomia

/ product / cell-phones / samsung /
»Veja todas as postagens personalizadas nas quais a taxonomia é de celulares AND samsung

/ products / telefones celulares / samsung / test-product-1
»Veja o produto (postagem personalizada única)


A questão

Como alguém tornaria isso possível? Meu pensamento inicial era usar uma taxonomia, tendo "telefones celulares" como o termo pai de "samsung" . Na verdade, acrescentar a taxonomia e seus termos não foi tão difícil. Mas isso levou a muitas outras questões, algumas bem conhecidas, outras nem tanto. De qualquer forma, não funciona assim, pois gera 404 problemas e o WP não permite certas coisas.
WP.org »taxonomia-arquivo-modelo

Isso me levou a repensar a estrutura, a deixar as taxonomias e seus termos e pensei; por que não criar uma segunda taxonomia e associar o tipo de postagem a ele e anexá-lo ao URL?

Boa pergunta, de fato, mas como?

DRSK
fonte
você pode conferir neste link que eu tenho problema com mesma coisa stackoverflow.com/questions/34351477/...
Sanjay Nakate

Respostas:

7

Isso é certamente possível utilizando algumas regras de reescrita próprias até certo ponto. A API WP_Rewrite expõe funções que permitem adicionar regras de reescrita (ou 'mapas') para converter uma solicitação em uma consulta.

Existem pré-requisitos para escrever boas regras de reescrita, e o mais importante é a compreensão básica de expressões regulares. O mecanismo de reescrita do WordPress usa expressões regulares para converter partes de um URL em consultas para obter postagens.

Este é um tutorial curto e bom sobre PHP PCRE (expressões regulares compatíveis com Perl).

Então, você adicionou duas taxonomias, vamos assumir que seus nomes são:

  • Tipo de Produto
  • product_brand

Podemos usá-los em consultas como:

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

A consulta seria ?product_type=cell-phones&product_brand=samsung. Se você digitar isso como sua consulta, receberá uma lista de telefones Samsung. Para reescrever /cell-phones/samsungnessa consulta, uma regra de reescrita deve ser adicionada.

add_rewrite_rule()fará isso por você. Aqui está um exemplo da aparência da sua regra de reescrita no caso acima:

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

Você precisará flush_rewrite_rules()assim que adicionar a regra de reescrita para salvá-la no banco de dados. Isso é feito apenas uma vez, não há necessidade de fazer isso com cada solicitação, uma vez que uma regra é liberada. Para removê-lo, basta descarregar sem a regra de reescrita adicionada.

Se você deseja adicionar paginação, pode fazê-lo fazendo algo como:

add_rewrite_rule( '^products/([^/]*)/([^/]*)/(\d*)?',
    'index.php?product_type=$matches[1]&product_brand=$matches[2]&p=$matches[3]',
    'top' );
soulseekah
fonte
11
Artigo mais simples que eu já vi sobre regras de reescrita do wordpress. Estive lendo muito, mas depois de ler isso, finalmente consegui fazer as coisas funcionarem. Obrigado! 1
evu
3

O resultado final

Isto é o que eu vim usando parcialmente pedaços de todas as respostas que tenho:

/**
 * 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');


Alguns pensamentos:

Isso funciona. Embora você seja "obrigado" a atribuir ambas as taxonomias a cada postagem ou o URL terá um resultado à direita '/'» '/products/taxonomy//postname'. Como vou atribuir ambas as taxonomias a todos os meus procedimentos, tendo um tipo e uma marca, esse código parece estar funcionando para minhas necessidades. Se alguém tiver alguma sugestão ou melhoria, sinta-se à vontade para responder!

DRSK
fonte
Excelente. Obrigado por postar sua solução. Por favor, selecione-o como a resposta uma vez que o tempo passou. Além disso, é recomendável votar novamente em qualquer resposta útil.
Marfarma
Estou tendo dificuldades para fazer isso funcionar, não sei por quê. Até copiar / colar em minhas funções, em vez de tentar portar suas alterações, gera muitos erros. Eu estou pensando que algo no núcleo do WordPress deve ter mudado entre quando isso foi escrito (mais de 3 anos atrás) e hoje. Eu estou tentando descobrir a mesma coisa: wordpress.stackexchange.com/questions/180994/…
JacobTheDev 12/15/15
flush_rewrite_rules()em init? não faça isso. basicamente, você está redefinindo suas regras de reescrita a cada carregamento de página.
honk31 29/01
1

Verifique desta forma, ainda há alguns bugs no arquivo da marca

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');
Luis Abarca
fonte
1

Embora não seja sua estrutura exata de URL desejada, você pode obter:

/ produtos
»Ver todas as postagens personalizadas

/ products / type / cell-phones
»Veja todas as postagens personalizadas com os celulares de taxonomia

/ products / type / telefones celulares / marca / samsung
»Veja todas as postagens personalizadas nas quais a taxonomia é telefones celulares E samsung

/ brand / samsung
»Veja todas as postagens personalizadas nas quais a taxonomia é samsung

/ product / test-product-1
»Visualizar o produto (postagem personalizada única)

sem precisar especificar regras personalizadas de reescrita.

No entanto, é necessário registrar suas taxonomias e tipos de postagem personalizados em uma ordem específica. O truque é registrar qualquer taxonomia em que a lesma comece com a lesma do seu tipo de postagem antes de registrar esse tipo de postagem personalizado. Por exemplo, assuma as seguintes lesmas:

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

Então você pode registrá-los nesta ordem:

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

Se você absolutamente precisa ter um URL como:

/ products / tipo / telefones celulares / marca / samsung / test-product-1
»Veja o produto (postagem personalizada única)

Então você exigiria uma regra de reescrita mais ou menos assim:

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

UPDATE /programming/3861291/multiple-custom-permalink-structures-in-wordpress

Veja como redefinir corretamente o URL de postagem única.

Defina a reescrita como false para o tipo de postagem personalizada. (Deixe o arquivo como está) e, depois de registrar as taxonomias e postagens, também registre as seguintes regras de reescrita.

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

Em seguida, filtre post_type_link para criar a estrutura de URL desejada - permitindo valores de taxonomia não definidos. Alterando o código da postagem vinculada, você teria:

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

Agora, só preciso descobrir como reescrever o URL da taxonomia da marca sem a tag da marca líder e devo corresponder exatamente ao URL desejado.

Marfarma
fonte