Adăugarea categoriilor în permalink pentru tipuri de postări personalizate
Știu că oamenii au mai întrebat acest lucru și au mers până la adăugarea tipului de postare personalizat și rescrierea pentru permalink.
Problema este că am 340 de categorii existente pe care aș dori să continui să le folosesc. Înainte puteam vedea /categorie/subcategorie/nume-postare
Acum am slug-ul customposttype/nume-postare. Selectarea categoriei nu mai apare în permalink... Nu am schimbat setarea permalink-ului în admin cu nimic diferit.
Îmi lipsește ceva sau trebuie să adaug ceva la acest cod?
function jcj_club_post_types() {
register_post_type( 'jcj_club', array(
'labels' => array(
'name' => __( 'Cluburi de Jazz' ),
'singular_name' => __( 'Club de Jazz' ),
'add_new' => __( 'Adaugă Nou' ),
'add_new_item' => __( 'Adaugă Club de Jazz Nou' ),
'edit' => __( 'Editează' ),
'edit_item' => __( 'Editează Cluburi de Jazz' ),
'new_item' => __( 'Club de Jazz Nou' ),
'view' => __( 'Vezi Club de Jazz' ),
'view_item' => __( 'Vezi Club de Jazz' ),
'search_items' => __( 'Caută Cluburi de Jazz' ),
'not_found' => __( 'Nu s-au găsit cluburi de jazz' ),
'not_found_in_trash' => __( 'Nu s-au găsit cluburi de jazz în Coș' ),
'parent' => __( 'Club de Jazz Părinte' ),
),
'public' => true,
'show_ui' => true,
'publicly_queryable' => true,
'exclude_from_search' => false,
'menu_position' => 5,
'query_var' => true,
'supports' => array(
'title',
'editor',
'comments',
'revisions',
'trackbacks',
'author',
'excerpt',
'thumbnail',
'custom-fields',
),
'rewrite' => array( 'slug' => 'cluburi-jazz-in', 'with_front' => true ),
'taxonomies' => array( 'category','post_tag'),
'can_export' => true,
)
);
Există 2 puncte de atac de acoperit atunci când adăugați reguli de rescriere pentru tipurile personalizate de articole:
Reguli de rescriere
Acest lucru se întâmplă când regulile de rescriere sunt generate în wp-includes/rewrite.php
în WP_Rewrite::rewrite_rules()
. WordPress vă permite să filtrați regulile de rescriere pentru elemente specifice cum ar fi articolele, paginile și diferite tipuri de arhivă. Unde vedeți posttype_rewrite_rules
partea posttype
ar trebui să fie numele tipului dvs. personalizat de articol. Alternativ, puteți utiliza filtrul post_rewrite_rules
atâta timp cât nu suprascrieți și regulile standard pentru articole.
În continuare, avem nevoie de funcția care generează efectiv regulile de rescriere:
// adăugăm noul nostru permastruct la regulile de rescriere
add_filter( 'posttype_rewrite_rules', 'add_permastruct' );
function add_permastruct( $rules ) {
global $wp_rewrite;
// setați structura dorită pentru permalink aici
$struct = '/%category%/%year%/%monthnum%/%postname%/';
// utilizați funcția de generare a regulilor de rescriere din WP
$rules = $wp_rewrite->generate_rewrite_rules(
$struct, // structura permalinkului
EP_PERMALINK, // Mască de endpoint: adaugă reguli de rescriere pentru endpointuri ale articolelor unice, cum ar fi paginile de comentarii etc...
false, // Paginat: adaugă reguli de rescriere pentru paginare, de ex. pentru arhive (nu este necesar aici)
true, // Feed: adaugă reguli de rescriere pentru endpointurile de feed
true, // Pentru comentarii: dacă regulile de feed ar trebui să fie pentru comentariile articolului - pe o pagină singulară adaugă endpointuri pentru feedul de comentarii
false, // Parcurge directoarele: dacă să genereze reguli pentru fiecare segment al permastructului delimitat de '/'. Setat întotdeauna pe false altfel regulile personalizate de rescriere vor fi prea lacome, apar în partea de sus a regulilor
true // Adaugă endpointuri personalizate
);
return $rules;
}
Principalul lucru de care trebuie să fiți atenți dacă decideți să vă jucați este valoarea booleană 'Walk directories'. Aceasta generează reguli de rescriere pentru fiecare segment al unui permastruct și poate cauza nepotriviri în regulile de rescriere. Când este solicitat un URL WordPress, matricea de reguli de rescriere este verificată de sus în jos. De îndată ce se găsește o potrivire, va încărca orice a întâlnit, așa că, de exemplu, dacă permastructul dvs. are o potrivire lacomă, cum ar fi /%category%/%postname%/
și walk directories este activat, va genera reguli de rescriere atât pentru /%category%/%postname%/
cât și pentru /%category%/
care se vor potrivi cu orice. Dacă acest lucru se întâmplă prea devreme, sunteți încurcați.
Permalinkuri
Aceasta este funcția care analizează permalinkurile tipului de articol și convertește un permastruct (de ex. '/%year%/%monthnum%/%postname%/') într-un URL real.
Următoarea parte este un exemplu simplu de ceea ce ar fi ideal o versiune a funcției get_permalink()
găsită în wp-includes/link-template.php
. Permalinkurile personalizate pentru articole sunt generate de get_post_permalink()
, care este o versiune mult mai simplificată a get_permalink()
. get_post_permalink()
este filtrat de post_type_link
, așa că folosim acest lucru pentru a crea un permastruct personalizat.
// analizăm linkurile generate
add_filter( 'post_type_link', 'custom_post_permalink', 10, 4 );
function custom_post_permalink( $permalink, $post, $leavename, $sample ) {
// facem lucrurile noastre doar dacă folosim permalinkuri frumoase
// și dacă este tipul nostru țintă de articol
if ( $post->post_type == 'posttype' && get_option( 'permalink_structure' ) ) {
// reținem structura dorită a permalinkului aici
// trebuie să generăm echivalentul cu date reale
// pentru a se potrivi cu regulile de rescriere stabilite anterior
$struct = '/%category%/%year%/%monthnum%/%postname%/';
$rewritecodes = array(
'%category%',
'%year%',
'%monthnum%',
'%postname%'
);
// setăm datele
$terms = get_the_terms($post->ID, 'category');
$unixtime = strtotime( $post->post_date );
// acest cod este din get_permalink()
$category = '';
if ( strpos($permalink, '%category%') !== false ) {
$cats = get_the_category($post->ID);
if ( $cats ) {
usort($cats, '_usort_terms_by_ID'); // ordonăm după ID
$category = $cats[0]->slug;
if ( $parent = $cats[0]->parent )
$category = get_category_parents($parent, false, '/', true) . $category;
}
// afișăm categoria implicită în permalinkuri, fără
// a fi nevoie să o atribuim explicit
if ( empty($category) ) {
$default_category = get_category( get_option( 'default_category' ) );
$category = is_wp_error( $default_category ) ? '' : $default_category->slug;
}
}
$replacements = array(
$category,
date( 'Y', $unixtime ),
date( 'm', $unixtime ),
$post->post_name
);
// finalizăm permalinkul
$permalink = home_url( str_replace( $rewritecodes, $replacements, $struct ) );
$permalink = user_trailingslashit($permalink, 'single');
}
return $permalink;
}
După cum s-a menționat, acesta este un caz foarte simplificat pentru generarea unui set de reguli de rescriere personalizate și a permalinkurilor și nu este deosebit de flexibil, dar ar trebui să fie suficient pentru a vă începe.
Trichere
Am scris un plugin care vă permite să definiți permastructuri pentru orice tipuri personalizate de articole, dar la fel cum puteți utiliza %category%
în structura permalinkului pentru articole, pluginul meu suportă %custom_taxonomy_name%
pentru orice taxonomii personalizate pe care le aveți, unde custom_taxonomy_name
este numele taxonomiei dumneavoastră, de ex. %club%
.
Va funcționa așa cum vă așteptați pentru taxonomii ierarhice/neierarhice.

pluginul este minunat, dar poți explica cum să rezolvi problema din întrebare fără pluginul tău?

Sunt de acord că e minunat că există un plugin care să rezolve problema (l-am marcat și este primul la care m-am gândit la această întrebare), dar răspunsul ar beneficia de un rezumat scurt despre care este problema și cum a rezolvat-o pluginul. :)

