Skip to content

Getting started

Requirements

  • PHP >= 8.2, extension curl dan sodium
  • Ekstensi Phalcon 5 terpasang sebagai PHP extension (bukan lewat composer)
  • guzzlehttp/guzzle (^7.4) terpasang otomatis lewat composer — dipakai Core\Auth\OAuth2\*/Core\Middleware\OAuth2Auth (client OAuth2/OIDC generik). Core\Auth\Casdoor\*/Core\Middleware\CasdoorAuth TIDAK butuh Guzzle sama sekali (tetap curl langsung) — lihat Casdoor & OAuth2/OIDC kalau cuma pakai Casdoor dan ingin tau kenapa dependency ini muncul di composer.lock Anda.
  • Opsional tergantung fitur yang dipakai: ext-sqlsrv + ext-pdo_sqlsrv (adapter SQL Server), ext-redis/ext-memcached (adapter session/cache)

Instalasi

json
{
    "repositories": [
        { "type": "vcs", "url": "git@git.aurorasystem.co.id:tirta-patriot/phoenix-core.git" }
    ],
    "require": {
        "tirta-patriot/phoenix-core": "^1.0"
    }
}
bash
composer require tirta-patriot/phoenix-core

Hapus baris "Core\\": "system/" dari autoload.psr-4 project Anda (sudah datang dari package), lalu hapus folder system/ fisiknya kalau sebelumnya di-copy manual.

Install langsung dari branch (belum di-tag)

Buat coba perubahan yang belum dirilis sebagai tag (mis. fix/feature yang masih di main tapi belum di-git tag), pakai constraint dev-{nama-branch} alih-alih ^x.y:

json
{
    "repositories": [
        { "type": "vcs", "url": "git@git.aurorasystem.co.id:tirta-patriot/phoenix-core.git" }
    ],
    "require": {
        "tirta-patriot/phoenix-core": "dev-main"
    }
}
bash
composer require tirta-patriot/phoenix-core:dev-main

Ganti main dengan nama branch lain kalau perlu (mis. dev-fix/nama-branch). Jangan pakai ini di production — begitu branch-nya berubah (force-push, commit baru), composer update bisa menarik kode yang belum pernah direview sebagai rilis. Kunci ke tag (§ di atas) begitu perubahannya sudah di-tag.

Quick start

App baru cukup:

php
// public/index.php
require_once __DIR__ . '/../vendor/autoload.php';

Core\Kernel::boot()->run();

Kernel::boot() (tanpa argumen) otomatis: registrasi ErrorHandler (strict default), deteksi BASEPATH lewat lokasi install package ini (Composer\InstalledVersions), Environment::boot() (muat .env, daftarkan helper env()/env_bool()), lalu TrustProxy::beforeExecute() (terjemahkan X-Forwarded-* dari app/config/trustproxy.php kalau ada, no-op kalau tidak) — urutan ini WAJIB persis begini: ErrorHandler duluan supaya error di Environment::boot() sendiri (.env malformed, dst) ikut tertangani rapi, bukan raw PHP fatal error yang bocorin full path/stack trace ke browser; TrustProxy sebelum request URI/baseURL dihitung, supaya app di belakang reverse proxy TLS-terminating tetap mendeteksi HTTPS dengan benar tanpa app perlu memanggil apa pun secara manual.

Kalau butuh kontrol eksplisit (mis. ErrorHandler::register(false) untuk app lama yang masih banyak warning laten, atau BASEPATH custom/tidak standar):

php
// public/index.php
define('BASEPATH', realpath(__DIR__ . '/..'));
require_once BASEPATH . '/vendor/autoload.php';

// Didaftarkan manual SEBELUM Kernel::boot() supaya menang — register()
// idempotent, panggilan pertama yang menang (lihat catatan di bawah).
Core\ErrorHandler::register(false);

Core\Kernel::boot(BASEPATH)->run();

