Comment définir la relation parent-enfant entre différents types de publication personnalisés

14

Je viens de mettre en place une relation post / parent entre un type de post "épisodes" et un type de post "cartoon-series".

J'ai utilisé ce morceau de code pour ajouter dans la boîte de méta pour attribuer le parent d'un autre type de message:

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.
}

Cela a fonctionné sur l'écran d'administration en me permettant de définir la série en tant que parent de l'épisode, mais lorsque j'essaie de consulter le message, j'obtiens un 404. La structure d'URL est la suivante:

domain/episodes/series-name/episode-name

L'URL de la série est:

domain/cartoon-series/series-name

J'aimerais que l'URL de l'épisode soit:

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

Qu'est-ce que je rate? Est-il possible de faire d'un type de message entier l'enfant d'un autre type de message? Donc, je pourrais même obtenir l'URL de la liste des épisodes:

domain/cartoon-series/series-name/episodes

Merci! Mat


Comme demandé, voici le code pour les deux types de messages personnalisés en question:

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

J'utilise le plugin CPT UI, donc je ne peux pas modifier ce code directement. C'est juste le code d'exportation fourni par l'interface utilisateur CPT.

Je n'ai pas d'autre code qui relie les deux CPT. C'est peut-être ce qui me manque. Je viens de trouver ce code en ligne qui place la métabox sur la page pour faire le lien. N'est-ce pas suffisant pour faire le travail? On dirait que cela définit le post_parent.

Merci! Mat

Mattaton
la source
Je suis désolé mais je me trompais. La relation parent-enfant est correctement définie. La méta-boîte n'utilise pas de méta-champ (c'est ce qui m'a dérouté la première fois), elle utilise la parent_idrequête var et elle n'a pas besoin de plus de code pour définir la relation. Le problème est que l'URL générée n'est pas reconnue par WordPress. J'ai essayé de trouver une règle de réécriture qui le fasse fonctionner mais je n'ai pas réussi. J'examine maintenant une solution.
cybmeta
Après une enquête, je pense que vous ne pouvez pas le faire fonctionner comme vous le souhaitez. Il semble impossible d'avoir un type de publication en tant que parent d'un autre type de publication. Eh bien, c'est possible, avec votre code, cette relation est en fait définie, mais voir le post enfant ne fonctionne pas dans le frontend. J'ai essayé de réécrire des règles et de pre_get_postsme connecter pour modifier la requête sans succès, quelque chose de plus compliqué est impliqué que je n'ai pas pu comprendre. Comme avoir un chat comme parent d'un chien. Je suggère d'utiliser un seul type de publication hiérarchique ou de définir la propriété en utilisant des méta-champs .
cybmeta
Je pense qu'un type de poste hirarchique correspond parfaitement à votre situation.
cybmeta
2
J'essaie vraiment de ne PAS être compliqué avec ça. Si une solution plus élégante est disponible, je suis à l'écoute. Je suis nouveau sur WP en général et je m'en suis plutôt bien sorti jusqu'à présent, mais celui-ci m'a déconcerté. En règle générale, je faisais simplement une série de dessins animés une catégorie et je l'assignais à l'épisode. Le problème est que j'ai également d'autres données imbriquées autres que des épisodes à inclure dans la série de dessins animés. Il semble donc que les séries de dessins animés devraient également être un CPT. C'est compliqué! :-D Pouvez-vous m'expliquer ce que vous voulez dire en utilisant un seul type de poste hiérarchique?
Mattaton

Réponses:

9

Enfin, j'ai trouvé une solution de travail. La série de dessins animés peut être enregistrée comme vous l'avez fait, mais les types de publication personnalisés des épisodes ne peuvent pas être hiérarchiques (je pense que WordPress s'attend à ce que le contenu parent soit du même type que le contenu enfant si la relation est définie à l'aide post_parentde la wp_poststable de base de données).

