Pengembangan Laravel
Aplikasi Laravel, dibangun dan dijaga tetap berjalan.
Dari model pertama hingga worker antrean, deploy, dan upgrade bertahun-tahun kemudian – ditulis, di-host, dan dirawat oleh satu tim.
Sebuah rilis, seperti yang terlihat di server
Setiap aplikasi Laravel yang kami jalankan dirilis dengan cara yang sama: diuji, dibangun, di-cache, dan diaktifkan tanpa downtime sedetik pun.
01ci ~/app $ php artisan test PASS Tests\Feature\CheckoutTest ✓ a paid order queues the invoice ✓ a declined card never marks the order paid PASS Tests\Unit\VatTest ✓ vat is added once, on the total 02app ~/releases/1400 $ composer install --no-dev --optimize-autoloaderInstalling dependencies from lock fileGenerating optimized autoload files 03app ~/releases/1400 $ php artisan migrate --force INFO Running migrations. 2026_09_27_090000_add_due_date_to_invoices ....... DONE 04app ~/releases/1400 $ php artisan optimize INFO Caching framework bootstrap, configuration, and metadata. config ...................................... DONE events ...................................... DONE routes ...................................... DONE views ....................................... DONE 05app ~/releases/1400 $ ln -sfn ~/releases/1400 ~/current06app ~/releases/1400 $ php artisan horizon:terminate && php artisan octane:reload 07app ~/releases/1400 $ sudo supervisorctl statushorizon RUNNING pid 48211, uptime 0:00:09octane RUNNING pid 31877, uptime 6 days, 2:14:51 08app ~/releases/1400 $ php artisan schedule:list */5 * * * * php artisan horizon:snapshot ... Next Due: 3 minutes from now 0 2 * * * php artisan model:prune ........ Next Due: 9 hours from now 0 9 * * * php artisan invoices:remind .... Next Due: 16 hours from now
Tes dulu
Tes dijalankan sebelum apa pun sampai ke server. Satu tes yang gagal menghentikan rilis.
Dependensi
Dipasang hanya dari file lock, tanpa paket pengembangan, dengan autoloader yang dioptimalkan.
Migrasi
Ditulis agar kode yang sedang berjalan tetap berfungsi dengan skema baru selama rilis beralih.
Cache
Konfigurasi, event, route, dan view di-cache. Sejak titik ini file environment tidak dibaca sama sekali, karena itulah env() hanya layak berada di file konfigurasi.
Peralihan
Satu tautan dipindahkan dan rilis baru langsung aktif. Rilis sebelumnya tetap di disk untuk rollback.
Worker
Horizon menuntaskan job yang sedang dikerjakan lalu memulai ulang dengan kode baru; Octane memuat ulang worker-nya dengan cara yang sama.
Diawasi
Supervisor menjaga Horizon dan Octane tetap berjalan, dan menghidupkan kembali salah satunya jika berhenti.
Penjadwal
Satu baris cron menjalankan setiap tugas terjadwal. Inilah yang akan dijalankannya berikutnya.
Dari satu klik hingga job yang selesai
Pekerjaan yang lambat keluar dari permintaan. Pelanggan langsung mendapat jawaban, dan worker mengerjakan sisanya di latar belakang.
-
01 · Permintaan
POST /checkoutPelanggan membayar
Controller memvalidasi pesanan, menyimpannya, dan langsung menjawab. Tidak ada proses lambat di sini.
-
02 · Job
PayOrder::dispatch()Bagian yang lambat menjadi job
Dikirim setelah database melakukan commit, sehingga worker tidak pernah mengambil pesanan yang sudah di-rollback.
-
03 · Antrean
redis · paymentsMenunggu di antreannya sendiri
Pembayaran punya antrean sendiri, sehingga ekspor yang panjang tidak pernah menahannya.
-
04 · Worker
horizon · supervisorSebuah worker mengambilnya
Dengan batas waktu, percobaan ulang yang menunggu makin lama setiap kali, dan batas jumlah yang berjalan bersamaan.
-
05 · Notifikasi
OrderPaid → mail, databaseSemua diberi tahu
Pelanggan menerima faktur lewat email, dan status pesanan berubah menjadi lunas di dasbor Anda.
failed_jobs
Job yang kehabisan percobaan ulang disimpan beserta error-nya, dan kami menerima peringatan. Job itu dicoba ulang setelah penyebabnya diperbaiki – tidak pernah hilang diam-diam.
Seluruh aplikasi, bukan hanya servernya
Tim kami membawa pengalaman PHP selama dua puluh lima tahun ke setiap proyek Laravel, dari model pertama hingga upgrade bertahun-tahun kemudian.
Bangun
Aplikasinya sendiri.
- Arsitektur
- Logika bisnis di action dan service, bukan di controller. Form request untuk validasi, policy untuk siapa boleh melakukan apa.
- Eloquent
- Relasi dimuat di awal saat sebuah halaman menampilkannya dalam daftar, sehingga satu halaman hanya butuh beberapa query, bukan ratusan. Saat pengembangan, lazy loading memicu error, sehingga masalahnya tertangkap sejak awal.
- Livewire · Inertia
- Livewire saat tim menulis PHP dan Blade; Inertia dengan Vue atau React saat front end adalah proyek tersendiri.
- API dengan Sanctum
- Token untuk aplikasi seluler dan mitra, sesi cookie untuk front end Anda sendiri, dan batas laju per klien.
- Pest · PHPUnit
- Tes untuk setiap alur yang menerima uang atau mengirim email, dijalankan pada setiap push sebelum rilis dibangun.
Jalankan
Yang membuatnya tetap merespons.
- Antrean dan Horizon
- Antrean terpisah untuk pekerjaan mendesak dan massal, masing-masing dengan worker, batas waktu, dan percobaan ulangnya sendiri, dipantau di dasbor Horizon.
- Penjadwal
- Satu baris cron menjalankan setiap tugas. Tugas yang tidak boleh tumpang-tindih, atau harus berjalan di satu server saja, ditandai demikian.
- Octane
- Swoole, RoadRunner, atau FrankenPHP menyimpan aplikasi di memori di antara permintaan. Sebelum mengaktifkannya, kami memeriksa kode untuk state yang bocor dari satu permintaan ke permintaan berikutnya.
- Redis
- Cache, sesi, antrean, dan lock, di Redis yang tidak bisa dijangkau dari internet.
- Supervisor
- Worker antrean, Horizon, dan Octane berjalan sebagai proses yang diawasi, dimulai ulang jika berhenti dan setelah setiap rilis.
Rawat
Yang membuatnya tetap mutakhir.
- Deploy tanpa downtime
- Setiap rilis dibangun di direktorinya sendiri dan diaktifkan dengan satu tautan. Kembali ke versi sebelumnya adalah langkah yang sama secara terbalik.
- Log dan eksepsi
- File log harian yang disimpan selama jangka waktu tertentu, dan setiap eksepsi dilaporkan kepada kami beserta permintaan yang memicunya.
- Upgrade
- Laravel merilis versi mayor setiap tahun. Kami memindahkan aplikasi satu versi demi satu versi, dengan tes yang lolos di setiap langkah.
Yang kami siapkan sejak hari pertama
Sebelum pelanggan pertama datang, setiap server Laravel yang kami jalankan sudah memiliki semua ini.
- Mode debug mati di produksi, dan hanya direktori public yang disajikan ke web
APP_DEBUG=false - Worker antrean di bawah Supervisor, dimulai ulang di setiap rilis
supervisord - Satu baris cron untuk penjadwal
* * * * * php artisan schedule:run - Redis untuk cache, sesi, dan antrean
CACHE_STORE=redis - Konfigurasi, event, route, dan view di-cache di setiap rilis
php artisan optimize - OPcache aktif, dan di-reset di setiap rilis
opcache.validate_timestamps=0 - Pool PHP-FPM yang disesuaikan dengan memori server
pm.max_children - Rilis di direktorinya sendiri, satu langkah dari rollback
current → releases/… - Job yang gagal dilaporkan kepada kami, tidak dibiarkan di tabel
failed_jobs - Rotasi log dan peringatan eksepsi
LOG_CHANNEL=daily - Cadangan database setiap malam, disalin ke luar server
backup · offsite - Sertifikat TLS yang diperbarui sendiri
Let's Encrypt
Rilis di disk
/var/www/example-app
├── current → releases/1400
├── releases/
│ ├── 1400
│ └── 0930
└── shared/
├── .env
└── storage/

Ceritakan tentang aplikasi Anda
Proyek baru, aplikasi yang butuh tempat, atau aplikasi yang tertahan di versi lama. Setiap proyek diberi penawaran setelah percakapan singkat.