Cum să setezi relația părinte-copil între tipuri de postări personalizate diferite
Tocmai am configurat o relație post/părinte între un tip de postare "episodes" și un tip de postare "cartoon-series".
Am folosit acest cod pentru a adăuga meta box-ul care permite atribuirea părintelui dintr-un alt tip de postare:
add_action('admin_menu', function() {
remove_meta_box('pageparentdiv', 'episodes', 'normal');
});
add_action('add_meta_boxes', function() {
add_meta_box('episodes-parent', 'Cartoon Series', 'episodes_attributes_meta_box', 'episodes', 'side', 'default');
});
function episodes_attributes_meta_box($post) {
$post_type_object = get_post_type_object($post->post_type);
if ( $post_type_object->hierarchical ) {
$pages = wp_dropdown_pages(array('post_type' => 'cartoon-series', 'selected' => $post->post_parent, 'name' => 'parent_id', 'show_option_none' => __('(fără părinte)'), 'sort_column'=> 'menu_order, post_title', 'echo' => 0));
if ( ! empty($pages) ) {
echo $pages;
} // verificare pentru pagini goale
} // verificare ierarhică
}
Codul funcționează în panoul de administrare permițându-mi să setez seria ca părinte pentru episod, dar când încerc să vizualizez postarea, primesc o eroare 404. Structura URL-ului este:
domain/episodes/series-name/episode-name
URL-ul pentru serie este:
domain/cartoon-series/series-name
Aș dori ca URL-ul pentru episod să fie:
domain/cartoon-series/series-name/episode-name
Ce îmi lipsește? Este posibil să fac un întreg tip de postare copilul altui tip de postare? Astfel, aș putea obține chiar și URL-ul pentru lista de episoade să fie:
domain/cartoon-series/series-name/episodes
Mulțumesc! Matt
Conform solicitării, iată codul pentru cele două tipuri de postări personalizate în discuție:
$labels = array(
"name" => "Cartoon Series",
"singular_name" => "Cartoon Series",
"menu_name" => "Cartoon Series",
"all_items" => "All Cartoon Series",
"add_new" => "Add New",
"add_new_item" => "Add New Cartoon Series",
"edit" => "Edit",
"edit_item" => "Edit Cartoon Series",
"new_item" => "New Cartoon Series",
"view" => "View",
"view_item" => "View Cartoon Series",
"search_items" => "Search Cartoon Series",
"not_found" => "No Cartoon Series Found",
"not_found_in_trash" => "No Cartoon Series Found in Trash",
"parent" => "Parent Cartoon Series",
);
$args = array(
"labels" => $labels,
"description" => "",
"public" => true,
"show_ui" => true,
"has_archive" => true,
"show_in_menu" => true,
"exclude_from_search" => false,
"capability_type" => "post",
"map_meta_cap" => true,
"hierarchical" => true,
"rewrite" => array( "slug" => "cartoon-series", "with_front" => true ),
"query_var" => true,
"supports" => array( "title", "revisions", "thumbnail" ), );
register_post_type( "cartoon-series", $args );
$labels = array(
"name" => "Episodes",
"singular_name" => "Episode",
);
$args = array(
"labels" => $labels,
"description" => "",
"public" => true,
"show_ui" => true,
"has_archive" => true,
"show_in_menu" => true,
"exclude_from_search" => false,
"capability_type" => "post",
"map_meta_cap" => true,
"hierarchical" => true,
"rewrite" => array( "slug" => "episodes", "with_front" => true ),
"query_var" => true,
"supports" => array( "title", "revisions", "thumbnail" ), );
register_post_type( "episodes", $args );
Folosesc plugin-ul CPT UI, deci nu pot edita direct acel cod. Acesta este doar codul de export pe care îl oferă CPT UI.
Nu am niciun alt cod care să lege cele două CPT-uri. Poate asta îmi lipsește. Am găsit doar acel cod online care plasează metabox-ul pe pagină pentru a face legătura. Nu este suficient pentru a face treaba? Se pare că setează post_parent.
Mulțumesc! Matt