@EugeneManuilov Bine, îmi pare rău că răspunsul este lung. Asta după ce l-am redus la elementele de bază!

Se pare că primul $permalink = home_url(...
este suprascris de $permalink = user_trailingslashit(...
și nu este niciodată utilizat. Sau greșesc? $post_link
nici măcar nu este definit. Ar fi trebuit să fie $permalink = user_trailingslashit( $permalink, 'single' );
?

Bună observație, ar fi trebuit să fie $permalink
nu $post_link
. Mersi :)

Am găsit o SOLUȚIE!!!
(După o cercetare nesfârșită.. Pot avea permalinkuri pentru CUSTOM POST TYPE de genul:
example.com/categorie/sub_categorie/numele-postului-meu
Iată codul (în functions.php sau într-un plugin):
//===PASUL 1 (afectează doar aceste CUSTOM POST TYPES)
$GLOBALS['my_post_typesss__MLSS'] = array('my_product1','....');
//===PASUL 2 (creează permalinkurile dorite)
add_filter('post_type_link', 'my_func88888', 6, 4 );
function my_func88888( $post_link, $post, $sdsd){
if (!empty($post->post_type) && in_array($post->post_type, $GLOBALS['my_post_typesss']) ) {
$SLUGG = $post->post_name;
$post_cats = get_the_category($id);
if (!empty($post_cats[0])){ $target_CAT= $post_cats[0];
while(!empty($target_CAT->slug)){
$SLUGG = $target_CAT->slug .'/'.$SLUGG;
if (!empty($target_CAT->parent)) {$target_CAT = get_term( $target_CAT->parent, 'category');} else {break;}
}
$post_link= get_option('home').'/'. urldecode($SLUGG);
}
}
return $post_link;
}
// PASUL 3 (implicit, când se accesează: "EXAMPLE.COM/categorie/nume-post"
// WP crede că se solicită un post standard. Așadar, adăugăm CUSTOM POST
// TYPE în acea interogare.
add_action('pre_get_posts', 'my_func4444', 12);
function my_func4444($q){
if ($q->is_main_query() && !is_admin() && $q->is_single){
$q->set( 'post_type', array_merge(array('post'), $GLOBALS['my_post_typesss'] ) );
}
return $q;
}

Am găsit soluția!
Pentru a avea permalink-uri ierarhice pentru tipurile personalizate de postări, instalați pluginul Custom Post Type Permalinks(https://wordpress.org/plugins/custom-post-type-permalinks/).
Actualizați tipul de postare înregistrat. Eu am tipul de postare numit help center
function help_centre_post_type(){
register_post_type('helpcentre', array(
'labels' => array(
'name' => __('Centru de Ajutor'),
'singular_name' => __('Centru de Ajutor'),
'all_items' => __('Vezi Postările'),
'add_new' => __('Postare Nouă'),
'add_new_item' => __('Centru de Ajutor Nou'),
'edit_item' => __('Editează Centrul de Ajutor'),
'view_item' => __('Vezi Centrul de Ajutor'),
'search_items' => __('Caută în Centrul de Ajutor'),
'no_found' => __('Nu s-a găsit nicio postare'),
'not_found_in_trash' => __('Nu există postări în coșul de gunoi')
),
'public' => true,
'publicly_queryable'=> true,
'show_ui' => true,
'query_var' => true,
'show_in_nav_menus' => false,
'capability_type' => 'page',
'hierarchical' => true,
'rewrite'=> [
'slug' => 'help-center',
"with_front" => false
],
"cptp_permalink_structure" => "/%help_centre_category%/%post_id%-%postname%/",
'menu_position' => 21,
'supports' => array('title','editor', 'thumbnail'),
'has_archive' => true
));
flush_rewrite_rules();
}
add_action('init', 'help_centre_post_type');
Și aici este taxonomia înregistrată
function themes_taxonomy() {
register_taxonomy(
'help_centre_category',
'helpcentre',
array(
'label' => __( 'Categorii' ),
'rewrite'=> [
'slug' => 'help-center',
"with_front" => false
],
"cptp_permalink_structure" => "/%help_centre_category%/",
'hierarchical' => true,
'public' => true,
'show_ui' => true,
'show_admin_column' => true,
'show_in_nav_menus' => true,
'query_var' => true
)
);
}
add_action( 'init', 'themes_taxonomy');
Această linie face ca permalink-ul să funcționeze
"cptp_permalink_structure" => "/%help_centre_category%/%post_id%-%postname%/",
puteți elimina %post_id%
și puteți păstra /%help_centre_category%/%postname%/"
Nu uitați să resetați permalink-urile din panoul de administrare.

+1 cea mai simplă soluție este să folosești acest plugin: https://wordpress.org/plugins/custom-post-type-permalinks/ funcționează perfect

Da, dar asta este pentru cazul în care ai un singur tip de postare personalizat, dar dacă ai mai multe tipuri de postări personalizate într-o singură temă, atunci soluția de mai sus este cea potrivită.
În plus, acesta modifică și slug-ul categoriei la fel ca slug-ul tipului de postare.

Aveți câteva erori în codul dumneavoastră. Am curățat codul existent:
<?php
function jcj_club_post_types() {
$labels = array(
'name' => __( 'Cluburi de Jazz' ),
'singular_name' => __( 'Club de Jazz' ),
'add_new' => __( 'Adaugă nou' ),
'add_new_item' => __( 'Adaugă Club de Jazz nou' ),
'edit' => __( 'Editează' ),
'edit_item' => __( 'Editează Cluburi de Jazz' ),
'new_item' => __( 'Club de Jazz nou' ),
'view' => __( 'Vezi Club de Jazz' ),
'view_item' => __( 'Vezi Club de Jazz' ),
'search_items' => __( 'Caută Cluburi de Jazz' ),
'not_found' => __( 'Nu s-au găsit cluburi de jazz' ),
'not_found_in_trash' => __( 'Nu s-au găsit cluburi de jazz în Coșul de Gunoi' ),
'parent' => __( 'Club de Jazz Părinte' ),
);
$args = array(
'public' => true,
'show_ui' => true,
'publicly_queryable' => true,
'exclude_from_search' => false,
'menu_position' => 5,
'query_var' => true,
'supports' => array( 'title','editor','comments','revisions','trackbacks','author','excerpt','thumbnail','custom-fields' ),
'rewrite' => array( 'slug' => 'cluburi-de-jazz-in', 'with_front' => true ),
'has_archive' => true
);
register_post_type( 'jcj_club', $args );
}
add_action( 'init','jcj_club_post_types' );
?>
Înlocuiți codul dumneavoastră cu codul de mai sus și verificați dacă funcționează. Răspundeți dacă aveți întrebări suplimentare și voi încerca să vă ajut.
EDITARE:
Am observat că am omis 'has_archive' => true
.