Lors de l'enregistrement des épisodes, la règle de réécriture doit être définie sur le slug souhaité, c'est-à-dire cartoon-series/%series_name%. Ensuite, nous pouvons filtrer le lien des épisodes à remplacer %series_name%par le nom réel du cartoon-seriestype de publication parent et une règle de réécriture pour dire à WordPress quand un type de publication de série de dessins animés est demandé et quand est un épisode.

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

REMARQUE : n'oubliez pas de vider les règles de réécriture après avoir enregistré le code ci-dessus et avant de l'essayer. Accédez à wp-admin/options-permalink.phpet cliquez sur Enregistrer pour régénérer les règles de réécriture.

REMARQUE 2 : Il est probable que davantage de règles de réécriture doivent être ajoutées, par exemple pour fonctionner pour les publications de pagination. De plus, il peut avoir besoin de plus de travail pour avoir une solution complète, par exemple, lors de la suppression d'une cartoon-seriessuppression également de tous les épisodes enfants? Ajouter un filtre dans l'écran d'édition administrateur pour filtrer les épisodes par parent post? Modifier le titre des épisodes dans l'écran d'édition administrateur pour afficher le nom de la série parent?

cybmeta
la source
Merci d'avoir regardé ça! Il semble que le code que vous avez publié supprime le nom de la série de dessins animés de l'URL. Au lieu de remplacer% series_name% par le nom de l'épisode,% series_name% doit être le nom du parent de l'épisode. Le nom de l'épisode serait après cela. Pour une raison quelconque, la zone Cartoon Series n'est pas remplie pour que je sélectionne un parent. C'est pourquoi je pensais que les épisodes devaient être hiérarchisés. Essayer de comprendre pourquoi.
Mattaton
Oui, les épisodes doivent être hiérarchisés pour que la méta-boîte Cartoon Series soit remplie.
Mattaton
Avec des épisodes hiérarchiques pour que je puisse définir le parent, l'url s'est encore aggravée. Avec le slug comme vous l'avez suggéré, j'ai deux fois le nom de la série dans l'url. Donc, au lieu domain/episodes/series-name/episode-namecomme avant, j'ai eudomain/episodes/series-name/series-name/episode-name
Mattaton
Comme je l'ai dit, les épisodes ne peuvent pas être hiérarchisés. J'ai modifié le code de la meta box pour qu'il soit rempli avec des types de publication non hiérarchiques. Utilisez le code exact que j'ai publié, je l'ai testé et cela fonctionne. Si vous utilisez un autre code, je ne peux pas savoir ce qui ne va pas. Copiez et collez simplement le code de la réponse et testez-le. Vous devrez peut-être désactiver le plug-in CPT UI ou, au moins, supprimer les types de publication personnalisés du plug-in tels qu'ils sont enregistrés dans le code.
cybmeta
Ah, mes excuses, j'avais rapidement scanné et pensé que la partie était la même. Vous avez raison, la page se charge maintenant et l'URL semble correcte.
Mattaton
-1

Vous devrez écrire votre propre code d'analyse d'URL pour cela car wordpress doit connaître le type de publication qu'il essaie de récupérer à partir de la base de données en fonction de la structure d'URL et votre structure d'URL ne donne aucune indication à ce sujet.

Ce n'est pas quelque chose de très facile à faire avec l'API de règles de réécriture de wordpress, mais rien ne vous empêche de contourner le mécanisme de réécriture et d'analyser les URL par vous-même. Quelque chose comme 1. exécuter les règles de réécriture de wordpress. Si un contenu a été trouvé, affichez-le et quittez 2. récupérez la première partie de l'URL, vérifiez s'il existe une publication correspondant à ce slug avec le type de publication attendu 3. boucle sur les autres parties de l'URL vérifiez que les publications existent et sont dans le bon type. 4. si tout correspond afficher le dernier message trouvé, sinon afficher une page 404

Mark Kaplun
la source