În sfârșit am găsit o soluție funcțională. Seriile de desene animate pot fi înregistrate așa cum ai făcut, dar posturile personalizate pentru episoade nu pot fi ierarhice (cred că WordPress se așteaptă ca conținutul părinte să fie de același tip cu conținutul copil dacă relația este stabilită folosind post_parent
în tabelul de baze de date wp_posts
).
La înregistrarea episoadelor, regula de rescriere trebuie setată la slug-ul dorit, adică cartoon-series/%series_name%
. Apoi putem filtra linkul episoadelor pentru a înlocui %series_name%
cu numele real al tipului de postare părinte cartoon-series
și o regulă de rescriere pentru a-i spune lui WordPress când este solicitat un tip de postare cartoon-series și când este un episod.
add_action('init', function(){
$labels = array(
"name" => "Serii de Desene Animate",
"singular_name" => "Serie de Desene Animate",
"menu_name" => "Serii de Desene Animate",
"all_items" => "Toate Seriile de Desene Animate",
"add_new" => "Adaugă Nou",
"add_new_item" => "Adaugă o Serie Nouă de Desene Animate",
"edit" => "Editează",
"edit_item" => "Editează Seria de Desene Animate",
"new_item" => "Serie Nouă de Desene Animate",
"view" => "Vizualizează",
"view_item" => "Vizualizează Seria de Desene Animate",
"search_items" => "Caută Serii de Desene Animate",
"not_found" => "Nu s-au găsit Serii de Desene Animate",
"not_found_in_trash" => "Nu s-au găsit Serii de Desene Animate în Gunoi",
"parent" => "Seria Părinte de Desene Animate",
);
$args = array(
"labels" => $labels,
"description" => "",
"public" => true,
"show_ui" => true,
"has_archive" => true,
"show_in_menu" => true,
"exclude_from_search" => false,
"capability_type" => "post",
"map_meta_cap" => true,
"hierarchical" => true,
"rewrite" => array( "slug" => "cartoon-series", "with_front" => true ),
"query_var" => true,
"supports" => array( "title", "revisions", "thumbnail" )
);
register_post_type( "cartoon-series", $args );
$labels = array(
"name" => "Episoade",
"singular_name" => "Episod",
);
$args = array(
"labels" => $labels,
"description" => "",
"public" => true,
"show_ui" => true,
"has_archive" => true,
"show_in_menu" => true,
"exclude_from_search" => false,
"capability_type" => "post",
"map_meta_cap" => true,
"hierarchical" => false,
"rewrite" => array( "slug" => "cartoon-series/%series_name%", "with_front" => true ),
"query_var" => true,
"supports" => array( "title", "revisions", "thumbnail" )
);
register_post_type( "episodes", $args );
});
add_action('add_meta_boxes', function() {
add_meta_box('episodes-parent', 'Serii de Desene Animate', 'episodes_attributes_meta_box', 'episodes', 'side', 'default');
});
function episodes_attributes_meta_box($post) {
$pages = wp_dropdown_pages(array('post_type' => 'cartoon-series', 'selected' => $post->post_parent, 'name' => 'parent_id', 'show_option_none' => __('(fără părinte)'), 'sort_column'=> 'menu_order, post_title', 'echo' => 0));
if ( ! empty($pages) ) {
echo $pages;
} // verificare pagini goale
}
add_action( 'init', function() {
add_rewrite_rule( '^cartoon-series/(.*)/([^/]+)/?$','index.php?episodes=$matches[2]','top' );
});
add_filter( 'post_type_link', function( $link, $post ) {
if ( 'episodes' == get_post_type( $post ) ) {
//Să obținem numele seriei părinte de desene animate
if( $post->post_parent ) {
$parent = get_post( $post->post_parent );
if( !empty($parent->post_name) ) {
return str_replace( '%series_name%', $parent->post_name, $link );
}
} else {
//Aceasta pare să nu funcționeze. Este intenționat să construiască permalink-uri frumoase
//când episoadele nu au părinte, dar pare că ar avea nevoie
//de reguli suplimentare de rescriere
//return str_replace( '/%series_name%', '', $link );
}
}
return $link;
}, 10, 2 );
NOTĂ: Nu uitați să reîmprospătați regulile de rescriere după salvarea codului de mai sus și înainte de a încerca. Accesați wp-admin/options-permalink.php
și faceți clic pe salvare pentru a regenera regulile de rescriere.
NOTĂ 2: Este posibil să fie necesară adăugarea mai multor reguli de rescriere, de exemplu pentru a funcționa pentru postările paginate. De asemenea, poate fi nevoie de ceva mai multă muncă pentru a avea o soluție completă, de exemplu, la ștergerea unei cartoon-series
să se șteargă și toate episoadele copil? Adăugați un filtru în ecranul de editare din administrare pentru a filtra episoadele după postul părinte? Modificați titlul episoadelor în ecranul de editare din administrare pentru a afișa numele seriei părinte?

