Membuat permalink jenis posting kustom hierarkis berfungsi seperti halnya halaman

16

Saya telah menggali setiap pertanyaan di sini pada permalink jenis posting kustom, tetapi sebagian besar tampaknya merupakan masalah dengan penulisan ulang taksonomi kustom, atau hilangnya flush_rewrite_rules () yang jelas tidak ada. Tetapi dalam kasus saya, saya hanya menggunakan jenis posting khusus (tanpa taksonomi), diatur menjadi hierarki (sehingga saya dapat menetapkan hubungan orang tua-anak), dengan "dukungan" yang tepat untuk atribut metabox, dll, dll. Saya Sudah menulis ulang aturan ribuan cara yang memerah. Saya sudah mencoba struktur permalink yang berbeda. Tetapi URL anak selalu menghasilkan 404!

Saya awalnya memiliki jenis pos kustom independen untuk elemen "induk" dan "anak" (menggunakan p2p), dan saya mungkin tidak akan kesulitan menggunakan taksonomi untuk pengelompokan "parental" - Saya tahu itu akan secara semantik lebih akurat. Tetapi untuk klien, akan lebih mudah bagi mereka untuk memvisualisasikan hierarki ketika "posting" ditampilkan di admin seperti halaman: pohon sederhana di mana anak-anak muncul di bawah orangtua, diawali dengan "-", dan di pesanan yang tepat. Juga, berbagai metode untuk menetapkan pesanan melalui drag-n-drop dapat digunakan. Pengelompokan melalui taksonomi (atau p2p) menghasilkan daftar "posting" datar dalam daftar admin, yang sama sekali tidak jelas secara visual.

Jadi apa yang saya kejar secara harfiah adalah perilaku yang sama persis dengan inti "halaman", tetapi dengan jenis posting kustom saya. Saya telah mendaftarkan jenis posting seperti yang diharapkan, dan di admin berfungsi dengan baik - Saya dapat menetapkan orangtua dan menu_order untuk setiap "posting" buletin, mereka muncul dengan benar di daftar edit:

Spring 2012
 First Article
 Second Article

Dan permalink mereka tampaknya dibangun dengan benar. Bahkan, jika saya mengubah apa pun tentang struktur, atau bahkan mengubah slug penulisan ulang ketika mendaftarkan jenis posting, mereka secara otomatis memperbarui dengan benar, jadi saya tahu ada sesuatu yang berfungsi:

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

Saya juga memiliki "halaman" inti standar dengan hubungan hierarkis dibuat, dan mereka terlihat sama saja di admin, tetapi sebenarnya juga berfungsi di front-end (baik URL induk maupun URL anak berfungsi dengan baik).

Struktur permalink saya disetel ke:

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

Saya juga telah mencoba ini (hanya karena begitu banyak jawaban lain yang mengindikasikan bahwa itu diperlukan, meskipun tidak masuk akal dalam kasus saya):

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

Daftar CPT saya termasuk:

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

Satu-satunya perbedaan yang terlihat antara anak - anak jenis posting kustom saya dan anak - anak halaman normal , adalah bahwa CPT saya memiliki siput di awal struktur permalink, kemudian diikuti oleh siput induk / anak (di mana halaman baru dimulai dengan siput induk / anak, tidak ada "awalan"). Mengapa ini akan mengacaukan segalanya, saya tidak tahu. Banyak artikel yang mengindikasikan bahwa ini adalah bagaimana seharusnya permalink CPT hirarkis seperti itu berperilaku - tetapi milik saya, meskipun dibentuk dengan baik, tidak berfungsi.

Yang juga membingungkan saya adalah ketika saya memeriksa query_vars untuk halaman 404 - mereka tampaknya mengandung nilai yang benar untuk WP untuk "menemukan" halaman anak saya, tetapi ada sesuatu yang tidak berfungsi.

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

Saya sudah mencoba ini dengan berbagai tema, termasuk dua puluh dua belas, hanya untuk memastikan itu bukan template yang hilang pada bagian saya.

Menggunakan Inspektur Aturan Tulis Ulang, inilah yang muncul untuk 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: 

bagaimana ditampilkan di halaman inspektur lain:

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

Output penulisan ulang ini akan membuat saya percaya bahwa permalink "tidak cantik" berikut ini akan berfungsi:

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

Itu tidak 404, tetapi itu menunjukkan item CPT induk "buletin", bukan anak. Permintaannya terlihat seperti ini:

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

Jawaban:

15

Ini adalah pertama kalinya saya berpartisipasi di sini di Stack Exchange, tetapi saya akan mencobanya dan melihat apakah saya dapat membantu mengarahkan Anda ke arah yang benar.

