03 β Birinchi plugin: tuzilish va hayot sikli¶
β¬ οΈ Oldingi: 02 β Lokal muhit va asboblar Β· π README Β· Keyingi: 04 β Hooks: action va filter (chuqur) β‘οΈ
Bu bobda: birinchi haqiqiy plugin'ni noldan quramiz β WordPress plugin'ni "ko'rishi" uchun zarur header (doc-block) maydonlarini, bitta fayl va papka tuzilishi o'rtasidagi farqni,
ABSPATHhimoyasini, plugin yuklanganini ko'rsatuvchi birinchi belgini, hamda eng muhimi βregister_activation_hook/register_deactivation_hook/uninstall.phporqali plugin hayot siklining (aktivatsiya β har so'rovda ishlash β deaktivatsiya β o'chirish) qaysi bosqichida nima qilish kerakligini o'rganamiz.
Muammo: WordPress kodingizni qachon "ko'radi"?¶
Tasavvur qiling: siz wp-content/plugins/ ichiga ajoyib bir PHP fayl tashladingiz, ichida zo'r funksiyalar bor. Lekin wp-admin'dagi Plugins sahifasini ochsangiz β u yerda hech narsa yo'q. Plugin'ingiz "ko'rinmaydi". Nega?
Chunki WordPress fayllarni shunchaki PHP kodi deb bilmaydi. U maxsus signal qidiradi β faylning eng tepasidagi izoh blokida Plugin Name: qatorini. Bu signal bo'lmasa, fayl WordPress uchun mavjud emas.
Bu bob ana shu signaldan boshlanadi va plugin'ning butun hayotini β yoqilganda, ishlab turganda, o'chirilganda va butunlay olib tashlanganda nima sodir bo'lishini β chiziq-chiziq tushuntiradi. Biz kitob bo'ylab quradigan "Kitoblar katalogi" plugin'ining poydevorini shu yerda quyamiz.
βΉοΈ Bu bob siz 02-bobda o'rgangan lokal WordPress muhitida (
wp-envyoki Docker)WP_DEBUGyoqilgan holda ishlashingizni faraz qiladi. Plugin'ni aktivatsiya qilish va admin'da ko'rish bilan bog'liq natijalar β "o'z saytingizda sinab ko'ring" ohangida beriladi.
Plugin header: WordPress o'qiydigan birinchi narsa¶
Plugin header β bu asosiy fayl boshidagi maxsus doc-block (PHP izohi). WordPress yangi plugin'larni qidirayotganda har bir fayl tepasini o'qiydi va shu maydonlarni topadi.
Mana bizning kitoblar-katalogi.php faylining boshi:
<?php
/**
* Plugin Name: Kitoblar katalogi
* Plugin URI: https://ioqil.uz/plugins/kitoblar-katalogi
* Description: Kitoblar uchun CPT, janr taksonomiyasi, sozlamalar va REST endpoint qo'shadi.
* Version: 0.1.0
* Requires at least: 7.0
* Requires PHP: 8.3
* Author: Oqil Imomnazarov
* Author URI: https://ioqil.uz
* Text Domain: kitoblar-katalogi
* Domain Path: /languages
* License: GPL-2.0-or-later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
*
* @package Oqil\KitobKatalog
*/
Har bir maydon nima uchun kerak:
| Maydon | Vazifasi |
|---|---|
| Plugin Name | Plugins ro'yxatida ko'rinadigan nom. Yagona majburiy maydon β busiz WordPress plugin'ni umuman ko'rmaydi. |
| Plugin URI | Plugin sahifasi (wordpress.org havolasi emas, o'z saytingiz). |
| Description | Qisqa tavsif (140 belgigacha), admin'da nom ostida chiqadi. |
| Version | Joriy versiya. WordPress yangilanishni va asset keshini shunga qarab boshqaradi. |
| Requires at least | Minimal WordPress versiyasi. |
| Requires PHP | Minimal PHP versiyasi. Muhit mos kelmasa, WordPress aktivatsiyani bloklaydi. |
| Author / Author URI | Muallif va uning havolasi. |
| Text Domain | i18n (lokalizatsiya) kaliti β odatda plugin slugi bilan bir xil. |
| Domain Path | Tarjima fayllari papkasi (/languages). |
| License / License URI | Litsenziya. WordPress ekotizimi GPL-mos litsenziyani talab qiladi. |
π Faqat Plugin Name texnik jihatdan majburiy, lekin professional plugin barcha maydonlarni to'ldiradi.
Requires PHP: 8.3deganingizda PHP 8.2'dagi foydalanuvchi plugin'ni aktivatsiya qila olmaydi β bu sizni va undan ham ko'proq foydalanuvchini "oq ekran" (fatal error) dan saqlaydi.π‘ Header maydon nomlari aniq yozilishi shart:
Requires at least(ko'plikda emas),Text Domain(ikki so'z). WordPress ularniPlugin Name:kabiNom: qiymatshaklida qidiradi. Xato yozsangiz, maydon shunchaki e'tiborga olinmaydi.
β οΈ Litsenziya bo'sh qoldirilmasin. wordpress.org katalogiga joylaganda GPL-mos litsenziya (GPL-2.0-or-later yoki keyinroq) talab qilinadi. Buni boshdanoq to'g'ri qo'ying.
ABSPATH: faylni to'g'ridan-to'g'ri kirishdan himoyalash¶
Header'dan keyin darhol mana bu ikki qatorni qo'shamiz:
declare(strict_types=1);
namespace Oqil\KitobKatalog;
// To'g'ridan-to'g'ri kirishni to'sish: fayl WordPress'siz so'ralsa, darhol chiqamiz.
if (!defined('ABSPATH')) {
exit;
}
ABSPATH β bu WordPress yuklanganda e'lon qiladigan konstanta (WordPress ildiz papkasining yo'li). Agar kimdir brauzerda to'g'ridan-to'g'ri .../wp-content/plugins/kitoblar-katalogi/kitoblar-katalogi.php manzilini ochsa, WordPress yuklanmagan bo'ladi β demak ABSPATH aniqlanmagan β demak exit ishlaydi va fayl hech narsa qilmasdan to'xtaydi.
β οΈ Bu kichik tekshiruv β muhim xavfsizlik odati. U faylingiz mantig'ini, o'zgaruvchilarini va xato xabarlarini begona ko'zlardan yashiradi. WordPress plugin'larida bu deyarli standart β har bir to'g'ridan-to'g'ri kirilishi mumkin bo'lgan PHP faylga qo'ying.
βΉοΈ
namespacehaqida to'liqroq 05-bobda gaplashamiz. Hozircha shuni bilsangiz kifoya:namespace Oqil\KitobKatalog;bizning funksiyalarimizni boshqa plugin'larning funksiyalaridan ajratib turadi β global "ism urushi"ni oldini oladi. Bu PHP'dagi oddiy namespace; WordPress'ga xos sehr emas. PHP namespace yangi bo'lsa, PHP kitobiga qarang.
Fayl tuzilishi: bitta fayl vs papka¶
Plugin'ni ikki xil joylash mumkin.
1-variant β bitta fayl. Eng oddiy plugin β wp-content/plugins/ ichidagi bitta .php fayl:
Bu kichik, bir vazifali plugin uchun yetarli (masalan, bitta filter qo'shadigan plugin).
2-variant β papka (tavsiya etiladi). Jiddiy plugin o'z papkasida yashaydi, asosiy fayl odatda papka bilan bir xil nomda bo'ladi:
wp-content/plugins/kitoblar-katalogi/
βββ kitoblar-katalogi.php β asosiy fayl (header shu yerda)
βββ includes/ β mantiq: sinflar, funksiyalar
β βββ class-cpt.php
β βββ class-settings.php
βββ uninstall.php β o'chirishda tozalash
βββ languages/ β tarjima fayllari
π Kitoblar katalogi uchun biz papka variantini tanlaymiz, chunki kitob davomida CPT, sozlamalar, REST va blok qo'shamiz β bularning hammasi bitta faylga sig'maydi. Asosiy fayl
kitoblar-katalogi.phpfaqat header + boshlang'ich ulanish (bootstrap) ni saqlaydi; haqiqiy mantiqincludes/ichidagi fayllarga bo'linadi (buni 05-bobda autoload bilan yig'amiz).
π‘ Slug izchilligi. Papka nomi, asosiy fayl nomi va text domain β uchalasi ham kitoblar-katalogi. Bu tasodif emas: izchil slug WordPress'da va sizning kodingizda ishni soddalashtiradi. Kitob bo'ylab namespace har doim Oqil\KitobKatalog, prefiks kitoblar_katalogi_ bo'lib qoladi.
Birinchi ish: plugin yuklanganini ko'rsatish¶
Plugin haqiqatan yuklanayotganini ko'rishning oddiy yo'li β admin panelida xabar (admin notice) chiqarish. Bu admin_notices hook'iga ulanadi:
/**
* Plugin yuklanganini admin'da ko'rsatuvchi vaqtinchalik xabar (faqat namoyish uchun).
*/
function salomlash_xabari(): void {
// Faqat sozlama huquqiga ega foydalanuvchiga ko'rsatamiz.
if (!current_user_can('manage_options')) {
return;
}
$matn = esc_html__('Kitoblar katalogi plugin yuklandi.', 'kitoblar-katalogi');
printf(
'<div class="notice notice-success is-dismissible"><p>%s</p></div>',
$matn
);
}
add_action('admin_notices', __NAMESPACE__ . '\\salomlash_xabari');
Bu yerda kichik kod bo'lsa-da, uchta muhim odat allaqachon bor:
- β οΈ
current_user_can('manage_options')β xabarni faqat kerakli huquqli foydalanuvchiga ko'rsatamiz. Hech qachon "hammaga ko'rsatib qo'yaqolaman" demang. - β οΈ
esc_html__()β matnni ham tarjima qilamiz (text domain bilan), ham escape qilamiz. Output har doim escape qilinadi (12-bobda chuqurroq). - π
__NAMESPACE__ . '\\salomlash_xabari'β callback'ni to'liq nom bilan beramiz, chunki funksiya namespace ichida. ('\\'β PHP satrida bitta backslash.)
π‘ Bu xabar β vaqtinchalik "tirik ekanini tekshirish" uchun. Haqiqiy plugin'da uni keyin olib tashlaysiz yoki ma'noli xabarga aylantirasiz. Diagnostika uchun
inithook'idaerror_log('Kitoblar katalogi: init')ham yozishingiz mumkin β budebug.logga tushadi (02-bob,WP_DEBUG_LOG).
Bu blok to'g'ri, lekin natijani (yashil xabar paneli) o'z saytingizda ko'rasiz: plugin'ni aktivatsiya qiling, so'ng istalgan admin sahifasini oching.
Hayot sikli: aktivatsiya, ishlash, deaktivatsiya, o'chirish¶
Endi eng muhim mavzu. Plugin bir tekisda ishlamaydi β uning hayotida tubdan farq qiladigan bosqichlar bor, va har birida WordPress boshqa hook'ni ishga tushiradi.
To'rt holatni ajratib oling:
- Aktivatsiya β foydalanuvchi "Activate" bosganda bir marta. Bir martalik sozlash uchun: jadval yaratish, dastlabki opsiyalarni qo'yish,
flush_rewrite_rules(). - Ishlash β plugin aktiv ekan, u har bir so'rovda (har sahifa yuklanganda) qaytadan yuklanadi va PHP qaytadan ishlaydi. Bu yerda holat saqlanmaydi: har so'rov toza varaqdan boshlanadi.
- Deaktivatsiya β "Deactivate" bosilganda bir marta. Vaqtinchalik narsalarni tozalaymiz (rejalashtirilgan cron, kesh), lekin foydalanuvchi ma'lumotini O'CHIRMAYMIZ.
- O'chirish (uninstall) β plugin butunlay o'chirilganda (Deactivate'dan keyin "Delete") bir marta. Mana shu yerda barcha izlarni β opsiyalar, jadvallar β tozalaymiz.
π Eng ko'p qilinadigan xato: deaktivatsiya va o'chirishni aralashtirish. Deaktivatsiya = vaqtincha to'xtatish (foydalanuvchi keyin yana yoqishi mumkin β ma'lumoti joyida turishi kerak). O'chirish = butunlay olib tashlash (endi tozalash o'rinli).
Aktivatsiya hook'i¶
const VERSION = '0.1.0';
/**
* Aktivatsiyada bir marta ishlaydi: dastlabki sozlamani qo'yadi va rewrite rules'ni yangilaydi.
*/
function aktivatsiya(): void {
add_option('kitoblar_katalogi_versiya', VERSION);
// CPT keyingi boblarda ro'yxatdan o'tadi; permalinklarni yangilab qo'yamiz.
flush_rewrite_rules();
}
register_activation_hook(__FILE__, __NAMESPACE__ . '\\aktivatsiya');
register_activation_hook(string $file, callable $callback) ikki argument oladi:
__FILE__β joriy fayl yo'li. WordPress shu yo'ldan plugin'ni aniqlaydi, shuning uchun bu asosiy plugin faylida chaqirilishi shart.- callback β aktivatsiyada bir marta chaqiriladigan funksiya.
flush_rewrite_rules() nima uchun? Plugin CPT yoki o'z URL strukturasini qo'shganda WordPress'ning ichki "URL β handler" jadvalini yangilash kerak. Aktivatsiyada bir marta yangilash to'g'ri yo'l. Buni har so'rovda chaqirish β sekinlikning klassik sababi, shuning uchun u faqat aktivatsiyada turadi.
β οΈ Aktivatsiya hook'ida og'ir ish qilmang. Bu o'rin tez bo'lishi kerak; ulkan migratsiyani yoki tashqi API'ni shu yerda ishga tushirish aktivatsiyani osib qo'yishi mumkin. Faqat zarur boshlang'ich sozlash.
Deaktivatsiya hook'i¶
/**
* Deaktivatsiyada ishlaydi: vaqtinchalik narsalarni tozalaydi, MA'LUMOTNI O'CHIRMAYDI.
*/
function deaktivatsiya(): void {
// Masalan: rejalashtirilgan wp-cron vazifalarini bekor qilish (17-bob).
flush_rewrite_rules();
}
register_deactivation_hook(__FILE__, __NAMESPACE__ . '\\deaktivatsiya');
register_deactivation_hook(string $file, callable $callback) β imzosi aktivatsiya bilan bir xil. Callback plugin hali aktiv holatida ishlaydi, shuning uchun plugin funksiyalariga kirish mumkin. Bu yerda CPT qoidalarini tozalash uchun yana flush_rewrite_rules() chaqiramiz.
π Oltin qoida: deaktivatsiyada foydalanuvchi yaratgan ma'lumotni (postlar, opsiyalardagi sozlamalar) o'chirmang. Odam plugin'ni vaqtincha o'chirib, keyin yana yoqishi mumkin β sozlamalari joyida turishini kutadi.
O'chirish (uninstall): ikki yo'l¶
Plugin butunlay o'chirilganda ma'lumotni tozalashning ikki yo'li bor. Ikkalasi ham WordPress hujjatida tasdiqlangan; tavsiya etilgani β uninstall.php.
1-yo'l β uninstall.php (tavsiya etiladi). Plugin papkasining ildizida shu nomli fayl bo'lsa, WordPress plugin o'chirilganda uni avtomatik chaqiradi:
<?php
/**
* Kitoblar katalogi o'chirilganda ishlaydi: plugin ma'lumotlarini butunlay tozalaydi.
*
* @package Oqil\KitobKatalog
*/
declare(strict_types=1);
// Xavfsizlik: bu fayl faqat WordPress'ning o'chirish jarayonida ishlashi shart.
if (!defined('WP_UNINSTALL_PLUGIN')) {
exit;
}
// Options API'da saqlangan barcha sozlamalarni o'chiramiz.
delete_option('kitoblar_katalogi_versiya');
delete_option('kitoblar_katalogi_sozlamalar');
// O'z jadvalingiz bo'lsa, uni DROP qilish ham shu yerda (10-bob).
β οΈ if (!defined('WP_UNINSTALL_PLUGIN')) exit; β uninstall.php da majburiy. WordPress o'chirish jarayonida WP_UNINSTALL_PLUGIN konstantasini e'lon qiladi; bu tekshiruvsiz fayl to'g'ridan-to'g'ri so'ralsa zararli ish qilishi mumkin.
2-yo'l β register_uninstall_hook(). Agar siz uninstall.php fayli o'rniga asosiy faylda hook'dan foydalanishni xohlasangiz:
/**
* Plugin o'chirilganda chaqiriladi. NAMED funksiya bo'lishi SHART.
*/
function ochirish(): void {
delete_option('kitoblar_katalogi_versiya');
delete_option('kitoblar_katalogi_sozlamalar');
}
register_uninstall_hook(__FILE__, __NAMESPACE__ . '\\ochirish');
register_uninstall_hook(string $file, callable $callback) β imzosi yana o'sha ikki argument.
β οΈ Diqqat: register_uninstall_hook callback'i named funksiya yoki static metod bo'lishi kerak β anonim funksiya BO'LMAYDI. Sababi: WordPress callback'ni bazaga saqlaydi (serializatsiya qiladi), anonim funksiyani esa serializatsiya qilib bo'lmaydi. uninstall.php da bu muammo yo'q, shu sababli ham u soddaroq va tavsiya etilgan yo'l.
βΉοΈ Qaysi birini tanlash? Ko'pchilik professional plugin
uninstall.phpni tanlaydi β u toza, asosiy faylni shishirmaydi va anonim-callback tuzog'i yo'q. Agar plugin papkasidauninstall.phpbo'lsa, uregister_uninstall_hookdan ustun turadi (WordPress hook'ni o'tkazib yuboradi). Ikkalasini birga ishlatishning hojati yo'q.
Plugin'ni aktivatsiya qilish¶
Hammasi joyida bo'lsa, plugin'ni ikki yo'l bilan yoqasiz (har ikkalasini o'z saytingizda bajaring):
wp-admin orqali. Admin panel β Plugins β ro'yxatda "Kitoblar katalogi" β Activate. Aktivatsiya hook'i shu daqiqada ishlaydi, so'ng yashil "plugin yuklandi" xabarini ko'rasiz.
WP-CLI orqali. Terminal'da (02-bobda o'rnatilgan):
Deaktivatsiya: wp plugin deactivate kitoblar-katalogi. Butunlay o'chirish: wp plugin delete kitoblar-katalogi (bu uninstall.php ni ishga tushiradi).
βΉοΈ Bu buyruqlar va wp-admin natijalari jonli WordPress'ni talab qiladi β shuning uchun ularni "o'z saytingizda sinab ko'ring" deb belgilaymiz. Plugin kodi to'g'ri (header, hook imzolari WordPress hujjati bilan tasdiqlangan va PHP sintaksisi tekshirilgan), lekin
flush_rewrite_rules,add_option,current_user_cankabi funksiyalar faqat ishlab turgan WordPress ichida mavjud.
π‘ WP_DEBUG yoqing. Aktivatsiya paytida fatal error bo'lsa (masalan, Requires PHP mos kelmasa yoki xayoliy funksiya chaqirilsa), WP_DEBUG yoqilgan bo'lsa siz aniq xabarni ko'rasiz; aks holda "oq ekran" chiqadi. Plugin yozayotganda har doim yoqib qo'ying.
Hammasi birga: minimal poydevor fayl¶
Mana kitoblar-katalogi.php ning to'liq, ishga tayyor minimal ko'rinishi β bu boblar davomida o'sib boradi:
<?php
/**
* Plugin Name: Kitoblar katalogi
* Plugin URI: https://ioqil.uz/plugins/kitoblar-katalogi
* Description: Kitoblar uchun CPT, janr taksonomiyasi, sozlamalar va REST endpoint qo'shadi.
* Version: 0.1.0
* Requires at least: 7.0
* Requires PHP: 8.3
* Author: Oqil Imomnazarov
* Author URI: https://ioqil.uz
* Text Domain: kitoblar-katalogi
* Domain Path: /languages
* License: GPL-2.0-or-later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
*
* @package Oqil\KitobKatalog
*/
declare(strict_types=1);
namespace Oqil\KitobKatalog;
if (!defined('ABSPATH')) {
exit;
}
const VERSION = '0.1.0';
function aktivatsiya(): void {
add_option('kitoblar_katalogi_versiya', VERSION);
flush_rewrite_rules();
}
register_activation_hook(__FILE__, __NAMESPACE__ . '\\aktivatsiya');
function deaktivatsiya(): void {
flush_rewrite_rules();
}
register_deactivation_hook(__FILE__, __NAMESPACE__ . '\\deaktivatsiya');
function salomlash_xabari(): void {
if (!current_user_can('manage_options')) {
return;
}
$matn = esc_html__('Kitoblar katalogi plugin yuklandi.', 'kitoblar-katalogi');
printf('<div class="notice notice-success is-dismissible"><p>%s</p></div>', $matn);
}
add_action('admin_notices', __NAMESPACE__ . '\\salomlash_xabari');
π Bu fayl β kitobning izchil namuna pluginining poydevori. 04-bobda hooks'ni chuqur o'rganamiz, 05-bobda mantiqni includes/ ga ko'chirib autoload bilan yig'amiz, keyin CPT, sozlamalar, REST va Gutenberg blok qo'shamiz.
Bu bobda nimani o'rgandik¶
- WordPress plugin'ni header (
Plugin Namemajburiy) orqali taniydi; professional plugin barcha maydonni to'ldiradi (Requires PHP: 8.3muhitni himoyalaydi). if (!defined('ABSPATH')) exit;β har faylda to'g'ridan-to'g'ri kirishdan himoya.- Papka tuzilishi (asosiy fayl +
includes/+uninstall.php+languages/) jiddiy plugin uchun standart. - Hayot sikli to'rt bosqich: aktivatsiya (bir marta), ishlash (har so'rovda), deaktivatsiya (bir marta), o'chirish (bir marta).
register_activation_hook/register_deactivation_hook/uninstall.phpβ har biri boshqa vazifa uchun. Deaktivatsiyada ma'lumotni o'chirmang; o'chirishda tozalang.
03-bob mashqlari¶
Mashqlarni o'z lokal WordPress muhitingizda bajaring (02-bob). Har bir PHP misolni terib,
php -lbilan sintaksisni tekshirib, so'ng saytingizda aktivatsiya qiling.
1 (Oson). wp-content/plugins/ ichida kitoblar-katalogi/ papkasini va undagi kitoblar-katalogi.php faylini yarating. Faqat Plugin Name: Kitoblar katalogi header'ini yozing va plugin Plugins ro'yxatida paydo bo'lishini tekshiring.
2 (Oson). Yuqoridagi headerga Description, Version, Author va Requires PHP: 8.3 maydonlarini qo'shing. Plugins ro'yxatida tavsif va versiya ko'rinishini kuzating.
3 (Oson). Faylga if (!defined('ABSPATH')) exit; qatorini qo'shing va nima uchun kerakligini bir jumlada izohlang.
4 (Oson). Text Domain qiymati nima uchun aynan kitoblar-katalogi (plugin slug) bo'lishi kerakligini tushuntiring.
5 (O'rta). admin_notices hook'iga ulanib, "Kitoblar katalogi tayyor" degan escape qilingan va faqat manage_options huquqlilarga ko'rinadigan xabar chiqaring.
Yechim
function kk_tayyor_xabari(): void {
if (!current_user_can('manage_options')) {
return;
}
printf(
'<div class="notice notice-info is-dismissible"><p>%s</p></div>',
esc_html__('Kitoblar katalogi tayyor', 'kitoblar-katalogi')
);
}
add_action('admin_notices', 'kk_tayyor_xabari');
current_user_can xabarni faqat huquqli foydalanuvchiga cheklaydi, esc_html__ esa matnni ham tarjima qiladi, ham escape qiladi. (Namespace ichida bo'lsa, callback'ni __NAMESPACE__ . '\\kk_tayyor_xabari' deb bering.)
6 (O'rta). Aktivatsiya hook'i yozing: u kitoblar_katalogi_versiya opsiyasini '0.1.0' qiymati bilan qo'shsin va flush_rewrite_rules() chaqirsin.
Yechim
function kk_aktivatsiya(): void {
add_option('kitoblar_katalogi_versiya', '0.1.0');
flush_rewrite_rules();
}
register_activation_hook(__FILE__, 'kk_aktivatsiya');
add_option opsiya mavjud bo'lmasagina qo'shadi. flush_rewrite_rules() aktivatsiyada bir marta chaqiriladi β har so'rovda emas (sekinlik sababi).
7 (O'rta). Deaktivatsiya hook'i yozing va u nima qilmasligi kerakligini izohda yozing.
Yechim
function kk_deaktivatsiya(): void {
// Vaqtinchalik narsalarni tozalaymiz (cron, kesh).
// DIQQAT: foydalanuvchi ma'lumotini (postlar, sozlamalar) O'CHIRMAYMIZ β
// odam plugin'ni keyin qayta yoqishi mumkin.
flush_rewrite_rules();
}
register_deactivation_hook(__FILE__, 'kk_deaktivatsiya');
Deaktivatsiya = vaqtincha to'xtatish. Ma'lumotni o'chirish faqat o'chirish (uninstall) bosqichida o'rinli.
8 (O'rta). uninstall.php faylini yarating: u WP_UNINSTALL_PLUGIN ni tekshirsin va kitoblar_katalogi_versiya opsiyasini o'chirsin.
Yechim
<?php
declare(strict_types=1);
if (!defined('WP_UNINSTALL_PLUGIN')) {
exit;
}
delete_option('kitoblar_katalogi_versiya');
uninstall.php plugin papkasi ildizida turadi va o'chirishda avtomatik chaqiriladi. WP_UNINSTALL_PLUGIN tekshiruvi β majburiy himoya: faylni to'g'ridan-to'g'ri so'rash hech narsa qilmasligini ta'minlaydi.
9 (O'rta). Bitta jadvalda deaktivatsiya va o'chirish (uninstall) o'rtasidagi farqni yozing: qachon ishlaydi, nima qilish o'rinli, ma'lumotga nima bo'ladi.
10 (Qiyin). register_uninstall_hook ni named funksiya bilan to'g'ri ulang va nima uchun anonim funksiya bu yerda ishlamasligini izohlang. So'ng nega ko'pchilik baribir uninstall.php ni afzal ko'rishini ayting.
Yechim
namespace Oqil\KitobKatalog;
if (!defined('ABSPATH')) {
exit;
}
function kk_ochirish(): void {
delete_option('kitoblar_katalogi_versiya');
delete_option('kitoblar_katalogi_sozlamalar');
}
register_uninstall_hook(__FILE__, __NAMESPACE__ . '\\kk_ochirish');
WordPress uninstall callback'ini bazaga saqlaydi (serializatsiya qiladi). Anonim funksiyani (closure) serializatsiya qilib bo'lmaydi β shuning uchun callback named funksiya yoki static metod bo'lishi shart. uninstall.php da esa hech qanday callback saqlanmaydi (fayl o'chirishda to'g'ridan-to'g'ri ishga tushadi), shuning uchun u soddaroq, asosiy faylni shishirmaydi va anonim-callback tuzog'i yo'q β shu sababli tavsiya etiladi. Agar uninstall.php mavjud bo'lsa, u register_uninstall_hook dan ustun turadi.
11 (Qiyin). Aktivatsiyada migratsiya kerakmi degan sof-PHP mantiq yozing: saqlangan versiyani joriy versiya bilan solishtirib, yangilash kerakligini bool qaytarsin (version_compare bilan). WordPress'siz php -r da ham ishlasin.
Yechim
function kk_migratsiya_kerakmi(?string $saqlangan, string $joriy): bool {
if ($saqlangan === null) {
return true; // birinchi aktivatsiya β sozlash kerak
}
return version_compare($saqlangan, $joriy, '<');
}
Aktivatsiya hook'ida ishlatilishi:
function kk_aktivatsiya(): void {
$saqlangan = get_option('kitoblar_katalogi_versiya') ?: null;
if (kk_migratsiya_kerakmi($saqlangan, VERSION)) {
// ... migratsiya / boshlang'ich sozlash ...
update_option('kitoblar_katalogi_versiya', VERSION);
}
flush_rewrite_rules();
}
kk_migratsiya_kerakmi toza, WordPress'siz funksiya β version_compare('0.1.0', '0.2.0', '<') true qaytaradi. Shuning uchun uni php -r bilan yoki unit-test bilan alohida sinash mumkin. Bu β mantiqni WordPress'ga bog'liq bo'lmagan, sinaladigan bo'laklarga ajratishning yaxshi namunasi (25-bob, testlash).
12 (Qiyin). Plugin'ni papka tuzilishida tashkil qiling: asosiy kitoblar-katalogi.php faqat header + ABSPATH + hook'larni saqlasin, salomlash_xabari funksiyasi esa includes/notices.php da bo'lib, asosiy fayldan require_once __DIR__ . '/includes/notices.php'; bilan ulansin. Har ikkala faylni php -l bilan tekshiring.
Yechim
kitoblar-katalogi/kitoblar-katalogi.php:
<?php
/**
* Plugin Name: Kitoblar katalogi
* Version: 0.1.0
* Requires PHP: 8.3
* Text Domain: kitoblar-katalogi
* License: GPL-2.0-or-later
*
* @package Oqil\KitobKatalog
*/
declare(strict_types=1);
namespace Oqil\KitobKatalog;
if (!defined('ABSPATH')) {
exit;
}
require_once __DIR__ . '/includes/notices.php';
function aktivatsiya(): void {
flush_rewrite_rules();
}
register_activation_hook(__FILE__, __NAMESPACE__ . '\\aktivatsiya');
kitoblar-katalogi/includes/notices.php:
<?php
declare(strict_types=1);
namespace Oqil\KitobKatalog;
if (!defined('ABSPATH')) {
exit;
}
function salomlash_xabari(): void {
if (!current_user_can('manage_options')) {
return;
}
printf(
'<div class="notice notice-success is-dismissible"><p>%s</p></div>',
esc_html__('Kitoblar katalogi plugin yuklandi.', 'kitoblar-katalogi')
);
}
add_action('admin_notices', __NAMESPACE__ . '\\salomlash_xabari');
__DIR__ joriy fayl papkasini beradi, shuning uchun require_once har doim to'g'ri yo'lni topadi. Har ikkala fayl boshida ABSPATH himoyasi bor. (05-bobda require_once o'rniga avtomatik autoload qo'yamiz.)
β¬ οΈ Oldingi: 02 β Lokal muhit va asboblar Β· π README Β· Keyingi: 04 β Hooks: action va filter (chuqur) β‘οΈ