Plugin Metadata
PandaPanel\Plugins\PluginMetadata adalah informasi yang dinyatakan plugin tentang dirinya sendiri: nama yang mudah dibaca manusia, Composer package tempat plugin dikirim, versi framework yang dibutuhkan, dan URL. Gunakan metadata terutama ketika plugin didistribusikan sebagai package, karena dua pertanyaan pertama saat plugin bermasalah selalu "plugin yang mana?" dan "versi berapa?", dan keduanya tidak dapat dijawab hanya dari nama class.
Contoh minimal yang berfungsi
<?php
declare(strict_types=1);
namespace Acme\Reporting;
use PandaPanel\Core\Panel;
use PandaPanel\Plugins\Plugin;
use PandaPanel\Plugins\PluginMetadata;
final class ReportingPlugin extends Plugin
{
public function register(Panel $panel): void
{
$panel->resources([Resources\ReportResource::class]);
}
public function metadata(): PluginMetadata
{
return new PluginMetadata(
name: 'Acme Reporting',
package: 'acme/panda-reporting',
requiresPanel: '^1.2',
url: 'https://github.com/acme/panda-reporting',
);
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
php artisan panel:plugins+-------+-----------------+-----------------+-----------------------+---------+----------+
| Panel | ID | Name | Package | Version | Requires |
+-------+-----------------+-----------------+-----------------------+---------+----------+
| admin | acme-reporting | Acme Reporting | acme/panda-reporting | 1.4.1 | ^1.2 |
+-------+-----------------+-----------------+-----------------------+---------+----------+2
3
4
5
Value object
namespace PandaPanel\Plugins;
final readonly class PluginMetadata
{
public function __construct(
public string $name,
public ?string $package = null,
public ?string $requiresPanel = null,
public ?string $url = null,
) {}
public function version(): ?string;
/** @return array{name: string, package: string|null, version: string|null, requiresPanel: string|null, url: string|null} */
public function toArray(): array;
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Class ini readonly, sehingga instance tidak dapat diubah setelah dibuat. Buat instance baru jika nilai metadata perlu berubah.
Parameter constructor
| Parameter | Type | Default | Arti |
|---|---|---|---|
name | string | wajib | Nama yang dapat dibaca manusia untuk laporan |
package | ?string | null | Nama Composer package, dipakai untuk lookup versi |
requiresPanel | ?string | null | Constraint bergaya Composer terhadap framework ini, misalnya ^1.2 |
url | ?string | null | Tempat membaca informasi plugin |
Keempatnya adalah promoted public property sehingga dapat dibaca langsung:
$metadata = $plugin->metadata();
$metadata->name; // 'Acme Reporting'
$metadata->package; // 'acme/panda-reporting'
$metadata->requiresPanel; // '^1.2'
$metadata->url; // 'https://github.com/acme/panda-reporting'2
3
4
5
6
Gunakan named argument. Urutan positional adalah name, package, requiresPanel, url, dan tiga parameter terakhir mudah tertukar.
version(): ?string
Mengembalikan versi package tempat plugin ini terpasang.
use PandaPanel\Plugins\PluginMetadata;
$metadata = new PluginMetadata(name: 'Pest', package: 'pestphp/pest');
$metadata->version(); // 'v4.7.8' — whatever composer actually installed2
3
4
5
Versi dibaca dari Composer\InstalledVersions::getPrettyVersion(), bukan ditulis manual. String versi yang ditulis tangan mudah lupa diperbarui; plugin yang melaporkan 1.2.0 padahal Composer memasang 1.4.1 lebih buruk daripada tidak melaporkan versi sama sekali.
Method ini mengembalikan null dalam dua kondisi:
| Kondisi | Alasan |
|---|---|
package bernilai null | Plugin berada langsung di aplikasi, bukan package tersendiri, sehingga tidak memiliki versi package. Ini normal; plugin tersebut mengikuti versi project. |
Composer tidak mengenal package | Nama package yang salah pada metadata adalah bug dokumentasi plugin, bukan alasan untuk menggagalkan boot aplikasi. |
use PandaPanel\Plugins\PluginMetadata;
(new PluginMetadata(name: 'Reporting'))->version(); // null
(new PluginMetadata(name: 'Ghost', package: 'nobody/nothing'))->version(); // null2
3
4
Keduanya sama-sama menghasilkan null dari version(), tetapi panel:plugins membedakannya: kasus pertama dicetak sebagai in this application, sedangkan package yang tidak dikenal dicetak unknown.
Lookup versi dilakukan setiap kali method dipanggil, jadi jangan menaruhnya di loop terhadap collection besar. Dalam penggunaan normal, method hanya dipanggil sekali per plugin untuk setiap row panel:plugins.
toArray(): array
Mengubah seluruh metadata menjadi array sekaligus me-resolve version():
$plugin->metadata()->toArray();[
'name' => 'Acme Reporting',
'package' => 'acme/panda-reporting',
'version' => '1.4.1',
'requiresPanel' => '^1.2',
'url' => 'https://github.com/acme/panda-reporting',
]2
3
4
5
6
7
Selalu ada lima key; empat key terakhir dapat bernilai null. Bentuk ini berguna untuk support page, health check, atau issue template:
use PandaPanel\Contracts\PanelPlugin;
$report = array_map(
static fn (PanelPlugin $plugin): array => $plugin->metadata()->toArray(),
panel('admin')->getPlugins(),
);2
3
4
5
6
Hasilnya berupa array yang tetap keyed by plugin ID karena getPlugins() juga keyed by ID.
Metadata default
PandaPanel\Plugins\Plugin menyediakan metadata default untuk plugin yang tidak mendeklarasikan metadata sendiri:
public function metadata(): PluginMetadata
{
return new PluginMetadata(name: Str::headline($this->id()));
}2
3
4
| Class | id() | metadata()->name | package | version() | requiresPanel |
|---|---|---|---|---|---|
ReportingPlugin | reporting | Reporting | null | null | null |
AcmeBillingPlugin | acme-billing | Acme Billing | null | null | null |
ID yang diubah menjadi headline adalah nama default yang masuk akal. package = null berarti tidak ada version lookup, sesuai untuk plugin yang tinggal langsung di aplikasi.
Override id() juga mengubah nama default karena nama diturunkan dari ID, bukan dari class.
Kapan metadata dibaca
| Caller | Data yang dibaca |
|---|---|
Panel::plugins() → PluginCompatibility::assert() | requiresPanel, serta name untuk error message |
panel:plugins | name, package, version(), requiresPanel |
Framework tidak membaca url. Nilai tersebut disimpan agar support page atau issue template dapat menampilkannya; framework sendiri tidak pernah membuka URL tersebut.
metadata() dipanggil saat Panel diregistrasikan, sehingga method ini berjalan pada application boot, termasuk ketika command console dijalankan. Jangan melakukan query database, resolve route, atau membaca current user dari metadata. Bentuk yang diharapkan adalah membangun PluginMetadata dari nilai konstan seperti pada contoh-contoh di atas.
Catatan
PluginMetadatabersifatfinal. Jangan extend class ini; metadata tambahan sebaiknya disimpan pada object plugin sendiri.packageharus sama persis dengan nama Composer package pada fieldnamedicomposer.json. Typo tidak melempar exception dan hanya dilaporkan sebagaiunknown.- Versi yang dilaporkan adalah versi yang benar-benar terpasang. Pada path repository atau git checkout nilainya dapat berupa branch alias seperti
dev-main; itu tetap jawaban yang valid dan dicetak apa adanya. requiresPaneldijelaskan lengkap di Kompatibilitas Versi, termasuk tiga kondisi ketika pemeriksaan sengaja dilewati.