Far sì che i tipi di post personalizzati gerarchici funzionino come le pagine


16

Ho esaminato tutte le domande qui sui permalink di tipo di post personalizzato, ma la maggior parte sembra essere o problemi con riscritture di tassonomia personalizzate o l'evidente mancanza di flush_rewrite_rules (). Ma nel mio caso, sto usando solo un tipo di post personalizzato (senza tassonomia), impostato su gerarchico (in modo da poter assegnare relazioni genitore-figlio), con il "supporto" adeguato per gli attributi metabox, ecc. I ho arrossito riscrivere le regole in mille modi diversi. Ho provato diverse strutture permalink. Ma gli URL figlio generano sempre 404!

Inizialmente avevo tipi di post personalizzati indipendenti per gli elementi "parent" e "child" (usando p2p) e probabilmente non avrei avuto problemi a usare una tassonomia per il raggruppamento "parentale" - so che sarebbero semanticamente più accurati. Ma per il cliente, è più facile per loro visualizzare la gerarchia quando i "post" sono visualizzati nell'amministratore proprio come le pagine sono: un semplice albero in cui i bambini appaiono sotto il genitore, con il prefisso "-", e nel ordine corretto. Inoltre, è possibile utilizzare vari metodi per assegnare l'ordine tramite il trascinamento della selezione. Il raggruppamento tramite tassonomia (o p2p) si traduce in un elenco semplice di "post" negli elenchi di amministrazione, che non è semplicemente visivamente ovvio.

Quindi quello che sto cercando è letteralmente lo stesso identico comportamento delle "pagine" principali, ma con il mio tipo di post personalizzato. Ho registrato il tipo di post esattamente come previsto, e nell'amministratore funziona perfettamente: posso assegnare un genitore e un menu_order per ogni "post" della newsletter, che appaiono correttamente negli elenchi di modifica:

Spring 2012
 First Article
 Second Article

E i loro permalink sembrano essere costruiti correttamente. In effetti, se cambio qualcosa sulla struttura, o addirittura modifico la lumaca di riscrittura quando registro il tipo di post, si aggiornano automaticamente correttamente, quindi so che qualcosa funziona:

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 */

Ho anche "pagine" di base standard con relazioni gerarchiche create e hanno lo stesso aspetto nell'amministratore, ma in realtà funzionano anche sul front-end (entrambi gli URL padre e figlio funzionano bene).

La mia struttura permalink è impostata su:

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

Ho anche tentato questo (solo perché molte altre risposte sembravano indicare che era necessario, anche se nel mio caso non aveva senso):

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

I miei argomenti di registro CPT includono:

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

L'unica differenza visibile tra i miei figli di tipo di post personalizzati e la pagina normale figli di , è che il mio CPT ha la lumaca all'inizio della struttura del permalink, quindi seguita dalle lumache padre / figlio (dove le pagine iniziano con le lumache padre / figlio, nessun "prefisso"). Perché questo rovinerebbe le cose, non lo so. Molti articoli sembrano indicare che questo è esattamente come dovrebbero comportarsi tali permalink CPT gerarchici, ma il mio, sebbene ben formato, non funziona.

Ciò che mi sconcerta anche è quando esamino query_vars per quella pagina 404: sembrano contenere i valori corretti per WP per "trovare" le mie pagine figlio, ma qualcosa non funziona.

$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
[...]

Ho provato questo con vari temi, tra cui venti dodici, solo per essere sicuro che non sia un modello mancante da parte mia.

Usando Rewrite Rules Inspector, questo è ciò che appare per l'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: 

come viene visualizzato su un'altra pagina dell'ispettore:

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

Questo output di riscrittura mi indurrebbe a credere che il seguente permalink "non carino" avrebbe funzionato:

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

Non 404, ma mostra l'elemento CPT padre "newsletter", non il figlio. La richiesta è simile alla seguente:

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

Risposte:


15

Questa è la prima volta che partecipo qui su Stack Exchange, ma ci proverò e vedrò se posso aiutarti a indicarti la giusta direzione.

