Types de publication personnalisés imbriqués avec permaliens

9

J'essaie de mettre en place une structure de type de publication personnalisée à plusieurs niveaux avec des permaliens qui ressemblent authors/books/chapters, avec des auteurs, des livres et des chapitres tous configurés comme leur propre type de publication personnalisé. Par exemple, une URL typique sur ce site pourrait ressembler àexample.com/authors/stephen-king/the-shining/chapter-3/

Chaque chapitre ne peut appartenir qu'à un seul livre, et chaque livre ne peut appartenir qu'à un seul auteur. J'ai envisagé d'utiliser des taxonomies au lieu des CPT pour les auteurs et les livres, mais je dois associer des métadonnées à chaque élément et je préfère l'interface de publication pour cela.

Je suis la plupart du chemin là-bas en configurant simplement chaque poste personnalisé en tant qu'enfant d'une entrée dans le CPT d'un niveau supérieur. Par exemple, je crée "Chapitre 3" et attribue "The Shining" comme parent à l'aide d'une méta-boîte personnalisée. "The Shining" a à son tour "Stephen King" comme parent. Je n'ai eu aucun mal à créer ces relations.

J'utilise des balises de réécriture dans les slugs CPT et les permaliens veulent fonctionner, mais ils ne sont pas tout à fait raison. En utilisant un analyseur de réécriture, je peux voir que les règles de réécriture sont réellement générées, mais elles ne semblent pas être dans le bon ordre et donc d'autres règles sont traitées en premier.

Voici une capture d'écran de mon analyseur de réécriture.

Voici comment j'ai enregistré mes CPT:

function cpt_init() {

  $labels = array(
    'name' => 'Authors'
   );

  $args = array(
    'labels' => $labels,
    'public' => true,
    'publicly_queryable' => true,
    'show_ui' => true, 
    'show_in_menu' => true, 
    'query_var' => true,
    'rewrite' => array(
        'slug' => 'author',
        'with_front' => FALSE,
    ),
    'with_front' => false,
    'capability_type' => 'post',
    'has_archive' => false, 
    'hierarchical' => true,
    'menu_position' => null,
    'supports' => array( 'title', 'editor' )
  ); 

  register_post_type('authors',$args);

  $labels = array(
    'name' => 'Books'
  );

  $args = array(
    'labels' => $labels,
    'public' => true,
    'publicly_queryable' => true,
    'show_ui' => true, 
    'show_in_menu' => true, 
    'query_var' => true,
    'rewrite' => array(
        'slug' => 'author/%authors%',
        'with_front' => FALSE,
    ),
    'with_front' => false,
    'capability_type' => 'post',
    'has_archive' => false, 
    'hierarchical' => true,
    'menu_position' => null,
    'supports' => array( 'title', 'editor' )
  ); 

  register_post_type('books',$args);


  $labels = array(
    'name' => 'Chapters'
   );

  $args = array(
    'labels' => $labels,
    'public' => true,
    'publicly_queryable' => true,
    'show_ui' => true, 
    'show_in_menu' => true, 
    'query_var' => true,
    'rewrite' => array(
        'slug' => 'author/%authors%/%books%',
        'with_front' => FALSE,
    ),
    'with_front' => FALSE,
    'capability_type' => 'post',
    'has_archive' => false, 
    'hierarchical' => true,
    'menu_position' => null,
    'supports' => array( 'title', 'editor' )
  ); 

  register_post_type('chapters',$args);

}

add_action( 'init', 'cpt_init' );

Existe-t-il un moyen de modifier la priorité de mes règles de réécriture afin que les auteurs, les livres et les chapitres soient tous mis en correspondance en premier?

Je sais également que je vais devoir ajouter un post_type_linkfiltre, mais cela semble secondaire pour obtenir les permaliens correctement en premier lieu. Si quelqu'un sait où je peux trouver un aperçu complet du fonctionnement de ce filtre, ce serait apprécié.

