08 β Taxonomiyalar¶
β¬ οΈ Oldingi: 07 β Custom Post Type'lar Β· π README Β· Keyingi: 09 β Meta box va custom fields β‘οΈ
Bu bobda: kontentni guruhlash va tasniflash uchun o'z taxonomiyalaringizni
register_taxonomy()bilan ro'yxatdan o'tkazishni β ierarxik (kategoriya-kabi daraxt) va tekis (teg-kabi) farqini, namuna plugin uchunkitobCPT'igajanrvakitob_tegtaxonomiyalarini ulashni,wp_insert_term/get_terms/wp_set_object_terms/get_the_terms/has_termbilan termlar ustida ishlashni, admin'da ustun va filtr ko'rsatishni hamda mavjud taxonomiyaniregister_taxonomy_for_object_typebilan CPT'ga qo'shishni β boshidan oxirigacha o'rganasiz.
Muammo: post'lar ko'p, ularni qanday tartibga solamiz?¶
07-bobda biz kitob Custom Post Type'ini yaratdik. Endi katalogimizda yuzlab kitob bor. Foydalanuvchi "barcha ilmiy kitoblarni ko'rsat" desa, yoki admin "faqat tarixiy kitoblarni tahrirlamoqchiman" desa β nima qilamiz? Har bir kitobning sarlavhasidan qidirishmi? Bu ishlamaydi.
WordPress'da kontentni guruhlash va tasniflash uchun maxsus mexanizm bor β u taxonomy (taksonomiya) deb ataladi. Aslida siz uni har kuni ishlatasiz: oddiy post'lardagi Category (rukn) va Tag (teg) β bular WordPress yadrosiga o'rnatilgan ikkita standart taxonomiya, xolos.
π Taxonomiya β bu post'larni guruhlash tizimi. Bitta taxonomiya ichida ko'plab term (atama) bo'ladi. Masalan
janrtaxonomiyasi, uning term'lari: "Ilmiy", "Tarix", "Badiiy". Har bir kitob bir yoki bir nechta term'ga tegishli bo'lishi mumkin.
Atamalarni aralashtirmaylik:
- Taxonomiya (taxonomy) β tasniflash tizimi. Misol:
category,post_tag, bizningjanr. - Term (atama) β taxonomiya ichidagi bitta qiymat. Misol: "Ilmiy", "Texnologiya".
- Object β taxonomiya bog'langan narsa. Odatda post (yoki CPT, yoki foydalanuvchi).
Standart category va post_tag bizga yetmaydi: ular post turiga bog'langan va ma'noviy jihatdan kitob janri uchun mos emas. Shuning uchun biz o'z taxonomiyamizni yaratamiz.
Ierarxik vs tekis: ikki xil taxonomiya¶
register_taxonomy()'ning eng muhim argumenti β hierarchical. U taxonomiyaning butun xulq-atvorini belgilaydi:
hierarchical => trueβ kategoriya-kabi. Term'lar ota-bola munosabatida daraxt hosil qiladi (masalan "Ilmiy" ostida "Fizika", "Biologiya"). Admin'da checkbox ro'yxati bilan ko'rinadi. Bizning janr uchun mos.hierarchical => false(standart) β teg-kabi. Term'lar tekis, ota-bolasi yo'q. Admin'da erkin matn maydoni (vergul bilan ajratilgan) bilan ko'rinadi. Bizning kitob teglari ("bestseller", "yangi", "chegirmada") uchun mos.
π‘ Tanlash mezoni sodda: agar term'lar bir-birining ichiga joylashadi (ota/bola) β
hierarchical => true. Agar ular faqat "yorliq" bo'lib, teng huquqli bo'lsa βfalse.hierarchicalning standart qiymatifalse(rasmiy hujjat: "Default false").
β οΈ hierarchicalni keyinroq o'zgartirsangiz, allaqachon kiritilgan term'lar yo'qolmaydi, lekin admin UI va URL tuzilishi o'zgaradi β buni loyihaning boshida hal qiling.
register_taxonomy() β sintaksis va imzo¶
Rasmiy imzo (developer.wordpress.org Code Reference bilan tasdiqlangan):
register_taxonomy(
string $taxonomy, // taxonomiya nomi (kalit, <= 32 belgi, kichik harf/raqam/_)
array|string $object_type, // qaysi post turi(lari)ga bog'lanadi: 'kitob' yoki ['kitob','post']
array|string $args = array() // sozlamalar
): WP_Taxonomy|WP_Error
β οΈ Argument tartibiga DIQQAT. Ko'p odam
register_post_type()bilan adashtiradi. Yodda tuting:register_taxonomy()'da birinchi β taxonomiya nomi, ikkinchi β qaysi CPT'ga bog'lanishi ($object_type), uchinchi β$args. CPT registratsiyasida esa birinchi β post turi nomi.
Taxonomiya init hook'ida ro'yxatdan o'tkaziladi (hujjat aniq aytadi: "Do not use before the 'init' hook"). CPT bilan bir xil init hook'ida β odatda CPT'dan keyin yoki yonida β chaqiriladi.
Eng muhim $args kalitlari¶
| Kalit | Vazifa |
|---|---|
labels |
Admin'dagi barcha matnlar (nom, "Yangi qo'shish", ...). |
hierarchical |
true = daraxt (checkbox), false = tekis (teg). Standart false. |
public |
Taxonomiyani ommaga ko'rsatish (frontend so'rovlari + admin UI). |
publicly_queryable |
Frontend'da ?janr=ilmiy kabi so'rovga ruxsat. |
show_ui |
Admin'da tahrirlash interfeysini ko'rsatish. |
show_in_menu |
Admin menyusida ko'rsatish (show_uiga tayanadi). |
show_in_rest |
REST API + blok muharririda ko'rsatish. Gutenberg'da panelda chiqishi uchun shart. |
show_admin_column |
Post ro'yxati jadvalida alohida ustun chiqaradi. |
show_tagcloud |
Teglar buluti vidjetida ko'rsatish. |
rewrite |
URL slug'i: ['slug' => 'janr']. false β chiroyli URL o'chadi. |
query_var |
URL so'rov o'zgaruvchisi (?janr=...). |
capabilities |
Term'larni boshqarish uchun ruxsatlar (rol/cap). |
default_term |
Bo'sh post uchun avtomatik biriktiriladigan standart term. |
meta_box_cb |
Tahrirlash sahifasidagi meta box'ning callback'i (false β yashiradi). |
π
show_in_rest => trueni unutmang. Blok muharririda (Gutenberg) taxonomiya paneli ko'rinishi va REST orqali term'larni o'qish-yozish uchun bu shart. 2026'da deyarli har doimtrueqo'yiladi.
Namuna: janr taxonomiyasini kitob CPT'iga ulash¶
Endi kitob bo'ylab izchil namuna plugin'imizni β Kitoblar katalogi (Oqil\KitobKatalog namespace, kitoblar-katalogi text domain) β kengaytiramiz. kitob CPT'iga ierarxik janr taxonomiyasini qo'shamiz.
<?php
namespace Oqil\KitobKatalog;
/**
* janr taxonomiyasini ro'yxatdan o'tkazadi (ierarxik, kategoriya-kabi).
*/
function register_janr_taxonomy(): void {
$labels = [
'name' => _x( 'Janrlar', 'taxonomy general name', 'kitoblar-katalogi' ),
'singular_name' => _x( 'Janr', 'taxonomy singular name', 'kitoblar-katalogi' ),
'search_items' => __( 'Janrlarni qidirish', 'kitoblar-katalogi' ),
'all_items' => __( 'Barcha janrlar', 'kitoblar-katalogi' ),
'parent_item' => __( 'Ota janr', 'kitoblar-katalogi' ),
'parent_item_colon' => __( 'Ota janr:', 'kitoblar-katalogi' ),
'edit_item' => __( 'Janrni tahrirlash', 'kitoblar-katalogi' ),
'update_item' => __( 'Janrni yangilash', 'kitoblar-katalogi' ),
'add_new_item' => __( 'Yangi janr qo\'shish', 'kitoblar-katalogi' ),
'new_item_name' => __( 'Yangi janr nomi', 'kitoblar-katalogi' ),
'menu_name' => __( 'Janrlar', 'kitoblar-katalogi' ),
];
$args = [
'labels' => $labels,
'hierarchical' => true, // kategoriya-kabi daraxt
'public' => true,
'show_ui' => true,
'show_in_menu' => true,
'show_in_rest' => true, // blok muharriri + REST uchun SHART
'show_admin_column' => true, // kitob ro'yxatida "Janrlar" ustuni
'show_tagcloud' => false,
'query_var' => true,
'rewrite' => [ 'slug' => 'janr' ],
];
register_taxonomy( 'janr', [ 'kitob' ], $args );
}
add_action( 'init', __NAMESPACE__ . '\\register_janr_taxonomy' );
π E'tibor bering: register_taxonomy( 'janr', [ 'kitob' ], $args ) β birinchi taxonomiya nomi, ikkinchi qaysi CPT'ga (['kitob']), uchinchi $args. Bog'lanish shu yerda β $object_type argumenti orqali β sodir bo'ladi.
β οΈ Permalink'ni yangilang.
rewriteishlashi uchun, plugin'ni aktivatsiya qilgandan so'ng Sozlamalar β Doimiy havolalar (Permalinks) sahifasini bir marta saqlang (yokiflush_rewrite_rules()ni faqat aktivatsiya hook'ida chaqiring β harinit'da emas, chunki u qimmat). Bu β o'z saytingizda bajariladigan illustrativ qadam.
Tekis teg taxonomiyasi ham qo'shamiz¶
Janr β daraxt. Lekin kitobga "bestseller", "yangi" kabi erkin yorliqlar ham kerak. Bu uchun tekis (hierarchical => false) taxonomiya yaratamiz:
<?php
namespace Oqil\KitobKatalog;
/**
* kitob_teg taxonomiyasini ro'yxatdan o'tkazadi (tekis, teg-kabi).
*/
function register_kitob_teg_taxonomy(): void {
$args = [
'labels' => [
'name' => _x( 'Kitob teglari', 'taxonomy general name', 'kitoblar-katalogi' ),
'singular_name' => _x( 'Kitob tegi', 'taxonomy singular name', 'kitoblar-katalogi' ),
'add_new_item' => __( 'Yangi teg qo\'shish', 'kitoblar-katalogi' ),
'menu_name' => __( 'Teglar', 'kitoblar-katalogi' ),
],
'hierarchical' => false, // teg-kabi tekis ro'yxat
'public' => true,
'show_in_rest' => true,
'show_admin_column' => true,
'rewrite' => [ 'slug' => 'kitob-teg' ],
];
register_taxonomy( 'kitob_teg', [ 'kitob' ], $args );
}
add_action( 'init', __NAMESPACE__ . '\\register_kitob_teg_taxonomy' );
π‘ Bitta
initcallback'ida CPT va ikkala taxonomiyani birga ro'yxatdan o'tkazsangiz ham bo'ladi. Muhimi β hammasiinit'da ishlasin. Ko'p odam alohida funksiyalarga ajratadi (toza kod uchun).
Mavjud taxonomiyani CPT'ga qo'shish¶
Ba'zan taxonomiya allaqachon ro'yxatdan o'tgan (sizniki yoki yadronikidir), va siz uni boshqa CPT'ga ham bog'lamoqchisiz. Buning uchun register_taxonomy_for_object_type() bor:
Masalan, standart post_tag (oddiy teglar) ni kitob CPT'iga ham ishlatmoqchimiz:
<?php
namespace Oqil\KitobKatalog;
function attach_post_tags_to_kitob(): void {
register_taxonomy_for_object_type( 'post_tag', 'kitob' );
}
add_action( 'init', __NAMESPACE__ . '\\attach_post_tags_to_kitob' );
βΉοΈ
register_taxonomy_for_object_type()mavjud taxonomiyaga qo'shimcha bog'lanish qo'shadi; muvaffaqiyatdatrueqaytaradi. Lekin u to'liq ishlashi uchun haminit'da chaqirilsin, va kerak bo'lsaregister_post_type($args['taxonomies'])ro'yxatiga ham qo'shing β eng ishonchli yo'l shu funksiyani ishlatish.
Term'lar bilan ishlash (kod orqali)¶
Admin'da term qo'shish β qulay, lekin plugin importi, migratsiya yoki avtomatlashtirish uchun term'larni kod orqali boshqarishni bilish shart. Mana asosiy funksiyalar.
wp_insert_term() β yangi term qo'shish¶
Rasmiy imzo (Code Reference bilan tasdiqlangan):
wp_insert_term(
string $term, // term NOMI (masalan 'Ilmiy')
string $taxonomy, // qaysi taxonomiyaga ('janr')
array|string $args = array() // description, parent, slug, alias_of
): array|WP_Error
β οΈ Tartib:
term,taxonomy,args. Birinchi β nom, ikkinchi β taxonomiya. Adashtirmang.
Muvaffaqiyatda ['term_id' => int, 'term_taxonomy_id' => int] massivini, xatoda WP_Error ni qaytaradi (masalan term allaqachon mavjud bo'lsa). Shuning uchun har doim natijani tekshiramiz:
<?php
namespace Oqil\KitobKatalog;
/**
* Plugin aktivatsiyasida boshlang'ich janrlarni yaratadi.
* Faqat term mavjud bo'lmasagina qo'shadi (term_exists tekshiruvi).
*/
function seed_default_janrlar(): void {
$janrlar = [ 'Ilmiy', 'Tarix', 'Badiiy', 'Texnologiya' ];
foreach ( $janrlar as $nom ) {
// term_exists() term bor-yo'qligini tekshiradi (takror oldini olamiz)
if ( ! term_exists( $nom, 'janr' ) ) {
$natija = wp_insert_term( $nom, 'janr' );
if ( is_wp_error( $natija ) ) {
// WP_Error -> log; soxta natija yozmaymiz
error_log( 'janr term xatosi: ' . $natija->get_error_message() );
continue;
}
// $natija['term_id'] endi yangi term ID'si
}
}
}
Ota-bola (ierarxik) term qo'shish β parent argumenti orqali:
$ilmiy = wp_insert_term( 'Ilmiy', 'janr' );
if ( ! is_wp_error( $ilmiy ) ) {
// 'Fizika' ni 'Ilmiy' ostiga joylashtiramiz
wp_insert_term( 'Fizika', 'janr', [
'parent' => $ilmiy['term_id'],
'description' => 'Fizikaga oid kitoblar',
'slug' => 'fizika',
] );
}
get_terms() β term'larni olish¶
Zamonaviy imzo (4.5.0'dan beri) β bitta $args massivi, taxonomiya esa 'taxonomy' kaliti orqali beriladi (rasmiy hujjat shuni tavsiya qiladi):
<?php
namespace Oqil\KitobKatalog;
// Barcha janrlarni olamiz (bo'sh bo'lganlari ham)
$janrlar = get_terms( [
'taxonomy' => 'janr',
'hide_empty' => false, // bironta kitob bog'lanmagan janrni ham ko'rsat
'orderby' => 'name',
'order' => 'ASC',
] );
if ( ! is_wp_error( $janrlar ) ) {
foreach ( $janrlar as $term ) {
// $term -> WP_Term obyekti: term_id, name, slug, count, parent ...
printf(
'<li>%s (%d ta kitob)</li>',
esc_html( $term->name ),
(int) $term->count
);
}
}
π Eski usuldan voz keching.
get_terms( 'janr', $args )(taxonomiya birinchi argument sifatida) β eskirgan (4.5.0'gacha bo'lgan). Yangi kodda har doim'taxonomy' => 'janr'ni$argsichida bering.
Foydali $args kalitlari: hide_empty (standart true), orderby (name/count/term_id), order, number (chegara), parent, child_of, slug, include, exclude.
wp_set_object_terms() β post'ga term biriktirish¶
Bu β eng muhim funksiya: kitobni janr(lar)ga bog'laydi.
wp_set_object_terms(
int $object_id, // post (kitob) ID'si
string|int|array $terms, // term: ID, nom/slug yoki ularning massivi
string $taxonomy, // 'janr'
bool $append = false // false=almashtir, true=qo'sh
): array|WP_Error
β οΈ
$appendga DIQQAT. Standartfalseβ mavjud term'lar almashtiriladi (eskirari olib tashlanadi).trueβ yangilari qo'shiladi, eskilari qoladi. Noto'g'ri qiymat bog'lanishlarni ovsiz o'chirib yuborishi mumkin.
<?php
namespace Oqil\KitobKatalog;
$kitob_id = 42;
// Kitobga ikkita janr biriktiramiz (oldingilari almashtiriladi)
$natija = wp_set_object_terms( $kitob_id, [ 'Ilmiy', 'Texnologiya' ], 'janr' );
if ( is_wp_error( $natija ) ) {
error_log( 'Term biriktirishda xato: ' . $natija->get_error_message() );
}
// Mavjudlariga qo'shimcha biriktirish (almashtirmasdan): $append = true
wp_set_object_terms( $kitob_id, [ 'Tarix' ], 'janr', true );
π‘
$termsga nom ham, slug ham, term_id ham berish mumkin. Agar nom/slug bo'yicha term hali mavjud bo'lmasa β WordPress uni avtomatik yaratadi (juda qulay import uchun).
get_the_terms() va has_term() β o'qish va tekshirish¶
get_the_terms() β bitta post'ning term'larini oladi:
<?php
namespace Oqil\KitobKatalog;
$janrlar = get_the_terms( $kitob_id, 'janr' );
// false = term yo'q; WP_Error = xato; shu sababli ikkalasini tekshiramiz
if ( $janrlar && ! is_wp_error( $janrlar ) ) {
$nomlar = wp_list_pluck( $janrlar, 'name' ); // faqat nomlar massivi
echo esc_html( implode( ', ', $nomlar ) );
}
has_term() β post berilgan term'ga tegishlimi (shartli mantiq uchun):
<?php
namespace Oqil\KitobKatalog;
// Joriy kitob "Ilmiy" janriga tegishlimi?
if ( has_term( 'Ilmiy', 'janr', $kitob_id ) ) {
echo '<span class="badge">Ilmiy nashr</span>';
}
// Bir nechta term'dan biri bormi (massiv)?
if ( has_term( [ 'Ilmiy', 'Texnologiya' ], 'janr' ) ) {
// joriy post'da (loop ichida) tekshiradi
}
CPT bilan to'liq bog'lanish va admin ko'rinishi¶
show_admin_column => true qo'yganimiz uchun, o'z saytingizda kitob ro'yxati jadvalida avtomatik "Janrlar" ustuni paydo bo'ladi (alohida kod yozish shart emas). Bu β illustrativ natija; uni wp-admin'da ko'rasiz.
Ierarxik taxonomiyada (janr) WordPress yuqorida filtr dropdownini ham avtomatik chiqaradi. Tekis taxonomiya (kitob_teg) uchun esa filtr avtomatik kelmaydi β uni restrict_manage_posts hook'i bilan qo'shamiz:
<?php
namespace Oqil\KitobKatalog;
/**
* kitob ro'yxati ustida kitob_teg taxonomiyasi uchun filtr dropdown qo'shadi.
*/
function add_kitob_teg_filter( string $post_type ): void {
if ( 'kitob' !== $post_type ) {
return;
}
$taxonomy = 'kitob_teg';
$tanlangan = isset( $_GET[ $taxonomy ] )
? sanitize_key( wp_unslash( $_GET[ $taxonomy ] ) )
: '';
$terms = get_terms( [ 'taxonomy' => $taxonomy, 'hide_empty' => false ] );
if ( is_wp_error( $terms ) || empty( $terms ) ) {
return;
}
echo '<select name="' . esc_attr( $taxonomy ) . '">';
echo '<option value="">' . esc_html__( 'Barcha teglar', 'kitoblar-katalogi' ) . '</option>';
foreach ( $terms as $term ) {
printf(
'<option value="%s"%s>%s</option>',
esc_attr( $term->slug ),
selected( $tanlangan, $term->slug, false ),
esc_html( $term->name )
);
}
echo '</select>';
}
add_action( 'restrict_manage_posts', __NAMESPACE__ . '\\add_kitob_teg_filter' );
π‘
$_GET'dan o'qiganda doimwp_unslash()+ sanitize (sanitize_key) ishlatamiz β 12-bobda xavfsizlik chuqur ochiladi.selected()esa tanlangan optiongaselectedatributini xavfsiz qo'yadi.
Ierarxik taxonomiya admin'da daraxt-checkbox bilan, tekis taxonomiya esa vergulli matn maydoni bilan ko'rinadi β bu farqni siz wp-admin'da kitob tahrirlash sahifasida ko'rasiz (illustrativ).
Xulosa¶
- Taxonomiya β post'larni guruhlash tizimi; uning ichidagi qiymatlar β term. Standartlari:
category,post_tag. register_taxonomy( $taxonomy, $object_type, $args )niinithook'ida chaqiring. Argument tartibi: nom, qaysi CPT, args.hierarchical => trueβ daraxt (kategoriya-kabi, checkbox);false(standart) β tekis (teg-kabi).show_in_rest => trueβ blok muharriri va REST uchun shart;show_admin_column => trueβ ro'yxatda ustun.- Term funksiyalari:
wp_insert_term($term, $taxonomy, $args),get_terms(['taxonomy'=>...]),wp_set_object_terms($id, $terms, $taxonomy, $append),get_the_terms($post, $taxonomy),has_term($term, $taxonomy, $post). $appendstandartfalseβ almashtiradi;trueβ qo'shadi.WP_Errorni har doimis_wp_error()bilan tekshiring.register_taxonomy_for_object_type($taxonomy, $object_type)β mavjud taxonomiyani CPT'ga qo'shadi.
Keyingi bobda har bir kitobga "muallif", "ISBN", "sahifalar soni" kabi maxsus maydonlar qo'shamiz β meta box va custom fields.
08-bob mashqlari¶
Mashqlarni o'zingiz bajaring. Kodni mktemp faylda
php -lbilan, mantiqni o'z WordPress saytingizda (02-bobdagiwp-env) sinab ko'ring. Har bir CPT/taxonomiyainit'da ro'yxatdan o'tsin.
1. (Oson) register_taxonomy()'ning birinchi va ikkinchi argumenti nima? register_post_type()'dan farqini bitta jumlada ayting.
2. (Oson) hierarchical => true va hierarchical => false admin interfeysida qanday ko'rinadi? Har biriga bittadan misol term keltiring.
3. (Oson) show_in_rest => true nima uchun kerak? Uni false qo'ysangiz blok muharririda nima yo'qoladi?
4. (Oson) Quyidagi qatordagi xatoni toping: register_taxonomy( ['kitob'], 'janr', $args );. To'g'risini yozing.
5. (O'rta) kitob CPT'iga nashriyot nomli ierarxik taxonomiya yarating (slug nashriyot, REST'da ko'rinsin, admin ustuni bo'lsin).
Yechim
<?php
namespace Oqil\KitobKatalog;
function register_nashriyot_taxonomy(): void {
register_taxonomy( 'nashriyot', [ 'kitob' ], [
'labels' => [
'name' => _x( 'Nashriyotlar', 'taxonomy general name', 'kitoblar-katalogi' ),
'singular_name' => _x( 'Nashriyot', 'taxonomy singular name', 'kitoblar-katalogi' ),
'menu_name' => __( 'Nashriyotlar', 'kitoblar-katalogi' ),
],
'hierarchical' => true,
'public' => true,
'show_in_rest' => true,
'show_admin_column' => true,
'rewrite' => [ 'slug' => 'nashriyot' ],
] );
}
add_action( 'init', __NAMESPACE__ . '\\register_nashriyot_taxonomy' );
hierarchical => true β daraxt; show_in_rest β Gutenberg paneli; show_admin_column β ro'yxat ustuni; rewrite β chiroyli URL (/nashriyot/...). Aktivatsiyadan keyin permalink'ni bir marta saqlang.
6. (O'rta) wp_insert_term() bilan janr taxonomiyasiga "Detektiv" term'ini qo'shing, lekin avval term_exists() bilan tekshirib, takrorlanishning oldini oling va WP_Errorni log qiling.
Yechim
<?php
namespace Oqil\KitobKatalog;
function qoshish_detektiv(): void {
if ( term_exists( 'Detektiv', 'janr' ) ) {
return; // allaqachon bor
}
$natija = wp_insert_term( 'Detektiv', 'janr', [
'description' => 'Detektiv janridagi kitoblar',
'slug' => 'detektiv',
] );
if ( is_wp_error( $natija ) ) {
error_log( 'Detektiv term: ' . $natija->get_error_message() );
return;
}
// $natija['term_id'] -> yangi ID
}
term_exists() takrorni oldini oladi, is_wp_error() xatoni tutadi β soxta natija yozmaymiz.
7. (O'rta) get_terms() yordamida janr taxonomiyasining barcha term'larini (bo'sh bo'lganlarini ham), nom bo'yicha tartiblab oling va <ul> ro'yxat sifatida xavfsiz chiqaring.
Yechim
<?php
namespace Oqil\KitobKatalog;
function janrlar_royxati(): string {
$terms = get_terms( [
'taxonomy' => 'janr',
'hide_empty' => false,
'orderby' => 'name',
'order' => 'ASC',
] );
if ( is_wp_error( $terms ) || empty( $terms ) ) {
return '';
}
$html = '<ul class="janrlar">';
foreach ( $terms as $term ) {
$html .= sprintf(
'<li>%s (%d)</li>',
esc_html( $term->name ),
(int) $term->count
);
}
return $html . '</ul>';
}
'taxonomy' => 'janr' β zamonaviy imzo. esc_html() β XSS himoyasi. count β shu term'dagi post soni.
8. (O'rta) wp_set_object_terms() bilan ID'si 10 bo'lgan kitobni "Ilmiy" va "Texnologiya" janrlariga biriktiring. So'ng $append = true bilan "Tarix" ni qo'shimcha biriktiring. $append ikkala holatda nima qiladi?
Yechim
<?php
namespace Oqil\KitobKatalog;
$kitob_id = 10;
// $append = false (standart): mavjudlarni ALMASHTIRADI
wp_set_object_terms( $kitob_id, [ 'Ilmiy', 'Texnologiya' ], 'janr' );
// $append = true: mavjudlariga QO'SHADI (eskilari qoladi)
wp_set_object_terms( $kitob_id, [ 'Tarix' ], 'janr', true );
false (standart) β eski bog'lanishlar o'chadi, faqat berilganlari qoladi. true β eskilari saqlanadi, yangilari qo'shiladi. Natijada kitob 3 janrda.
9. (O'rta) has_term() va get_the_terms() farqini tushuntiring. Qaysi biri bool, qaysi biri obyektlar massivi qaytaradi? Har biriga bittadan foydalanish holati keltiring.
Yechim
has_term( $term, $taxonomy, $post )->bool. "Bu post 'Ilmiy' janridami?" kabi shartli mantiq uchun:if ( has_term( 'Ilmiy', 'janr' ) ) { ... }.get_the_terms( $post, $taxonomy )->WP_Term[]|false|WP_Error. Post'ning barcha term'larini ro'yxatlash/ko'rsatish uchun:$terms = get_the_terms( $id, 'janr' );so'ngforeach.
get_the_terms false (term yo'q) yoki WP_Error qaytarishi mumkin β shuning uchun if ( $terms && ! is_wp_error( $terms ) ) bilan ikkalasini tekshiring.
10. (O'rta) register_taxonomy_for_object_type() qachon kerak bo'ladi? Standart category taxonomiyasini kitob CPT'iga qo'shadigan kodni yozing.
Yechim
<?php
namespace Oqil\KitobKatalog;
function kategoriyani_kitobga_ulash(): void {
register_taxonomy_for_object_type( 'category', 'kitob' );
}
add_action( 'init', __NAMESPACE__ . '\\kategoriyani_kitobga_ulash' );
Bu funksiya allaqachon ro'yxatdan o'tgan taxonomiyani (yadronikidir yoki sizniki) boshqa post turiga qo'shganda kerak β qaytadan register_taxonomy() chaqirish shart bo'lmaganda. init'da, taxonomiya ro'yxatga olingach chaqiriladi.
11. (Qiyin) janr taxonomiyasiga boshlang'ich term'lar (Ilmiy, Tarix, Badiiy) ni faqat plugin aktivatsiyasida bir marta yaratadigan to'liq kod yozing. Takrorlanishni oldini oling, WP_Errorni log qiling. (Eslatma: aktivatsiya hook'ida taxonomiya hali ro'yxatda bo'lishi uchun avval uni qo'lda ro'yxatdan o'tkazing yoki init'ni chaqiring.)
Yechim
<?php
namespace Oqil\KitobKatalog;
/**
* Aktivatsiyada janr term'larini ekadi.
* Taxonomiya init'da ro'yxatga olinadi; aktivatsiya hook'i admin so'rovi
* davomida init'dan KEYIN ishlaydi, shuning uchun 'janr' allaqachon mavjud.
*/
function activate_seed_janrlar(): void {
// Ehtiyot uchun taxonomiya borligini tekshiramiz
if ( ! taxonomy_exists( 'janr' ) ) {
register_janr_taxonomy(); // o'sha init callback'imiz
}
$boshlangich = [ 'Ilmiy', 'Tarix', 'Badiiy' ];
foreach ( $boshlangich as $nom ) {
if ( term_exists( $nom, 'janr' ) ) {
continue;
}
$natija = wp_insert_term( $nom, 'janr' );
if ( is_wp_error( $natija ) ) {
error_log( 'Seed janr xatosi: ' . $natija->get_error_message() );
}
}
}
// Asosiy plugin faylida:
register_activation_hook( __FILE__, __NAMESPACE__ . '\\activate_seed_janrlar' );
taxonomy_exists() + register_janr_taxonomy() β taxonomiyaning aktivatsiya paytida tayyor bo'lishini kafolatlaydi. term_exists() + is_wp_error() β xavfsiz ekish. Bu o'z saytingizda aktivatsiyada bir marta ishlaydi.
12. (Qiyin) Tekis kitob_teg taxonomiyasi uchun restrict_manage_posts bilan admin filtr dropdown qo'shing (faqat kitob ro'yxatida), tanlangan qiymatni xavfsiz o'qing va selected() bilan belgilang.
Yechim
<?php
namespace Oqil\KitobKatalog;
function kitob_teg_filtri( string $post_type ): void {
if ( 'kitob' !== $post_type ) {
return;
}
$tax = 'kitob_teg';
$tanlangan = isset( $_GET[ $tax ] )
? sanitize_key( wp_unslash( $_GET[ $tax ] ) )
: '';
$terms = get_terms( [ 'taxonomy' => $tax, 'hide_empty' => false ] );
if ( is_wp_error( $terms ) || empty( $terms ) ) {
return;
}
echo '<select name="' . esc_attr( $tax ) . '">';
echo '<option value="">' . esc_html__( 'Barcha teglar', 'kitoblar-katalogi' ) . '</option>';
foreach ( $terms as $t ) {
printf(
'<option value="%s"%s>%s</option>',
esc_attr( $t->slug ),
selected( $tanlangan, $t->slug, false ),
esc_html( $t->name )
);
}
echo '</select>';
}
add_action( 'restrict_manage_posts', __NAMESPACE__ . '\\kitob_teg_filtri' );
restrict_manage_posts ro'yxat ustidagi filtr maydonida ishlaydi. wp_unslash()+sanitize_key() β xavfsiz input; esc_attr/esc_html β xavfsiz chiqish; selected(...,...,false) β false 3-argument matnni qaytaradi (echo qilmaydi). Filtr o'zi WP_Query'ni avtomatik filtrlaydi (taxonomiya query_var orqali).
13. (Qiyin) Bitta kitobning barcha janr term'larini, agar ota term bo'lsa "Ota > Bola" ko'rinishida, vergul bilan ajratib xavfsiz chiqaradigan funksiya yozing.
Yechim
<?php
namespace Oqil\KitobKatalog;
function kitob_janrlari_yoli( int $kitob_id ): string {
$terms = get_the_terms( $kitob_id, 'janr' );
if ( ! $terms || is_wp_error( $terms ) ) {
return '';
}
$qatorlar = [];
foreach ( $terms as $term ) {
$yol = [ $term->name ];
$parent = $term->parent;
// Ota zanjirini yuqoriga ko'tarilib yig'amiz
while ( $parent ) {
$ota = get_term( $parent, 'janr' );
if ( is_wp_error( $ota ) || ! $ota ) {
break;
}
array_unshift( $yol, $ota->name );
$parent = $ota->parent;
}
$qatorlar[] = esc_html( implode( ' > ', $yol ) );
}
return implode( ', ', $qatorlar );
}
get_the_terms() post term'larini, get_term( $id, $tax ) esa ota term'ni oladi. while orqali ota zanjirini yuqoriga ko'tarilamiz; esc_html() har bir nomni himoya qiladi. false/WP_Error ikkala holat tekshirilgan.
14. (Qiyin) janr taxonomiyasi bo'yicha frontend so'rovi yozing: faqat "Ilmiy" janridagi kitoblarni WP_Query + tax_query bilan oling va sarlavhalarini xavfsiz chiqaring.
Yechim
<?php
namespace Oqil\KitobKatalog;
function ilmiy_kitoblar(): string {
$q = new \WP_Query( [
'post_type' => 'kitob',
'posts_per_page' => 10,
'tax_query' => [
[
'taxonomy' => 'janr',
'field' => 'slug', // slug bo'yicha qidiramiz
'terms' => [ 'ilmiy' ],
],
],
] );
if ( ! $q->have_posts() ) {
return '<p>' . esc_html__( 'Kitob topilmadi.', 'kitoblar-katalogi' ) . '</p>';
}
$html = '<ul>';
while ( $q->have_posts() ) {
$q->the_post();
$html .= '<li>' . esc_html( get_the_title() ) . '</li>';
}
wp_reset_postdata(); // global $post ni tiklash SHART
return $html . '</ul>';
}
tax_query taxonomiya bo'yicha filtr; field => 'slug' + terms => ['ilmiy']. Loopdan keyin wp_reset_postdata() global $postni tiklaydi (unutilsa keyingi loop'lar buziladi). query_posts() ishlatmang β WP_Query afzal.
15. (Qiyin) Plugin deaktivatsiyasida taxonomiyani tozalash kerakmi? flush_rewrite_rules() qachon va qayerda chaqirilishi kerak? Tushuntiring va kod skeletini yozing.
Yechim
<?php
namespace Oqil\KitobKatalog;
// AKTIVATSIYA: avval taxonomiya/CPT ro'yxatga olinsin, KEYIN rewrite flush
function activate(): void {
register_janr_taxonomy(); // taxonomiyani ro'yxatga olamiz
register_kitob_teg_taxonomy();
flush_rewrite_rules(); // chiroyli URL'lar yangilanadi (QIMMAT, faqat shu yerda)
}
register_activation_hook( __FILE__, __NAMESPACE__ . '\\activate' );
// DEAKTIVATSIYA: rewrite qoidalarini tozalaymiz
function deactivate(): void {
flush_rewrite_rules();
}
register_deactivation_hook( __FILE__, __NAMESPACE__ . '\\deactivate' );
flush_rewrite_rules() qimmat β faqat aktivatsiya/deaktivatsiyada chaqiriladi, hech qachon init'da har so'rovda emas. Taxonomiya term'larini odatda deaktivatsiyada o'chirmaymiz (foydalanuvchi ma'lumotini yo'qotmaslik uchun) β to'liq tozalash faqat uninstall.php'da, ataylab qilinadi. Bu β o'z saytingizda aktivatsiyada sinaladi.
β¬ οΈ Oldingi: 07 β Custom Post Type'lar Β· π README Β· Keyingi: 09 β Meta box va custom fields β‘οΈ