Tipos de postagem personalizada aninhada com links permanentes

9

Estou tentando configurar uma estrutura de tipo de postagem personalizada em vários níveis com links permanentes que parecem authors/books/chapterscom autores, livros e capítulos configurados como seu próprio tipo de postagem personalizada. Por exemplo, um URL típico neste site pode parecerexample.com/authors/stephen-king/the-shining/chapter-3/

Cada capítulo pode pertencer apenas a um livro e cada livro pode pertencer apenas a um autor. Considerei usar taxonomias em vez de CPTs para autores e livros, mas preciso associar metadados a cada item e prefiro a interface de postagem para isso.

Estou na maior parte do caminho, simplesmente configurando cada postagem personalizada como filho de uma entrada no CPT de um nível acima. Por exemplo, eu crio o "Capítulo 3" e atribuo "O Iluminado" como pai usando uma caixa de meta personalizada. "The Shining", por sua vez, tem "Stephen King" como pai. Não tive problemas para criar esses relacionamentos.

Estou usando tags de reescrita nas lesmas do CPT e os permalinks querem funcionar, mas eles não estão certos. Usando um analisador de reescrita, posso ver que as regras de reescrita são realmente geradas, mas elas não parecem estar na ordem correta e, portanto, outras regras são processadas primeiro.

Aqui está uma captura de tela do meu analisador de reescrita.

Veja como eu registrei meus CPTs:

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 alguma maneira de alterar a prioridade das minhas regras de reescrita para que autores, livros e capítulos sejam correspondidos primeiro?

Eu também sei que vou ter que adicionar um post_type_linkfiltro, mas isso parece secundário para obter os permalinks corretamente em primeiro lugar. Se alguém souber onde posso encontrar uma visão abrangente de como esse filtro funciona, isso seria apreciado.

Dalton
fonte
Você já pensou em usar o Pages? Você obteria a estrutura correta do link permanente automaticamente.
Michael Hampton
Eu definitivamente considerei isso. O problema com as páginas é que podemos ter 100 itens netos para um único autor, o que será muito difícil de gerenciar nas páginas admin. Além disso, precisamos ser capazes de consultar por tipo de postagem.
Dalton
Estou trabalhando em uma solução, mas tenho uma pergunta rápida: é essencial ter 'autor' na frente de cada link permanente? Porque esse parece ser o defensor. Eu acho que está confundindo o WordPress um pouco demais, especialmente porque essa é uma lesma permanente também usada para páginas de autores do WP. Se ter 'autor' for necessário, acho que tudo ainda é possível ... será apenas mais complicado.
Rachel Carden
Opa, eu não sabia que o autor entraria em conflito com a lesma de autor do WP embutida. Não, isso não é necessário, pode ser qualquer coisa. Eu assumi que precisava de algo lá porque é um CPT, mas poderia facilmente ser "escritores" ou qualquer outra coisa.
21712 Dalton
Percebi que a confusão realmente está nos CPTs que compartilham o 'autor' como a lesma de base. Depois de definir 'author' como a lesma dos 'autores' da CPT e depois definir 'author /% author%' para os capítulos 'CPT' e 'author /% author% /% book%' para os capítulos da CPT ' ', o WordPress acha que as postagens para' livros 'e as postagens para' capítulos 'são literalmente postagens hierárquicas para crianças para' autores '. Isso faz sentido? Nos meus testes, você pode manter o 'autor' como base para os 'autores' da CPT e funciona muito bem. Então substitua minha pergunta anterior por: você precisa de 'author' ou a lesma pode começar com% author%?
Rachel Carden

Respostas:

11

Se você deseja manter 'autores' como lesma de base nos permalinks, por exemplo , example.com/authors/stephen-king/ para o CPT dos autores, example.com/authors/stephen-king/the-shining/ para o CPT 'books' e example.com/authors/stephen-king/the-shining/chapter-3/ para o CPT 'capítulos', o WordPress pensará que praticamente tudo é um post de 'autores' ou um filho hierárquico de 'autores 'post e, como esse não é o caso, o WordPress acaba ficando muito confuso.

