Come impostare la relazione genitore-figlio tra diversi tipi di post personalizzati


14

Ho appena creato una relazione post / genitore tra un tipo di post "episodi" e un tipo di post "serie di cartoni animati".

Ho usato questo pezzetto di codice da aggiungere nella meta box per assegnare il genitore da un altro tipo di post:

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' => __('(no parent)'), 'sort_column'=> 'menu_order, post_title', 'echo' => 0));
        if ( ! empty($pages) ) {
            echo $pages;
        } // end empty pages check
    } // end hierarchical check.
}

Ha funzionato sulla schermata di amministrazione nel permettermi di impostare la serie come genitore dell'episodio, ma quando provo a visualizzare il post, ottengo un 404. La struttura dell'URL è:

domain/episodes/series-name/episode-name

L'URL per la serie è:

domain/cartoon-series/series-name

Vorrei che l'URL dell'episodio fosse:

domain/cartoon-series/series-name/episode-name

Cosa mi sto perdendo? È possibile impostare un intero tipo di post come figlio di un altro tipo di post? Quindi, potrei anche ottenere l'URL per l'elenco degli episodi:

domain/cartoon-series/series-name/episodes

Grazie! opaco


Come richiesto, ecco il codice per i due tipi di post personalizzati in questione:

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

Sto usando il plug-in dell'interfaccia utente CPT, quindi non posso modificare direttamente quel codice. Questo è solo il codice di esportazione fornito dall'interfaccia utente CPT.

Non ho altri codici che collegano i due CPT. Forse è quello che mi manca. Ho appena trovato quel codice online che inserisce il metabox nella pagina per fare il collegamento. Non è abbastanza per fare il lavoro? Sembra che imposta post_parent.

Grazie! opaco


Mi dispiace ma ho sbagliato. La relazione padre-figlio è impostata correttamente. La meta-box non sta usando un meta-campo (questo è ciò che mi ha confuso la prima volta), usa la parent_idquery var e non ha bisogno di altro codice per impostare la relazione. Il problema è che l'URL generato non è riconosciuto da WordPress. Ho cercato di trovare una regola di riscrittura che lo faccia funzionare ma non ho avuto successo. Sto studiando una soluzione.
cybmeta,

Dopo alcune indagini, penso che non riesci a farlo funzionare come desideri. Non è possibile avere un tipo di post come genitore di un altro tipo di post. Bene, è possibile, con il tuo codice quella relazione è effettivamente impostata, ma vedere il post figlio non funziona nel frontend. Ho provato a riscrivere le regole e ad agganciarmi pre_get_postsper modificare la query senza successo, è coinvolto qualcosa di più complicato che non sono stato in grado di capire. Come avere un gatto essere il genitore di un cane. Suggerisco di usare solo un tipo di post gerarchico o di impostare la realtionship usando i meta field .
cybmeta,

Penso che un tipo di post hirarchico si adatti perfettamente alla tua situazione.
cybmeta,

2
Sto davvero cercando di NON essere complicato con questo. Se è disponibile una soluzione più elegante, sono tutto orecchi. Sono nuovo di WP in generale e finora ho fatto abbastanza bene, ma questo mi ha lasciato perplesso. In genere, vorrei solo rendere la serie di cartoni animati una categoria e assegnarla all'episodio. Il problema è che ho anche altri dati nidificati diversi dagli episodi da inserire nella serie di cartoni animati. Quindi, sembra che anche le serie di cartoni animati debbano essere un CPT. È complicato! MrGreen Puoi spiegarmi cosa intendi usando un solo tipo di post gerarchico?
Mattaton,

Risposte:


9

Finalmente ho trovato una soluzione funzionante. Le serie di cartoni animati possono essere registrate come hai fatto tu, ma i tipi di post personalizzati degli episodi non possono essere gerarchici (penso che WordPress si aspetti che il contenuto principale sia dello stesso tipo del contenuto secondario se la relazione viene impostata utilizzando post_parentnella wp_poststabella del database).

Quando registri gli episodi, la regola di riscrittura deve essere impostata sulla lumaca che desideri, ovvero cartoon-series/%series_name%. Quindi possiamo filtrare il link degli episodi da sostituire %series_name%con il nome effettivo del cartoon-seriestipo di post principale e una regola di riscrittura da dire a WordPress quando viene richiesto un tipo di post serie di cartoni animati e quando è un episodio.

