Composer dan Autoloading
Halaman ini menjelaskan apa yang perlu di-install pada server production, flag Composer mana yang penting, dan satu bagian PandaBear yang benar-benar bergantung pada Composer autoloader — bukan sekadar dimuat olehnya. Gunakan referensi ini ketika menulis langkah install pada deploy, atau ketika panel:cache menemukan class lebih sedikit dari yang Anda harapkan.
Contoh minimal yang berfungsi
composer install --no-dev --prefer-dist --optimize-autoloader --no-interactionSetelah itu, dan baru setelah itu:
php artisan panel:cacheINFO Panels cached: 2 panels, 1 resources, 5 pages, 4 widgets.Urutan tersebut adalah inti halaman ini. Detail lainnya menjelaskan alasannya.
Package
"require": {
"chocoalano/panel": "^0.1"
}2
3
| Value | |
|---|---|
| Package | chocoalano/panel |
| Vendor directory | vendor/chocoalano/panel |
| PHP namespace | PandaPanel\ |
| Service provider | PandaPanel\PandaPanelServiceProvider |
| Facade alias | PandaPanel → PandaPanel\Facades\PandaPanel |
Provider dan alias dideklarasikan pada block extra.laravel milik package. Laravel package discovery akan meregistrasikan keduanya secara otomatis. Anda tidak perlu menambahkan provider apa pun ke bootstrap/providers.php.
Application yang masih menggunakan nama package lama panda/panel hanya perlu mengganti satu baris dependency. Lihat Package name migration.
Requirement
"require": {
"php": "^8.2",
"ext-json": "*",
"ext-zip": "*",
"composer-runtime-api": "^2.2",
"composer/semver": "^3.0",
"inertiajs/inertia-laravel": "^3.0",
"laravel/framework": "^12.0|^13.0",
"laravel/fortify": "^1.37.2",
"symfony/finder": "^7.0|^8.0"
}2
3
4
5
6
7
8
9
10
11
| Requirement | Digunakan untuk |
|---|---|
ext-json | seluruh serialized shape yang dikirim ke Vue |
ext-zip | import/export XLSX; file XLSX sebenarnya adalah ZIP container |
composer-runtime-api | Composer\InstalledVersions, untuk membaca versi plugin |
composer/semver | PluginCompatibility saat mengevaluasi constraint requiresPanel plugin |
inertiajs/inertia-laravel | seluruh Panel response merupakan Inertia response |
laravel/fortify | Security Settings dan Email Code second factor |
symfony/finder | melakukan traversal pada discovery path |
ext-zip sengaja menjadi hard requirement, bukan dicek ketika export pertama dijalankan. Server tanpa extension tersebut gagal di composer install, yaitu titik yang paling murah dan paling mudah untuk menemukan masalah environment.
Tidak ada code di src/ yang bergantung pada package require-dev, sehingga --no-dev aman digunakan di production. Dependency development hanya digunakan untuk suite package ini: Pest, Pint, Larastan, Mockery, dan Testbench.
Versi yang didukung dan matrix yang benar-benar dijalankan CI dijelaskan di compatibility matrix.
Memahami setiap flag Composer
composer install --no-dev --prefer-dist --optimize-autoloader --no-interaction| Flag | Dampak pada Panel application |
|---|---|
--no-dev | tidak meng-install Pest, Pint, Larastan, Testbench; runtime Panel tidak membutuhkannya |
--prefer-dist | mendownload archive daripada melakukan clone; lebih cepat untuk deploy |
--optimize-autoloader | menghasilkan classmap yang lebih optimal sehingga class dapat ditemukan tanpa filesystem probe tambahan |
--no-interaction | deploy tidak memiliki operator yang dapat menjawab prompt |
Flag yang jangan digunakan adalah --no-scripts. Laravel package discovery dijalankan melalui Composer script. Jika scripts dilewati, service provider PandaBear tidak pernah diregistrasikan sehingga seluruh Panel route seolah-olah tidak ada — gejalanya terlihat seperti package belum ter-install.
Bagian yang benar-benar bergantung pada autoloader
Discovery tidak melakukan parsing file untuk mengetahui class apa yang dideklarasikan. Ia meminta Composer PSR-4 map:
// PandaPanel\Discovery\ClassResolver
foreach (ClassLoader::getRegisteredLoaders() as $loader) {
foreach ($loader->getPrefixesPsr4() as $namespace => $roots) {
// …
}
}2
3
4
5
6
File yang berada di bawah PSR-4 root dapat diterjemahkan menjadi class name berdasarkan namespace root tersebut. File di luar seluruh PSR-4 root menghasilkan null, karena pada kenyataannya Composer juga tidak akan dapat meng-autoload file tersebut.
use PandaPanel\Discovery\ClassResolver;
ClassResolver::forPath(app_path('Panels/Admin/Resources/Users/UserResource.php'));
// 'App\Panels\Admin\Resources\Users\UserResource'
ClassResolver::forPath('/tmp/Orphan.php');
// null2
3
4
5
6
7
| Method | Signature | Return |
|---|---|---|
forPath | static forPath(string $path): ?class-string | class yang diimplikasikan oleh path, atau null jika di luar seluruh PSR-4 root |
Prefix map di-memoize pada static selama process hidup. Namespace terpanjang dicocokkan terlebih dahulu agar nested prefix mengalahkan parent prefix.
Dua konsekuensi deployment yang penting:
- Class Panel di namespace yang tidak dikenal Composer tidak terlihat oleh discovery. File memang ditemukan, tetapi resolve menjadi
nulldan dilewati. Jika jumlah Resource pada outputpanel:cachelebih sedikit dari yang diharapkan, periksa PSR-4 config padacomposer.json. panel:cacheharus dijalankan setelahcomposer install. Manifest dibangun dari class name yang dihasilkan map autoloader tersebut. Manifest yang dibuat terhadap autoloader lama dapat menunjuk ke class yang sudah pindah.
PanelDiscoverer kemudian hanya mempertahankan concrete class yang mengimplementasikan contract sesuai jenisnya — ResourceContract, PageContract, atau WidgetContract. Abstract base class maupun trait dalam directory yang sama dilewati secara aman.
Setelah manifest tersedia, discovery tidak berjalan lagi
use PandaPanel\Cache\PanelManifest;
app(PanelManifest::class)->exists(); // true di production2
3
Setelah manifest tersedia, PandaBear tidak lagi mengubah filesystem path menjadi class name pada setiap boot. Tidak ada lagi Finder, reflection, maupun ClassResolver. Autoloader hanya bekerja seperti autoloader biasa untuk class yang memang digunakan runtime.
Karena itu optimized Composer autoloader sepenuhnya kompatibel dengan PandaBear. Satu-satunya command yang membutuhkan PSR-4 prefix map untuk discovery, yaitu panel:cache, dijalankan setelah install menghasilkan map tersebut.
Regenerasi autoloader tanpa Composer install
composer dump-autoload --optimize
php artisan panel:clear
php artisan panel:cache2
3
Jika Anda menambah class langsung di server atau mengubah namespace pada composer.json tanpa menjalankan composer install, regenerate autoloader lalu rebuild Panel manifest. Hanya melakukan bagian pertama akan meninggalkan manifest lama yang belum mengenal class baru.
Versi plugin berasal dari Composer
php artisan panel:plugins membaca metadata package yang benar-benar ter-install melalui Composer, bukan version string yang ditulis manual oleh plugin author:
use Composer\InstalledVersions;
InstalledVersions::getPrettyVersion('acme/panel-audit'); // '1.4.1'2
3
php artisan panel:plugins
php artisan panel:plugins --panel=admin2
Plugin yang menyebut package yang tidak dikenali Composer menampilkan unknown, bukan string kosong, karena kedua kondisi tersebut memiliki arti berbeda.
Metadata Composer yang sama digunakan oleh PandaPanel\Plugins\PluginCompatibility untuk menolak plugin yang constraint requiresPanel-nya tidak cocok dengan versi framework yang ter-install:
use PandaPanel\Plugins\PluginCompatibility;
PluginCompatibility::assert($plugin, 'admin'); // throws PanelRegistrationException
PluginCompatibility::assert($plugin, 'admin', '1.2.0'); // check against a version explicitly2
3
4
| Method | Signature | Throws |
|---|---|---|
assert | static assert(PanelPlugin $plugin, string $panelId, ?string $installed = null): void | PandaPanel\Exceptions\PanelRegistrationException |
Compatibility check dilewati ketika:
- plugin tidak mendeklarasikan constraint;
- framework tidak di-install sebagai package Composer biasa, misalnya path repository atau git checkout;
- installed version merupakan branch alias seperti
dev-main.
Constraint semver tidak dapat dievaluasi dengan benar terhadap branch alias. Menolak seluruh plugin ketika framework sedang dikembangkan melalui checkout juga akan membuat ecosystem sulit diuji.
Konsekuensinya, staging yang menggunakan path repository tidak benar-benar meniru compatibility validation production. Untuk monorepo hal tersebut mungkin memang diinginkan, tetapi untuk staging mirror production sebaiknya diperhatikan.
composer.lock
Untuk application, commit composer.lock. File ini adalah catatan dependency persis yang sudah diuji, sama seperti .panel-assets.json mencatat asset source yang telah dipublish.
composer install # mengikuti lock file
composer update # menulis ulang lock file — jangan digunakan saat deploy2
Package mendeklarasikan minimum-stability: stable dan prefer-stable: true, sehingga pre-release package tidak diambil tanpa disengaja.
Hal yang perlu diperhatikan
--no-scriptsmelewati Laravel package discovery. Provider tidak ter-register dan seluruh Panel route dapat 404.- Class di luar seluruh PSR-4 root dilewati secara senyap. Dari sudut pandang autoloader, class tersebut memang tidak dapat dimuat.
- Menjalankan
composer installsetelahpanel:cachedapat meninggalkan manifest terhadap tree lama. Urutan yang benar: install, lalu cache. - Tanpa
ext-zip, XLSX tidak dapat digunakan. Kegagalan sengaja muncul saat Composer install, bukan ketika user pertama kali melakukan export. - Compatibility constraint plugin tidak aktif pada path repository. Plugin yang meminta framework
^2.0dapat tetap register di checkout1.x. --no-devtidak memengaruhi frontend. Vue source berada diresources/jsmilik application; Composer tidak mengelolanya.