07 β Custom Post Type'lar¶
β¬ οΈ Oldingi: 06 β Settings API va admin sahifalar Β· π README Β· Keyingi: 08 β Taxonomiyalar β‘οΈ
Bu bobda: WordPress'ning standart
postvapageturlaridan tashqari o'z kontent turlaringizni β masalankitobβ yaratishni o'rganamiz:register_post_type()niinithook'da to'g'ri argumentlar (labels,public,show_in_rest,supports,rewrite,capability_type) bilan chaqirish, slug/permalink uchunflush_rewrite_rules()ni FAQAT aktivatsiyada ishlatish, to'liq label'lar generatsiyasi va admin ro'yxatiga o'z ustunlaringizni (manage_{cpt}_posts_columnsfilter +manage_{cpt}_posts_custom_columnaction) qo'shish β hammasi "Kitoblar katalogi" plugin'i misolida.
Muammo: blog post hammasiga yetmaydi¶
Tasavvur qiling, mijoz sizdan kutubxona sayti so'radi. Har bir kitobning nomi, muallifi, ISBN'i, muqovasi va tavsifi bor. "Oson-ku," deysiz, "har bir kitobni oddiy post qilib qo'yaman." Bir hafta o'tib muammolar boshlanadi:
- Kitoblar oddiy blog yozuvlari bilan aralashib ketdi β
wp-admin/edit.phpda ikkalasi bir ro'yxatda. - Kitoblar uchun "Kategoriyalar" emas, "Janrlar" kerak edi, lekin ular oddiy postlar bilan teglarni bo'lishadi.
- URL
sayt.uz/2026/06/qardoshlar/ko'rinishida β sana bilan, lekin kitobga sana mantiqsiz. Mijozsayt.uz/kitob/qardoshlar/xohlaydi. - Mijoz "yangi kitob qo'shish" tugmasini izlaydi, lekin "Yangi yozuv" yozuvi uni chalg'itadi.
Yechim β Custom Post Type (CPT, o'z kontent turi). Bu WordPress'ga "menda post va page dan tashqari yana bir kontent turi bor, uni kitob deb atayman, o'z menyusi, o'z URL'i va o'z admin ekrani bilan" deyishning rasmiy yo'li.
π CPT nima? WordPress ichida hamma narsa β yozuv, sahifa, hatto menyu elementi va biriktirma (attachment) β bitta wp_posts jadvalida saqlanadi. Ularni bir-biridan ajratuvchi maydon β post_type ustuni. Standart turlar: post, page, attachment, revision, nav_menu_item. Custom Post Type β shu ustunga o'z qiymatingizni (kitob) ro'yxatga olib, WordPress'dan unga to'liq admin tajribasi yaratishni so'rashdir.
Nega temada emas, plugin'da?¶
Ko'p havaskor register_post_type() ni tema functions.php'ga yozadi. Bu β xato. Sababi oddiy: temani almashtirsangiz, kitoblaringiz ham yo'qoladi (aniqrog'i, ko'rinmay qoladi β wp_posts da turaveradi, lekin hech kim uni ro'yxatga olmaydi, shuning uchun admin va frontend uni ko'rsatmaydi).
π‘ Oltin qoida: Kontent β bu funksionallik, dizayn emas. Funksionallik plugin'ga tegishli, tema esa faqat ko'rinish uchun. Kitoblaringiz tema'dan mustaqil yashashi kerak. Shuning uchun CPT har doim plugin'da ro'yxatga olinadi.
Biz uni shu kitobning izchil namuna plugin'i β Kitoblar katalogi (slug kitoblar-katalogi, namespace Oqil\KitobKatalog, text domain kitoblar-katalogi) ichiga qo'shamiz.
register_post_type() β yagona kalit funksiya¶
CPT yaratishning butun siri β bitta funksiyada:
Birinchi argument β CPT'ning ichki nomi (post_type ustuniga yoziladigan qiymat), masalan kitob. Ikkinchisi β uning xatti-harakatini boshqaradigan ulkan argumentlar massivi.
β οΈ post_type nomi 20 belgidan oshmasin va kichik harf, raqam, _/- dan iborat bo'lsin. WordPress ba'zi nomlarni (post, page, revision, nav_menu_item, action, order, theme va boshqalar) band qilgan β ularni ishlatmang. Konfliktdan qochish uchun o'z prefiksingizni qo'shish yaxshi amaliyot (masalan kk_kitob), lekin URL chiroyli bo'lishi uchun biz bu yerda sodda kitob ni ishlatamiz va slug'ni o'zimiz nazorat qilamiz.
Eng muhim: qaysi hook'da chaqirish kerak?¶
π register_post_type() ni FAQAT init hook'ida chaqiring. Rasmiy hujjat aniq aytadi: post turini init dan oldin ro'yxatga olmang. init β WordPress to'liq yuklangan, lekin so'rov hali bajarilmagan payt. Plugin'lar, tema va WordPress yadrosi shu yerda o'z turlarini, taksonomiyalarini va shortcode'larini e'lon qiladi.
β οΈ CPT'ni init da ro'yxatga oling, lekin register_activation_hook da EMAS. Aktivatsiya hook'i faqat bir marta β plugin yoqilganda ishlaydi. Agar CPT'ni faqat o'sha yerda ro'yxatga olsangiz, keyingi har bir sahifa yuklanishida WordPress uni "bilmaydi". (Aktivatsiyada nimadir qilamiz, lekin u β flush_rewrite_rules, pastda ko'ramiz.)
Args, bittalab: nimani nazorat qiladi?¶
Argumentlar massivi katta. Quyida kitob uchun eng muhimlarini izohlaymiz β har biri rasmiy Code Reference bilan tasdiqlangan.
labels β admindagi BARCHA matnlar¶
labels β bu CPT bilan bog'liq har bir admin matni: menyu nomi, "Yangi qo'shish" tugmasi, "Tahrirlash", bo'sh ro'yxat xabari va h.k. Ularni qo'lda bittalab yozish zerikarli, shuning uchun WordPress yordamchi funksiyaga ega:
π get_post_type_labels() singular va plural nomdan to'liq label massivini generatsiya qiladi β lekin u registratsiya ichida avtomatik chaqiriladi va faqat ingliz tilidan kelib chiqadi. Toza o'zbekcha (va tarjima qilinadigan) interfeys uchun biz label'larni qo'lda, to'liq beramiz. Bu β professional plugin belgisi.
$labels = [
'name' => __( 'Kitoblar', 'kitoblar-katalogi' ),
'singular_name' => __( 'Kitob', 'kitoblar-katalogi' ),
'menu_name' => __( 'Kitoblar', 'kitoblar-katalogi' ),
'name_admin_bar' => __( 'Kitob', 'kitoblar-katalogi' ),
'add_new' => __( 'Yangi qo\'shish', 'kitoblar-katalogi' ),
'add_new_item' => __( 'Yangi kitob qo\'shish', 'kitoblar-katalogi' ),
'new_item' => __( 'Yangi kitob', 'kitoblar-katalogi' ),
'edit_item' => __( 'Kitobni tahrirlash', 'kitoblar-katalogi' ),
'view_item' => __( 'Kitobni ko\'rish', 'kitoblar-katalogi' ),
'view_items' => __( 'Kitoblarni ko\'rish', 'kitoblar-katalogi' ),
'all_items' => __( 'Barcha kitoblar', 'kitoblar-katalogi' ),
'search_items' => __( 'Kitoblarni qidirish', 'kitoblar-katalogi' ),
'not_found' => __( 'Kitob topilmadi.', 'kitoblar-katalogi' ),
'not_found_in_trash' => __( 'Savatda kitob topilmadi.', 'kitoblar-katalogi' ),
'featured_image' => __( 'Muqova rasmi', 'kitoblar-katalogi' ),
'set_featured_image' => __( 'Muqova rasmini tanlash', 'kitoblar-katalogi' ),
'remove_featured_image' => __( 'Muqovani olib tashlash', 'kitoblar-katalogi' ),
'archives' => __( 'Kitoblar arxivi', 'kitoblar-katalogi' ),
'item_published' => __( 'Kitob chop etildi.', 'kitoblar-katalogi' ),
'item_updated' => __( 'Kitob yangilandi.', 'kitoblar-katalogi' ),
];
βΉοΈ
__( 'Yangi qo\'shish', ... )da apostrof\'bilan ekran qilingan β chunki PHP satri yagona tirnoq ichida. Bu PHP'ning oddiy qoidasi, WordPress'ga aloqasi yo'q. i18n (__()va text domain) ni 24-bobda chuqur ko'ramiz; hozircha har matnni__()ga o'rab, ikkinchi argument sifatida plugin text domain'ini berishni odat qiling.
Asosiy xatti-harakat argumentlari¶
| Argument | kitob uchun |
Nima qiladi |
|---|---|---|
public |
true |
Bosh "kalit". true bo'lsa CPT frontend'da ko'rinadi, qidiruvga kiradi, admin UI hosil bo'ladi. Ko'p boshqa argumentlar shundan kelib chiqadi. |
show_ui |
true |
Admin'da tahrirlash interfeysini hosil qiladi (odatda public dan meros oladi). |
show_in_menu |
true |
Admin yon menyuda alohida element. true β yuqori daraja; 'edit.php?post_type=...' β boshqa menyu ostida; false β yashirin. |
show_in_rest |
true |
MUHIM. REST API'da va shuning hisobiga blok muharririda (Gutenberg) ochiladi. false bo'lsa eski klassik muharrir ishlaydi. Zamonaviy CPT uchun har doim true. |
menu_icon |
'dashicons-book' |
Menyu yonidagi ikonka. WordPress'ga o'rnatilgan Dashicons klassi, rasm URL'i yoki base64 SVG. |
menu_position |
20 |
Menyudagi tartib raqami (20 β "Sahifalar" yonida). null bo'lsa eng pastga tushadi. |
supports |
massiv (pastda) | CPT muharriri qaysi maydonlarni ko'rsatishi. |
has_archive |
true |
CPT uchun arxiv sahifasini yoqadi (sayt.uz/kitob/). |
rewrite |
massiv (pastda) | URL/permalink tuzilishi. |
hierarchical |
false |
false β post kabi tekis (ota-bola yo'q). true β page kabi (ota-bola, "Ota" tanlovi). Kitoblar uchun teks yetadi. |
capability_type |
'post' |
CPT'ga kim kira oladi degan ruxsatlar (edit_post, publish_posts ...) qaysi turdan "klonlanadi". 'post' β oddiy postlar bilan bir xil ruxsat. |
β οΈ show_in_rest ni true qilishni unutmang. Bu eng tez-tez uchraydigan xato: CPT yaratasiz, lekin blok muharriri ochilmaydi yoki REST endpoint /wp/v2/kitob bo'sh qaytaradi. Sababi β show_in_rest standart bo'yicha false. Zamonaviy WordPress'da REST = blok muharriri + headless + JS β shuning uchun uni yoqing.
supports β muharrirda qaysi qutilar?¶
supports massivi CPT tahrirlash ekranida qaysi maydonlar chiqishini belgilaydi:
titleβ kitob nomi (sarlavha qatori).editorβ asosiy kontent (tavsif, blok muharriri).thumbnailβ muqova rasmi (Featured Image). Bu paydo bo'lishi uchun temadaadd_theme_support( 'post-thumbnails' )ham kerakligini eslang.excerptβ qisqacha tavsif.custom-fieldsβ meta maydonlar uchun standart quti (ISBN, muallif kabilarni biz 09-bobda meta box bilan chiroyliroq qilamiz).
π‘ Kerakmas maydonni qo'shmang. Masalan kitobga izoh kerak bo'lmasa,
commentsnisupportsga qo'shmang β admin sof bo'ladi.
Slug, permalink va rewrite¶
Mijoz sayt.uz/kitob/qardoshlar/ ko'rinishidagi toza URL'ni xohlagandi. Buni rewrite argumenti boshqaradi:
'has_archive' => true,
'rewrite' => [
'slug' => 'kitob', // URL bo'lagi: /kitob/<nom>
'with_front' => false, // permalink prefiksini (masalan /blog) qo'shmaydi
],
slugβ URL'dagi bo'lak.kitobdesangiz, har kitobsayt.uz/kitob/qardoshlar/bo'ladi, arxiv esa (has_archive => truetufayli)sayt.uz/kitob/.with_frontβ agar permalink sozlamalaringizda umumiy prefiks (/blog) bo'lsa, uni qo'shadimi. CPT uchun odatdafalsetoza ko'rinadi.
flush_rewrite_rules() β faqat aktivatsiyada!¶
URL qoidalari (rewrite rules) WordPress tomonidan keshlanadi. Yangi CPT'ni slug bilan qo'shganingizda, WordPress hali bu qoidalarni bilmaydi β sayt.uz/kitob/qardoshlar/ ga kirsangiz 404 olasiz. Yechim β qoidalarni qaytadan generatsiya qilish: flush_rewrite_rules().
β οΈ flush_rewrite_rules() ni HECH QACHON init da yoki har so'rovda chaqirmang! Rasmiy hujjat aniq ogohlantiradi: bu juda qimmat operatsiya (barcha qoidalarni o'chirib qaytadan quradi). Uni har sahifa yuklanishida chaqirsangiz, saytingiz sezilarli sekinlashadi. Bu β eng keng tarqalgan ishlash muammolaridan biri.
π To'g'ri naqsh: flush_rewrite_rules() ni FAQAT aktivatsiya hook'ida (register_activation_hook) chaqiring. Va muhimi β avval CPT'ni ro'yxatga oling, keyin flush qiling, aks holda flush qiladigan qoidalar hali mavjud bo'lmaydi.
register_activation_hook( __FILE__, 'oqil_kk_activate' );
function oqil_kk_activate(): void {
// 1) Avval CPT'ni ro'yxatga olamiz β qoidalar hosil bo'lsin.
oqil_kk_register_kitob_cpt();
// 2) Endi qoidalarni yangilaymiz (bir martagina, aktivatsiyada).
flush_rewrite_rules();
}
π‘ Deaktivatsiyada ham
flush_rewrite_rules()chaqirib, CPT qoidalarini tozalash yaxshi odob (register_deactivation_hook). Aktivatsiya/deaktivatsiya hooklarini 03-bobda ko'rgandik.
β οΈ Plugin'ni allaqachon faollashtirgan bo'lsangiz va keyin slug'ni o'zgartirsangiz, aktivatsiya qayta ishlamaydi. O'sha paytda Sozlamalar β Doimiy havolalar (Permalinks) sahifasini ochib "Saqlash" bosish ham qoidalarni yangilaydi β bu rivojlanish paytida tez yo'l.
To'liq registratsiya kodi¶
Endi hammasini birlashtiramiz. Bu β plugin'ingizning includes/cpt.php fayli bo'lishi mumkin:
<?php
/**
* Kitoblar katalogi β CPT registratsiyasi.
*
* @package Oqil\KitobKatalog
*/
declare( strict_types = 1 );
// To'g'ridan-to'g'ri kirishni bloklash.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* "kitob" Custom Post Type'ini ro'yxatga oladi.
*/
function oqil_kk_register_kitob_cpt(): void {
$labels = [
'name' => __( 'Kitoblar', 'kitoblar-katalogi' ),
'singular_name' => __( 'Kitob', 'kitoblar-katalogi' ),
'menu_name' => __( 'Kitoblar', 'kitoblar-katalogi' ),
'name_admin_bar' => __( 'Kitob', 'kitoblar-katalogi' ),
'add_new' => __( 'Yangi qo\'shish', 'kitoblar-katalogi' ),
'add_new_item' => __( 'Yangi kitob qo\'shish', 'kitoblar-katalogi' ),
'new_item' => __( 'Yangi kitob', 'kitoblar-katalogi' ),
'edit_item' => __( 'Kitobni tahrirlash', 'kitoblar-katalogi' ),
'view_item' => __( 'Kitobni ko\'rish', 'kitoblar-katalogi' ),
'all_items' => __( 'Barcha kitoblar', 'kitoblar-katalogi' ),
'search_items' => __( 'Kitoblarni qidirish', 'kitoblar-katalogi' ),
'not_found' => __( 'Kitob topilmadi.', 'kitoblar-katalogi' ),
'not_found_in_trash' => __( 'Savatda kitob topilmadi.', 'kitoblar-katalogi' ),
'featured_image' => __( 'Muqova rasmi', 'kitoblar-katalogi' ),
'archives' => __( 'Kitoblar arxivi', 'kitoblar-katalogi' ),
];
$args = [
'labels' => $labels,
'public' => true,
'show_ui' => true,
'show_in_menu' => true,
'show_in_rest' => true, // Blok muharriri + REST API uchun.
'menu_icon' => 'dashicons-book',
'menu_position' => 20,
'supports' => [ 'title', 'editor', 'thumbnail', 'excerpt', 'custom-fields' ],
'has_archive' => true,
'hierarchical' => false,
'rewrite' => [
'slug' => 'kitob',
'with_front' => false,
],
'capability_type' => 'post',
'map_meta_cap' => true,
];
register_post_type( 'kitob', $args );
}
add_action( 'init', 'oqil_kk_register_kitob_cpt' );
/**
* Aktivatsiya: CPT'ni ro'yxatga olib, rewrite qoidalarini bir marta yangilaydi.
*/
function oqil_kk_activate(): void {
oqil_kk_register_kitob_cpt();
flush_rewrite_rules();
}
register_activation_hook( __FILE__, 'oqil_kk_activate' );
/**
* Deaktivatsiya: CPT qoidalarini tozalaydi.
*/
function oqil_kk_deactivate(): void {
flush_rewrite_rules();
}
register_deactivation_hook( __FILE__, 'oqil_kk_deactivate' );
βΉοΈ Jonli sinov (o'z saytingizda). Bu kodni plugin'ingizga qo'shib, plugin'ni
wp-admin β Plugin'larda qayta faollashtiring (deaktivatsiya β aktivatsiya β yangi aktivatsiya hook ishga tushishi uchun). So'ng admin menyuda kitob ikonkali "Kitoblar" elementi paydo bo'ladi, "Yangi kitob qo'shish" bilan bir nechta kitob yarating vasayt.uz/kitob/<nom>/URL'ini ochib ko'ring. Bu natijalar ishlab turgan WordPress'ni talab qiladi βphp -lfaqat kodning sintaksisini tekshiradi.
π 'capability_type' => 'post' va 'map_meta_cap' => true birga β kitoblarga ruxsatlarni oddiy postlar kabi boshqaradi (edit_posts, publish_posts ...). Agar kitoblar uchun alohida ruxsatlar (masalan faqat "kutubxonachi" roli tahrirlaydigan) kerak bo'lsa, capability_type ni [ 'kitob', 'kitoblar' ] qilib custom capabilities yaratasiz β buni 11-bobda (Rollar va capabilities) ko'ramiz.
Admin ro'yxatiga o'z ustunlaringiz¶
Standart CPT ro'yxati (wp-admin β Kitoblar) faqat "Sarlavha", "Sana" ustunlarini ko'rsatadi. Kutubxonachi har kitobning muallifini va muqovasini to'g'ridan-to'g'ri ro'yxatda ko'rishni xohlaydi. Buni ikkita hook hal qiladi.
1-qadam: ustun sarlavhalarini qo'shish β filter¶
π manage_{post_type}_posts_columns filter ustunlar massivini (kalit β sarlavha) oladi va o'zgartirilganini qaytaradi. kitob uchun hook nomi manage_kitob_posts_columns bo'ladi.
/**
* Kitob ro'yxatiga "Muqova" va "Muallif" ustunlarini qo'shadi.
*
* @param string[] $columns Mavjud ustunlar (kalit => sarlavha).
* @return string[]
*/
function oqil_kk_kitob_columns( array $columns ): array {
$new = [];
foreach ( $columns as $key => $label ) {
// "Sarlavha" dan oldin "Muqova"ni joylaymiz.
if ( 'title' === $key ) {
$new['kitob_muqova'] = __( 'Muqova', 'kitoblar-katalogi' );
}
$new[ $key ] = $label;
// "Sarlavha" dan keyin "Muallif"ni joylaymiz.
if ( 'title' === $key ) {
$new['kitob_muallif'] = __( 'Muallif', 'kitoblar-katalogi' );
}
}
return $new;
}
add_filter( 'manage_kitob_posts_columns', 'oqil_kk_kitob_columns' );
π‘ To'g'ridan-to'g'ri
$columns['kitob_muallif'] = ...desangiz ham bo'ladi, lekin u eng oxirga (Sana'dan keyin) tushadi. Yuqoridagiforeachtartibni aniq nazorat qilish uchun β ustunni xohlagan joyga qo'yamiz.
2-qadam: ustun qiymatlarini chizish β action¶
Filter faqat sarlavhalarni qo'shdi; har bir qatorda nima ko'rsatilishini esa action hal qiladi:
π manage_{post_type}_posts_custom_column action ikkita argument oladi: $column (ustun kaliti) va $post_id (joriy yozuv ID'si) β aynan shu tartibda. Shuning uchun add_action ning oxirgi argumenti 2 (accepted_args).
/**
* Maxsus ustunlar qiymatini chizadi.
*
* @param string $column Ustun kaliti.
* @param int $post_id Yozuv ID'si.
*/
function oqil_kk_kitob_column_content( string $column, int $post_id ): void {
switch ( $column ) {
case 'kitob_muqova':
if ( has_post_thumbnail( $post_id ) ) {
// get_the_post_thumbnail xavfsiz HTML qaytaradi.
echo get_the_post_thumbnail( $post_id, [ 50, 70 ] );
} else {
echo '<span aria-hidden="true">β</span>';
}
break;
case 'kitob_muallif':
// Muallif meta'da saqlangan deb faraz qilamiz (09-bobda kiritamiz).
$muallif = get_post_meta( $post_id, '_kitob_muallif', true );
if ( '' !== $muallif ) {
// Matnli meta'ni KONTEKST bo'yicha escape qilamiz.
echo esc_html( $muallif );
} else {
echo '<span aria-hidden="true">β</span>';
}
break;
}
}
add_action( 'manage_kitob_posts_custom_column', 'oqil_kk_kitob_column_content', 10, 2 );
β οΈ Har doim escape qiling. Meta'dan kelgan matnni ($muallif) to'g'ridan-to'g'ri echo qilmang β XSS xavfi. Matn kontekstida esc_html() ishlating. get_the_post_thumbnail() esa allaqachon xavfsiz <img> HTML'ini qaytargani uchun uni qo'shimcha escape qilish shart emas (aks holda HTML buziladi). Escaping kontekstini 12-bobda chuqur ko'ramiz.
π‘ Ustunni saralanadigan (sortable) qilish.
manage_edit-kitob_sortable_columnsfilteri bilan ustunni bosib saralashni yoqishingiz mumkin, so'ngpre_get_postsdaorderbyni meta'ga ulaysiz. Bu βmeta_query/meta_valueorqali, lekin katta kataloglarda ishlash xarajati borligini unutmang (26-bob). Hozircha ko'rsatish yetarli.
Tez-tez uchraydigan xatolar¶
β οΈ 404 har yangi kitobda. Demak rewrite qoidalari yangilanmagan. Plugin'ni qayta faollashtiring yoki Doimiy havolalar sahifasini saqlang. Va flush_rewrite_rules() ni init ga qo'ymaganingizni tekshiring.
β οΈ Blok muharriri ochilmaydi / REST bo'sh. show_in_rest => true qo'yilmagan.
β οΈ CPT yo'qoladi. Registratsiyani init da emas, faqat aktivatsiyada qoldirgansiz. CPT har so'rovda init da ro'yxatga olinishi shart.
β οΈ Menyu ikonkasi ko'rinmaydi. menu_icon da noto'g'ri Dashicons klassi. To'g'ri ro'yxat β Dashicons sahifasida (dashicons- prefiksi bilan).
π Tayanch bilim. Bu bobning kodlari sof PHP funksiyalari va massivlarga tayanadi (declare(strict_types=1), tip e'lonlari, match/switch). Agar bu sizga notanish bo'lsa, PHP β Mutlaqo Noldan va PHP β Ekspert Darajasi kitoblariga qaytib oling.
Xulosa¶
- CPT β
wp_postsjadvalidagipost_typeustuniga o'z qiymatingizni (kitob) ro'yxatga olib, unga to'liq admin tajribasini olishdir. - CPT har doim plugin'da, tema'da emas β kontent funksionallik, dizayn emas.
register_post_type( 'kitob', $args )ni faqatinithook'ida chaqiring.- Muhim args:
labels(to'liq, tarjima qilingan),public,show_in_rest(true!),supports,menu_icon,has_archive,rewrite['slug'],hierarchical,capability_type. flush_rewrite_rules()β qimmat; uni FAQAT aktivatsiyada, CPT'ni ro'yxatga olgandan KEYIN chaqiring.- Admin ustunlari:
manage_kitob_posts_columnsfilter (sarlavhalar) +manage_kitob_posts_custom_columnaction (qiymatlar,accepted_args = 2), va qiymatlarni escape qiling.
Keyingi bobda kitoblarni janrlarga ajratamiz β bu uchun Custom Taxonomy yaratamiz va uni kitob CPT'ga bog'laymiz.
07-bob mashqlari¶
Mashqlarni o'z lokal WordPress saytingizda (02-bob:
wp-env/Docker) bajaring. Har plugin'ni teringan, faollashtirgan va admin'da ko'rgan bo'ling.
1 (Oson). register_post_type() ning birinchi argumenti nima va u qaysi maksimal uzunlikda bo'lishi kerak? Nima uchun ba'zi nomlar (post, page) band?
2 (Oson). register_post_type() qaysi hook'da chaqirilishi kerak va nega aynan o'sha hook?
3 (Oson). show_in_rest ni true qilmasangiz nima ishlamay qoladi? Kamida ikkita oqibatini ayting.
4 (Oson). public => true qaysi boshqa argumentlarni avtomatik o'zgartiradi? Kamida uchtasini sanang.
5 (O'rta). film nomli CPT yarating: supports da title, editor, thumbnail; slug film; menyu ikonkasi dashicons-video-alt2; blok muharririda ochilsin; arxivi bo'lsin.
Yechim
function oqil_kk_register_film_cpt(): void {
$args = [
'labels' => [
'name' => __( 'Filmlar', 'kitoblar-katalogi' ),
'singular_name' => __( 'Film', 'kitoblar-katalogi' ),
'add_new_item' => __( 'Yangi film qo\'shish', 'kitoblar-katalogi' ),
'edit_item' => __( 'Filmni tahrirlash', 'kitoblar-katalogi' ),
'not_found' => __( 'Film topilmadi.', 'kitoblar-katalogi' ),
],
'public' => true,
'show_in_rest' => true,
'menu_icon' => 'dashicons-video-alt2',
'supports' => [ 'title', 'editor', 'thumbnail' ],
'has_archive' => true,
'rewrite' => [ 'slug' => 'film', 'with_front' => false ],
];
register_post_type( 'film', $args );
}
add_action( 'init', 'oqil_kk_register_film_cpt' );
public => true show_ui, show_in_menu, publicly_queryable va boshqalarni o'zi yoqadi, shuning uchun ularni qaytadan yozish shart emas. Slug'ni yangiladingiz, demak plugin'ni qayta faollashtiring (yoki Doimiy havolalarni saqlang).
6 (O'rta). Nima uchun flush_rewrite_rules() ni init hook'da chaqirish xato? Texnik sababini (ishlash + qoidalar generatsiyasi) tushuntiring.
7 (O'rta). hierarchical => true va hierarchical => false orasidagi farqni misol bilan ayting. kitob uchun qaysi biri to'g'ri va nega?
8 (O'rta). kitob ro'yxatiga "ISBN" nomli ustun qo'shing (sarlavhadan keyin), qiymati _kitob_isbn meta'sidan olinsin va escape qilinsin. Meta bo'sh bo'lsa β ko'rsatilsin.
Yechim
// Sarlavhalar (filter).
function oqil_kk_kitob_isbn_column( array $columns ): array {
$new = [];
foreach ( $columns as $key => $label ) {
$new[ $key ] = $label;
if ( 'title' === $key ) {
$new['kitob_isbn'] = __( 'ISBN', 'kitoblar-katalogi' );
}
}
return $new;
}
add_filter( 'manage_kitob_posts_columns', 'oqil_kk_kitob_isbn_column' );
// Qiymat (action) β accepted_args = 2.
function oqil_kk_kitob_isbn_value( string $column, int $post_id ): void {
if ( 'kitob_isbn' !== $column ) {
return;
}
$isbn = get_post_meta( $post_id, '_kitob_isbn', true );
echo '' !== $isbn ? esc_html( $isbn ) : '<span aria-hidden="true">β</span>';
}
add_action( 'manage_kitob_posts_custom_column', 'oqil_kk_kitob_isbn_value', 10, 2 );
Diqqat: action callback'i ikki argument oladi ($column, $post_id), shuning uchun add_action da accepted_args 2 bo'lishi shart. ISBN'ni escape qildik β XSS xavfini bartaraf etish uchun.
9 (O'rta). menu_position ni 5 va 100 qilib sinab ko'ring. Menyuda CPT qayerda paydo bo'ladi? null bo'lsa-chi? (Lokal saytingizda kuzating.)
10 (Qiyin). To'liq mini-plugin yozing: header bilan, tadbir (event) CPT'sini ro'yxatga oladi (supports: title, editor, thumbnail, excerpt; slug tadbir; ikonka dashicons-calendar-alt; REST'da; arxivli), aktivatsiyada flush_rewrite_rules ni to'g'ri naqsh bilan chaqiradi va admin ro'yxatiga "Boshlanish sanasi" (_tadbir_sana meta'dan) ustunini qo'shadi.
Yechim
<?php
/**
* Plugin Name: Tadbirlar
* Description: "tadbir" Custom Post Type'i va admin ustuni.
* Version: 1.0.0
* Requires at least: 7.0
* Requires PHP: 8.3
* Text Domain: tadbirlar
*
* @package Oqil\Tadbirlar
*/
declare( strict_types = 1 );
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
function oqil_tadbir_register(): void {
$args = [
'labels' => [
'name' => __( 'Tadbirlar', 'tadbirlar' ),
'singular_name' => __( 'Tadbir', 'tadbirlar' ),
'add_new_item' => __( 'Yangi tadbir qo\'shish', 'tadbirlar' ),
'edit_item' => __( 'Tadbirni tahrirlash', 'tadbirlar' ),
'not_found' => __( 'Tadbir topilmadi.', 'tadbirlar' ),
],
'public' => true,
'show_in_rest' => true,
'menu_icon' => 'dashicons-calendar-alt',
'supports' => [ 'title', 'editor', 'thumbnail', 'excerpt' ],
'has_archive' => true,
'rewrite' => [ 'slug' => 'tadbir', 'with_front' => false ],
];
register_post_type( 'tadbir', $args );
}
add_action( 'init', 'oqil_tadbir_register' );
function oqil_tadbir_activate(): void {
oqil_tadbir_register();
flush_rewrite_rules();
}
register_activation_hook( __FILE__, 'oqil_tadbir_activate' );
function oqil_tadbir_deactivate(): void {
flush_rewrite_rules();
}
register_deactivation_hook( __FILE__, 'oqil_tadbir_deactivate' );
function oqil_tadbir_columns( array $columns ): array {
$new = [];
foreach ( $columns as $key => $label ) {
$new[ $key ] = $label;
if ( 'title' === $key ) {
$new['tadbir_sana'] = __( 'Boshlanish sanasi', 'tadbirlar' );
}
}
return $new;
}
add_filter( 'manage_tadbir_posts_columns', 'oqil_tadbir_columns' );
function oqil_tadbir_column_value( string $column, int $post_id ): void {
if ( 'tadbir_sana' !== $column ) {
return;
}
$sana = get_post_meta( $post_id, '_tadbir_sana', true );
echo '' !== $sana ? esc_html( $sana ) : '<span aria-hidden="true">β</span>';
}
add_action( 'manage_tadbir_posts_custom_column', 'oqil_tadbir_column_value', 10, 2 );
Aktivatsiyada avval oqil_tadbir_register() chaqirilib, keyin flush_rewrite_rules() β to'g'ri tartib. Ustun action'i accepted_args = 2 bilan ulangan, qiymat escape qilingan, ABSPATH tekshiruvi to'g'ridan-to'g'ri kirishni bloklaydi.
11 (Qiyin). kitob CPT'siga maxsus capabilities qo'shing: capability_type => [ 'kitob', 'kitoblar' ] va map_meta_cap => true. So'ng administrator roliga edit_kitoblar, publish_kitoblar, edit_others_kitoblar kabi ruxsatlarni bering. Nima uchun aks holda hech kim (hatto admin ham) kitob qo'sha olmaydi?
Yechim
function oqil_kk_register_kitob_cpt(): void {
$args = [
'labels' => [ /* ... oldingidek ... */ ],
'public' => true,
'show_in_rest' => true,
'supports' => [ 'title', 'editor', 'thumbnail' ],
'has_archive' => true,
'rewrite' => [ 'slug' => 'kitob' ],
'capability_type' => [ 'kitob', 'kitoblar' ],
'map_meta_cap' => true,
];
register_post_type( 'kitob', $args );
}
add_action( 'init', 'oqil_kk_register_kitob_cpt' );
// Aktivatsiyada admin roliga kitob ruxsatlarini beramiz.
function oqil_kk_add_caps(): void {
$role = get_role( 'administrator' );
if ( null === $role ) {
return;
}
$caps = [
'edit_kitob', 'read_kitob', 'delete_kitob',
'edit_kitoblar', 'edit_others_kitoblar', 'publish_kitoblar',
'read_private_kitoblar', 'delete_kitoblar',
];
foreach ( $caps as $cap ) {
$role->add_cap( $cap );
}
}
function oqil_kk_activate(): void {
oqil_kk_register_kitob_cpt();
oqil_kk_add_caps();
flush_rewrite_rules();
}
register_activation_hook( __FILE__, 'oqil_kk_activate' );
capability_type ni [ 'kitob', 'kitoblar' ] qilganingizda WordPress endi edit_posts emas, edit_kitoblar ruxsatini tekshiradi. Bu ruxsat hech qaysi rolda yo'q β shuning uchun hatto admin ham menyuni ko'rmaydi, toki uni qo'lda bermaguningizcha. Rollar va capabilities chuqur 11-bobda; bu yerda asosiy tushuncha β custom capability'lar avtomatik berilmaydi.
12 (Qiyin). "Sarlavha"ga bosib o'tmasdan ham kitob ustunidagi "Muallif" bo'yicha saralash mumkin bo'lsin: manage_edit-kitob_sortable_columns filteri va pre_get_posts action'i bilan amalga oshiring. Katta katalogda bu naqshning ishlash xavfini ayting.
Yechim
// Ustunni saralanadigan qilamiz.
function oqil_kk_sortable( array $columns ): array {
$columns['kitob_muallif'] = 'kitob_muallif';
return $columns;
}
add_filter( 'manage_edit-kitob_sortable_columns', 'oqil_kk_sortable' );
// Saralashni meta'ga ulaymiz.
function oqil_kk_sort_query( \WP_Query $query ): void {
if ( ! is_admin() || ! $query->is_main_query() ) {
return;
}
if ( 'kitob_muallif' === $query->get( 'orderby' ) ) {
$query->set( 'meta_key', '_kitob_muallif' );
$query->set( 'orderby', 'meta_value' );
}
}
add_action( 'pre_get_posts', 'oqil_kk_sort_query' );
Saralash kaliti (filter'da bergan 'kitob_muallif') orderby ga aylanadi; pre_get_posts da uni meta_key + orderby => meta_value ga bog'laymiz.
β οΈ Ishlash xavfi: meta_value bo'yicha saralash wp_postmeta jadvaliga JOIN qiladi va bu jadval indekslanmagan meta_value ustuni bo'yicha sekin bo'lishi mumkin. Minglab kitobli katalogda bu sezilarli sekinlik beradi. Yechim β muallifni alohida ustun/jadvalda saqlash yoki taxonomiya qilish (08-bob), yoki keshlash (26-bob). Bu yerda meta_value qisqalik uchun; ishlab chiqarishda o'lchang.
β¬ οΈ Oldingi: 06 β Settings API va admin sahifalar Β· π README Β· Keyingi: 08 β Taxonomiyalar β‘οΈ