add_action('init', function(){
    $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" => 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', 'Cartoon Series', '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' => __('(no parent)'), 'sort_column'=> 'menu_order, post_title', 'echo' => 0));
        if ( ! empty($pages) ) {
            echo $pages;
        } // end empty pages check
}

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 ) ) {
        //Lets go to get the parent cartoon-series name
        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 {
            //This seems to not work. It is intented to build pretty permalinks
            //when episodes has not parent, but it seems that it would need
            //additional rewrite rules
            //return str_replace( '/%series_name%', '', $link );
        }

    }
    return $link;
}, 10, 2 );

NOTA : ricordarsi di svuotare le regole di riscrittura dopo aver salvato il codice sopra e prima di provarlo. Vai a wp-admin/options-permalink.phpe fai clic su Salva per rigenerare le regole di riscrittura.

NOTA 2 : è probabile che debbano essere aggiunte più regole di riscrittura, ad esempio per lavorare con post impaginati. Inoltre potrebbe essere necessario un po 'più di lavoro per avere una soluzione completa, ad esempio, quando si elimina una cartoon-seriescancellazione anche tutti gli episodi secondari? Aggiungi un filtro nella schermata di modifica dell'amministratore per filtrare gli episodi in base al genitore post? Modificare il titolo degli episodi nella schermata di modifica dell'amministratore per mostrare il nome della serie principale?


Grazie per aver esaminato questo! Sembra che il codice che hai pubblicato stia eliminando il nome della serie di cartoni animati dall'URL. Invece di sostituire% series_name% con il nome dell'episodio,% series_name% dovrebbe essere il nome del genitore dell'episodio. Il nome dell'episodio sarebbe dopo quello. Per qualche motivo, la casella Serie Cartoon non viene popolata per me per selezionare un genitore. Ecco perché pensavo che gli episodi dovessero essere gerarchici. Sto cercando di capire perché.
Mattaton,

Sì, gli episodi devono essere gerarchici per poter popolare la meta box Cartoon Series.
Mattaton,

Con episodi gerarchici in modo da poter impostare il genitore, l'URL è peggiorato. Con la lumaca come hai suggerito, ottengo due volte il nome della serie nell'URL. Quindi, invece di domain/episodes/series-name/episode-namecome prima, ho avutodomain/episodes/series-name/series-name/episode-name
Mattaton il

Come ho detto, gli episodi non possono essere gerarchici. Ho modificato il codice meta box per essere popolato con tipi di post non gerarchici. Usa il codice esatto che ho pubblicato, l'ho testato e funziona. Se usi un altro codice non posso sapere cosa c'è che non va. Basta copiare e incollare il codice dalla risposta e testarlo. Potrebbe essere necessario disabilitare il plug-in dell'interfaccia utente CPT o, almeno, eliminare i tipi di post personalizzati dal plug-in man mano che sono registrati nel codice.
cybmeta,

Ah, mi scuso, ho scansionato rapidamente e ho pensato che quella parte fosse la stessa. Hai ragione, la pagina si carica ora e l'URL sembra corretto.
Mattaton,


-1

Dovrai scrivere il tuo codice di analisi dell'URL per questo dato che wordpress deve conoscere il tipo di post che tenta di recuperare dal DB in base alla struttura dell'URL e la tua struttura dell'URL non fornisce alcun suggerimento a questo.

Questo non è qualcosa che è molto facile da fare con l'API delle regole di riscrittura di wordpress, ma non c'è nulla che ti impedisca di bypassare il meccanismo di riscrittura e analizzare gli URL da solo. Qualcosa come 1. eseguire le regole di rewite di wordpress. Se è stato trovato un contenuto, visualizzalo ed esci 2. ottieni la prima parte dell'URL, controlla se esiste un post corrispondente a quella lumaca con il tipo di post previsto 3. loop sulle restanti parti dell'URL verifica che i post esistano e siano nel giusto tipo. 4. se tutto corrisponde, visualizza l'ultimo post trovato, altrimenti visualizza una pagina 404

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.