Modülden Kanca Kaydetme
Modül dizininize bir hooks.php koyarsınız; bir modülün çekirdeğe dokunmadan uzanma biçimi budur.
Genel Bakış
Genişletmenin tamamı kancalar üzerinden yapılır. Bir modül, sahip olduğu tek dosyadan olayı yakalar, bir değeri değiştirir, işaretleme enjekte eder, yetenek kaydeder ya da bir işlemi reddeder. coremio/ içindeki hiçbir şey modülünüzün varlığını bilmez.
Katalog beş kategoride 979 kanca noktası taşıyor: ui 343, action 298, filter 196, gate 131, register 11. Ad tahmin etmek yerine kataloğa bakın.
Ön Koşullar
coremio/modules/{Tip}/{Ad}/altında bir modül dizini; on altı tipin hepsi olur.- Kanca adı,
hooks/INDEX.mddosyasından kopyalanmış olarak. Var olmayan bir ad sessizce başarısız olur. - O kancanın
hooks/{domain}/altındaki sayfası: parametreler, hangisinin referans olduğu ve dönüş sözleşmesi.
Yapı
coremio/modules/*/*/hooks.php deseniyle bulunur: ad ve konum sabittir.
Adım Adım
Dosyayı Oluşturun
- Modül dizininizin köküne,
{Ad}.phpveconfig.phpdosyalarının yanınahooks.phpekleyin. - Dosya include edilir; en üst seviyede düz ifadeler yazın.
- Kendi
src/dizininizdeki sınıflar otomatik yüklenmez; başvurmadan önceinclude_onceile yükleyin.
Kendi Durumunuzla Kapılayın
- Modülü kurmadan yapılandırmanızı yükleyin: yükleyiciye üçüncü argüman olarak
truegeçin. - Her dinleyiciyi kendi etkinlik işaretinizin, lisanslı bir modülse lisansınızın kontrolüne sarın.
- Dosyayı ucuz tutun; bir kancaya dokunan her istekte çalışır.
Dinleyici Kaydedin
- Ekleme metodunu kanca adı, bir öncelik ve ya bir closure ya da bir tanım dizisiyle çağırın.
- Yalnız ihtiyacınız olan parametreleri bildirin; motor bunları konum sırasına göre eşler.
- Bir değeri değiştirmek için o parametreyi referansla bildirin; yalnız referanslı varyant onu geri taşır.
Öncelik Seçin
- Küçük olan önce çalışır. Varsayılan yoktur, bu yüzden sayıyı bilinçli geçin.
- Sonraki bir kaydı gölgelemek için küçük (rota ezmeleri böyle çalışır), en sona eklenmek için büyük bir sayı kullanın.
Referans
Kayıt
class Hook
{
// $properties YA bir callable YA da bir tanım dizisidir (aşağıdaki üç biçime bakın).
public static function add($name, $priority, $properties = []): void;
public static function run($name, ...$args): array; // değerle
public static function runRefs($name, &...$args): array; // HER argüman referansla
public static function runDetailed($name, ...$args): array; // dinleyici başına telemetri
}
| Çalıştırma metodu | Döndürdüğü | Dinleyici exception fırlatırsa |
|---|---|---|
run | null olmayan her dönüş, öncelik sırasında | loglanır, sonraki dinleyici çalışır |
runRefs | aynısı, ayrıca referans düzenlemeleriniz çağırana ulaşır | loglanır, sonraki dinleyici çalışır |
runDetailed | [['source' => ['type','class','method','file','line'], 'value' => …, 'error' => ?string], …], null'lar korunur | error alanına yazılır |
| hepsi, bilinmeyen ad | boş dizi | hiçbir şey olmaz; yazım hatası sessizdir |
Üç Kayıt Biçimi
// 1. Closure. Çağrılabilir olan her şey doğrudan girer.
Hook::add('action:service.created', 10, function ($id, $data) {
// ...
});
// 2. Örnek metodu. Sınıf argümansız olarak BİR KEZ kurulur ve istek boyunca
// önbellekte tutulur, bu yüzden yapıcısı parametresiz çalışmalıdır.
Hook::add('filter:invoice.totals', 10, [
'class' => 'MyAddonHooks',
'method' => 'adjustTotals',
]);
// 3. Statik metot. Hiçbir şey kurulmaz.
Hook::add('ui:admin.service_detail.bottom', 10, [
'class' => 'MyAddonHooks',
'method::static' => 'renderPanel',
]);
Sınıf bulunamazsa ya da metot yoksa dinleyici null döner ve istek devam eder. Bu tam olarak hiç tetiklenmemiş bir kanca gibi görünür. Closure tercih edin.
Argümanlar Dinleyicinize Nasıl Ulaşır
// Dinleyicinizin $i konumunda bildirdiği her parametre için:
// referansla bildirilmiş VE $i konumunda argüman var -> referansla geçirilir
// $i konumunda argüman var -> değerle geçirilir
// $i konumunda argüman yok -> parametre düşürülür,
// yani varsayılanınız geçerli olur
$callArgs = [];
foreach ($reflection->getParameters() as $i => $param) {
if ($param->isPassedByReference() && isset($args[$i])) $callArgs[] = &$args[$i];
else if (isset($args[$i])) $callArgs[] = $args[$i];
}
Kancanın verdiğinden az parametre bildirmek güvenlidir. Bir referans, değişikliğinizi ancak kanca referanslı varyantla tetiklendiyse geri taşır. Değer geçen bir kancada &$deger sessizce hiçbir şeyi değiştirmez.
Beş Kategori ve Her Birinin Beklediği Dönüş
| Önek | Dinleyiciniz ne yapar | Dönüş değeriniz |
|---|---|---|
action: | bir olaya tepki verir | yoksayılır |
filter: | bir değeri kullanılmadan önce değiştirir | düzenleme referans parametresi üzerinden gider |
ui: | işaretleme, stil ya da script enjekte eder | basılacak dize |
register: | bir yetenek kaydeder: cron görevi, rota, menü öğesi, widget | kayıt verisi, ya da hiçbir şey kaydetmemek için false |
gate: | bir işlemi veto eder | boş olmayan değer engeller, null devam ettirir |
Ad kategori:domain.subject.action biçimindedir; küçük harf, parçalar snake_case. Bir ui: adı yerleştirme kelimesiyle biter: dinleyicisine bağlam verilmez, hedefi addan çıkarır.
Kanca Dosyasında Kendi Yapılandırmanızı Okuma
// $nominc = true, sınıfı dahil ETMEDEN yapılandırmayı ve dil dosyasını yükler.
public static function Load($type = '', $name = '', $nominc = false, $status = '');
public static function Config($type, $module);
public static function getInstance(string $type, string $name, array $params = []): ?object;
Modules::Load('Addons', 'MyAddon', true); // yalnız yapılandırma, sınıf yok
$my_config = Modules::Config('Addons', 'MyAddon') ?: [];
if (($my_config['status'] ?? false) && License::valid_addon('my-addon')) {
// ... dinleyicileri burada kaydedin
}
Örneği bir dinleyicinin içinde kurun. Kayıt yapıp yapmayacağınıza karar vermek için modülü her istekte kurmak, bir modülün paneli yavaşlatmasının en yaygın sebebidir.
Örnek
Dört noktaya dokunan bir kanca dosyası: bir olay, bir değer, bir sayfa ve zamanlanmış bir görev.
<?php
// src/ sınıfları otomatik yüklenmez: bu dosyanın andığı şeyi, anmadan önce include edin.
include_once __DIR__ . DS . 'src' . DS . 'Notifier.php';
use WISECP\Modules\Addons\MyAddon\Src\Notifier;
// Sınıfsız yapılandırma. Tek ucuz çağrı, aşağıda bir şey kaydedilip kaydedilmeyeceğine karar verir.
Modules::Load('Addons', 'MyAddon', true);
$my_config = Modules::Config('Addons', 'MyAddon') ?: [];
if (!($my_config['status'] ?? false)) return;
/* Bir olay. Bu kanca ($id, $data) ile tetiklenir: yeni users_products kimliği ve eklenen
satır. Dönüş değeri yoksayılır, yani işi yapın ve hiçbir şey söylemeyin. */
Hook::add('action:service.created', 10, function ($id, $data) {
Notifier::service_created((int) $id, is_array($data) ? $data : []);
});
/* Bir değer. $totals REFERANSLA bildirilir, çünkü bu kanca runRefs ile tetiklenir;
$invoice ve $items salt okunur bağlamdır. */
Hook::add('filter:invoice.totals', 10, function (&$totals, $invoice, $items) {
if ((int) ($invoice['legal'] ?? 0) !== 1) return;
$fee = (float) ($GLOBALS['my_addon_fee'] ?? 0);
if ($fee <= 0) return;
$totals['total'] = round((float) $totals['total'] + $fee, 4);
});
/* İşaretleme. Dizeyi döndürün; yüzey onu basar. Örneği YUKARIDA değil BURADA kurun. */
Hook::add('ui:admin.service_detail.bottom', 20, fn ($service) =>
Modules::getInstance('Addons', 'MyAddon')->render_service_panel(is_array($service) ? $service : []));
/* Bir yetenek. Kayıt kancaları besledikleri şeyin bootstrap'ı sırasında koşar. */
Hook::add('register:cronjobs', 1, function () {
include_once __DIR__ . DS . 'cronjobs' . DS . 'SyncTask.php';
CronJobQueue::register(
\WISECP\Modules\Addons\MyAddon\CronJobs\SyncTask::TYPE,
\WISECP\Modules\Addons\MyAddon\CronJobs\SyncTask::class
);
});
Okuma tarafı: yukarıdaki değer kancasını tetikleyen çekirdek çağrısı.
// coremio/helpers/Invoices.php, recalculate_totals() içinde: rakamlar kurulduktan sonra
// ve satıra yazılmadan önce.
Hook::runRefs('filter:invoice.totals', $totals, $invoice, $items);
// $totals artık dinleyicilerin içinde bıraktığı şeydir ve $persist onu yazar.
Kendi modülünüz bir genişletme noktası yayınladığında aynı özen geçerlidir:
// Değerle: diğer modüllerin izleyebileceği bir olay.
Hook::run('action:myaddon.sync_finished', $summary, $startedAt);
// Referansla: burada bağlam olanlar dahil HER argüman referanstır, bu yüzden her biri
// önce düz bir değişken olmalıdır.
$context = ['id' => $recordId, 'lang' => Language::selected()];
Hook::runRefs('filter:myaddon.payload', $payload, $context);
// Bir kapı: herhangi bir dinleyiciden gelen boş olmayan dönüş işlemi durdurur.
$veto = Hook::run('gate:myaddon.export', $recordId);
if (array_filter($veto)) throw new Exception((string) current(array_filter($veto)));
Tuzaklar
İmza variadic ve referanslıdır. Herhangi bir konumdaki sabit, cast, fonksiyon dönüşü ya da null-birleştirme ifadesi ölümcül hatadır. Her birini önce düz bir değişkene alın; değer geçen varyantta bu sorun yoktur.
Motor her throwable'ı yakalar, loga yazar ve devam eder. Entegrasyonunuz gerçekleşmez, sayfa normal görünür, hiçbir şey bunu söylemez; en sık sebep unutulmuş bir include_once'tur. Dinleyici hareketsiz görünüyorsa önce hata logunu okuyun.
Kanca dosyaları tembel okunur, ilk çalıştırma çağrısında; kuruluş tarihi sıfır tarihiyken hiç okunmaz. Daha erken gereken her şey (bir rota, bir izin kataloğu) router kurulurken yüklenen router.php dosyasına konur.
En üst seviyede modülünüzü kurmak, veritabanına sormak ya da bir servise çıkmak bunun bedelini her seferinde, müşteri sayfaları dahil ödetir. Yapılandırmayı sınıfsız yükleyiciyle okuyun ve örneği dinleyicinin içinde kurun.
Aynı sayıyla iki dinleyici kaydetmek ikincisine bir sonraki boş yuvayı verir; sıra kayıt sırasını, o da modül dizinlerinin alfabetik sırasını izler. Kalabalıktan uzak bir sayı seçin.
İ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.