Secara default, CPT hirarkis berperilaku persis seperti yang Anda gambarkan. Awalan siput unik, "buletin" dalam kasus ini, adalah untuk membiarkan mesin penulisan ulang tahu cara membedakan permintaan untuk jenis posting yang berbeda.

Argumen registrasi CPT tersebut terlihat baik-baik saja, tetapi ketika CPT diminta, pagenamevar kueri tidak boleh memiliki nilai dan namevar kueri harus sama dengan di newslettersini, sehingga tampaknya ada konflik di suatu tempat di pengaturan Anda.

Untuk membantu men-debug, instal dan aktifkan Plugin Inspektur Aturan Tulis Ulang , lalu kunjungi layar di " Alat -> Aturan Tulis Ulang ."

  1. Saat melihat daftar, semua aturan Anda untuk buletin CPT harus didaftar sebelum aturan penulisan ulang halaman apa pun . Verifikasi hal ini dengan memindai kolom " Sumber ".
  2. Jika itu memeriksa, masukkan URL untuk CPT "artikel pertama" Anda di bidang " URL Kecocokan " dan klik tombol "Filter" untuk melihat aturan mana yang cocok. Ini harus cocok dengan aturan buletin dan aturan halaman, tetapi aturan buletin harus menjadi yang pertama.

Jika itu tidak mengungkapkan masalah, cari post_namekolom di wp_postsuntuk menemukan posting lain dengan siput "artikel pertama" untuk melihat apakah mungkin ada tabrakan. Lakukan pencarian "buletin" juga, hanya untuk memastikan.

Tambahkan potongan berikut untuk memeriksa vars permintaan Anda di awal permintaan untuk memeriksa dan melihat mana yang sedang diatur oleh kecocokan aturan penulisan ulang (kunjungi CPT anak di ujung depan). Jika pagenamevar tidak muncul di sini, maka sedang diatur oleh sesuatu nanti dalam permintaan:

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

Setiap plugin / fungsi yang memodifikasi kueri vars dapat menyebabkan konflik, jadi nonaktifkan jika Anda masih melihat masalah. Juga siram aturan penulisan ulang Anda setelah setiap langkah, terutama jika permintaan cocok dengan aturan yang salah pada langkah kedua di atas (biarkan layar "Permalinks" terbuka di tab yang terpisah dan segarkan saja).

Brady Vercher
sumber
Saya telah mengedit pertanyaan untuk menampilkan output dari inspektur aturan penulisan ulang, karena komentar ini tidak memungkinkan pemformatan yang cukup. Aturan untuk CPT ditampilkan di bagian atas daftar, sebelum hal lain - tetapi tidak yakin aturan mana di bawah ini yang merupakan aturan "halaman" (tidak jelas). Juga, tidak ada tabrakan di post_namekolom.
somatik
apakah Anda memiliki pemikiran tentang struktur permalink yang tepat? Saya telah kembali ke /%postname%/sejak memasukkan /%category%/hanya tampaknya membingungkan hal-hal lebih lanjut dalam inspektur menulis ulang. Saya bahkan melihat orang mengklaim bahwa /%category%/secara ajaib dipetakan untuk CPT berarti "orang tua", meskipun saya tidak menemukan ini benar.
somatik
Output itu tampaknya datang untuk plugin yang berbeda, itulah sebabnya Anda tidak melihat "sumber" aturan. Either way, sepertinya aturan Anda cocok dengan baik. Saya telah mengedit jawaban saya untuk memasukkan potongan untuk memeriksa var permintaan sebelumnya dalam permintaan untuk memastikan mereka diatur dengan benar.
Brady Vercher
Sedangkan untuk struktur permalink, saya bukan penggemar termasuk kategori. Ini hanyalah bagian bergerak yang tidak membantu apa pun, dan pos dapat menjadi bagian dari banyak kategori. Jika ada kemungkinan sama sekali bahwa Anda dapat mengubah struktur permalink di masa depan atau ingin CPT lain dimuat tanpa awalan siput, saya akan merekomendasikan "namespacing" struktur Anda dengan sesuatu yang tetap dan unik seperti /blog/%postname%/.
Brady Vercher
itu adalah plugin yang tepat, tetapi ada dua halaman: "analisis penulisan ulang" dan "aturan penulisan ulang", keduanya menawarkan URL uji. Saya mencoba halaman lain dan itu menunjukkan sumber sebagai "program" untuk grup indentasi pertama, dan "halaman" untuk yang kedua.
somatik
5

