Cum să creezi o structură de permalink-uri cu taxonomii personalizate și tipuri de postări personalizate precum nume-bază/taxonomie-părinte/taxonomie-copil/nume-postare-personalizată

20 ian. 2012, 02:37:40
Vizualizări: 75.8K
Voturi: 64

Am căutat pe acest site și pe Google pentru răspuns și nu am găsit nimic. Practic, vreau să fac exact ce se cere în această postare, dar am nevoie de o taxonomie ierarhică. Răspunsul oferit în acea postare funcționează excelent, dar doar cu o taxonomie pe un singur nivel. Este posibil să fac ce îmi doresc? Am încercat o mulțime de lucruri, dar niciunul nu funcționează, în cel mai bun caz obțin permalink-urile corecte dar rezultă în erori 404.

Pentru a ilustra vizual ce doresc:

/basename/ - ideal o pagină, dar cred că va cauza o coliziune de permalink-uri    
/basename/top-cat/ - arhivă taxonomie personalizată părinte    
/basename/top-cat/child-cat/ - arhivă taxonomie personalizată copil    
/basename/top-cat/child-cat/grandchild-cat/ - arhivă taxonomie personalizată nepot    
/basename/top-cat/child-cat/grandchild-cat/post-name/ - postarea mea de tip personalizat

Poți face acest lucru cu postările și categoriile predefinite, cum poți face asta cu taxonomii personalizate și tipuri de postări personalizate? Știu că trebuie să folosești 'rewrite' => array( 'slug' => 'tax-name', 'with_front' => true, 'hierarchical' => true ), pentru a obține slug-uri ierarhice, care funcționează bine pe paginile de arhivă, dar postările de tip personalizat rezultă în 404. Dacă elimin partea cu 'hierarchical' => true atunci postările funcționează, dar pierd URL-urile ierarhice (doar /basename/grandchild-cat/post-name/ funcționează).

Deci, există vreo soluție? Vă mulțumesc mult, acest lucru mă înnebunește de aproximativ 3 săptămâni.

0
Toate răspunsurile la întrebare 4
10
78

După ce am combinat mai multe fragmente din alte răspunsuri, am reușit să fac totul să funcționeze! Așadar, iată soluția pentru cei dintre voi care vă luptați și voi cu această problemă:

Acest articol și acesta m-au ajutat destul de mult, așa că mulțumesc celor care le-au scris.

Notă: tot acest cod, plus codul inițial de înregistrare a tipului de postare personalizat și a taxonomiei, trebuie introdus în fișierul functions.php.

Mai întâi, asigură-te că ai definit corect slug-urile pentru tipurile de postare personalizate și taxonomii: pentru tipul de postare personalizat, ar trebui să fie basename/%taxonomy_name%, iar slug-ul pentru taxonomie ar trebui să fie doar basename. Nu uita să adaugi și 'hierarchical' => true în array-ul rewrite al taxonomiei pentru a obține termeni imbricați în URL. De asemenea, asigură-te că query_var este setat la true în ambele cazuri.

Trebuie să adaugi o nouă regulă de rewrite, astfel încât WordPress să știe cum să interpreteze structura URL-ului tău. În cazul meu, partea din URL care reprezintă tipul de postare personalizat va fi întotdeauna al 5-lea segment, așa că am definit regula de potrivire în consecință. Reține că poate fi necesar să modifici acest lucru dacă folosești mai multe sau mai puține segmente de URL. Dacă vei avea niveluri variate de termeni imbricați, va trebui să scrii o funcție care să verifice dacă ultimul segment de URL este un tip de postare personalizat sau un termen de taxonomie, pentru a ști ce regulă să adaugi (întreabă-mă dacă ai nevoie de ajutor pentru asta).

add_filter('rewrite_rules_array', 'mmp_rewrite_rules');
function mmp_rewrite_rules($rules) {
    $newRules  = array();
    $newRules['basename/(.+)/(.+)/(.+)/(.+)/?$'] = 'index.php?custom_post_type_name=$matches[4]'; // structura mea personalizată va avea întotdeauna numele postării ca al 5-lea segment de URL
    $newRules['basename/(.+)/?$']                = 'index.php?taxonomy_name=$matches[1]'; 

    return array_merge($newRules, $rules);
}

Apoi, trebuie să adaugi acest cod pentru a-i permite WordPress să gestioneze %taxonomy_name% în structura de rewrite a slug-ului tipului de postare personalizat:

