Como fazer com que os links permanentes hierárquicos de postagens funcionem exatamente como as páginas


16

Examinei todas as perguntas aqui nos permalinks personalizados de tipo de postagem, mas a maioria parece ter problemas com reescrições de taxonomia personalizada ou a falta óbvia de flush_rewrite_rules (). Mas, no meu caso, estou usando apenas um tipo de postagem personalizado (sem taxonomia), definido como hierárquico (para que eu possa atribuir relacionamentos pai-filho), com o "suporte" adequado para os atributos metabox, etc., etc. reescrevi regras de mil maneiras diferentes. Eu tentei diferentes estruturas permalink. Mas os URLs filhos sempre resultam em 404!

Originalmente, eu tinha tipos de postagem personalizados independentes para os elementos "pai" e "filho" (usando p2p) e provavelmente não teria problemas para usar uma taxonomia para o agrupamento "parental" - sei que esses seriam semanticamente mais precisos. Porém, para o cliente, é mais fácil visualizar a hierarquia quando as "postagens" são exibidas no administrador da mesma forma que as páginas: uma árvore simples em que os filhos aparecem embaixo do pai, prefixados com um "-" e no ordem correta. Além disso, vários métodos para atribuir ordem via arrastar e soltar podem ser usados. O agrupamento via taxonomia (ou p2p) resulta em uma lista simples de "postagens" nas listagens de administradores, o que simplesmente não é tão visualmente óbvio.

Então, o que eu busco é literalmente o mesmo comportamento das "páginas" principais, mas com o meu tipo de postagem personalizada. Registrei o tipo de postagem da maneira esperada e, no administrador, ele funciona perfeitamente - posso atribuir um pai e um menu_order para cada "postagem" do boletim informativo, eles aparecem corretamente nas listagens de edição:

Spring 2012
 First Article
 Second Article

E seus links permanentes parecem ter sido construídos adequadamente. De fato, se eu mudar alguma coisa sobre a estrutura ou alterar a lesma de reescrita ao registrar o tipo de postagem, eles serão atualizados automaticamente corretamente, então eu sei que algo está funcionando:

http://mysite.com/parent-page/child-page/                  /* works for pages! */
http://mysite.com/post-type/parent-post/child-post/        /* should work? */
http://mysite.com/newsletter/spring-2012/                  /* works! */
http://mysite.com/newsletter/spring-2012/first-article/    /* 404 */
http://mysite.com/newsletter/spring-2012/second-article/   /* 404 */

Também tenho "páginas" principais padrão com relacionamentos hierárquicos criados e têm a mesma aparência no administrador, mas também funcionam no front-end (os URLs pai e filho funcionam bem).

Minha estrutura de link permanente está definida como:

http://mysite.com/%postname%/

Eu também tentei isso (apenas porque muitas outras respostas pareciam indicar que era necessária, embora não fizesse sentido no meu caso):

http://mysite.com/%category%/%postname%/

Os argumentos do meu registro CPT incluem:

