Registrasi Route
Route Panel diregistrasikan saat boot, satu route group untuk setiap Panel, melalui PandaPanel\Routing\PanelRouteRegistrar.
Satu config key dapat mematikan seluruh proses registrasi route.
Gunakan halaman ini ketika Anda perlu:
- mengontrol kapan route Panel diregistrasikan;
- membuat test harness yang membutuhkan Panel tanpa HTTP route;
- mendaftarkan Panel dari package lain setelah boot;
- atau memahami bagian framework apa yang tetap berjalan ketika route registration dimatikan.
Contoh minimal yang berfungsi
// config/panda-panel.php
'register_routes' => true,2
3
php artisan route:list --path=adminuse Illuminate\Support\Facades\Route;
Route::has('panel.admin.dashboard'); // true
route('panel.admin.dashboard', absolute: false); // '/admin'
route('panel.admin.resources.users.index', absolute: false); // '/admin/users'2
3
4
5
Itu adalah behavior default.
Panel yang tercantum di:
config('panda-panel.panels')langsung memiliki route pada path yang dideklarasikannya tanpa langkah tambahan.
Apa yang dilakukan route registration
Setelah seluruh Panel selesai diregistrasikan, PandaPanelServiceProvider::boot() memanggil registrar satu kali:
private function registerRoutes(): void
{
if ($this->app->make('config')->get('panda-panel.register_routes') !== true) {
return;
}
$this->app->make(PanelRouteRegistrar::class)->registerAll();
}2
3
4
5
6
7
8
Registrar membuat satu group per Panel:
$attributes = [
'prefix' => $panel->getPath(),
'as' => $panel->getRouteNamePrefix(), // 'panel.admin.'
'middleware' => [
...$panel->getMiddleware(), // ['web', 'auth', 'verified']
ResolvePanel::class.':'.$panel->getId(),
RequireTwoFactor::class.':'.$panel->getId(),
RequireEmailCode::class.':'.$panel->getId(),
...($panel->hasTenancy() ? [ResolveTenant::class.':'.$panel->getId()] : []),
],
];
if ($panel->getDomain() !== null) {
$attributes['domain'] = $panel->getDomain();
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
Di dalam group tersebut, registrar menambahkan route dengan urutan konseptual berikut:
- guest auth pages milik Panel, yang berada di luar auth stack;
- dashboard;
- global search;
- form options;
- uploads;
- form state;
- export/import download;
- Notification Centre;
- two-factor challenge;
- Action endpoints;
- Relation endpoints;
- seluruh standalone Page;
- seluruh Resource Page.
Inventory lengkap route name, HTTP verb, dan path ada di Routing.
Dua aturan berlaku untuk seluruh route tersebut.
Pertama, setiap route menunjuk ke controller method, bukan Closure. Karena itu:
php artisan route:cachetetap dapat digunakan.
Kedua, Panel id diberikan langsung ke ResolvePanel sebagai middleware parameter, bukan dicari dari URL. Dengan desain ini, dua Panel yang memiliki prefix mirip tetap tidak ambigu saat request berjalan.
PandaPanel\Routing\PanelRouteRegistrar
public function __construct(Registrar $router, PanelManager $manager);
public function registerAll(): void;
public function register(Panel $panel): void;2
3
4
5
Class ini merupakan container singleton dan dibangun menggunakan:
Illuminate\Contracts\Routing\Registrarserta Panel Manager.
use PandaPanel\Routing\PanelRouteRegistrar;
app(PanelRouteRegistrar::class)->registerAll(); // seluruh Panel yang sudah terdaftar
app(PanelRouteRegistrar::class)->register(panel('admin')); // satu Panel2
3
4
Jika Panel baru diregistrasikan setelah boot, gunakan:
register()secara manual.
Laravel melakukan cache terhadap route name lookup. Setelah menambahkan route baru secara dinamis, refresh lookup tersebut agar route('panel.x.dashboard') dapat langsung me-resolve:
use Illuminate\Support\Facades\Route;
use PandaPanel\Core\Panel;
use PandaPanel\Facades\PandaPanel;
use PandaPanel\Routing\PanelRouteRegistrar;
$panel = PandaPanel::register(
Panel::make('door')
->path('door')
->login()
);
app(PanelRouteRegistrar::class)
->register($panel);
Route::getRoutes()
->refreshNameLookups();2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Test suite PandaBear menggunakan pattern yang sama untuk Panel yang didefinisikan langsung di test.
Mematikan route registration
// config/panda-panel.php
'register_routes' => false,2
3
Config dibandingkan dengan:
!== trueArtinya hanya boolean true yang mengaktifkan route registration.
Jika dimatikan:
| Tetap berjalan | Berhenti berjalan |
|---|---|
| Panel tetap diregistrasikan dan registry tetap dibangun | Tidak ada route group untuk Panel |
| Discovery tetap berjalan atau manifest tetap dibaca | Tidak ada URL Panel yang dapat dijawab |
Empat middleware web tetap ditambahkan | — |
| Empat middleware alias tetap diregistrasikan | — |
| Migration loading, publishing, dan command registration tetap berjalan | — |
| Guest redirect tetap diregistrasikan | Tetapi tidak memiliki Panel Login route untuk dituju; PanelLoginRedirect menghasilkan null pada Panel yang mendeklarasikan login(), lalu Laravel dapat menghasilkan 401 |
use PandaPanel\Facades\PandaPanel;
PandaPanel::resources('admin')->all(); // still answers
Route::has('panel.admin.dashboard'); // false2
3
4
Switch ini cocok untuk test harness yang hanya ingin memeriksa metadata/registry tanpa menambahkan banyak route pada setiap test.
Application yang ingin mengambil alih route registration juga dapat memanggil registrar dari provider sendiri:
// A provider of your own, booted after PandaPanelServiceProvider.
public function boot(): void
{
if (! $this->app->routesAreCached()) {
app(PanelRouteRegistrar::class)->registerAll();
}
}2
3
4
5
6
7
8
Tidak ada config register_routes per Panel.
Jika sebuah Panel memang tidak seharusnya memiliki route dari framework, Panel tersebut seharusnya tidak dimasukkan ke config('panda-panel.panels').
Route cache
PandaBear mendukung dan mengharapkan penggunaan:
php artisan route:cachedi production.
Registrar tidak menghasilkan Closure dan middleware parameter berupa string, sehingga route Panel kompatibel dengan Laravel route cache.
Recommended deployment:
php artisan route:cache
php artisan panel:cache2
Kedua cache menjawab pertanyaan berbeda:
route:cache
→ membekukan route definition
panel:cache
→ membekukan class list Resource/Page/Widget
yang jika tidak dicache akan ditemukan melalui discovery2
3
4
5
6
Jika Panel baru ditambahkan ke config setelah route:cache dibuat, Panel tersebut tidak mendapatkan route sampai route cache dibangun ulang.
php artisan optimize juga menjalankan panel:cache karena provider mendaftarkan:
$this->optimizes(
optimize: 'panel:cache',
clear: 'panel:clear',
key: 'panels',
);2
3
4
5
Failure saat route registration
Dua kondisi berikut sengaja menggagalkan boot:
PandaPanel\Exceptions\PanelRegistrationException::collidingRoutePath(
$path,
$existing,
$incoming
);
PandaPanel\Exceptions\PanelRegistrationException::unregisteredParentResource(
$resource,
$parent
);2
3
4
5
6
7
8
9
10
Route path collision. Terjadi ketika dua Resource pada Panel yang sama menghasilkan route shape yang sama.
Nama route parameter dihapus saat comparison.
Jadi:
{record}dan:
{parentRecord}dianggap shape yang sama.
Contoh collision:
ManageRelatedRecords
projects/{record}/tasks2
dengan nested Resource:
projects/{parentRecord}/tasksLaravel sendiri akan mencocokkan route pertama dan secara silent membuat route kedua tidak pernah terjangkau. PandaBear lebih memilih menggagalkan boot dengan error yang jelas.
Parent Resource belum terdaftar. Nested Resource harus memiliki parent Resource yang diregistrasikan pada Panel yang sama.
Jika tidak, nested Resource dapat menghasilkan URL hierarchy menuju parent route yang tidak pernah ada.
Karena itu registration dihentikan dengan PanelRegistrationException.
Kedua failure tersebut merupakan RuntimeException dan tidak ditangkap oleh framework.
Hal yang perlu diperhatikan
- Mematikan route registration tidak mematikan discovery. Registry tetap dibangun. Cost booting Panel tidak hilang; yang dihilangkan hanya HTTP routing.
- Panel yang didaftarkan setelah boot tidak otomatis memiliki route. Panggil
register()pada registrar laluRoute::getRoutes()->refreshNameLookups(). - Mengubah middleware Panel setelah boot tidak mengubah route yang sudah dibuat. Middleware stack sudah disalin ke route group saat registration.
- Jika
route:cachegagal setelah menambah Page, penyebabnya bukan route PandaBear. Registrar tidak menggunakan Closure. Periksaroutes/web.phpatau route default lain yang menyimpan object. - Panel diroute berdasarkan urutan id.
PanelRegistry::all()di-sort berdasarkan id sehingga output registration dan route cache deterministic, terlepas dari urutan provider di config.