Environment::boot() aman dipanggil manual juga sebelum Kernel::boot() (idempotent, no-op kedua) — app lama yang sudah punya baris itu di public/index.php-nya TIDAK perlu diubah.

Core\Kernel::boot() otomatis mendaftarkan Core\DefaultServiceProvider, yang menyediakan service: config, crypt, request, response, cookies, router, security, url, filter, logger, eventsManager, dispatcher, session, db (+ db.{key} per koneksi tambahan), viewCache, dataCache, modelsManager, escaper, flash, annotations, registry, modelsMetadata, view, Hashids\Hashids::class.

Core\ErrorHandler::register() (opsional, tapi sangat disarankan) memasang set_error_handler/set_exception_handler/register_shutdown_function yang:

  • Render halaman debug (Phalcon\Support\Debug) kalau APP_DEBUG=true DAN APP_ENV bukan production — dua syarat sekaligus, supaya stack trace tidak pernah bocor di production meski APP_DEBUG ketinggalan true.
  • Respons JSON ({error, message}, + trace kalau debug) untuk request AJAX (X-Requested-With: XMLHttpRequest) atau Accept: application/json.
  • Render lewat View/Volt kalau service view tersedia di DI — cari app/views/Errors/notFound.volt (404), Errors/unauthorized.volt (401/403), Errors/error{code}.volt (kalau ada), fallback Errors/error500.volt. Kalau app belum punya file .volt yang cocok sama sekali, jatuh ke HTML generik bawaan — dicek pakai file_exists() dulu, bukan cuma andalkan try/catch, karena Phalcon\Mvc\View::render() TIDAK throw kalau file target tidak ada (cuma balikin content kosong), jadi tanpa cek ini response bisa 500 dengan body benar-benar kosong.
  • Exception Phalcon\(Mvc\)Dispatcher\Exception (route/controller/action tidak ketemu) otomatis dipetakan ke 404, bukan 500.
  • Aman didaftarkan SEBELUM Environment::boot() (lihat urutan di atas) — isDebugMode() fallback ke getenv() mentah kalau helper env()/env_bool() belum ke-load, jadi error di Environment::boot() sendiri (.env malformed, dst) tetap tertangani rapi, bukan raw PHP fatal error yang bocorin full path server + stack trace ke browser.

register(bool $throwOnWarnings = true) — parameter opsional untuk app existing/legacy yang punya banyak warning laten (undefined variable/array key, dst) yang selama ini diam-diam ditoleransi PHP:

php
Core\ErrorHandler::register(false); // lenient: warning cuma di-error_log(), TIDAK 500-in page
  • Default true (strict) — E_WARNING/E_NOTICE/E_DEPRECATED dkk langsung jadi ErrorException yang menghentikan request. Cocok untuk app baru/bersih — bug ketahuan sesegera mungkin.
  • false (lenient) — level di atas cuma di-error_log(), request lanjut jalan seperti PHP klasik. E_RECOVERABLE_ERROR dan E_USER_ERROR (fatal eksplisit lewat trigger_error(..., E_USER_ERROR)) tetap fatal apa pun nilai parameter ini — dua level itu bukan "gaya kode lama", tapi indikasi state sudah rusak.
  • register() idempotent — panggilan PERTAMA yang menang, panggilan berikutnya jadi no-op (termasuk parameternya diabaikan). Ini WAJIB tahu: Core\Kernel::boot() sendiri memanggil ErrorHandler::register() tanpa argumen sebagai fallback default untuk app yang belum sempat register manual. Karena idempotent, app yang sudah panggil register(false) lebih dulu (lihat urutan Quick start di atas) TIDAK akan ketimpa balik ke strict oleh panggilan fallback Kernel itu — tapi kalau urutannya kebalik (Kernel jalan duluan sebelum app sempat register), app kehilangan kontrol parameter ini sama sekali. Bug nyata ini pernah kejadian: register(false) di public/index.php terlihat tidak berefek sampai ketemu akar masalahnya.