$args = array(
    'public'                => true,
    'publicly_queryable'    => true,
    'show_ui'               => true,
    'has_archive'           => 'newsletter',
    'hierarchical'          => true,
    'query_var'             => true,
    'supports'              => array( 'title', 'editor', 'thumbnail', 'page-attributes' ),
    'rewrite'               => array( 'slug' => 'newsletter', 'with_front' => false ),

A única diferença visível entre meus filhos do tipo postagem personalizada e filhos da página normal é que meu CPT tem a lesma no início da estrutura do link permanente, seguido pelas lesmas pai / filho (onde as páginas apenas começam com as lesmas pai / filho, sem "prefixo"). Por que isso estragaria tudo, eu não sei. Muitos artigos parecem indicar que é exatamente assim que esses permalinks hierárquicos de CPT devem se comportar - mas os meus, embora bem formados, não funcionam.

O que também me deixa desconcertado é quando examino os query_vars para essa página 404 - eles parecem conter os valores corretos para o WP "encontrar" minhas páginas filhas, mas algo não está funcionando.

$wp_query object WP_Query {46}
public query_vars -> array (58)
'page' => integer 0
'newsletter' => string(25) "spring-2012/first-article"
'post_type' => string(10) "newsletter"
'name' => string(13) "first-article"
'error' => string(0) ""
'm' => integer 0
'p' => integer 0
'post_parent' => string(0) ""
'subpost' => string(0) ""
'subpost_id' => string(0) ""
'attachment' => string(0) ""
'attachment_id' => integer 0
'static' => string(0) ""
'pagename' => string(13) "first-article"
'page_id' => integer 0
[...]

Eu tentei isso com vários temas, incluindo vinte e doze, apenas para ter certeza de que não está faltando algum modelo da minha parte.

Usando o Rewrite Rules Inspector, é isso que aparece no URL: http://mysite.com/newsletter/spring-2012/first-article/

newsletter/(.+?)(/[0-9]+)?/?$   
       newsletter: spring-2012/first-article
           page: 
(.?.+?)(/[0-9]+)?/?$    
       pagename: newsletter/spring-2012/first-article
           page: 

como é exibido em outra página do inspetor:

RULE:
newsletter/(.+?)(/[0-9]+)?/?$
REWRITE:
index.php?newsletter=$matches[1]&page=$matches[2]
SOURCE:
newsletter

Essa saída de reescrita me levaria a acreditar que o seguinte link permanente "não bonito" funcionaria:

http://mysite.com/?newsletter=spring-2012&page=first-article

Não 404, mas mostra o item principal de CPT "boletim informativo", não o filho. A solicitação é assim:

Array
(
    [page] => first-article
    [newsletter] => spring-2012
    [post_type] => newsletter
    [name] => spring-2012
)

Respostas:


15

Esta é a minha primeira vez participando aqui no Stack Exchange, mas vou tentar e ver se posso ajudar a apontá-lo na direção certa.

Por padrão, os CPTs hierárquicos se comportam exatamente da maneira que você descreveu. O prefixo de slug exclusivo, "boletim informativo", neste caso, é permitir que o mecanismo de reescrita saiba diferenciar solicitações para diferentes tipos de postagem.

Esses argumentos de registro de CPT parecem bons, mas quando um CPT é solicitado, a pagenameconsulta var não deve ter um valor e a nameconsulta var deve ser a mesma que newsletteraqui, portanto, parece que há um conflito em algum lugar da sua configuração.

Para ajudar na depuração, instale e ative o plug-in do Inspetor de regras de reescrita e visite a tela em " Ferramentas -> Regras de reescrita ".

  1. Ao examinar a lista, todas as suas regras para o boletim informativo CPT devem ser listadas antes de qualquer página reescrever regras. Verifique esse é o caso, verificando a coluna " Origem ".
  2. Se isso ocorrer, insira o URL do seu CPT de "primeiro artigo" no campo " Corresponder URL " e clique no botão "Filtro" para ver qual regra corresponde. Ele deve corresponder a uma regra de boletim informativo e uma regra de página, mas a regra de boletim informativo deve ser a primeira.

Se isso não revelar nenhum problema, pesquise na post_namecoluna wp_postspara encontrar outras postagens com a lesma "primeiro artigo" para ver se pode haver uma colisão. Faça uma pesquisa por "newsletter" também, apenas para ter certeza.

Adicione o seguinte snippet para inspecionar seus vars de consulta no início da solicitação para verificar e quais estão sendo definidos pela correspondência de regra de reescrita (visite o CPT filho no front end). Se o pagenamevar não aparecer aqui, será definido por algo posteriormente na solicitação:

add_filter( 'request', 'se77513_display_query_vars', 1 );

function se77513_display_query_vars( $query_vars ) {
    echo '<pre>' . print_r( $query_vars, true ) . '</pre>';

    return $query_vars;
}

Quaisquer plug-ins / funções que modifiquem os vars de consulta podem estar causando um conflito, portanto, desative-os se você ainda encontrar problemas. Além disso, limpe suas regras de reescrita após cada etapa, especialmente se a solicitação corresponder a uma regra errada na segunda etapa acima (mantenha a tela "Permalinks" aberta em uma guia separada e atualize-a).


Editei a pergunta para mostrar a saída do inspetor de regras de reescrita, pois esses comentários não permitem formatação suficiente. As regras para o CPT são exibidas no topo da lista, antes de mais nada - mas não tenho certeza de quais das regras abaixo são regras de "página" (não está claro). Além disso, não há colisões na post_namecoluna.
sommatic

você pensa sobre a estrutura permanente do link permanente? Voltei a /%postname%/incluir desde que a inclusão /%category%/parece confundir ainda mais as coisas no reescrito do inspetor. Eu já vi pessoas afirmarem que /%category%/é magicamente mapeado para CPTs como "pai", embora eu não ache isso verdade.
sommatic

Essa saída parece vir para um plug-in diferente, e é por isso que você não vê a "fonte" da regra. De qualquer forma, parece que sua regra está sendo compatível. Editei minha resposta para incluir um snippet para inspecionar os vars de consulta anteriormente na solicitação para garantir que eles estejam sendo definidos corretamente.
Brady Vercher

Quanto à estrutura do permalink, não sou fã de incluir a categoria. É apenas mais uma parte móvel que não ajuda em nada, e as postagens podem pertencer a várias categorias. Se houver alguma chance de você alterar a estrutura do link permanente no futuro ou desejar que outro CPT seja carregado sem um prefixo de slug, eu recomendo "colocar o nome" na sua estrutura com algo fixo e único /blog/%postname%/.
Brady Vercher

é o plug-in certo, mas há duas páginas: "reescrever analisador" e "reescrever regras", ambas com URL de teste. Tentei a outra página e ela mostrou a fonte como "programa" para o primeiro grupo recuado e "página" para o segundo.
sommatic

5

O parent/Childlink permanente Funciona imediatamente, desde que você defina

'hierarchical'=> true,
'supports' => array('page-attributes' ....

Atualizar:

Acabei de testar novamente e funciona como esperado, com este caso de teste:

add_action('init','test_post_type_wpa77513');
function test_post_type_wpa77513(){
    $args = array(
        'public' => true,
        'publicly_queryable' => true,
        'show_ui' => true, 
        'show_in_menu' => true, 
        'query_var' => true,
        'rewrite' => true,
        'capability_type' => 'post',
        'has_archive' => true, 
        'hierarchical' => true,
        'supports' => array( 'title', 'editor', 'thumbnail', 'page-attributes' )
    ); 

    register_post_type( 'newsletter', $args );
}

e permalink definido como /%postname%/Recebo boletim / pai / filho trabalhando bem.


meu código acima não o mostrava, mas eu tenho page-attributesnos suportes (que é realmente apenas mostrar o metabox para atribuir parentesco, não deve afetar os permalinks) - mas obter 404. Que estrutura de ligação permanente precisa ser definida? ou isso importa?
sommatic

@ sommatic Acabei de testar novamente e está funcionando bem, quanto ao permalink, não tenho certeza se isso importa, mas de qualquer maneira atualizei minha resposta.
Bainternet

Posso confirmar que, com a adição de uma matriz de argumentos para 'labels' (sem a qual a CPT não aparecerá no admin), este exemplo básico funciona em uma instalação básica do WP3.5 com vinte e doze. Mas estou percebendo algumas diferenças importantes nos seus register_post_type$ args: usei 'rewrite' => array( 'slug' => 'newsletter', 'with_front' => false ), onde você usou apenas true. Você também simplesmente passou truepor has_archiveonde passei pela lesma. No entanto, quando correspondi aos seus argumentos, ainda recebi 404 ... Ainda tentando rastrear onde estou errado.
sommatic

3

Além de perguntar »Você tentou desligá-lo e ligá-lo novamente?« , Também tenho que perguntar "Você tem algum plug-in ativo e o seu Tema está fazendo alguma coisa para os permalinks (por exemplo: registrar taxonomia, tipos de postagem, adicionar regras de reescrita) etc.)?

Se assim for: Isso ainda acontece, depois de você desabilitar todos os plugins e mudar para TwentyEleven? insira a descrição da imagem aqui

Para depurar ainda mais, acesse o GitHub e pegue o plug-in "Rewrite" do Toschos . Em seguida, mude para o repositório oficial de plugins no wp.org e use o plugin MonkeyManRewriteAnalyzer . Eu até escrevi uma pequena extensão para colar as duas partes um pouco. Isso fornecerá muitos detalhes sobre sua configuração.


bem, se eu desabilitar tudo , não terei o tipo de postagem personalizada que é o ponto dessa pergunta ... mas sim, tentei mesmo com o tema vinte e doze. Ainda estou pesquisando os poucos plugues necessários para ver o que está atrapalhando a consulta, pois pelo que posso ver, os links permanentes são bem-formados.
sommatic

@somatic de vocês é claro que não incapacitantes :)
kaiser

@somatic Ver atualização.
kaiser

1

Então, depois de confirmar que eu poderia obter o comportamento esperado da página hierárquica com uma instalação completamente limpa e apenas uma única declaração de CPT, eu sabia que a falha estava em algum lugar do meu próprio plug-in que eu uso para lidar com a criação de CPT (muito complexo, manipula metaboxes personalizados, taxonomias etc). O problema era que, apesar de todos os conselhos para verificar problemas de reescrita ou consulta, eu não conseguia ver nada obviamente errado. Eu verifiquei todos os filtros e ganchos, visualizando a consulta em cada ponto e sem ver nada que causasse o 404.

Portanto, fiquei com a tarefa de desabilitar / habilitar manualmente cada uma das 9 classes grandes e, em seguida, encontrar pelo menos 2 delas causando o 404, passando por cada função uma por uma e desabilitando / habilitando-as e, em seguida, rastreando a linha por linha dentro dessas funções - uma força bruta tenta ver exatamente o que estava causando o 404, mesmo que eu não soubesse o porquê.

Foi quando eu descobri que há uma consequência no uso $query->get_queried_object(). Parece que o uso dessa função wrapper realmente modifica a própria consulta $, que eu pensei que estava retornando inalterada no final da minha função. Três filtros por 2 aulas estavam envolvidos que modificou a consulta: parse_query, posts_orderby, posts_join- e todas as funções de retorno estavam chamando $query->get_queried_object()no passado $queryarg para, em seguida, fazer alguns testes condicionais e às vezes modificar a consulta vars (como em casos especiais ordem de classificação). Curiosamente, essas funções realmente funcionaram bem no que foram projetadas para fazer, apesar do meu uso da função. Eu nunca notei nada de errado com a consulta $ retornada antes!

De alguma forma, depois de mais de um ano de desenvolvimento e uso em dezenas de locais de produção ao vivo, nunca havia experimentado efeitos adversos por esse erro. Somente quando eu me aventurei em CPTs hierárquicos, essa pequena diferença subitamente quebrou as coisas. Isso é parte do que me emocionou tanto com isso - o melhor que pude dizer, meus filtros de consulta eram confiáveis!

Confesso que ainda não sei exatamente por que chamar essa função quebra apenas esse pequeno aspecto das páginas filho do CPT - e, no entanto, nunca manifestou outros problemas! Mas ficou claro que usá-lo em um retorno de chamada de filtro alterou o retorno de $queryalguma forma. Ao remover esta chamada, meus erros 404 desapareceram.

Obrigado por todas as dicas - gostaria de poder dividir a recompensa, pois obtive insights de cada resposta, mesmo que a solução final não tivesse relação alguma. Essa foi uma lição educacional para não confiar cegamente no seu código, mesmo que ele funcione para você de maneira confiável por um longo tempo ou não esteja produzindo erros óbvios.

Às vezes, como o gráfico de Kaiser personifica tão perfeitamente, você só precisa começar a acionar interruptores até que as luzes voltem a acender. No meu caso, tive que seguir a mesma estratégia de solução de problemas até as linhas individuais de uma função antes de poder ver o problema.


Você também pode usar a função wrapper get_queried_object()sem interceptar o $wpdbobjeto.
kaiser

mas o que $queryisso agarra? Eu estou usando isso dentro de um filtro para parse_query, e preciso obter especificamente o objeto consultado de um específico $queryque é passado a partir do filtro ...
sommatic

Eu apenas tentei usar o wrapper dentro do meu filtro para parse_query. Causou os mesmos erros 404 novamente. Eu tenho que encontrar uma maneira de replicar o que get_queried_object()faz sem entupir esses filtros ...
sommatic

-2

Você está executando a versão mais atual do WP? Acho que essa é a primeira pergunta (como quando você liga para o suporte técnico e eles perguntam se o seu computador está conectado!), Pois li que esse problema foi solucionado na atualização de versão mais recente.

Há uma postagem no digwp.com que aborda esse problema (http://digwp.com/2011/06/dont-use-postname/). Aparentemente, o WP não consegue distinguir facilmente a diferença entre postagens e páginas e, se você iniciar seus URLs com uma opção baseada em texto, o WP acionará um sinalizador que cria uma regra para cada página / postagem que você possui. Se você tiver muito conteúdo em seu site, isso pode resultar em um grande número de solicitações e o servidor provavelmente expirará, o que resultará em um monte de 404, mesmo que as páginas estejam lá.

Então. Se você usar uma estrutura baseada em números primeiro, em seguida, sua estrutura baseada em texto, aposto que seu problema 404 seria resolvido. Agora, considerando os problemas de SEO, eu não usaria uma estrutura de datas, mas tomar essa decisão será lógico o suficiente para você.


2
Estou no 3.5. A partir do WP3.3.1, esse problema no digiwp foi corrigido.
somático
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.