09 β Meta box va custom fields¶
β¬ οΈ Oldingi: 08 β Taxonomiyalar Β· π README Β· Keyingi: 10 β Ma'lumotlar bazasi: $wpdb, options, transients β‘οΈ
Bu bobda: post'ga qo'shimcha tuzilgan ma'lumot biriktirishni β
kitobCPT'ga muallif, ISBN va nashr yili kabi maydonlarni β o'rganasiz:add_meta_boxbilan tahrirlash sahifasiga forma chiqarish,save_post_{cpt}hook'idaupdate_post_metaorqali xavfsiz saqlash (nonce +current_user_can+ autosave tekshiruvi + sanitize + escape β bularning HAR BIRI majburiy),get_post_meta/update_post_meta/delete_post_metabilan ishlash, varegister_post_metaorqali meta'ni REST API hamda blok muharririga ochish (zamonaviy yo'l) β oxirida custom fields va ACF qisqa taqqoslanadi.
Muammo: post'ga "qo'shimcha qadoq" kerak¶
07-bobda kitob Custom Post Type'ini yaratdik, 08-bobda unga janr taxonomiyasini bog'ladik. Lekin haqiqiy kitobning muallifi, ISBN raqami, nashr yili va narxi bor. Bularni qayerga yozamiz?
- Sarlavha β
post_title. Tavsif βpost_content. Janr β taxonomiya. Bular tayyor. - Ammo "muallif" β bu na sarlavha, na taksonomiya. Bu post'ga biriktirilgan qo'shimcha qiymat.
WordPress'da bunday qiymatlar post meta (custom fields) deb ataladi. Har bir post'ga cheksiz miqdorda kalit β qiymat juftliklarini biriktirish mumkin. Tasavvur qiling: post β bu paket, meta β paketga yopishtirilgan stikerlar ("Muallif: Anvar", "ISBN: 978...", "Yil: 2026").
π Post meta wp_postmeta jadvalida saqlanadi. Har bir juftlik alohida qator: post_id, meta_key, meta_value. Shuning uchun bitta post'ning o'nlab meta'si bo'lishi mumkin.
Endi savol β bu meta'ni admin foydalanuvchi qanday kiritadi? Tahrirlash sahifasida unga forma kerak. Aynan shu yerda meta box keladi.
Meta box nima?¶
Post tahrirlash sahifasini ochsangiz β sarlavha, kontent muharriri (blok muharriri), o'ng tomonda "Publish", "Kategoriyalar", "Teglar" qutilarini ko'rasiz. Ana shu qutilarning har biri β meta box. WordPress yadrosining o'zi ham meta box'lardan foydalanadi.
Biz ham o'z qutimizni qo'shamiz: "Kitob tafsilotlari" deb nomlangan, ichida muallif/ISBN/yil maydonlari bo'lgan forma.
Meta box ikki bo'lakdan iborat:
- Ro'yxatdan o'tkazish β
add_meta_box()chaqirig'i (qachon, qayerda, qaysi funksiya formani chizadi). - Saqlash β forma yuborilganda kiritilgan qiymatlarni
wp_postmeta'ga yozish.
Eng muhim haqiqat: meta box avtomatik saqlamaydi. add_meta_box faqat forma ko'rsatadi. Saqlashni siz save_post hook'ida qo'lda yozasiz. Boshlovchilar shu yerda qoqiladi.
add_meta_box imzosi¶
add_meta_box(
string $id, // qutining HTML id'si (noyob)
string $title, // foydalanuvchi ko'radigan sarlavha
callable $callback, // formani echo qiluvchi funksiya
string|array|WP_Screen $screen = null, // qaysi ekran(lar): 'kitob', 'post'...
string $context = 'advanced', // 'normal' | 'side' | 'advanced'
string $priority = 'default', // 'high' | 'core' | 'default' | 'low'
array $callback_args = null // callback'ga $args sifatida uzatiladi
);
add_meta_box ni add_meta_boxes action ichida chaqirish kerak β bu hook tahrirlash ekrani yig'ilayotganda ishga tushadi.
$contextβ qutining joyi:'normal'(kontent ostida, keng),'side'(o'ng ustun, tor),'advanced'(normal ostida).$priorityβ bir kontekst ichidagi tartib:'high'yuqorida,'low'pastda.$callbackβ formani echo qiladigan funksiya. Unga birinchi argument sifatida joriyWP_Postobyekti keladi.
βΉοΈ Imzo developer.wordpress.org Code Reference bilan tasdiqlangan: add_meta_box( $id, $title, $callback, $screen, $context, $priority, $callback_args ).
Eng oddiy meta box (yon ustunda eslatma)¶
Avval kichik, prefiks'li (kk_) misol β yon ustunda bitta textarea:
add_action( 'add_meta_boxes', 'kk_oddiy_meta_box' );
function kk_oddiy_meta_box(): void {
add_meta_box(
'kk_eslatma', // ID
'Tahrirchi eslatmasi', // sarlavha
'kk_eslatma_render', // callback
'kitob', // faqat 'kitob' CPT ekranida
'side' // o'ng ustun
);
}
function kk_eslatma_render( $post ): void {
$qiymat = get_post_meta( $post->ID, '_kk_eslatma', true );
echo '<textarea name="kk_eslatma" rows="3" class="widefat">'
. esc_textarea( $qiymat ) . '</textarea>';
}
Diqqat: chiqishni esc_textarea() bilan escape qildik β meta'da kiritilgan matn </textarea> kabi belgilar saqlasa, ularni "sindirib" XSS qilmasligi uchun. Lekin bu misol hali saqlamaydi β keyingi bo'limda to'liq, xavfsiz versiyani yozamiz.
To'liq, xavfsiz meta box: kitob tafsilotlari¶
Endi izchil namuna plugin'imizning haqiqiy qismini quramiz. Namespace Oqil\KitobKatalog, text domain kitoblar-katalogi. Meta kalitlarni _ bilan boshlaymiz (masalan _kitob_muallif) β pastki chiziq bilan boshlangan meta kalit WordPress'ning eski "Custom Fields" panelida yashirin bo'ladi (faqat bizning meta box'imiz orqali tahrirlanadi).
1-qism: formani ro'yxatdan o'tkazish va chizish¶
namespace Oqil\KitobKatalog;
// Meta box'larni ro'yxatdan o'tkazish
add_action( 'add_meta_boxes', __NAMESPACE__ . '\\add_kitob_meta_box' );
function add_kitob_meta_box(): void {
add_meta_box(
'kitob_tafsilot', // ID
__( 'Kitob tafsilotlari', 'kitoblar-katalogi' ), // sarlavha
__NAMESPACE__ . '\\render_kitob_meta_box', // callback
'kitob', // ekran (CPT slug)
'normal', // kontekst
'high' // prioritet
);
}
function render_kitob_meta_box( \WP_Post $post ): void {
// Nonce maydonini chiqaramiz (CSRF himoyasi) β pastda batafsil
wp_nonce_field( 'kitob_meta_saqlash', 'kitob_meta_nonce' );
// Mavjud qiymatlarni o'qiymiz
$muallif = get_post_meta( $post->ID, '_kitob_muallif', true );
$isbn = get_post_meta( $post->ID, '_kitob_isbn', true );
$yil = get_post_meta( $post->ID, '_kitob_yil', true );
?>
<p>
<label for="kitob_muallif"><strong><?php esc_html_e( 'Muallif', 'kitoblar-katalogi' ); ?></strong></label><br>
<input type="text" id="kitob_muallif" name="kitob_muallif"
value="<?php echo esc_attr( $muallif ); ?>" class="widefat">
</p>
<p>
<label for="kitob_isbn"><strong><?php esc_html_e( 'ISBN', 'kitoblar-katalogi' ); ?></strong></label><br>
<input type="text" id="kitob_isbn" name="kitob_isbn"
value="<?php echo esc_attr( $isbn ); ?>" class="widefat">
</p>
<p>
<label for="kitob_yil"><strong><?php esc_html_e( 'Nashr yili', 'kitoblar-katalogi' ); ?></strong></label><br>
<input type="number" id="kitob_yil" name="kitob_yil"
value="<?php echo esc_attr( (string) $yil ); ?>" min="0" max="2100">
</p>
<?php
}
Bu yerda allaqachon ikki xavfsizlik qoidasi bor:
- β οΈ Escape (chiqishda). Har bir qiymatni HTML atributiga qo'yganda
esc_attr()ishlatdik. Meta'da" onmouseover="alert(1)kabi qiymat saqlangan bo'lsa, escape'siz u atributdan "chiqib ketib" XSS qiladi.esc_attruni xavfsiz qiladi. - π
wp_nonce_field()formaga yashirin xavfsizlik tokeni qo'shadi. Bu β keyingi qadam (saqlash) uchun "bu forma haqiqatan bizning saytimizdan yuborildi" deb tasdiqlash usuli.
2-qism: xavfsiz saqlash¶
Endi eng muhim qism. Forma yuborilganda WordPress save_post (va save_post_{cpt}) hook'ini ishga tushiradi. Biz aynan save_post_kitob ga ulanmiz β u faqat kitob post turi saqlanganda chaqiriladi, shuning uchun ortiqcha "bu kitobmi?" tekshiruvi kerak emas.
namespace Oqil\KitobKatalog;
// Saqlash β faqat 'kitob' CPT uchun. accepted_args=2: $post_id va $post
add_action( 'save_post_kitob', __NAMESPACE__ . '\\save_kitob_meta', 10, 2 );
function save_kitob_meta( int $post_id, \WP_Post $post ): void {
// 1. Autosave/revisiyani o'tkazib yuboramiz
if ( wp_is_post_autosave( $post_id ) || wp_is_post_revision( $post_id ) ) {
return;
}
// 2. Nonce tekshiruvi (CSRF himoyasi)
if ( ! isset( $_POST['kitob_meta_nonce'] )
|| ! wp_verify_nonce( sanitize_key( $_POST['kitob_meta_nonce'] ), 'kitob_meta_saqlash' ) ) {
return;
}
// 3. Ruxsat tekshiruvi
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return;
}
// 4. Sanitize + saqlash
if ( isset( $_POST['kitob_muallif'] ) ) {
$muallif = sanitize_text_field( wp_unslash( $_POST['kitob_muallif'] ) );
update_post_meta( $post_id, '_kitob_muallif', $muallif );
}
if ( isset( $_POST['kitob_isbn'] ) ) {
$isbn = sanitize_text_field( wp_unslash( $_POST['kitob_isbn'] ) );
update_post_meta( $post_id, '_kitob_isbn', $isbn );
}
if ( isset( $_POST['kitob_yil'] ) ) {
$yil = absint( $_POST['kitob_yil'] ); // 0 yoki musbat butun son
if ( $yil > 0 ) {
update_post_meta( $post_id, '_kitob_yil', $yil );
} else {
delete_post_meta( $post_id, '_kitob_yil' );
}
}
}
π Saqlashning "to'rt darvozasi" β har biri majburiy:
- Autosave/revisiya. WordPress siz yozayotganda avtomatik saqlaydi (autosave) va har saqlashda eski nusxa (revision) yaratadi. Bu paytda
$_POST'da forma maydonlari bo'lmaydi, shuning uchun ularni tekshirmasak β mavjud meta'ni bo'sh qiymat bilan o'chirib yuborishimiz mumkin.wp_is_post_autosave()vawp_is_post_revision()shundan himoya qiladi. - Nonce. Forma haqiqatan bizning saytimizdan kelganini tasdiqlaydi (CSRF). Pastda batafsil.
- Capability.
current_user_can( 'edit_post', $post_id )β bu foydalanuvchi aynan shu post'ni tahrirlash huquqiga egami? Bo'lmasa β to'xta. - Sanitize. Tashqaridan kelgan hech qaysi qiymatga ishonmaymiz. Matnni
sanitize_text_field(), sonniabsint()bilan tozalaymiz.wp_unslash()β WordPress$_POST'ga qo'shgan ortiqcha\slesh'larni olib tashlaydi (buni sanitize'dan oldin qilish kerak).
β οΈ Bu to'rttasidan bittasi yo'q bo'lsa β plugin'ingiz zaif. Nonce'siz meta box β eng keng tarqalgan WordPress zaifligi. Spec'da ham add_meta_box nonce'siz β β eskirgan/xato amaliyot deb belgilangan.
Nonce: soxta so'rovni qanday rad etadi¶
Nonce ("number used once") β formaga biriktiriladigan, harakatga va foydalanuvchiga bog'langan, vaqt bilan cheklangan xavfsizlik tokeni. Maqsadi β CSRF (Cross-Site Request Forgery) hujumini to'sish.
Tasavvur qiling: zararli sayt foydalanuvchiga "g'olib bo'ldingiz!" tugmasini ko'rsatadi, lekin u aslida sizning saytingizga yashirin forma yuboradi (foydalanuvchi sizning saytga login bo'lgan holatda). Nonce'siz bu so'rov o'tib ketadi. Nonce bilan β server "bu token mendan chiqmagan" deb rad etadi.
Ikki funksiya:
// Formada β yashirin maydon chiqaradi:
wp_nonce_field( 'kitob_meta_saqlash', 'kitob_meta_nonce' );
// ^ action (kontekst) ^ maydon nomi
// Saqlashda β tekshiradi:
wp_verify_nonce( $nonce, $action );
// 1 = 0-12 soat oldin yaratilgan, 2 = 12-24 soat, false = yaroqsiz
Imzolar (docs bilan tasdiqlangan):
wp_nonce_field( int|string $action = -1, string $name = '_wpnonce', bool $referer = true, bool $display = true ): stringwp_verify_nonce( string $nonce, string|int $action = -1 ): int|false
π‘ Muqobil β check_admin_referer(). Aksariyat admin formalar uchun qulayroq usul: u nonce'ni tekshiradi va yaroqsiz bo'lsa so'rovni o'zi to'xtatadi (die). Saqlashdagi nonce blokini shunday qisqartirsa bo'ladi:
// wp_verify_nonce o'rniga (xohlasangiz):
if ( ! isset( $_POST['kitob_meta_nonce'] ) ) {
return;
}
check_admin_referer( 'kitob_meta_saqlash', 'kitob_meta_nonce' );
// bu yergacha yetib kelsa β nonce yaroqli; aks holda WP avval to'xtatgan
Meta box'da wp_verify_nonce + return ko'proq ishlatiladi, chunki saqlash bir nechta hook bilan zanjir bo'lib ketishi mumkin va biz "jim qaytish" ni xohlaymiz. Ikkalasi ham to'g'ri.
Meta'ni o'qish, yozish, o'chirish¶
Meta box'dan tashqarida ham (frontend shablon, REST callback, boshqa hook) meta bilan ishlaysiz. To'rtta asosiy funksiya:
// O'QISH β bitta qiymat (single):
$muallif = get_post_meta( $post_id, '_kitob_muallif', true ); // string qaytaradi
// O'QISH β barcha meta (kalit => [qiymatlar] massivi):
$barchasi = get_post_meta( $post_id );
// O'QISH β bir kalitning HAMMA qiymatlari (single=false):
$janrlar = get_post_meta( $post_id, '_kitob_qoshimcha_janr', false ); // massiv
// YOZISH/YANGILASH β kalit yo'q bo'lsa yaratadi, bor bo'lsa yangilaydi:
update_post_meta( $post_id, '_kitob_yil', 2026 );
// QO'SHISH β bitta kalitga BIR NECHTA qiymat (single emas):
add_post_meta( $post_id, '_kitob_qoshimcha_janr', 'fantastika' );
// O'CHIRISH:
delete_post_meta( $post_id, '_kitob_yil' );
π $single parametri β eng ko'p chalkashtiradigan joy. get_post_meta( $id, $key, true ) β to'g'ridan-to'g'ri qiymatni qaytaradi (sizga kerak bo'lgani). get_post_meta( $id, $key, false ) β qiymatlar massivini qaytaradi (bir kalitga ko'p qiymat yozgan bo'lsangiz). Aralashtirmang: bitta qiymat uchun doim true.
β οΈ Chiqarganda escape qiling. Meta'ni frontend'da ko'rsatganda kontekstga mos escape shart:
// Frontend shablon (single.php yoki shortcode):
echo esc_html( get_post_meta( $post_id, '_kitob_muallif', true ) );
update_post_meta imzosi (docs bilan tasdiqlangan): update_post_meta( int $post_id, string $meta_key, mixed $meta_value, mixed $prev_value = '' ): int|bool. To'rtinchi argument β agar bir kalitda bir nechta qiymat bo'lsa, qaysi birini yangilashni belgilaydi (odatda kerak emas).
register_post_meta: meta'ni REST va blok muharririga ochish (ZAMONAVIY)¶
Yuqoridagi meta box β klassik (eski blok muharriri yon panelidan tashqari) usul. Lekin 2026'da meta'ni blok muharriri va REST API ham ko'rishi kerak: zamonaviy plugin'lar meta'ni React-asosli sidebar panellaridan tahrirlaydi (23-bobda ko'ramiz), wp/v2/kitob REST endpoint'i esa meta'ni JSON ichida qaytarishi kerak.
Buning kaliti β register_post_meta(). U meta kalitni "ro'yxatdan o'tkazadi": tipini, sanitize qoidasini va REST'da ko'rinishini e'lon qiladi.
namespace Oqil\KitobKatalog;
add_action( 'init', __NAMESPACE__ . '\\register_kitob_meta' );
function register_kitob_meta(): void {
register_post_meta(
'kitob', // post turi
'_kitob_muallif', // meta kalit
[
'show_in_rest' => true, // REST + blok muharririga ochiq
'single' => true, // bitta qiymat
'type' => 'string', // 'string'|'integer'|'number'|'boolean'|'array'|'object'
'default' => '',
'sanitize_callback' => 'sanitize_text_field',
'auth_callback' => static fn(): bool => current_user_can( 'edit_posts' ),
]
);
register_post_meta(
'kitob',
'_kitob_yil',
[
'show_in_rest' => true,
'single' => true,
'type' => 'integer',
'default' => 0,
'sanitize_callback' => 'absint',
'auth_callback' => static fn(): bool => current_user_can( 'edit_posts' ),
]
);
}
π Nima beradi register_post_meta?
show_in_rest => trueβ metawp/v2/kitobjavobiningmetaobyektida paydo bo'ladi va REST orqali yangilanadi.sanitize_callbackβ meta REST yoki blok muharriri orqali yozilganda WordPress avtomatik tozalaydi (meta box'dagi qo'lda sanitize bu yo'lni qoplamaydi).auth_callbackβ meta'ni REST orqali kim yangilashi mumkinligini hal qiladi. Imzo:register_post_meta( string $post_type, string $meta_key, array $args ): bool(docs bilan tasdiqlangan;$argskalitlariregister_meta()bilan bir xil:type,single,default,sanitize_callback,auth_callback,show_in_rest).
β οΈ Pastki chiziqli (_) kalitlar va REST. _ bilan boshlangan "himoyalangan" meta kalitni REST orqali ochish uchun auth_callback SHART β aks holda WordPress uni REST'da yangilashga ruxsat bermaydi. Yuqorida shuning uchun auth_callback berdik.
π‘ Meta box bilan register_post_meta birga. Eng kuchli yondashuv β ikkalasi: meta box klassik tahrirlash tajribasini, register_post_meta esa REST/blok integratsiyasini beradi. Klassik meta box'da sanitize'ni o'zingiz qilasiz; REST yo'lida sanitize_callback ishlaydi. Ikkala yo'l ham himoyalangan bo'lishi kerak.
OOP variant (izchil arxitektura)¶
05-bobdagi OOP yondashuvni eslang β meta box'ni sinf ichiga yig'ib, nonce action/name'ni konstanta qilamiz. Bu kattaroq plugin'da toza:
namespace Oqil\KitobKatalog\Admin;
final class KitobMetaBox {
private const NONCE_ACTION = 'kitob_meta_saqlash';
private const NONCE_NAME = 'kitob_meta_nonce';
public function register(): void {
add_action( 'add_meta_boxes', [ $this, 'add' ] );
add_action( 'save_post_kitob', [ $this, 'save' ], 10, 2 );
}
public function add(): void {
add_meta_box(
'kitob_tafsilot',
__( 'Kitob tafsilotlari', 'kitoblar-katalogi' ),
[ $this, 'render' ],
'kitob',
'normal',
'high'
);
}
public function render( \WP_Post $post ): void {
wp_nonce_field( self::NONCE_ACTION, self::NONCE_NAME );
$muallif = get_post_meta( $post->ID, '_kitob_muallif', true );
printf(
'<p><label>%s<br><input type="text" name="kitob_muallif" value="%s" class="widefat"></label></p>',
esc_html__( 'Muallif', 'kitoblar-katalogi' ),
esc_attr( $muallif )
);
}
public function save( int $post_id, \WP_Post $post ): void {
if ( wp_is_post_autosave( $post_id ) || wp_is_post_revision( $post_id ) ) {
return;
}
if ( ! isset( $_POST[ self::NONCE_NAME ] )
|| ! wp_verify_nonce( sanitize_key( $_POST[ self::NONCE_NAME ] ), self::NONCE_ACTION ) ) {
return;
}
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return;
}
if ( isset( $_POST['kitob_muallif'] ) ) {
update_post_meta(
$post_id,
'_kitob_muallif',
sanitize_text_field( wp_unslash( $_POST['kitob_muallif'] ) )
);
}
}
}
( new KitobMetaBox() )->register();
βΉοΈ O'z saytingizda sinab ko'ring. Bu kod sintaktik to'g'ri va docs bilan tasdiqlangan, lekin meta box admin'da ko'rinishi, formani to'ldirib saqlash, REST'da meta'ni ko'rish kabi natijalar ishlab turgan WordPress saytini talab qiladi (02-bobdagi wp-env). Plugin'ni aktivatsiya qiling, yangi kitob qo'shing β "Kitob tafsilotlari" qutisi paydo bo'ladi.
Custom fields vs ACF (qisqacha)¶
Ko'p loyihalarda ACF (Advanced Custom Fields) plugini ishlatiladi. ACF β bu meta maydonlarni kod yozmasdan, admin interfeysidan yaratish imkonini beradigan plugin: drag-and-drop bilan maydon turlari (matn, rasm, takrorlanuvchi, munosabat) qo'shasiz.
| Jihat | Qo'lda (add_meta_box + meta) |
ACF |
|---|---|---|
| Boshqaruv | To'liq sizda, kod | Admin UI, kamroq kod |
| Bog'liqlik | Yo'q (yadro funksiyalari) | Tashqi plugin'ga bog'liqlik |
| Maydon turlari | O'zingiz yozasiz | Tayyor o'nlab tur |
| Distribution plugin | Tavsiya etiladi | Mijoz saytini ACF'siz qoldirmaslik kerak |
π Qachon nima? Mijozning bitta sayti uchun tez ish β ACF qulay. Tarqatiladigan (wordpress.org) plugin yozayotgan bo'lsangiz β qo'lda yozing: foydalanuvchini boshqa plugin'ga majburlamang. Bu kitob "expert plugin muhandisi" yetishtirgani uchun qo'lda usulni chuqur o'rganamiz; ACF'ni esa endi "qopqoq ostida nima borligini" bilib ishlatasiz.
Xulosa¶
- Post meta β post'ga biriktirilgan
kalit β qiymatqo'shimcha ma'lumot (wp_postmetajadvali). - Meta box β
add_meta_box()(add_meta_boxeshook'da) tahrirlash sahifasiga forma qo'yadi; saqlashni o'zingizsave_post_{cpt}da yozasiz. - Saqlashning to'rt darvozasi: autosave/revisiya tekshiruvi β nonce β capability β sanitize. Hammasi majburiy.
- Escape (chiqishda) + sanitize (kirishda) β meta box formasida
esc_attr/esc_textarea, saqlashdasanitize_text_field/absint+wp_unslash. get_post_meta/update_post_meta/delete_post_metaβ meta bilan ishlash;$single=truebitta qiymat uchun.register_post_metameta'ni REST + blok muharririga ochadi (show_in_rest,sanitize_callback,auth_callback) β zamonaviy plugin'da deyarli har doim kerak.- ACF β tez UI yechimi; tarqatiladigan plugin uchun qo'lda yozing.
Keyingi bobda meta'dan ham chuqurroq β $wpdb bilan o'z jadvallaringiz, Options va Transients API'ni o'rganamiz.
09-bob mashqlari¶
Quyidagi mashqlar
kitoblar-katalogiplugini ustida ishlaydi (namespaceOqil\KitobKatalog, CPTkitob). Har bir kod misolini o'z saytingizda aktivatsiya qilib sinab ko'ring.
Oson¶
- (Oson)
kitobCPT'gasidekontekstda "Eslatma" nomli meta box qo'shing, ichida bittatextarea. Faqat formani chizing (saqlamasdan). Chiqishniesc_textareabilan escape qiling. - (Oson)
get_post_meta( $id, $key, true )vaget_post_meta( $id, $key, false )farqini ayting: qaysi biri stringni, qaysi biri massivni qaytaradi? - (Oson) Nima uchun
wp_nonce_fieldni formada,wp_verify_nonceni esa saqlashda ishlatamiz? Nonce qaysi hujum turidan himoya qiladi? - (Oson) Quyidagi qatorda xato bor β toping:
<input value="<?php echo $muallif; ?>">. To'g'rilang. - (Oson)
update_post_metavaadd_post_metaqachon farq qiladi? Bitta kalitga ikki martaupdate_post_metachaqirilsa nima bo'ladi?
O'rta¶
- (O'rta)
kitobmeta box'iga "Narx" (_kitob_narx) maydonini qo'shing. Saqlashda butun songaabsint, yoki o'nli son uchunfloatvalishlating. Manfiy qiymatni rad eting.
Yechim
Formaga (render funksiyasiga) qo'shing:
$narx = get_post_meta( $post->ID, '_kitob_narx', true );
?>
<p>
<label for="kitob_narx"><strong><?php esc_html_e( 'Narx (so\'m)', 'kitoblar-katalogi' ); ?></strong></label><br>
<input type="number" id="kitob_narx" name="kitob_narx" step="0.01" min="0"
value="<?php echo esc_attr( (string) $narx ); ?>" class="widefat">
</p>
Saqlash funksiyasiga (to'rt darvozadan keyin) qo'shing:
if ( isset( $_POST['kitob_narx'] ) ) {
$narx = (float) wp_unslash( $_POST['kitob_narx'] );
if ( $narx >= 0 ) {
update_post_meta( $post_id, '_kitob_narx', $narx );
}
}
(float) kast son bo'lmagan kiritmani 0.0 ga aylantiradi; manfiy bo'lsa yozmaymiz. O'nli son uchun absint (butun) emas, (float) to'g'ri.
- (O'rta) Meta box saqlash funksiyasidagi to'rt tekshiruvni to'g'ri tartibda yozing (autosave, nonce, capability, sanitize) va har birini bir jumla bilan izohlang.
Yechim
function save_kitob_meta( int $post_id, \WP_Post $post ): void {
// 1) Autosave/revisiya: $_POST bo'sh, mavjud meta'ni o'chirmaslik uchun chiqamiz
if ( wp_is_post_autosave( $post_id ) || wp_is_post_revision( $post_id ) ) {
return;
}
// 2) Nonce: forma haqiqatan bizning saytdan kelganini tasdiqlaydi (CSRF)
if ( ! isset( $_POST['kitob_meta_nonce'] )
|| ! wp_verify_nonce( sanitize_key( $_POST['kitob_meta_nonce'] ), 'kitob_meta_saqlash' ) ) {
return;
}
// 3) Capability: bu foydalanuvchi shu post'ni tahrirlay oladimi?
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return;
}
// 4) Sanitize: tashqi qiymatni unslash + tozalab saqlaymiz
if ( isset( $_POST['kitob_muallif'] ) ) {
update_post_meta( $post_id, '_kitob_muallif',
sanitize_text_field( wp_unslash( $_POST['kitob_muallif'] ) ) );
}
}
Tartib muhim: og'ir ishni (sanitize/saqlash) faqat barcha xavfsizlik darvozalaridan o'tgandan keyin bajaramiz.
- (O'rta)
_kitob_muallifva_kitob_yilmeta'niregister_post_metabilan REST'ga oching (show_in_rest, mostype,sanitize_callback,auth_callback). Nega_bilan boshlangan kalitdaauth_callbackshart?
Yechim
add_action( 'init', function (): void {
register_post_meta( 'kitob', '_kitob_muallif', [
'show_in_rest' => true,
'single' => true,
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
'auth_callback' => static fn(): bool => current_user_can( 'edit_posts' ),
] );
register_post_meta( 'kitob', '_kitob_yil', [
'show_in_rest' => true,
'single' => true,
'type' => 'integer',
'sanitize_callback' => 'absint',
'auth_callback' => static fn(): bool => current_user_can( 'edit_posts' ),
] );
} );
_ bilan boshlangan kalit "himoyalangan" hisoblanadi: WordPress uni REST orqali yozishga standart holatda ruxsat bermaydi. auth_callback kim yozishi mumkinligini aniq belgilab beradi, shusiz REST yangilash bloklanadi.
- (O'rta) ISBN'ni tozalaydigan sof PHP funksiya yozing: faqat raqamlar va
X/xbelgilarini qoldirsin, qolganini olib tashlasin, natijani katta harf qilsin. WP'sizphp -rbilan sinaladigan bo'lsin.
Yechim
function kk_sanitize_isbn( string $raw ): string {
$faqat = preg_replace( '/[^0-9Xx]/', '', $raw );
return strtoupper( $faqat );
}
var_dump( kk_sanitize_isbn( '978-0-13-468599-1' ) ); // "9780134685991"
var_dump( kk_sanitize_isbn( '0-306-40615-x' ) ); // "030640615X"
Bu funksiya WordPress'siz ishlaydi (php bilan to'g'ridan-to'g'ri ishga tushadi). Meta box saqlashda esa: update_post_meta( $post_id, '_kitob_isbn', kk_sanitize_isbn( wp_unslash( $_POST['kitob_isbn'] ) ) );.
- (O'rta)
kitobCPT'ning admin ro'yxat jadvaliga "Muallif" ustunini qo'shing (manage_kitob_posts_columnsfiltri +manage_kitob_posts_custom_columnaction). Qiymatniesc_htmlbilan chiqaring.
Yechim
add_filter( 'manage_kitob_posts_columns', function ( array $columns ): array {
$columns['kitob_muallif'] = __( 'Muallif', 'kitoblar-katalogi' );
return $columns;
} );
add_action( 'manage_kitob_posts_custom_column', function ( string $column, int $post_id ): void {
if ( 'kitob_muallif' === $column ) {
echo esc_html( get_post_meta( $post_id, '_kitob_muallif', true ) );
}
}, 10, 2 );
Filter ustun sarlavhalarini, action esa har qatordagi qiymatni boshqaradi. Chiqishni doim escape qiling.
Qiyin¶
- (Qiyin) To'liq, xavfsiz meta box yozing:
kitobuchun muallif (matn), ISBN (yuqoridagikk_sanitize_isbnbilan) va yil (absint, 0 bo'lsa o'chiriladi). Nonce + capability + autosave + escape bilan to'liq.
Yechim
namespace Oqil\KitobKatalog;
add_action( 'add_meta_boxes', __NAMESPACE__ . '\\add_kitob_meta_box' );
add_action( 'save_post_kitob', __NAMESPACE__ . '\\save_kitob_meta', 10, 2 );
function add_kitob_meta_box(): void {
add_meta_box(
'kitob_tafsilot',
__( 'Kitob tafsilotlari', 'kitoblar-katalogi' ),
__NAMESPACE__ . '\\render_kitob_meta_box',
'kitob', 'normal', 'high'
);
}
function kk_sanitize_isbn( string $raw ): string {
return strtoupper( preg_replace( '/[^0-9Xx]/', '', $raw ) );
}
function render_kitob_meta_box( \WP_Post $post ): void {
wp_nonce_field( 'kitob_meta_saqlash', 'kitob_meta_nonce' );
$muallif = get_post_meta( $post->ID, '_kitob_muallif', true );
$isbn = get_post_meta( $post->ID, '_kitob_isbn', true );
$yil = get_post_meta( $post->ID, '_kitob_yil', true );
?>
<p><label><strong><?php esc_html_e( 'Muallif', 'kitoblar-katalogi' ); ?></strong><br>
<input type="text" name="kitob_muallif" value="<?php echo esc_attr( $muallif ); ?>" class="widefat"></label></p>
<p><label><strong>ISBN</strong><br>
<input type="text" name="kitob_isbn" value="<?php echo esc_attr( $isbn ); ?>" class="widefat"></label></p>
<p><label><strong><?php esc_html_e( 'Nashr yili', 'kitoblar-katalogi' ); ?></strong><br>
<input type="number" name="kitob_yil" min="0" max="2100" value="<?php echo esc_attr( (string) $yil ); ?>"></label></p>
<?php
}
function save_kitob_meta( int $post_id, \WP_Post $post ): void {
if ( wp_is_post_autosave( $post_id ) || wp_is_post_revision( $post_id ) ) {
return;
}
if ( ! isset( $_POST['kitob_meta_nonce'] )
|| ! wp_verify_nonce( sanitize_key( $_POST['kitob_meta_nonce'] ), 'kitob_meta_saqlash' ) ) {
return;
}
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return;
}
if ( isset( $_POST['kitob_muallif'] ) ) {
update_post_meta( $post_id, '_kitob_muallif',
sanitize_text_field( wp_unslash( $_POST['kitob_muallif'] ) ) );
}
if ( isset( $_POST['kitob_isbn'] ) ) {
update_post_meta( $post_id, '_kitob_isbn',
kk_sanitize_isbn( wp_unslash( $_POST['kitob_isbn'] ) ) );
}
if ( isset( $_POST['kitob_yil'] ) ) {
$yil = absint( $_POST['kitob_yil'] );
$yil > 0
? update_post_meta( $post_id, '_kitob_yil', $yil )
: delete_post_meta( $post_id, '_kitob_yil' );
}
}
Har bir maydon mustaqil isset bilan tekshiriladi; yil 0 bo'lsa meta o'chiriladi (eski yilni qoldirmaslik uchun).
- (Qiyin) Meta box'ni
final classichida yig'ing (OOP). Nonce action/name'ni konstanta qiling,register()metodi ikkala hook'ni ulasin. Render va save metodlarini to'liq yozing.
Yechim
namespace Oqil\KitobKatalog\Admin;
final class KitobMetaBox {
private const NONCE_ACTION = 'kitob_meta_saqlash';
private const NONCE_NAME = 'kitob_meta_nonce';
public function register(): void {
add_action( 'add_meta_boxes', [ $this, 'add' ] );
add_action( 'save_post_kitob', [ $this, 'save' ], 10, 2 );
}
public function add(): void {
add_meta_box(
'kitob_tafsilot',
__( 'Kitob tafsilotlari', 'kitoblar-katalogi' ),
[ $this, 'render' ],
'kitob', 'normal', 'high'
);
}
public function render( \WP_Post $post ): void {
wp_nonce_field( self::NONCE_ACTION, self::NONCE_NAME );
$muallif = get_post_meta( $post->ID, '_kitob_muallif', true );
printf(
'<p><label>%s<br><input type="text" name="kitob_muallif" value="%s" class="widefat"></label></p>',
esc_html__( 'Muallif', 'kitoblar-katalogi' ),
esc_attr( $muallif )
);
}
public function save( int $post_id, \WP_Post $post ): void {
if ( wp_is_post_autosave( $post_id ) || wp_is_post_revision( $post_id ) ) {
return;
}
if ( ! isset( $_POST[ self::NONCE_NAME ] )
|| ! wp_verify_nonce( sanitize_key( $_POST[ self::NONCE_NAME ] ), self::NONCE_ACTION ) ) {
return;
}
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return;
}
if ( isset( $_POST['kitob_muallif'] ) ) {
update_post_meta( $post_id, '_kitob_muallif',
sanitize_text_field( wp_unslash( $_POST['kitob_muallif'] ) ) );
}
}
}
( new KitobMetaBox() )->register();
Konstanta nonce action/name'ni render va save'da bir manbadan oladi β xato (turli string) ehtimoli yo'qoladi.
- (Qiyin) Quyidagi meta box'da uchta xavfsizlik nuqsoni bor. Hammasini toping va to'g'rilangan kodni yozing.
add_action( 'save_post', 'kk_save' );
function kk_save( $post_id ) {
update_post_meta( $post_id, '_kitob_muallif', $_POST['kitob_muallif'] );
}
Yechim
Nuqsonlar:
- Nonce yo'q β har qanday so'rov (CSRF) meta'ni o'zgartira oladi.
- Capability tekshiruvi yo'q β ruxsatsiz foydalanuvchi ham yozadi.
- Sanitize/unslash yo'q β
$_POSTto'g'ridan-to'g'ri saqlanadi (saqlangan XSS xavfi). Bonus: autosave tekshiruvi ham yo'q,issetham yo'q.
To'g'rilangan:
add_action( 'save_post_kitob', 'kk_save', 10, 2 );
function kk_save( int $post_id, \WP_Post $post ): void {
if ( wp_is_post_autosave( $post_id ) || wp_is_post_revision( $post_id ) ) {
return;
}
if ( ! isset( $_POST['kitob_meta_nonce'] )
|| ! wp_verify_nonce( sanitize_key( $_POST['kitob_meta_nonce'] ), 'kitob_meta_saqlash' ) ) {
return;
}
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return;
}
if ( isset( $_POST['kitob_muallif'] ) ) {
update_post_meta( $post_id, '_kitob_muallif',
sanitize_text_field( wp_unslash( $_POST['kitob_muallif'] ) ) );
}
}
Render funksiyasida wp_nonce_field( 'kitob_meta_saqlash', 'kitob_meta_nonce' ); ham bo'lishi shart.
- (Qiyin) Meta box'ni ham klassik forma, ham
register_post_metabilan REST'ga ochish strategiyasini tasvirlang: ikkalasi qachon ishlaydi, sanitize qaysi yo'lda qayerda bajariladi, va nima uchun ikkala yo'lni ham himoyalash kerak?
Yechim
- Klassik forma yo'li (eski/klassik tahrirlash, meta box): qiymat
$_POSTorqali keladi β sizsave_post_kitobda qo'lda nonce + capability +sanitize_text_field/absintqilasiz.register_post_metaningsanitize_callbackbu yo'lda ishlamaydi. - REST/blok yo'li (sidebar paneli,
wp/v2/kitob): qiymat REST request orqali keladi β WordPressregister_post_metadagisanitize_callbackvaauth_callbackni avtomatik qo'llaydi. - Nega ikkalasi ham? Hujumchi qaysi yo'lni tanlashini siz nazorat qilmaysiz. Faqat formani himoyalab REST'ni ochiq qoldirsangiz β meta'ni REST orqali tozalanmagan/ruxsatsiz yozish mumkin bo'ladi. Shuning uchun: formada qo'lda himoya,
register_post_metadasanitize_callback+auth_callback. Ikkala eshik ham qulflanadi.
- (Qiyin)
_kitob_qoshimcha_janrkalitiga bir nechta qiymat (ko'p qiymatli meta) saqlaydigan va o'qiydigan kod yozing:add_post_meta/get_post_meta($id, $key, false)ishlating, eski qiymatlarni qayta yozishdan oldin tozalang.
Yechim
// Saqlash: avval eski hammasini o'chir, keyin yangilarini qo'sh (unique=false)
function kk_save_qoshimcha_janrlar( int $post_id, array $janrlar ): void {
delete_post_meta( $post_id, '_kitob_qoshimcha_janr' ); // hamma eski qiymat
foreach ( $janrlar as $janr ) {
$toza = sanitize_text_field( $janr );
if ( '' !== $toza ) {
add_post_meta( $post_id, '_kitob_qoshimcha_janr', $toza, false );
}
}
}
// O'qish: barcha qiymatlar massivi (single=false)
$janrlar = get_post_meta( $post_id, '_kitob_qoshimcha_janr', false );
foreach ( $janrlar as $janr ) {
echo esc_html( $janr ) . '<br>';
}
add_post_meta(..., false) β bir kalitga ko'p qator yozadi; delete_post_meta (qiymatsiz) shu kalitning barcha qatorlarini o'chiradi. O'qishda false massiv qaytaradi. (Eslatma: ko'pincha bunday holatda taxonomy to'g'riroq tanlov β meta faqat tartiblanmaydigan, qidirilmaydigan qo'shimcha uchun.)
β¬ οΈ Oldingi: 08 β Taxonomiyalar Β· π README Β· Keyingi: 10 β Ma'lumotlar bazasi: $wpdb, options, transients β‘οΈ