Per impostazione predefinita, i CPT gerarchici si comportano esattamente come descritto. L'unico prefisso slug, "newsletter" in questo caso, è far sapere al motore di riscrittura come distinguere le richieste per diversi tipi di post.

Quegli argomenti di registrazione CPT sembrano a posto, ma quando viene richiesto un CPT, la pagenamequery var non dovrebbe avere un valore e la namequery var dovrebbe essere la stessa di newsletterqui, quindi sembra che ci sia un conflitto da qualche parte nella tua configurazione.

Per facilitare il debug, installa e attiva il plug-in Inspector regole di riscrittura , quindi visita la schermata " Strumenti -> Riscrivi regole ".

  1. Mentre guardi l'elenco, tutte le tue regole per la newsletter CPT dovrebbero essere elencate prima di qualsiasi pagina riscrivere le regole. Verifica questo caso eseguendo la scansione della colonna " Origine ".
  2. In questo caso, inserisci l'URL del CPT del "primo articolo" nel campo " Corrispondenza URL " e fai clic sul pulsante "Filtro" per vedere quale regola corrisponde. Dovrebbe corrispondere a una regola di newsletter e una regola di pagina, ma la regola di newsletter dovrebbe essere la prima.

Se ciò non rivela alcun problema, cerca nella post_namecolonna wp_postsper trovare altri post con la lumaca "primo articolo" per vedere se potrebbe esserci una collisione. Cerca anche una "newsletter", per essere sicuro.

Aggiungi lo snippet seguente per esaminare le query della query all'inizio della richiesta per verificare e vedere quali sono stati impostati dalla corrispondenza della regola di riscrittura (visita il CPT figlio sul front-end). Se il pagenamevar non viene visualizzato qui, viene impostato da qualcosa più avanti nella richiesta:

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

Eventuali plug-in / funzioni che modificano le query potrebbero causare un conflitto, quindi disabilitali se riscontri ancora problemi. Svuota anche le regole di riscrittura dopo ogni passaggio, soprattutto se la richiesta corrispondeva a una regola errata nel secondo passaggio precedente (tieni aperta la schermata "Permalink" in una scheda separata e aggiorna semplicemente).


Ho modificato la domanda per mostrare l'output dell'ispettore delle regole di riscrittura, poiché questi commenti non consentono una formattazione sufficiente. Le regole per il CPT vengono visualizzate in cima all'elenco, prima di ogni altra cosa, ma non sono sicuro di quale delle regole seguenti siano regole di "pagina" (non chiare). Inoltre, nessuna collisione nella post_namecolonna.
somatic

hai qualche idea sulla corretta struttura del permalink? Sono tornato da /%postname%/quando l'inclusione /%category%/sembra solo confondere ulteriormente le cose nell'ispettore di riscrittura. Ho anche visto persone affermare che /%category%/è mappato magicamente per CPT come "genitore", anche se non lo trovo vero.
somatic

Quell'output sembra provenire da un plug-in diverso, motivo per cui non vedi la "fonte" della regola. Ad ogni modo, sembra che la tua regola stia andando bene. Ho modificato la mia risposta per includere uno snippet per ispezionare le query in precedenza nella richiesta per accertarmi che siano impostati correttamente.
Brady Vercher,

Per quanto riguarda la struttura del permalink, non sono un fan di includere la categoria. È solo un'altra parte mobile che non aiuta nulla e i post possono appartenere a più categorie. Se c'è qualche possibilità che tu possa cambiare la struttura del permalink in futuro o che desideri caricare un altro CPT senza un prefisso slug, ti consiglio di "spaziare i nomi" sulla tua struttura con qualcosa di fisso e unico come /blog/%postname%/.
Brady Vercher,

è il plug-in giusto, ma ci sono due pagine: "riscrivi analizzatore" e "riscrivi regole", entrambi che offrono un URL di prova. Ho provato l'altra pagina e ha mostrato l'origine come "programma" per il primo gruppo rientrato e "pagina" per il secondo.
somatic