function filter_post_type_link($link, $post)
{
    if ($post->post_type != 'custom_post_type_name')
        return $link;

    if ($cats = get_the_terms($post->ID, 'taxonomy_name'))
    {
        $link = str_replace('%taxonomy_name%', get_taxonomy_parents(array_pop($cats)->term_id, 'taxonomy_name', false, '/', true), $link); // vezi funcția personalizată definită mai jos
    }
    return $link;
}
add_filter('post_type_link', 'filter_post_type_link', 10, 2);

Am creat o funcție personalizată bazată pe funcția WordPress get_category_parents:

// propria mea funcție pentru a face ceea ce face get_category_parents pentru alte taxonomii
function get_taxonomy_parents($id, $taxonomy, $link = false, $separator = '/', $nicename = false, $visited = array()) {    
    $chain = '';   
    $parent = &get_term($id, $taxonomy);

    if (is_wp_error($parent)) {
        return $parent;
    }

    if ($nicename)    
        $name = $parent -> slug;        
else    
        $name = $parent -> name;

    if ($parent -> parent && ($parent -> parent != $parent -> term_id) && !in_array($parent -> parent, $visited)) {    
        $visited[] = $parent -> parent;    
        $chain .= get_taxonomy_parents($parent -> parent, $taxonomy, $link, $separator, $nicename, $visited);

    }

    if ($link) {
        // nimic, nu reușesc să fac asta să funcționeze :(
    } else    
        $chain .= $name . $separator;    
    return $chain;    
}

Apoi, trebuie să resetezi permalinkurile (doar încarcă pagina de setări a permalinkurilor).

Acum, totul "ar trebui" să funcționeze! Creează mai mulți termeni de taxonomie și imbrică-i corect, apoi creează câteva postări de tip personalizat și categorizează-le corect. Poți crea și o pagină cu slug-ul basename, și totul ar trebui să funcționeze așa cum am specificat în întrebarea mea. Poate vei dori să creezi niște pagini de arhivă personalizate pentru taxonomii, pentru a controla cum arată și să adaugi un widget de taxonomie pentru a afișa categoriile imbricate în bara laterală.

Sper că te ajută!

23 ian. 2012 20:31:57
Comentarii

Salut Jeff, mulțumesc pentru răspuns! Sunt aproape gata, după 4 ore de luptat cu asta. Singura mea problemă este că primesc o dublă slash înaintea numelui postului (ca aici: portfolio/diseno-grafico-2/logo//alquimia-sonora/). Mă poți ajuta?

Cmorales Cmorales
7 apr. 2012 22:50:17

@Cmorales, Nu sunt sigur fără să văd codul tău, dar caută un loc unde definesti manual o slash înaintea numelui postului, poate în înregistrarea slug-ului CPT sau în funcția filter_post_type? Dacă nu poți identifica unde adaugi slash-ul în plus, ai putea pur și simplu să elimini ultimul caracter din valoarea returnată de funcția get_taxonomy_parents apelată în filter_post_type_link, pentru că asta va lăsa o slash la final, care este prima din cele duble. Mult succes.

Jeff Jeff
9 apr. 2012 18:32:23

Am creat permalink-urile conform ghidului tău, dar link-ul implicit în WordPress pentru tipul personalizat de postare este: domain.com/my-post-type/custom-post-type-name (domain.com/place/lotus-hotel) Am testat codul tău în functions.php, dar nu găsesc modalitatea de a adăuga taxonomia personalizată la link-ul de mai sus (domain.com/place/tokyo/lotus-hotel) - tokyo este taxonomia mea personalizată

User User
5 mai 2012 07:04:51

Rezolvat - vezi întrebarea. Jeff, mulțumesc pentru explicație! Dar ai putea, te rog, să postezi structura custom posttype / taxonomy? Așa aș putea să văd ce fac gresit? Aș fi foarte recunoscător!

Reitze Bos Reitze Bos
28 mar. 2012 12:26:18

Mulțumesc mult mult mult pentru asta. O mică problemă totuși, se pare că poluează regulile de rescriere cu o grămadă de intrări %taxonomy_name% sau în cazul meu: apps/%primary_tag%/([^/]+)/page/?([0-9]{1,})/?$] => index.php?%primary_tag%$matches[1]&apps-post=$matches[2]&paged=$matches[3] Regulile pe care le adaug manual au prioritate și par să facă treaba, dar aceste intrări sugerează că ceva nu e chiar în regulă. Ai vreo idee?

Hari Honor Hari Honor
16 mai 2012 13:22:08