Dalton
la source
Avez-vous pensé à utiliser simplement Pages? Vous obtiendrez automatiquement la bonne structure de permalien.
Michael Hampton
Je l'ai définitivement considéré. Le problème avec les pages est que nous pouvons avoir 100 petits-enfants pour un seul auteur, ce qui sera très difficile à gérer dans les pages d'administration. De plus, nous devons pouvoir interroger par type de publication.
Dalton
Je travaille sur une solution mais j'ai une question rapide: est-il essentiel d'avoir "auteur" devant chaque permalien? Parce que cela semble être le bâton. Je pense que cela déroute un peu trop WordPress, d'autant plus que c'est un slug de permalien également utilisé pour les pages d'auteurs WP. Si avoir "auteur" est requis, je pense que tout est encore faisable ... ce sera juste plus compliqué.
Rachel Carden
Oups, je ne savais pas que l'auteur allait entrer en conflit avec le slug WP intégré. Non, ce n'est pas obligatoire, ça pourrait être n'importe quoi. J'ai supposé que j'avais besoin de quelque chose parce que c'est un CPT, mais cela pourrait tout aussi bien être des "écrivains" ou autre chose.
Dalton
Je me suis rendu compte que la confusion résidait en fait avec les CPT partageant l '«auteur» en tant que limace de base. Une fois que vous avez défini «auteur» comme slug pour les «auteurs» du CPT, puis que vous avez défini «auteur /% auteur%» pour les «livres» du CPT et «auteur /% auteur% /% livre%» pour les chapitres du CPT » '', WordPress pense que les publications pour les `` livres '' et les publications pour les `` chapitres '' sont littéralement des publications pour enfants hiérarchiques pour les `` auteurs ''. Cela a-t-il du sens? Dans mes tests, vous pouvez garder «auteur» comme base pour les «auteurs» du CPT et cela fonctionne très bien. Remplacez donc ma question précédente par: avez-vous besoin de 'author' ou le slug peut-il commencer par% author%?
Rachel Carden

Réponses:

11

Si vous souhaitez conserver les «auteurs» comme slug de base dans les permaliens, par exemple example.com/authors/stephen-king/ pour le CPT «auteurs», example.com/authors/stephen-king/the-shining/ pour le `` livres '' CPT et example.com/authors/stephen-king/the-shining/chapter-3/ pour les `` chapitres '' CPT, WordPress pensera que tout est à peu près tout un `` auteur '' ou un enfant hiérarchique d'un `` auteur '' 'et, comme ce n'est pas le cas, WordPress devient finalement très confus.

Cela dit, il existe une solution de contournement qui est assez basique, mais tant que votre structure de permalien suit toujours le même ordre, c'est-à-dire que le mot «auteurs» est toujours suivi par un slug d'auteur, qui est toujours suivi par un slug de livre qui est toujours suivi par une limace de chapitre, alors vous devriez être prêt à partir.

Dans cette solution, il n'est pas nécessaire de définir le slug de réécriture dans la définition de type de message personnalisé pour les `` chapitres '' et les `` livres '', mais définissez le slug de réécriture des `` auteurs '' simplement comme `` auteurs '', placez le code suivant dans vos fonctions.php fichier et "vider" vos règles de réécriture.

add_action( 'init', 'my_website_add_rewrite_tag' );
function my_website_add_rewrite_tag() {
    // defines the rewrite structure for 'chapters', needs to go first because the structure is longer
    // says that if the URL matches this rule, then it should display the 'chapters' post whose post name matches the last slug set
    add_rewrite_rule( '^authors/([^/]*)/([^/]*)/([^/]*)/?','index.php?chapters=$matches[3]','top' );
    // defines the rewrite structure for 'books'
    // says that if the URL matches this rule, then it should display the 'books' post whose post name matches the last slug set
    add_rewrite_rule( '^authors/([^/]*)/([^/]*)/?','index.php?books=$matches[2]','top' );   
}

// this filter runs whenever WordPress requests a post permalink, i.e. get_permalink(), etc.
// we will return our custom permalink for 'books' and 'chapters'. 'authors' is already good to go since we defined its rewrite slug in the CPT definition.
add_filter( 'post_type_link', 'my_website_filter_post_type_link', 1, 4 );
function my_website_filter_post_type_link( $post_link, $post, $leavename, $sample ) {
    switch( $post->post_type ) {

        case 'books':

            // I spoke with Dalton and he is using the CPT-onomies plugin to relate his custom post types so for this example, we are retrieving CPT-onomy information. this code can obviously be tweaked with whatever it takes to retrieve the desired information.
            // we need to find the author the book belongs to. using array_shift() makes sure only one author is allowed
            if ( $author = array_shift( wp_get_object_terms( $post->ID, 'authors' ) ) ) {
                if ( isset( $author->slug ) ) {
                    // create the new permalink
                    $post_link = home_url( user_trailingslashit( 'authors/' . $author->slug . '/' . $post->post_name ) );
                }
            }

            break;

        case 'chapters':

            // I spoke with Dalton and he is using the CPT-onomies plugin to relate his custom post types so for this example, we are retrieving CPT-onomy information. this code can obviously be tweaked with whatever it takes to retrieve the desired information.
            // we need to find the book it belongs to. using array_shift() makes sure only one book is allowed
            if ( $book = array_shift( wp_get_object_terms( $post->ID, 'books' ) ) ) {

                // now to find the author the book belongs to. using array_shift() makes sure only one author is allowed
                $author = array_shift( wp_get_object_terms( $book->term_id, 'authors' ) );

                if ( isset( $book->slug ) && $author && isset( $author->slug ) ) {
                    // create the new permalink
                    $post_link = home_url( user_trailingslashit( 'authors/' . $author->slug . '/' . $book->slug . '/' . $post->post_name ) );
                }

            }

            break;

    }
    return $post_link;
}