5

Il parent/Childpermalink Funziona fuori dalla scatola fintanto che imposti

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

Aggiornare:

L'ho appena provato di nuovo e funziona come previsto, con questo caso di test:

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 impostato su /%postname%/Ottengo la newsletter / genitore / figlio che funziona bene.


il mio codice sopra non lo mostrava, ma ho page-attributesnei supporti (che in realtà riguarda solo la visualizzazione del metabox per l'assegnazione dei genitori, non dovrebbe influenzare i permalink) - ma ottenere i 404. Quale struttura di permalink deve essere impostata? o importa?
somatic

@somatic l'ho appena testato di nuovo e funziona benissimo, per quanto riguarda il permalink non sono sicuro che dovrebbe avere importanza, ma in ogni modo ho aggiornato la mia risposta.
Bainternet,

Posso confermare che, con l'aggiunta di una matrice di argomenti per "etichette" (senza la quale CPT non apparirà in admin), questo esempio di base funziona su un'installazione vanilla di WP3.5 con twentlytwelve. Ma noto alcune differenze chiave nei tuoi register_post_type$ args: ho usato 'rewrite' => array( 'slug' => 'newsletter', 'with_front' => false ), dove hai usato solo true. È anche semplicemente passati trueper has_archive, dove ho passato la lumaca. Tuttavia, quando ho abbinato i tuoi argomenti, ho ancora 404 ... Sto ancora cercando di rintracciare dove sto sbagliando.
somatic

3

Oltre a chiedere »Hai provato a spegnerlo e riaccenderlo?« , Devo anche chiedere "Hai qualche plugin attivo e il tuo Tema sta facendo qualcosa ai permalink (ad esempio: registrare tassonomia, tipi di post, aggiungere regole di riscrittura , eccetera.)?

In tal caso: succede ancora dopo aver disabilitato tutti i plugin e passato a TwentyEleven? inserisci qui la descrizione dell'immagine

Per eseguire il debug ulteriormente, vai su GitHub e prendi il plugin Toschos "Rewrite" . Passa quindi al repository plugin ufficiale su wp.org e prendi il plugin MonkeyManRewriteAnalyzer . Ho anche scritto una piccola estensione per incollare entrambi un po 'insieme. Questo ti darà molti dettagli sulla tua configurazione.


bene, se disabilito tutto , non avrò il tipo di post personalizzato che è il punto di questa domanda ... ma sì, ho provato anche con il tema dei venti dodici. Sto ancora scavando tra le poche prese necessarie per vedere cosa sta rovinando la query, poiché da quello che posso vedere, i permalink stessi sono ben formati.
somatic

@somatic Ovviamente non disabiliti il ​​tuo :)
kaiser

@somatic Vedi aggiornamento.
Kaiser

1

Quindi, dopo aver confermato che avrei potuto ottenere il comportamento della pagina gerarchica previsto con un'installazione completamente pulita e solo una singola dichiarazione CPT, sapevo che l'errore si trovava da qualche parte nel mio plugin che uso per gestire la creazione di CPT (molto complesso, gestisce metabox personalizzati, tassonomie , eccetera). Il problema era che, nonostante tutti i consigli per verificare la presenza di problemi di riscrittura o query, non riuscivo a vedere nulla di evidentemente sbagliato. Ho controllato ogni filtro e hook, visualizzando la query in ogni punto e non vedendo nulla che potesse causare il 404.

Quindi mi è stato affidato il compito di disabilitare / abilitare manualmente ciascuna delle 9 classi di grandi dimensioni, e quindi, trovando almeno 2 di loro a causare il 404, passando attraverso ciascuna funzione una per una e disabilitandole / abilitandole, quindi tracciando la linea per riga all'interno di quelle funzioni - un tentativo di forza bruta di vedere esattamente cosa stava causando il 404, anche se non sapevo perché.