Mulțumesc că te-ai uitat peste asta! Se pare că codul pe care l-ai postat elimină numele serialului de desene animate din URL. În loc să înlocuiască %series_name% cu numele episodului, %series_name% ar trebui să fie numele părintelui episodului. Numele episodului ar trebui să fie după acesta. Din nu știu ce motiv, căsuța "Serial de Desene Animate" nu se completează pentru mine ca să pot selecta un părinte. De aceea am crezut că episoadele trebuie să fie ierarhice. Încerc să înțeleg de ce.

Da, episoadele trebuie să fie ierarhice pentru ca căsuța meta "Serial de Desene Animate" să se poată completa.

Cu episoadele ierarhice ca să pot seta părintele, URL-ul a devenit și mai rău. Cu slug-ul cum ai sugerat, primesc numele serialului în URL de două ori. Deci, în loc de domain/episodes/nume-serial/nume-episod
ca înainte, am obținut domain/episodes/nume-serial/nume-serial/nume-episod

Cum am spus, episoadele nu pot fi ierarhice. Am modificat codul meta box-ului pentru a fi populat cu tipuri de postări ne-ierarhice. Folosește exact codul pe care l-am postat, l-am testat și funcționează. Dacă folosești alt cod, nu pot ști care este problema. Doar copiază și lipește codul din răspuns și testează-l. Poate fi necesar să dezactivezi pluginul CPT UI sau, cel puțin, să ștergi tipurile de postări personalizate din plugin, deoarece acestea sunt înregistrate în cod.

Ah, îmi cer scuze, am scanat rapid și am crezut că acea parte era identică. Ai dreptate, pagina se încarcă acum și URL-ul arată corect.

Dacă acest răspuns îți rezolvă întrebarea, te rog să marchezi răspunsul ca acceptat bifând marcajul de sub săgețile de vot din stânga-sus a răspunsului.

Nu este nevoie de hard-coding în acest caz, poți folosi pur și simplu acest plugin:
https://wordpress.org/plugins/add-hierarchy-parent-to-post/
Poți chiar să iei codul din el. Totuși, s-ar putea să nu fie o soluție completă.

Va trebui să scrieți propriul cod de parsare a URL-urilor pentru aceasta, deoarece WordPress trebuie să cunoască tipul postării pe care încearcă să o recupereze din baza de date pe baza structurii URL-ului, iar structura URL-ului vostru nu oferă niciun indiciu în acest sens.
Aceasta nu este o sarcină foarte ușoară de realizat cu API-ul de reguli de rescriere din WordPress, dar nu există nimic care să vă împiedice să ocoliți mecanismul de rescriere și să parsați URL-urile manual. Ceva de genul: 1. Rulați regulile de rescriere WordPress. Dacă s-a găsit conținut, afișați-l și ieșiți 2. Luați prima parte a URL-ului, verificați dacă există o postare care să se potrivească cu acel slug și tipul de postare așteptat 3. Parcurgeți restul părților URL-ului și verificați că postările există și sunt de tipul corect 4. Dacă totul se potrivește, afișați ultima postare găsită, altfel afișați o pagină 404
