web-dev-qa-db-fra.com

Comment définir une relation parent-enfant entre différents types d'articles personnalisés

Je viens de mettre en place une relation post/parent entre un "post" de type post et un post "série-dessin animé".

J'ai utilisé ce bit de code pour ajouter dans la boîte de méta pour assigner 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 pour l'épisode, mais lorsque j'essaie de voir le message, je reçois un 404. La structure de l'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 taper un message entier sur l'enfant d'un autre type de message? Alors, 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 publication 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, je ne peux donc pas éditer ce code directement. Ce n'est que le code d'exportation fourni par l'interface utilisateur CPT.

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

Merci! Mat

12
Mattaton

Enfin, j'ai trouvé une solution efficace. La série de dessins animés peut être enregistrée comme vous le faites, mais les types de publication d'épisodes personnalisés 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 de post_parent dans wp_posts base de données).

Lors de l'enregistrement d'épisodes, la règle de réécriture doit être définie sur le slug souhaité, à savoir cartoon-series/%series_name%. Ensuite, nous pouvons filtrer le lien épisodes pour remplacer %series_name% par le nom réel du type d'article cartoon-series parent et une règle de réécriture à indiquer à WordPress lorsqu'un type d'article de série de dessins animés est demandé et à quel moment correspond à 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 );

NOTE: 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.php et cliquez sur Enregistrer pour régénérer les règles de réécriture.

NOTE 2 : Il est probable que davantage de règles de réécriture doivent être ajoutées, par exemple pour travailler avec des publications paginées. De plus, il faudra peut-être plus de travail pour avoir une solution complète, par exemple, lorsque vous supprimez un cartoon-series et supprimez également tous les épisodes enfants? Ajouter un filtre dans l'écran d'édition d'administrateur pour filtrer les épisodes par post parent? Modifier le titre des épisodes dans l'écran d'édition d'administrateur pour afficher le nom de la série parent?

9
cybmeta

Pas besoin de HARD-CODING dans ce cas ... Vous pouvez simplement utiliser ce plugin:

https://wordpress.org/plugins/add-hierarchy-parent-to-post/

Vous pouvez même en récupérer le code. Cependant, il se peut que ce ne soit pas une solution complète.

1
T.Todua