The parent/Childpermalink Bekerja di luar kotak selama Anda set

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

Memperbarui:

Saya hanya mengujinya lagi dan berfungsi seperti yang diharapkan, dengan test case ini:

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

dan permalink diatur agar /%postname%/saya mendapatkan buletin / orang tua / anak yang bekerja dengan baik.

Bainternet
sumber
kode saya di atas tidak menunjukkannya, tetapi saya memiliki page-attributesdukungan (yang benar-benar hanya tentang menunjukkan metabox untuk menetapkan keturunan, seharusnya tidak mempengaruhi permalink) - tetapi mendapatkan 404. Struktur permalink apa yang perlu ditetapkan? atau apakah itu penting?
somatik
@ Otomatis saya baru saja mengujinya lagi dan itu berfungsi dengan baik, seperti untuk permalink saya tidak yakin apakah itu penting, tetapi cara saya memperbarui jawaban saya.
Bainternet
Saya dapat mengkonfirmasi bahwa, dengan penambahan array argumen untuk 'label' (tanpanya CPT tidak akan muncul di admin), contoh dasar ini bekerja pada instalasi vanilla WP3.5 dengan dua belas twentlytwelve. Tapi saya memperhatikan beberapa perbedaan utama dalam register_post_type$ args Anda: Saya menggunakan 'rewrite' => array( 'slug' => 'newsletter', 'with_front' => false ), di mana Anda hanya menggunakan true. Anda juga hanya berlalu trueuntuk has_archive, di mana aku melewati siput. Namun, ketika saya mencocokkan args Anda, saya masih mendapatkan 404 ... Masih mencoba melacak di mana saya salah.
somatik
3

Selain bertanya »Sudahkah Anda mencoba mematikannya lagi dan lagi?« , Saya juga harus bertanya "Apakah Anda memiliki plugin yang aktif dan apakah Tema Anda melakukan apa saja pada permalinks (misalnya: mendaftarkan taksonomi, tipe posting, menambahkan aturan penulisan ulang) , dll.)?

Jika demikian: Apakah ini masih terjadi, setelah Anda menonaktifkan semua plugin dan beralih ke TwentyEleven? masukkan deskripsi gambar di sini

Untuk debug lebih lanjut, pergilah ke GitHub dan ambil Toschos "Rewrite" Plugin . Kemudian beralih ke repo plugin resmi di wp.org dan ambil MonkeyManRewriteAnalyzer Plugin . Saya bahkan menulis sedikit ekstensi untuk merekatkan keduanya sedikit menjadi satu. Ini akan memberi Anda banyak detail tentang pengaturan Anda.

kaisar
sumber
baik, jika saya menonaktifkan semuanya , saya tidak akan memiliki jenis posting khusus yang merupakan inti dari pertanyaan ini ... tapi ya, saya telah mencoba bahkan dengan tema Twentywwelve. Saya masih menggali melalui beberapa colokan yang diperlukan untuk melihat apa yang mengacaukan permintaan, seperti dari apa yang saya lihat, permalink itu sendiri terbentuk dengan baik.
somatik
@somatis Tentu saja tidak menonaktifkan milik Anda :)
kaiser
@somatis Lihat pembaruan.
kaiser
1

Jadi setelah mengonfirmasi bahwa saya bisa mendapatkan perilaku halaman hierarkis yang diharapkan dengan instalasi yang benar-benar bersih dan hanya satu deklarasi CPT, saya tahu ada kesalahan di suatu tempat di dalam plugin saya sendiri yang saya gunakan untuk menangani pembuatan CPT (sangat kompleks, menangani metabox khusus, taksonomi) , dll). Masalahnya adalah, terlepas dari semua saran untuk memeriksa masalah penulisan ulang atau permintaan, saya tidak dapat melihat sesuatu yang jelas salah. Saya memeriksa setiap filter dan kait, melihat kueri di setiap titik dan tidak melihat apa pun yang akan menyebabkan 404.

Jadi saya dibiarkan dengan tugas menonaktifkan / mengaktifkan secara manual masing-masing dari 9 kelas besar, dan kemudian, menemukan setidaknya 2 dari mereka yang menyebabkan 404, melalui masing-masing fungsi satu per satu dan menonaktifkan / mengaktifkannya, dan kemudian menelusuri garis demi baris di dalam fungsi-fungsi itu - suatu upaya kekerasan mencoba untuk melihat secara tepat apa yang menyebabkan 404, bahkan jika saya tidak tahu mengapa.