En savoir plus sur le plugin CPT-onomies

Rachel Carden
la source
Cela fonctionne parfaitement, merci! J'ai l'impression d'avoir tellement appris. Le plugin CPT-onomies est également très cool. wordpress.org/extend/plugins/cpt-onomies
Dalton
J'ai le sentiment que vous pourriez rencontrer des obstacles au fur et à mesure que votre "bibliothèque" grandit, mais j'ai déjà du code en tête, alors si vous le faites, faites le moi savoir.
Rachel Carden
@RachelCarden Que faites-vous lorsque deux livres ont le même titre mais des auteurs différents? Il y aura une collision dans l'URL réécrite! Comment résolvez-vous cela?
Segfault
1
@Segfault Vous devrez récupérer tous les slugs d'auteur afin de pouvoir les coder en dur dans les règles de réécriture: foreach ($ author_slugs as $ author_slug) {add_rewrite_rule ('^ auteurs /'. $ Author_slug. '/ ([ ^ /] *) / ([^ /] *) /? ',' index.php? author = '. $ author_slug.' & chapitres = $ correspond à [2] ',' top '); add_rewrite_rule ('^ auteurs /'. $ author_slug. '/(( ^^ / dipl.) /?', 'index.php?authors='. $ author_slug. '& books = $ correspond à [1]', 'top') ; }
Rachel Carden
@Segfault Vous pouvez utiliser get_terms () , si vous utilisez une CPT-onomy, ou get_posts () pour récupérer les noms des publications / slugs.
Rachel Carden
4

Je n'ai pas d'expérience personnelle avec un tel scénario, mais Randy Hoyt a fait une présentation au WordCamp San Fran le week-end dernier sur les "types de messages subordonnés" qui ressemble à ce dont vous parlez.

Voici sa page pour la conférence qui comprend ses diapositives de présentation et des liens vers un plugin qu'il a créé pour travailler avec des types de publication subordonnés: http://randyhoyt.com/wordpress/subordinate-post-types/

mannieschumpert
la source
Merci, cela ressemble à une bonne ressource. Cependant, il n'est pas clair si cela prend en charge les relations avec les petits-enfants (cela ne semble pas le cas dans mes tests) et cela n'aide pas vraiment avec les permaliens. J'ai déjà trouvé un moyen de mettre en place mes relations enfant / parent (bien que ce soit une très bonne façon de le faire), mais les permaliens sont vraiment le problème sur lequel je suis coincé maintenant.
Dalton
1

Les règles seront ajoutées à extra_rules_top de WP_Rewrite dans l'ordre d'ajout des permastructs supplémentaires. Ainsi, la modification de l'ordre dans lequel vous enregistrez les types de publication modifiera l'ordre des règles de réécriture générées, ce qui fera en sorte que la réécriture du chapitre correspondra en premier. Cependant, puisque vous utilisez le query_var des autres post_types, le wp_query peut finir par correspondre à l'un de ceux-ci comme nom de post interrogé avant de correspondre au chapitre comme vous le souhaitez.

Je créerais de nouvelles balises de réécriture pour représenter les espaces réservés pour l'auteur parent et le livre parent, c'est-à-dire:

add_rewrite_tag('%parent-book%', '([^/]+)', 'parent_book=');

En faisant cela, vous devrez filtrer 'query_vars' pour rendre public 'parent_book'. Ensuite, vous devrez ajouter un filtre à pre_get_posts qui convertira le nom défini en tant que parent_book query_var en post_id et le définira en tant que «post_parent».

prettyboymp
la source
Pourriez-vous s'il vous plaît fournir des exemples de code pour les filtres que vous avez mentionnés? De plus, à quoi ressemblerait la balise de réécriture pour le petit-enfant CPT?
Dalton