8 · Naik ke produksi
Tujuan: proses deploy yang menghasilkan panel yang sama di server seperti di mesin Anda — dan postur keamanan yang bukan sekadar return true.
Pertama, tutup pintu yang tadi dibiarkan terbuka
Langkah 5 memberi ProductPolicy enam metode yang semuanya mengembalikan true. Itu wajar untuk tutorial, dan tidak wajar untuk apa pun selain itu. Setiap layar panel mendelegasikan keputusan ke Gate milik Laravel, jadi policy adalah aturannya:
<?php
declare(strict_types=1);
namespace App\Policies;
use App\Models\Product;
use App\Models\User;
final class ProductPolicy
{
public function viewAny(User $user): bool
{
return $user->is_admin;
}
public function view(User $user, Product $product): bool
{
return $user->is_admin;
}
public function create(User $user): bool
{
return $user->is_admin;
}
public function update(User $user, Product $product): bool
{
return $user->is_admin && $product->status !== 'archived';
}
public function delete(User $user, Product $product): bool
{
return $user->is_admin && $product->status === 'draft';
}
public function deleteAny(User $user): bool
{
return $user->is_admin;
}
}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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
Lalu beri panelnya aturan akses sendiri — separuh lainnya dari pasangan yang dibahas di langkah 4:
// app/Panels/Admin/AdminPanelProvider.php
use App\Models\User;
use Illuminate\Contracts\Auth\Authenticatable;
return $panel
->path('admin')
->name('Admin')
->auth()
->canAccess(static fn (?Authenticatable $user): bool
=> $user instanceof User && $user->is_admin)
->discoverResources(app_path('Panels/Admin/Resources'))
->discoverPages(app_path('Panels/Admin/Pages'))
->discoverWidgets(app_path('Panels/Admin/Widgets'));2
3
4
5
6
7
8
9
10
11
12
13
Pengguna yang sudah login tetapi ditolak mendapat 403, bukan redirect. Menyembunyikan navigasi bukan kontrol akses, dan panel ini tidak berpura-pura sebaliknya.
Buktikan, jangan cuma diyakini:
$this->actingAs(User::factory()->create())->get('/admin')->assertForbidden();
$this->actingAs(User::factory()->admin()->create())->get('/admin')->assertOk();2
Proses deploy-nya
Lima langkah dan satu restart:
composer install --no-dev --prefer-dist --optimize-autoloader
php artisan migrate --force
npm ci
npm run build
php artisan optimize # config, route, event, view — dan panel:cache
php artisan queue:restart2
3
4
5
6
7
8
9
10
Kenapa urutannya begitu
| Langkah | Bergantung pada langkah sebelumnya karena |
|---|---|
composer install | tidak bergantung apa pun — dia yang pertama |
migrate --force | migrasinya milik kode yang baru |
npm ci && npm run build | komponen yang dipublikasikan ke resources/js juga milik kode yang baru |
optimize | panel:cache me-resolve nama kelas lewat peta PSR-4 Composer, jadi manifest yang ditulis sebelum composer install menyebut kelas yang sudah pindah |
queue:restart | worker yang dijalankan sebelum deploy masih menjalankan kode lama, termasuk manifest panel yang lama |
Dua di antaranya cukup krusial untuk diulang: cache setelah Composer, jangan sebelumnya, dan restart worker paling akhir — worker yang restart di tengah deploy akan kembali sambil membawa separuh dari deploy itu.
panel:cache membekukan daftar kelas
Setelah dijalankan, discovery berhenti berjalan. Resource yang ditambahkan sesudahnya tidak punya route, tidak punya entri navigasi, dan tidak memunculkan error. Itu persis yang Anda inginkan di produksi dan persis yang tidak Anda inginkan di lokal, jadi: php artisan panel:clear saat development, php artisan optimize saat deploy.
Checklist
| Kenapa | |
|---|---|
.panel-assets.json ikut di-commit | Berkas ini mencatat versi frontend panel yang dipublikasikan aplikasi ini. Tanpanya, proses upgrade tidak bisa membedakan hasil suntingan Anda dari salinan basi |
npm run build dijalankan di server, atau hasil build-nya ikut dikirim | Memasang bukan berarti mem-build. Panel yang tampil tanpa gaya berarti build tidak pernah dijalankan |
| Setiap model di balik resource punya policy | Gate ditanya di setiap halaman. Tanpa policy artinya 403 |
Panelnya punya aturan canAccess() | Kalau tidak, setiap pengguna terautentikasi bisa masuk |
php artisan optimize dijalankan setelah composer install | Lihat penjelasan di atas |
php artisan queue:restart dijalankan paling akhir | Kalau tidak, ekspor, impor, dan notifikasi berantre menjalankan kode lama |
--no-dev aman | Tidak ada bagian src/ paket ini yang memakai dependensi require-dev |
ext-zip tersedia di server | Impor dan ekspor XLSX adalah kontainer ZIP. Composer gagal saat instalasi, bukan saat ekspor pertama |
Yang diperiksa setelah deploy
php artisan route:list --name=panel.
php artisan panel:cache # mencetak apa saja yang ditemukan, dalam jumlah2
Jumlahnya itulah pemeriksaannya. Untuk tutorial ini: satu panel, satu resource, satu widget. Angka nol di tempat yang seharusnya berisi berarti path discovery tidak lagi cocok dengan lokasi kelasnya.
Kalau gagal
| Gejala | Penyebab | Perbaikan |
|---|---|---|
| Resource hilang dari sidebar setelah deploy | panel:cache berjalan sebelum composer install | Jalankan ulang php artisan optimize |
| Ikon tidak tampil | Key-nya belum ada di registry saat build | php artisan panel:icons, lalu build ulang |
| Toast tidak pernah sampai | Worker antrean belum di-restart | php artisan queue:restart |
| Semuanya 403 | canAccess() yang baru membaca kolom yang belum diisi siapa pun | Isi is_admin pada akun operator |
| Layar panel tanpa gaya | npm run build tidak dijalankan, atau dijalankan sebelum publikasi | Build setelah composer install |
Selesai
Anda kini punya panel dengan resource, tabel yang bisa dicari, form yang memvalidasi, action dengan konfirmasi, dasbor yang menghitung, dan policy yang benar-benar berarti. Itulah keseluruhan lingkarannya — semua isi dokumentasi lainnya adalah bentuk yang sama, dengan variasi lebih banyak.
Ke mana selanjutnya
| Kalau Anda ingin… | Baca |
|---|---|
| Memahami apa yang barusan dibangun | Core concepts — panel, discovery, siklus request |
| Menambah data terkait pada sebuah produk | Relation managers |
| Menambah panel kedua untuk pelanggan | Multi-panel applications |
| Membatasi semuanya per tenant | Tenancy concepts |
| Menulis kolom atau field Vue sendiri | Frontend customization |
| Mengekspor tabel ke CSV atau XLSX | Import and export |
| Menguji semuanya | Test setup dan helper-nya |
| Melihat seluruh halaman | Peta dokumentasi |
Baca juga
- Production checklist — deploy yang sama, dengan seluruh alasannya
- Panel cache di produksi, Route cache
- Authorization — dua pemeriksaan itu, secara lengkap
- Negative security tests — memastikan pintunya benar-benar tertutup