Com isso dito, há uma solução alternativa que é bastante básica, mas desde que sua estrutura de link permanente sempre siga a mesma ordem, ou seja, a palavra 'autores' é sempre seguida por uma lesma de autor, que é sempre seguida por uma lesma de livro que é sempre seguida por uma lesma de capítulo, então você deve estar pronto.

Nesta solução, não há necessidade de definir a lesma de reescrita na definição de tipo de postagem personalizada para 'capítulos' e 'livros', mas defina a 'lesma de reescrita dos autores como simplesmente' autores ', coloque o seguinte código em suas funções.php arquivar e "liberar" suas regras de reescrita.

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

Saiba mais sobre o plugin CPT-onomies

Rachel Carden
fonte
Isso funciona perfeitamente, obrigado! Sinto que aprendi muito. O plugin CPT-onomies também é muito legal. wordpress.org/extend/plugins/cpt-onomies
Dalton
Tenho a sensação de que você pode encontrar alguns obstáculos à medida que sua "biblioteca" cresce, mas eu já tenho algum código em mente, então, se você souber, me avise.
Rachel Carden
@ RachelCarden O que você faz quando dois livros têm o mesmo título, mas autores diferentes? Haverá uma colisão no URL reescrito! Como voce resolve isso?
Segfault
11
@Segfault Você precisará recuperar todas as lesmas de autor para codificá-las nas regras de reescrita: foreach ($ author_slugs como $ author_slug) {add_rewrite_rule ('^ autores /'. $ Author_slug. '/ ([ ^ /] *) / ([^ /] *) /? ',' index.php? autores = '. $ author_slug.' & capítulos = $ corresponde a [2] ',' top '); add_rewrite_rule ('^ autores /'. $ author_slug. '/([^/}*)/?','index.php?authors='. $ author_slug. '& books = $ correspondências [1]', 'top') ; }
Rachel Carden
@Segfault Você pode usar get_terms () , se estiver usando uma CPT-onomy, ou get_posts () para recuperar os nomes das postagens / lesmas.
Rachel Carden
4

Não tenho experiência pessoal com esse cenário, mas Randy Hoyt fez uma apresentação no WordCamp San Fran, no final de semana passado, sobre "Subordinate Post Types", que soa como o que você está falando.

Aqui está sua página para a palestra, que inclui os slides da apresentação e os links para um plug-in que ele criou para trabalhar com tipos de postagem subordinados: http://randyhoyt.com/wordpress/subordinate-post-types/

mannieschumpert
fonte
Obrigado, isso parece um bom recurso. Não está claro se isso suporta os relacionamentos com os netos (não parece nos meus testes) e na verdade não ajuda com os links permanentes. Eu já descobri uma maneira de estabelecer meus relacionamentos entre pais e filhos (embora essa seja uma maneira muito legal de fazê-lo), mas os links permanentes são realmente o problema em que estou preso agora.
Dalton
1

As regras serão adicionadas ao extra_rules_top do WP_Rewrite na ordem em que as estruturas extras são adicionadas. Portanto, mudar a ordem em que você registra os tipos de postagem altera a ordem das regras de reescrita geradas, fazendo com que a reescrita do capítulo seja correspondida primeiro. No entanto, como você está usando o query_var dos outros post_types, o wp_query pode acabar correspondendo a um deles como o nome da postagem consultada antes de corresponder ao capítulo como você deseja.

Eu criaria novas tags de reescrita para representar os espaços reservados para o autor pai e o livro pai, ou seja:

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

Ao fazer isso, você precisará filtrar 'query_vars' para tornar público o 'parent_book'. Em seguida, você precisará adicionar um filtro aos pre_get_posts que converterá o nome definido como o parent_book query_var em post_id e o definirá como 'post_parent'.

prettyboymp
fonte
Você poderia fornecer exemplos de código para os filtros mencionados? Além disso, como seria a tag de reescrita para o neto CPT?
Dalton