Modül Yaşam Döngüsü
Bir modülün diske gelişiyle silinişi arasında olan biten. Ne zaman yüklenir, ne zaman kurulur, etkinlik işareti nerede durur ve hangi metodunuz çağrılır.
Genel Bakış
Bir kurulum yordamı yoktur. Dizini yerine kopyalamak kurulumun kendisidir; modül bir sonraki istekte listelenir. Sonrasındaki her şey, ayrı ayrı başlatılan küçük adımlardan oluşur. Bu adımlardaki metotların neredeyse hepsi isteğe bağlıdır: platform sınıfınızda var mı diye bakar, yoksa devam eder.
İki kavram kolayca karışır. Mevcut, dizinin var olması demektir; modülün listelenmesi, kanca dosyasının çalıştırılması ve isteyen herkes tarafından kurulabilmesi için bu yeter. Etkin ise bir operatörün onu seçmiş olması demektir ve bu kararın nerede saklandığı tamamen tipe bağlıdır. Kapalı olmak, kodunuzun yüklenmesini hiçbir şekilde engellemez.
Yapı
Aşamalar
| Aşama | Neyle olur | Modülünüzde ne çalışır | Nasıl geri alınır |
|---|---|---|---|
| Diskte | Dizin kopyalanır, bir arşivden çıkarılır ya da panel tarafından indirilir | Hiçbir şey. Gelmiş olmak hiçbir kodu çalıştırmaz | Dizini silmek |
| Kancalar kaydedilir | Her istekte, her modül dizini için, hiçbir duruma bakılmadan | hooks.php, baştan sona | Yalnız gövdeyi kendiniz kapılayarak ya da dosyayı kaldırarak |
| Yüklenir | Bir yer kayıt defterinden bu modülü ya da tipinin tamamını ister | Hiçbir şey. config.php ve dil dosyası statik bir önbelleğe okunur | Geri alınacak bir şey yok; önbellek bir istek boyu yaşar |
| Kurulur | Fabrikadan bir nesne istenir | Taban yapıcı, sonra yazdıysanız sizinki | Geri alınacak bir şey yok; nesne bir istek boyu önbelleklenir |
| Bağlanır | Çağıran taraf bir hizmet, sipariş ya da ürün bağlar | Varsa sizin set_service geçersiz kılmanız | Aynı nesneye başka bir şey bağlamak |
| Etkinleşir | Operatör açar ya da bir içe aktarıma hemen etkinleştirmesi söylenir | activate(), ardından enable(); ikisi de isteğe bağlı, ikisi de reddedebilir | Kapatmak |
| Kapanır | Operatör kapatır | deactivate(), ardından disable(); ikisi de isteğe bağlı | Yeniden açmak; bu da etkinleştirme metotlarını tekrar koşturur |
| Silinir | Modül listesindeki silme eylemi | uninstall(), hiçbir dosyaya dokunulmadan önce | Dosyaları geri koymak. Sildiğiniz veriyi hiçbir şey geri getirmez |
Referans
Etkinlik İşareti Nerede Durur
Dört tip kendi yapılandırma dosyasında bir status anahtarı tutar. Kalanı başka bir yerde seçilir ve ikisinde böyle bir işaret hiç yoktur.
| Tip | Karar nerede saklanır | Kim yazar |
|---|---|---|
| Addons | Modülün kendi config.php dosyasındaki status | Eklenti listesindeki anahtar, taban durum metodu üzerinden |
| Product | Modülün kendi config.php dosyasındaki status | O modül grubunun ayar ekranı; her modülün dosyasını tek geçişte yazar |
| Fraud | Modülün kendi config.php dosyasındaki status | Dolandırıcılık ayarları ekranı |
| SocialAuth | Modülün kendi config.php dosyasındaki status | Sosyal giriş ayarları |
| Mail, SMS, IP, Currency | Platformun modül yapılandırmasındaki tek bir modül adı | O grubun ayar ekranı. Aynı anda yalnız biri etkin olabilir |
| Payment | Platformun modül yapılandırmasındaki modül adı listesi | Ödeme ayarları ekranı; ayrıca kart saklama geçidini adlandıran ayrı bir girdi |
| Authentication | Platformun modül yapılandırmasındaki modül adı listesi | Güvenlik ayarları |
| Captcha | Seçenek yapılandırmasındaki seçili tip, yanında bir açık kapalı işaretiyle | Güvenlik ayarları |
| Servers | Hiçbir yerde işaret yok | Modülü adlandıran bir sunucu kaydı onu kullanıma sokar |
| Registrars | Hiçbir yerde işaret yok | Modülü gösteren bir üst düzey alan adı uzantısı onu kullanıma sokar |
| Storage, Pipe, Imports | Kullanıldığı noktada seçilir | Sırasıyla yedek hedefi, destek posta kutusu ve içe aktarma koşusu |
Bildirebileceğiniz Yaşam Döngüsü Metotları
İlk beşi salt konvansiyondur. Hiçbir taban sınıf onları bildirmez; her biri method_exists ile aranır ve yoksa atlanır. Yanlış bir dönüş, ait olduğu adımı durdurur. Son ikisi farklıdır ve bu fark önemlidir. change_addon_status eklenti tabanında zaten uygulanmıştır. testConnection ise sosyal giriş tabanında abstract bildirilmiştir; yani orada isteğe bağlı değil zorunludur.
// Etkinleştirme yolu, bu sırayla. Önce activate(), sonra enable() koşar.
// false döndürmek modülü kapalı bırakır ve hiçbir şey yazılmaz.
public function activate(): bool;
public function enable(): bool;
// Kapatma yolu, bu sırayla.
public function deactivate(): bool;
public function disable(): bool;
// Modül dizini kaldırılmadan önce koşar. false döndürmek silmeyi iptal eder.
// Bu argümansız boolean biçim EKLENTİ biçimidir.
public function uninstall(): bool;
// Authentication tipi aynı adı farklı bir biçimle yeniden kullanır: saklanan
// kayıt verisi geçilir ve bir dizi döndürülür. Yalnız 'error' iptal eder.
public function uninstall(array $data = []): array; // ['status' => 'successful']
// Test butonu. İki biçim var ve hangisini alacağınıza çağıran taraf karar verir:
// sosyal giriş sağlayıcıları ARGÜMANSIZ çağrılır (tabanda abstract),
// servis sağlayıcılar ise tek argüman olarak birleştirilmiş yapılandırmayla çağrılır.
public function testConnection(): bool; // SocialAuth
public function testConnection($config = []): bool; // Registrars
// Eklenti tabanında zaten uygulanmıştır: yukarıdaki dört metodu koşturur, sonra
// yeni durumu config.php'ye yazar. Yalnız o davranışı değiştirmek için geçersiz kılın.
public function change_addon_status($arg = '');
Bir servis sağlayıcıda argümansız testConnection() bildirmek tuzağın ta kendisidir. Taban, birleştirilmiş yapılandırma dizisini ilk argüman olarak geçer. Operatörün girdiği kimlik bilgilerini sınamak için gereken değeri atmış olursunuz. Kurulu her servis sağlayıcı $config = [] bildirir. Aynısı uninstall için de geçerlidir: eklenti biçimi argüman almaz, kimlik doğrulama biçimi saklanan kayıt dizisini alır.
Eklenti Durum Zinciri
Sıranın tamamı budur. Düşen bir enable() çağrısının modülü neden olduğu gibi bıraktığını görmenin en hızlı yolu bunu okumaktır.
public function change_addon_status($arg = '')
{
$status = $arg == "enable";
$apply = true;
if ($status && method_exists($this, 'activate')) $apply = $this->activate();
if ($status && method_exists($this, 'enable')) $apply = $this->enable();
if (!$status && method_exists($this, 'deactivate')) $apply = $this->deactivate();
if (!$status && method_exists($this, 'disable')) $apply = $this->disable();
// Bayrak EN SON yazılır, hem de yalnız modül onay verdiyse.
if ($apply) {
$config = $this->config;
$config["status"] = $status;
$this->save_config($config);
}
return $apply;
}
Onu çağıran operation; bir reddin operatöre nasıl ulaştığını ve iki argümanın nereden geldiğini görün:
$key = (string) Filter::init("POST/module", "route");
$status = (int) Filter::init("POST/status", "rnumbers");
$instance = Modules::getInstance("Addons", $key);
if (!method_exists($instance, "change_addon_status"))
throw new Exception("Module class does not have a method named change_addon_status.");
$status = $status ? "enable" : "disable";
// Fırlatılan bir istisna doğrudan hata mesajı olarak dışarı çıkar. false dönüşü ise
// eski yoldur: çağıran taraf o zaman gerekçe için eski hata özelliğini okur.
$result = $instance->change_addon_status($status);
if (!$result) throw new Exception($instance->error ?: "Unknown error");
User::addAction($adata["id"], "alteration", "change-addon-status-" . $status, ['module' => $key]);
Hook::run('action:addon.status_changed', $key, $status);
Yaşam Döngüsü Kancaları
Kapılar veto edebilir, eylemler yalnız izler. Boş olmayan bir dize döndüren kapı, o dizeyi operatörün gördüğü hataya çevirir.
Örnek
Kendi şemasını kuran bir etkinleştirme, veriyi bilerek koruyan bir kapatma ve nihayet onu silen bir kaldırma. Üçünün de amacı şudur: yalnız sonuncusu yıkıcıdır.
public function enable(): bool
{
// Bilerek idempotent: enable() her yeniden etkinleştirmede ve güncellemeden sonra tekrar koşar.
$this->check_database();
return true;
}
/** Yalnız ekler. Asla düşürmez, var olan bir kolonu asla yeniden yazmaz. */
private function check_database(): void
{
if (!\WDB::hasTable("Acme_events"))
\WDB::exec('CREATE TABLE `Acme_events` ('
. '`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,'
. '`service_id` INT(11) UNSIGNED NOT NULL DEFAULT 0,'
. '`payload` TEXT NULL DEFAULT NULL,'
. 'PRIMARY KEY (`id`)'
. ') ENGINE = InnoDB CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci;');
// Tablo ilk gönderildikten sonra eklenen kolonlar tek tek kontrol edilir.
$col = \WDB::query("SHOW COLUMNS FROM `Acme_events` LIKE 'created_at'");
if (!($col ? \WDB::getAssoc($col) : false))
\WDB::exec("ALTER TABLE `Acme_events` ADD `created_at` INT(11) UNSIGNED NOT NULL DEFAULT '0'");
}
public function disable(): bool
{
// Burada hiçbir şey düşürülmez. Kapatmak geri alınabilir bir işlemdir; modülü bir
// öğleden sonra kapatan operatör bir yıllık satırı kaybetmemelidir.
return true;
}
public function uninstall(): bool
{
// Kaybedilecek bir şey varken sessizce yok etmek yerine reddedin.
// select() OLUŞTURUCUYU döndürür, yani build() ve getAssoc() onun üzerinde çağrılır.
// Oluşturucuyu WDB::getAssoc() metoduna argüman olarak vermek ölümcüldür: o
// parametre bir PDOStatement bekler, onu da WDB::query() döndürür.
$stmt = \WDB::select('COUNT(id) AS total')->from('Acme_events');
$rows = $stmt->build() ? (int) (($stmt->getAssoc() ?: [])['total'] ?? 0) : 0;
if ($rows > 0 && !(int) \Filter::init("POST/purge", "rnumbers"))
throw new \Exception($this->lang['error-uninstall-has-data'] ?? 'The module still holds records.');
\WDB::exec("DROP TABLE IF EXISTS `Acme_events`");
return true;
}
Diğer taraf, modülde değil bir dinleyicide; çünkü silme dinleyicisinin tepki verdiği sınıftan daha uzun yaşaması gerekir:
// Modül etkin olsun olmasın, HER istekte koşar. Burayı yalnız kayıtlara ayırın.
Hook::add('gate:module.addon_delete', 1, function ($key) {
if ($key !== 'Acme') return '';
$stmt = WDB::select('COUNT(id) AS cnt')->from('Acme_events');
$stmt->where('processed', '=', 0);
$open = $stmt->build() ? (int) (($stmt->getAssoc() ?: [])['cnt'] ?? 0) : 0;
// Boş olmayan dize reddin kendisidir ve operatörün okuduğu şey odur.
return $open > 0 ? 'Acme still has ' . $open . ' unprocessed events.' : '';
});
Hook::add('action:addon.status_changed', 1, function ($key, $status) {
if ($key !== 'Acme') return;
Cache::getInstance()->clear(['acme']);
});
Tuzaklar
İlk etkinleştirmede ve her yeniden etkinleştirmede çalışır; bir güncellemenin şemayı yeniden kurduğu olağan yer de burasıdır. Oluşturmadan önce kontrol edin, kolonları tek tek ekleyin ve operatörün düzenlediği bir satırı asla ezmesine izin vermeyin. Tohumlama yalnız boş tabloya sayım kapısıyla yapıldığında güvenlidir.
Kapatma her tabloyu ve her satırı olduğu gibi bırakmalıdır; o bir anahtardır, temizlik değil. Silme yalnız dizini kaldırır, yani modülünüzün veritabanına yazdığı her şey hayatta kalır. Veri de gidecekse, dosyalar yok olmadan önce çalışan tek adım olan kaldırma metodunda düşürün.
Kanca dosyaları modüller dizini gezilerek toplanır, hiçbir duruma bakılmadan. Gövde modülün kendi etkinlik işaretini önce kontrol etmiyorsa dinleyicileriniz modül kapalıyken de çalışır. Kanca dosyasını bir kayıt listesi olarak görün ve kararı her dinleyicinin içine koyun.
Fırlatılan bir istisna ekrandaki mesaj olur. Mesajsız bir yanlış dönüş ise "Unknown error" kelimelerini üretir. Çağıran taraf bu durumda yeni kodun doldurmadığı eski hata özelliğine düşer ve operatör hiçbir şey öğrenmez.
Kaldırma metodunu eklenti silme eylemi çağırır; bir de kimlik doğrulama tipi, kayıt kaldırılırken çağırır. Başka herhangi bir tipteki modülü silmek, kapı kancası reddetme şansını kullandıktan sonra dosyaları kaldırır. Sınıfınızdaki hiçbir metot çağrılmaz. Kaldırma anında çalışması gereken ne varsa, kimsenin çağırmadığı bir metoda değil kapının arkasına koyun.
İlgili Makaleler
Geri bildiriminiz için teşekkürler!
Yukarıda bulamadığınız her şey için destek ekibimiz her zaman yanınızda.