"Dacă vei avea niveluri variate de termeni imbricați, atunci va trebui să scrii o funcție pentru a verifica dacă ultimul segment din URI este un custom post type sau un termen de taxonomie pentru a ști ce regulă să adaugi (cere-mi ajutor dacă ai nevoie...)..." Ei bine, poți să mă ajuți, te rog? :)

Cmorales Cmorales
23 mai 2013 01:47:33

^ exact asta aveam nevoie. știe cineva cum să fac asta? vezi întrebarea mea aici: http://wordpress.stackexchange.com/questions/102246/wordpress-returns-404-on-custom-rewrite-rules

reikyoushin reikyoushin
7 iun. 2013 17:55:26

A funcționat bine, dar din nu știu ce motiv, doar categoria părinte este afișată și niciuna dintre cele copil. Am copiat exact cum ai postat și am schimbat doar numele post type-ului și taxonomiei unde era indicat. Ai vreo idee?

paper_robots paper_robots
12 feb. 2014 02:17:29

Știu că e puțin învechit, dar ai vreo idee despre cum să păstrez '/basename' direcționat către cele mai recente articole din acel post type, indiferent de taxonomie?

Daron Spence Daron Spence
4 feb. 2015 19:29:46

După 3 ore de căutări pe Google, acesta este răspunsul. Pentru cei care utilizați un format /post_type/term/slug/ (fără ierarhie), puteți elimina funcția get_taxonomy_parents() și o puteți înlocui cu $cats[0]->slug deoarece există deja o verificare pentru existența termenilor. Acea funcție este și ceea ce adaugă un alt slash.

EmilyH EmilyH
18 dec. 2020 00:44:01
Arată celelalte 5 comentarii
1

Aruncă o privire la acest plugin (acum pe github). Acesta oferă URL-uri ierarhice pentru categorii, dar poți adapta ușor pentru orice taxonomie.

Crearea regulilor urmează o funcție recursivă.

17 sept. 2012 19:02:20
Comentarii

Acest plugin nu mai este disponibil.

Enkode Enkode
6 dec. 2018 00:34:16
0

Pentru a gestiona diferite niveluri de imbricare,

/basename/top-cat/ -> Arhivă Top Cat
/basename/top-cat/post-name/ -> Postare în Top Cat
/basename/top-cat/child-cat/ -> Arhivă Child Cat
/basename/top-cat/child-cat/post-name/ -> Postare în Child Cat

Am ajuns să folosesc soluția lui Jeff fără filtrul rewrite_rules_array. În schimb, am utilizat filtrul request pentru a verifica dacă ultima parte a URL-ului este un nume de postare valid și a-l adăuga la query_vars.

ex.

function vk_query_vars($qvars){
    if(is_admin()) return $qvars;
    $custom_taxonomy = 'product_category';
    if(array_key_exists($custom_taxonomy, $qvars)){
        $custom_post_type = 'product';


        $pathParts = explode('/', $qvars[$custom_taxonomy]);
        $numParts = sizeof($pathParts);

        $lastPart = array_pop($pathParts);
        $post = get_page_by_path($lastPart, OBJECT, $custom_post_type);
        if( $post && !is_wp_error($post) ){
            $qvars['p'] = $post->ID;
            $qvars['post_type'] = $custom_post_type;
        }
    }
    return $qvars;
}
add_filter('request', 'vk_query_vars');
3 mai 2020 18:58:15
0

Iată soluția mea bazată pe cea a lui Jeff. rewrite_rules_array poate să nu fie necesar în funcție de aplicația ta. Această variantă simplifică filter_post_type_link și nu necesită funcții suplimentare. Folosește funcția încorporată get_term_parents_list()

function PLUGIN_filter_post_type_link($post_link, $post)
{
    $postTypes = ['CUSTOM-POST-TYPE'];
    $taxonomy = 'TAXONOMIE';

    /* dacă tipul postării se potrivește */
    if (in_array($post->post_type, $postTypes, $strict=true)) {
        /* dacă taxonomia este atribuită */
        if ($terms = get_the_terms($post->ID, $taxonomy)
        ) {
            $args = [
                'format' => 'slug',
                'separator' => '/',
                'link' => false,
                'inclusive' => true,
            ];

            return str_replace(
                "%{$taxonomy}%",
                rtrim(
                    get_term_parents_list($terms[0]->term_id, $taxonomy, $args),
                    "/"
                ),
                $post_link);
        }
        /* elimină taxonomia și slash-ul final din post_link */
        return str_replace("%{$taxonomy}%/", '', $post_link);
    }
    return $post_link;
}
7 iul. 2021 17:52:02