Questo è quando ho scoperto che c'è una conseguenza nell'uso $query->get_queried_object(). Sembrerebbe che l'utilizzo di questa funzione wrapper modifichi in realtà $ query stessa, che a mio avviso stavo tornando invariato alla fine della mia funzione. Tre filtri attraverso 2 classi sono state coinvolte che ha modificato la query: parse_query, posts_orderby, posts_join- e tutte le funzioni di callback chiamavano $query->get_queried_object()sul passato $queryarg per poi eseguire alcuni test condizionali e talvolta modificare la query Vars (come, per speciali casi ordinamento). Stranamente, queste funzioni in realtà hanno funzionato bene in quello che sono state progettate per fare, nonostante il mio uso della funzione. Non ho mai notato nulla di sbagliato con la query $ restituita prima!

In qualche modo, dopo più di un anno di sviluppo e utilizzo in dozzine di siti di produzione dal vivo, non avevo mai avuto effetti negativi da questo errore. Solo quando mi sono avventurato in CPT gerarchici questa piccola differenza ha improvvisamente rotto le cose. Questo fa parte di ciò che mi ha colpito così tanto in questo - come meglio potevo dire, i miei filtri di query erano affidabili!

Confesso che ancora non so esattamente perché chiamare questa funzione interrompa solo questo piccolo aspetto delle pagine secondarie CPT - e tuttavia non abbia mai manifestato altri problemi! Ma era chiaro che usarlo all'interno di un callback di filtro alterava in $queryqualche modo il reso . Rimuovendo questa chiamata, i miei errori 404 sono scomparsi.

Grazie per tutti i suggerimenti - vorrei poter dividere la generosità, poiché ho acquisito informazioni da ogni risposta, anche se la soluzione definitiva non era in qualche modo correlata. Questa è stata una lezione educativa per non fidarti ciecamente del tuo codice, anche se ha funzionato in modo affidabile per molto tempo o non sta producendo errori evidenti.

A volte, come la carta di Kaiser incarna in modo così ordinato, devi solo iniziare a premere gli interruttori fino a quando le luci non si riaccendono. Nel mio caso, ho dovuto adottare la stessa strategia di risoluzione dei problemi fino alle singole linee in una funzione prima di poter vedere il problema.


È inoltre possibile utilizzare la funzione wrapper get_queried_object()senza intercettare l' $wpdboggetto.
Kaiser

ma che $querycosa afferra? Sto usando questo all'interno di un filtro per parse_query, e ho bisogno di ottenere specificamente l'oggetto interrogato di uno specifico $queryche viene passato dal filtro ...
somatic

Ho appena provato a usare il wrapper all'interno del mio filtro per parse_query. Ha causato nuovamente gli stessi errori 404. Devo trovare un modo per replicare ciò che get_queried_object()fa senza sporcare questi filtri ...
somatico

-2

Stai eseguendo la versione più recente di WP? Immagino sia la prima domanda (come quando chiami il supporto tecnico e ti chiedono se il tuo computer è collegato!), Poiché ho letto che questo problema è stato risolto nell'aggiornamento della versione più recente.

C'è un post su digwp.com che affronta questo problema (http://digwp.com/2011/06/dont-use-postname/). Apparentemente WP non può facilmente distinguere tra post e pagine e, se avvii i tuoi URL con un'opzione testuale, WP innesca un flag che crea una regola per ogni pagina / post che hai. Se hai molti contenuti sul tuo sito, ciò può comportare un numero enorme di richieste e il tuo server probabilmente scadrà, il che comporterà un mucchio di 404 anche se le pagine sono lì.

Così. Se si utilizza prima una struttura basata su numeri, quindi la struttura basata su testo, scommetterei che il tuo problema 404 sarebbe stato risolto. Ora, considerando i problemi di SEO, non userei una struttura di date, ma prendere quella decisione sarà abbastanza logico per te.


2
Sono al 3.5. A partire da WP3.3.1 questo problema su digiwp è stato risolto.
somatic
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.