Saat itulah saya menemukan ada konsekuensi untuk menggunakan $query->get_queried_object(). Tampaknya menggunakan fungsi pembungkus ini benar-benar mengubah $ query itu sendiri, yang saya pikir saya kembali tidak berubah di akhir fungsi saya. Tiga filter di 2 kelas yang terlibat bahwa dimodifikasi query: parse_query, posts_orderby, posts_join- dan semua fungsi callback memanggil $query->get_queried_object()pada berlalu $queryarg untuk kemudian menjalankan beberapa tes kondisional dan kadang-kadang memodifikasi query vars (seperti untuk kasus-kasus urutan khusus). Anehnya, fungsi-fungsi ini benar-benar bekerja dengan baik pada apa yang dirancang untuk mereka lakukan, meskipun saya menggunakan fungsi tersebut. Saya tidak pernah melihat ada yang salah dengan $ query yang dikembalikan sebelumnya!

Entah bagaimana, setelah lebih dari setahun pengembangan dan penggunaan di puluhan lokasi produksi langsung, saya tidak pernah mengalami efek buruk dari kesalahan ini. Hanya ketika saya menjelajah ke CPT hirarkis, satu perbedaan kecil ini tiba-tiba memecahkan banyak hal. Itu adalah bagian dari apa yang membuat saya sangat keras dengan ini - yang terbaik yang bisa saya katakan, filter kueri saya dapat dipercaya!

Saya akui saya masih tidak tahu persis mengapa memanggil fungsi ini hanya memecah satu aspek kecil dari halaman anak-anak CPT - namun tidak pernah memanifestasikan masalah lain! Tapi itu jelas bahwa menggunakannya dalam panggilan balik filter membuat $queryentah bagaimana dikembalikan . Dengan menghapus panggilan ini, kesalahan 404 saya hilang.

Terima kasih atas semua tipsnya - semoga saya dapat membagi hadiahnya, karena saya memperoleh wawasan dari setiap jawaban, bahkan jika solusi akhirnya agak tidak berhubungan. Ini telah menjadi pelajaran edukatif untuk tidak mempercayai kode Anda secara membabi buta, meskipun itu telah bekerja untuk Anda sejak lama, atau itu tidak menghasilkan kesalahan yang jelas.

Kadang-kadang, sebagai bagan kaiser yang terwujud dengan begitu rapi, Anda hanya perlu mulai melempar sakelar hingga lampu kembali menyala. Dalam kasus saya, saya harus mengambil strategi pemecahan masalah yang sama sampai ke garis individu dalam suatu fungsi sebelum saya bisa melihat masalahnya.

somatik
sumber
Anda juga dapat menggunakan fungsi pembungkus get_queried_object()tanpa memotong $wpdbobjek.
kaiser
tapi yang mana $queryyang ambil? Saya menggunakan ini di dalam filter untuk parse_query, dan perlu secara khusus mendapatkan objek kueri tertentu dari $queryyang dilewatkan dari filter ...
somatic
Saya baru saja mencoba menggunakan pembungkus di dalam filter saya untuk parse_query. Itu menyebabkan 404 kesalahan yang sama lagi. Saya harus menemukan cara untuk meniru apa yang get_queried_object()terjadi tanpa merusak filter ini ...
somatic
-2

Apakah Anda menjalankan versi WP terbaru? Saya kira itu pertanyaan pertama (seperti ketika Anda menghubungi dukungan teknis dan mereka bertanya apakah komputer Anda terhubung!), Karena saya telah membaca bahwa masalah ini telah diatasi dalam pembaruan versi terbaru.

Ada posting di digwp.com yang membahas masalah ini (http://digwp.com/2011/06/dont-use-postname/). Tampaknya WP tidak dapat dengan mudah membedakan antara posting dan halaman, dan jika Anda memulai url Anda dengan opsi berbasis teks, WP memicu flag yang membuat aturan untuk setiap halaman / postingan yang Anda miliki. Jika Anda memiliki banyak konten di situs Anda, itu dapat menghasilkan sejumlah besar permintaan dan server Anda mungkin akan habis, yang akan menghasilkan banyak 404 bahkan jika halaman ada di sana.

Begitu. Jika Anda menggunakan struktur berbasis angka terlebih dahulu, maka struktur berbasis teks Anda, saya bertaruh bahwa masalah 404 Anda akan teratasi. Sekarang, mempertimbangkan masalah SEO, saya tidak akan menggunakan struktur tanggal, tetapi membuat keputusan itu akan cukup logis untuk Anda.

Melanie Sumner
sumber
2
Saya di 3.5. Pada WP3.3.1 masalah ini pada digiwp sudah diperbaiki.
somatik