Izinkan saya menjelaskan pemrosesan permintaan oleh WordPress, dan metode untuk mengubah perilaku WordPress untuk mencapai tujuan Anda.
Parsing permintaan
Ketika WordPress menerima permintaan, itu memulai proses membedah permintaan dan mengubahnya menjadi sebuah halaman. Inti dari proses ini dimulai ketika metode kueri utama WordPress WP::main()
dipanggil. Fungsi ini mem-parsing kueri, seperti yang Anda identifikasi dengan benar, di parse_request()
(di includes/class-wp.php
). Di sana, WordPress mencoba untuk mencocokkan URL dengan salah satu aturan penulisan ulang . Ketika URL dicocokkan, itu membuat string kueri bagian-bagian URL dan mengkodekan bagian-bagian ini (segala sesuatu di antara dua garis miring) menggunakan urlencode()
, untuk mencegah karakter khusus seperti &
dari mengacaukan string kueri. Karakter yang disandikan ini mungkin menyebabkan Anda berpikir bahwa masalahnya ada di sana, tetapi mereka benar-benar berubah menjadi karakter "asli" yang sesuai saat menguraikan string kueri.
Menjalankan kueri yang terkait dengan permintaan
Setelah WordPress mem-parsing URL, ia mengatur kelas kueri utama WP_Query
,, yang dilakukan dengan main()
metode WP
kelas yang sama. Daging sapi WP_Query
dapat ditemukan dalam get_posts()
metodenya di mana semua argumen kueri diuraikan dan disanitasi dan kueri SQL aktual dibuat (dan, akhirnya, jalankan).
Dalam metode ini, pada baris 2730, kode berikut dijalankan:
$q['name'] = sanitize_title_for_query( $q['name'] );
Ini membersihkan posting untuk mengambilnya dari tabel posting. Outputing info debug di dalam loop menunjukkan bahwa ini adalah tempat masalahnya: nama posting Anda my-permalink~
,, ditransformasikan my-permalink
, yang kemudian digunakan untuk mengambil posting dari database.
Fungsi sanitasi judul posting
Fungsi sanitize_title_for_query
panggilan sanitize_title
dengan parameter yang tepat, yang mulai membersihkan judul. Sekarang inti dari fungsi ini menerapkan sanitize_title
filter:
$title = apply_filters( 'sanitize_title', $title, $raw_title, $context );
Filter ini telah, di WordPress asli, fungsi tunggal yang melekat padanya: sanitize_title_with_dashes
. Saya telah menulis tinjauan luas tentang apa fungsi ini, yang dapat ditemukan di sini . Dalam fungsi ini, garis yang menyebabkan masalah Anda adalah
$title = preg_replace('/[^%a-z0-9 _-]/', '', $title);
Baris ini menghapus semua karakter kecuali karakter alfanumerik, spasi, tanda hubung, dan garis bawah.
Memecahkan masalah Anda
Jadi, pada dasarnya ada satu cara untuk menyelesaikan masalah Anda: menghapus sanitize_title_with_dashes
fungsi dari filter dan menggantinya dengan fungsi Anda sendiri. Ini sebenarnya tidak terlalu sulit untuk dilakukan, tetapi :
- Ketika WordPress mengubah proses internal judul sanitasi, ini akan memiliki efek besar pada situs web Anda.
- Plugin lain yang menghubungkan ke filter ini mungkin tidak menangani fungsi baru dengan benar.
Paling penting : WordPress menggunakan hasil sanitize_title
fungsi secara langsung dalam query SQL dengan baris ini:
$where .= " AND $wpdb->posts.post_name = '" . $q['name'] . "'";
Jika Anda pernah mempertimbangkan untuk mengubah filter, pastikan Anda keluar dari judul dengan benar sebelum digunakan dalam kueri!
Kesimpulan: menyelesaikan masalah Anda tidak perlu sejauh menyangkut keamanan, tetapi jika Anda ingin melakukannya, ganti sanitize_title_with_dashes
dengan fungsi Anda sendiri dan perhatikan untuk melarikan diri SQL.
NB semua nama file dan nomor baris sesuai dengan file WordPress 4.4.2.