Migrasi Nama Package
Composer package saat ini adalah chocoalano/panel. Package sebelumnya menggunakan nama lain, dan aplikasi yang diinstal sebelum rename hanya membutuhkan satu perubahan utama — baris require — ditambah pemeriksaan terhadap satu hal yang sempat rusak secara diam-diam akibat rename lalu diperbaiki kembali: PluginCompatibility::PACKAGE, constant yang digunakan framework untuk mencari version dirinya sendiri. Gunakan halaman ini ketika meng-upgrade instalasi dari sebelum rename, atau ketika Anda mengelola plugin yang mendeklarasikan requiresPanel.
Untuk project yang hanya perlu menyesuaikan nama package tanpa melakukan upgrade lainnya, lihat juga Getting started: migrasi nama package.
Contoh minimal yang dapat langsung digunakan
composer remove panda/panel
composer require chocoalano/panel
php artisan panel:plugins # every plugin still registers, at which version
php artisan test2
3
4
5
Tidak ada published file yang harus diubah, tidak ada namespace yang berubah, dan tidak ada config yang berganti nama. Baris require adalah inti migrasinya; bagian lainnya menjelaskan efek samping rename di sekitar mekanisme tersebut.
Apa yang berubah dan apa yang tetap sama
| Sebelum | Sesudah | |
|---|---|---|
| Composer package | panda/panel | chocoalano/panel |
| Vendor directory | vendor/panda/panel | vendor/chocoalano/panel |
| Nama npm package | @panda/panel | @chocoalano/panel |
Semua hal yang dirujuk langsung oleh code aplikasi tetap sama:
| Value | |
|---|---|
| PHP namespace | PandaPanel\ |
| Service provider | PandaPanel\PandaPanelServiceProvider |
| Facade alias | PandaPanel → PandaPanel\Facades\PandaPanel |
| Config file | config/panda-panel.php |
| Publish tags | panda-panel, panda-panel-config, panda-panel-assets, panda-panel-migrations, panda-panel-stubs |
| Artisan commands | panel:install, panel:user, panel:assets, panel:cache, panel:clear, panel:icons, panel:plugins, panel:publish, dan lima generator make:panel* |
| Route names | panel.{id}.* |
| Published paths | resources/js/panel, resources/js/pages, resources/css/panda-panel.css |
| Nama project | Panda Panel |
Artinya tidak ada statement use yang perlu diubah, tidak ada migration yang harus dijalankan, dan tidak ada asset yang perlu dipublish atau dibuild ulang hanya karena rename. Nama npm tersebut adalah toolchain milik repository ini sendiri — "private": true, version 0.0.0, dan tidak pernah dipublikasikan ke npm. Komponen masuk ke aplikasi melalui vendor:publish, bukan npm install. Jadi kecuali Anda meng-clone repository framework, nama npm tersebut tidak pernah menjadi dependency milik project Anda.
Baris require
Biarkan Composer menuliskannya:
composer remove panda/panel
composer require chocoalano/panel2
Atau edit composer.json lalu jalankan update:
"require": {
"chocoalano/panel": "^0.1"
}2
3
composer update chocoalano/panelcomposer require menulis caret constraint, dan itu adalah default yang tepat. Makna constraint tersebut — termasuk mengapa ^0.1 tidak akan otomatis masuk ke 0.2 — dijelaskan di Kebijakan versioning.
Tidak ada metapackage yang meng-alias nama lama ke nama baru. Instalasi panda/panel yang sudah terkunci tetap dapat berjalan dari vendor/ karena lockfile merupakan catatan version yang terpasang, bukan subscription terhadap package. Yang tidak akan diterima adalah release setelah rename karena release baru hanya diterbitkan dengan nama baru.
Pastikan nama apa yang benar-benar di-resolve project, terutama pada repository yang history-nya memuat kedua nama:
composer why chocoalano/panel # which constraint pulled it in
composer show chocoalano/panel # the resolved version
composer show --installed | grep panel2
3
Path yang menulis vendor directory secara eksplisit
Vendor directory adalah tempat utama nama lama dapat tertinggal meskipun migrasi lain sudah bersih. vendor/panda/panel dapat muncul di script, step CI, .gitignore, include path editor, atau command diff yang dibutuhkan ketika published asset conflict:
php artisan panel:assets
# CONFLICT resources/js/panel/tables/DataTable.vue
diff -u resources/js/panel/tables/DataTable.vue \
vendor/chocoalano/panel/resources/js/panel/tables/DataTable.vue2
3
4
5
grep -rn 'panda/panel' --exclude-dir=vendor --exclude-dir=node_modules .PluginCompatibility::PACKAGE
Ini adalah konsekuensi teknis paling penting dari rename. Memahaminya lebih baik daripada sekadar menerapkan perbaikan karena pola yang sama dapat terulang ketika package lain berganti nama.
PandaPanel\Plugins\PluginCompatibility menolak plugin yang dibangun untuk version framework yang tidak cocok. Agar dapat melakukan itu, class harus mengetahui version framework yang terpasang dan meminta informasi tersebut kepada Composer menggunakan nama package yang disimpan dalam private constant:
/**
* This package, as composer knows it.
*
* Must match `name` in `composer.json` exactly.
*/
private const PACKAGE = 'chocoalano/panel';2
3
4
5
6
Ketika package di-rename, constant tersebut sempat tidak ikut diperbarui. Tidak ada fatal error. Yang terjadi justru rantai empat langkah yang masing-masing terlihat masuk akal secara individual:
| Langkah | Perilaku | Mengapa terlihat masuk akal jika dilihat sendiri |
|---|---|---|
| 1 | InstalledVersions::getPrettyVersion('panda-panel') melempar exception | Composer memang tidak mengenal package dengan nama itu |
| 2 | catch (Throwable) menghasilkan null | "Tidak diinstal sebagai Composer package" memang kondisi valid untuk path repository, git checkout, dan test suite repository ini |
| 3 | Version null membuat assert() return lebih awal | Tidak ada version yang dapat dibandingkan dengan constraint |
| 4 | Plugin tetap diregistrasikan | Tidak ada pemeriksaan yang menolak registration |
Hasilnya adalah jenis regression yang paling sulit terlihat: setiap constraint requiresPanel yang dideklarasikan plugin lolos tanpa pernah diperiksa pada semua instalasi sejak rename. Logic pemeriksaan tetap ada, tetapi tidak akan pernah menghasilkan penolakan.
Perilaku sekarang
use PandaPanel\Contracts\PanelPlugin;
use PandaPanel\Exceptions\PanelRegistrationException;
public static function assert(
PanelPlugin $plugin,
string $panelId,
?string $installed = null,
): void2
3
4
5
6
7
8
| Parameter | Tipe | Default | Arti |
|---|---|---|---|
$plugin | PandaPanel\Contracts\PanelPlugin | wajib | Dibaca untuk metadata()->requiresPanel, metadata()->name, dan id() |
$panelId | string | wajib | Dicantumkan dalam exception karena plugin yang sama dapat terpasang pada beberapa panel |
$installed | string|null | null | Version framework yang diperiksa; default-nya version yang dilaporkan Composer untuk PACKAGE |
Pemeriksaan dijalankan pada saat plugin registration — titik paling awal ketika jawaban sudah tersedia dan titik terakhir sebelum plugin mulai mengubah panel — lalu melempar PandaPanel\Exceptions\PanelRegistrationException ketika Composer\Semver\Semver::satisfies() menghasilkan false:
The [Billing] plugin ([billing], registered on the [admin] panel) requires panda-panel ^2.0, and
1.4.1 is installed. Upgrade the plugin, or pin this framework to a version it supports.2
Message tersebut adalah inti dari class ini. Failure mode yang digantikannya biasanya berupa Call to undefined method Panel::whatever() di tengah request, yang menyebut framework tetapi tidak menjelaskan plugin mana yang meminta API tersebut, plugin version berapa yang sedang digunakan, atau constraint apa yang tidak cocok.
Karena registration terjadi saat boot, constraint yang tidak terpenuhi menggagalkan setiap route dan setiap Artisan command sampai diselesaikan — termasuk panel:plugins. Ini disengaja: exception sudah memberikan nama plugin, panel, constraint, dan installed version, sehingga informasinya lebih berguna daripada membiarkan application boot dalam state yang tidak kompatibel.
Tiga kondisi yang tetap dilewati
Ketiganya memang berarti tidak ada pertanyaan compatibility yang dapat dijawab. Menganggap salah satunya sebagai error akan menghasilkan false refusal:
| Kondisi | Hasil | Alasan |
|---|---|---|
requiresPanel adalah null | lolos | Sebagian besar plugin tidak memiliki constraint; tidak mendeklarasikan compatibility bukan berarti otomatis incompatible |
| Framework tidak diinstal sebagai Composer package | lolos | Path repository, git checkout, atau test suite repository ini tidak memiliki package version yang bisa dibandingkan |
Version adalah dev-* atau mengandung no-version-set | lolos | Constraint tidak dapat dievaluasi terhadap branch; 1.0.0+no-version-set adalah placeholder Composer untuk root package tanpa version |
Kondisi kedua persis sama dengan state yang secara tidak sengaja dibuat oleh constant lama, sehingga bug tersebut tidak terlihat: setiap instalasi berperilaku seolah framework dijalankan langsung dari git checkout.
Test yang mengunci nama package
tests/Feature/Panel/PluginTest.php membandingkan constant dengan composer.json, sehingga rename berikutnya yang lupa memperbarui constant akan gagal di test, bukan mematikan compatibility check secara diam-diam:
use PandaPanel\Plugins\PluginCompatibility;
it('looks up its own version under the name composer knows it by', function (): void {
$reflection = new ReflectionClass(PluginCompatibility::class);
expect($reflection->getConstant('PACKAGE'))
->toBe(json_decode((string) file_get_contents(base_path('composer.json')), true)['name']);
});2
3
4
5
6
7
8
Satu assertion ini menjadi pengaman agar rename package tidak kembali menonaktifkan seluruh constraint tanpa indikasi.
Dampaknya bagi aplikasi
Plugin dengan constraint yang tidak cocok dengan installed version sekarang ditolak dengan message yang jelas, padahal sebelumnya plugin bisa diregistrasikan tanpa pemeriksaan. Jalankan pengecekan sebelum upgrade:
php artisan panel:plugins # every panel
php artisan panel:plugins --panel=admin # one panel2
+-------+---------+-----------+--------------------+---------+----------+
| Panel | ID | Name | Package | Version | Requires |
+-------+---------+-----------+--------------------+---------+----------+
| admin | billing | Billing | acme/panda-billing | 2.1.0 | ^0.1 |
| admin | audit | Audit Log | in this application| unknown | any |
+-------+---------+-----------+--------------------+---------+----------+2
3
4
5
6
Command menampilkan enam column. Tiga value memiliki representasi eksplisit agar kondisi yang berbeda tidak terlihat sebagai cell kosong: in this application ketika metadata tidak memiliki package, unknown ketika package disebut tetapi Composer tidak mengenalnya, dan any ketika plugin tidak mendeklarasikan requiresPanel. Plugin tanpa package juga memiliki version unknown, yang merupakan jawaban normal untuk plugin yang hidup langsung di aplikasi dan mengikuti version aplikasi. Jika tidak ada plugin di panel mana pun, command menampilkan No plugins are registered. dan exit 0.
Jika sebuah plugin ditolak, hanya ada tiga pilihan: upgrade plugin, longgarkan constraint jika plugin milik Anda, atau lepaskan plugin dari panel.
Dampaknya bagi pembuat plugin
requiresPanel menggunakan constraint bergaya Composer yang dievaluasi terhadap chocoalano/panel. Jadi nilai tersebut selalu merujuk ke version framework, bukan version package plugin Anda:
protected $signature = 'panel:plugins {--panel= : Only this panel}';use PandaPanel\Plugins\Plugin;
use PandaPanel\Plugins\PluginMetadata;
final class BillingPlugin extends Plugin
{
public function id(): string
{
return 'billing';
}
public function metadata(): PluginMetadata
{
return new PluginMetadata(
name: 'Billing',
package: 'acme/panda-billing', // your package — unaffected by the rename
requiresPanel: '^0.1', // a constraint against chocoalano/panel
url: 'https://github.com/acme/panda-billing',
);
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
composer.json milik plugin Anda juga perlu menggunakan nama baru pada require; jika tidak, Composer tidak dapat me-resolve dependency:
public function __construct(
public string $name,
public ?string $package = null,
public ?string $requiresPanel = null,
public ?string $url = null,
) {}2
3
4
5
6
Ada dua hal yang perlu diuji karena keduanya tidak benar-benar teruji hanya dengan menginstal plugin di checkout framework:
"require": {
"chocoalano/panel": "^0.1"
}2
3
Jika Anda mengganti nama package milik sendiri
Pelajaran dari rename ini singkat dan berlaku untuk package apa pun yang membaca version dirinya sendiri pada runtime:
namepadacomposer.jsonadalah satu-satunya source of truth untuk nama package.- Setiap tempat yang menulis ulang nama tersebut — constant, config default, snippet dokumentasi — adalah copy, dan copy dapat drift.
- Jika copy kedua memang tidak dapat dihindari, kunci dengan test yang membandingkannya langsung terhadap
composer.json. - Lebih baik lookup gagal secara jelas daripada otomatis turun menjadi "unknown". Class ini memang memilih fallback dengan alasan valid, tetapi biaya dari keputusan tersebut adalah bug rename yang dibahas di halaman ini.
use PandaPanel\Exceptions\PanelRegistrationException;
use PandaPanel\Plugins\PluginCompatibility;
// Passing $installed is how the refusal is tested at all: in a checkout the
// framework has no composer version, so the check is skipped and every
// constraint passes.
PluginCompatibility::assert(new BillingPlugin, 'admin', '0.1.5'); // satisfied — returns
expect(fn () => PluginCompatibility::assert(new BillingPlugin, 'admin', '0.2.0'))
->toThrow(PanelRegistrationException::class);2
3
4
5
6
7
8
9
10
Memverifikasi migrasi
grep -rn 'chocoalano/panel' src/ config/ composer.jsoncomposer show chocoalano/panel # resolved version and source
composer why chocoalano/panel # what required it
php artisan panel:plugins # every plugin registers, with versions
php artisan panel:assets # unchanged — no published file mentions the package name
php artisan about --only=environment # PHP and Laravel, for a bug report
php artisan test2
3
4
5
6
panel:assets yang melaporkan tidak ada perubahan adalah hasil yang diharapkan. Tidak ada published file di resources/js yang merujuk langsung ke nama Composer package, sehingga rename ini tidak membutuhkan republish frontend maupun rebuild.
Catatan
- Nama project tetap Panda Panel. Rename hanya terjadi pada Composer vendor namespace. Bahkan exception masih dapat menuliskan
requires panda-panel ^2.0karena itu adalah nama project, bukan package coordinate. config/panda-panel.phptetap menggunakan nama yang sama. Menggantinya akan mematahkan semuaconfig('panda-panel.*')dan tidak memberikan manfaat.- Constraint yang tidak terpenuhi menghentikan application boot. Registration berlangsung saat boot, sehingga semua route dan semua Artisan command gagal — termasuk
panel:plugins. Baca exception karena nama plugin dicantumkan di sana. - Git checkout tidak mereproduksi penolakan version.
dev-maindan1.0.0+no-version-setsama-sama melewati check. Constraint yang ditolak pada aplikasi dapat lolos di development checkout; kirim$installedsecara eksplisit pada test. - Plugin tanpa
packagetidak memiliki version. Itu adalah kondisi normal untuk plugin yang hidup langsung di aplikasi, bukan error. getPrettyVersion()melempar exception, bukan mengembalikan null. Inilah yang membuat bug lama menjadi silent dan mengapaPandaPanel\Plugins\PluginCompatibilitymembungkus pemanggilan tersebut dengantry.- Tidak ada yang memaksa project melakukan upgrade. Lockfile lama tetap berjalan; project hanya berhenti menerima release setelah rename.
Lihat juga
- Getting started: migrasi nama package — rename yang sama dari sisi instalasi
- Panduan upgrade — posisi perubahan
requiredalam proses upgrade - Breaking changes — bagian constraint compatibility yang dipulihkan
- Kebijakan versioning — arti constraint yang Anda tulis
- Changelog, Release checklist
- Plugin compatibility, Plugin metadata, Plugin contract
panel:plugins,panel:assets- Menyelesaikan konflik asset
- Troubleshooting: error instalasi Packagist