Learn
Pelajari Tentang Flight
Flight adalah kerangka kerja PHP yang cepat, sederhana, dan dapat diperluas. Ini cukup serbaguna dan dapat digunakan untuk membangun berbagai macam aplikasi web. Ini dibangun dengan kesederhanaan dalam pikiran dan ditulis dengan cara yang mudah dipahami dan digunakan.
Konsep Kerangka Kerja yang Penting
Mengapa Kerangka Kerja?
Berikut adalah artikel singkat tentang mengapa Anda harus menggunakan kerangka kerja. Ini adalah ide bagus untuk memahami manfaat menggunakan kerangka kerja sebelum Anda mulai menggunakannya.
Selain itu, tutorial yang sangat baik telah dibuat oleh @lubiana. Meskipun tidak membahas secara mendetail tentang Flight secara spesifik, panduan ini akan membantu Anda memahami beberapa konsep utama yang mengelilingi kerangka kerja dan mengapa mereka bermanfaat untuk digunakan. Anda dapat menemukan tutorial di sini.
Flight Dibandingkan dengan Kerangka Kerja Lain
Jika Anda berpindah dari kerangka kerja lain seperti Laravel, Slim, Fat-Free, atau Symfony ke Flight, halaman ini akan membantu Anda memahami perbedaan antara keduanya.
Topik Inti
Pengautoloadan
Pelajari cara mengautoload kelas Anda sendiri dalam aplikasi Anda.
Routing
Pelajari cara mengelola rute untuk aplikasi web Anda. Ini juga termasuk pengelompokan rute, parameter rute, dan middleware.
Middleware
Pelajari cara menggunakan middleware untuk menyaring permintaan dan respons dalam aplikasi Anda.
Permintaan
Pelajari cara menangani permintaan dan respons dalam aplikasi Anda.
Respons
Pelajari cara mengirim respons kepada pengguna Anda.
Peristiwa
Pelajari cara menggunakan sistem peristiwa untuk menambahkan peristiwa khusus ke aplikasi Anda.
Template HTML
Pelajari cara menggunakan mesin tampilan bawaan untuk merender template HTML Anda.
Keamanan
Pelajari cara mengamankan aplikasi Anda dari ancaman keamanan umum.
Konfigurasi
Pelajari cara mengonfigurasi kerangka kerja untuk aplikasi Anda.
Memperluas Flight
Pelajari cara memperluas kerangka kerja dengan menambahkan metode dan kelas Anda sendiri.
Peristiwa dan Penyaringan
Pelajari cara menggunakan sistem peristiwa untuk menambahkan hook ke metode Anda dan metode kerangka kerja internal.
Kontainer Penyuntikan Ketergantungan
Pelajari cara menggunakan kontainer penyuntikan ketergantungan (DIC) untuk mengelola ketergantungan aplikasi Anda.
API Kerangka Kerja
Pelajari tentang metode inti dari kerangka kerja.
Migrasi ke v3
Kompatibilitas ke belakang sebagian besar telah dipertahankan, tetapi ada beberapa perubahan yang harus Anda ketahui saat bermigrasi dari v2 ke v3.
Pemecahan Masalah
Ada beberapa masalah umum yang mungkin Anda temui saat menggunakan Flight. Halaman ini akan membantu Anda memecahkan masalah tersebut.
Learn/flight_vs_laravel
Flight vs Laravel
Apa itu Laravel?
Laravel adalah framework yang memiliki fitur lengkap yang dilengkapi dengan segala hal menarik dan ekosistem yang berfokus pada pengembang, tetapi dengan biaya dalam hal kinerja dan kompleksitas. Tujuan Laravel adalah agar pengembang memiliki tingkat produktivitas tertinggi dan untuk memudahkan tugas-tugas umum. Laravel adalah pilihan yang baik bagi pengembang yang mencari untuk membangun aplikasi web berfitur lengkap untuk perusahaan. Itu datang dengan beberapa pertukaran, terutama dalam hal kinerja dan kompleksitas. Mempelajari dasar-dasar Laravel bisa jadi mudah, tetapi menguasai framework ini bisa memakan waktu.
Ada juga banyak modul Laravel sehingga pengembang sering merasa bahwa satu-satunya cara untuk menyelesaikan masalah adalah melalui modul-modul ini, padahal sebenarnya Anda bisa saja menggunakan perpustakaan lain atau menulis kode Anda sendiri.
Kelebihan dibandingkan Flight
- Laravel memiliki ekosistem yang besar dari pengembang dan modul yang dapat digunakan untuk memecahkan masalah umum.
- Laravel memiliki ORM berfitur lengkap yang dapat digunakan untuk berinteraksi dengan basis data Anda.
- Laravel memiliki jumlah dokumentasi dan tutorial yang luar biasa yang dapat digunakan untuk mempelajari framework ini.
- Laravel memiliki sistem autentikasi bawaan yang dapat digunakan untuk mengamankan aplikasi Anda.
- Laravel memiliki podcast, konferensi, pertemuan, video, dan sumber daya lainnya yang dapat digunakan untuk mempelajari framework ini.
- Laravel ditujukan untuk pengembang berpengalaman yang mencari untuk membangun aplikasi web berfitur lengkap untuk perusahaan.
Kekurangan dibandingkan Flight
- Laravel memiliki lebih banyak hal yang terjadi di balik layar dibandingkan dengan Flight. Ini datang dengan biaya yang dramatis dalam hal kinerja. Lihat benchmark TechEmpower untuk informasi lebih lanjut.
- Flight ditujukan untuk pengembang yang ingin membangun aplikasi web yang ringan, cepat, dan mudah digunakan.
- Flight ditujukan untuk kesederhanaan dan kemudahan penggunaan.
- Salah satu fitur inti Flight adalah bahwa ia berusaha sebaik mungkin untuk menjaga kompatibilitas ke belakang. Laravel menyebabkan banyak frustrasi antara versi besar.
- Flight ditujukan untuk pengembang yang menjelajahi dunia framework untuk pertama kalinya.
- Flight tidak memiliki ketergantungan, sedangkan Laravel memiliki jumlah ketergantungan yang sangat banyak
- Flight juga dapat melakukan aplikasi tingkat perusahaan, tetapi tidak memiliki sebanyak kode boilerplate seperti yang dimiliki Laravel. Itu juga akan memerlukan lebih banyak disiplin dari pihak pengembang untuk menjaga segala sesuatunya terorganisir dan terstruktur dengan baik.
- Flight memberi pengembang lebih banyak kontrol atas aplikasinya, sedangkan Laravel memiliki banyak keajaiban di balik layar yang bisa membuat frustrasi.
Learn/migrating_to_v3
Migrasi ke v3
Kompatibilitas ke belakang sebagian besar telah dipertahankan, tetapi ada beberapa perubahan yang harus Anda perhatikan saat migrasi dari v2 ke v3.
Perilaku Buffering Output (3.5.0)
Buffering output adalah proses di mana output yang dihasilkan oleh skrip PHP disimpan dalam buffer (internal di PHP) sebelum dikirim ke klien. Ini memungkinkan Anda untuk memodifikasi output sebelum dikirim ke klien.
Dalam aplikasi MVC, Controller adalah "pengelola" dan mengatur apa yang dilakukan tampilan. Memiliki output yang dihasilkan di luar controller (atau dalam kasus Flight kadang-kadang fungsi anonim) merusak pola MVC. Perubahan ini bertujuan untuk lebih selaras dengan pola MVC dan untuk membuat framework lebih dapat diprediksi dan lebih mudah digunakan.
Di v2, buffering output ditangani sedemikian rupa sehingga tidak secara konsisten menutup buffer output sendiri dan ini membuat unit testing dan streaming menjadi lebih sulit. Untuk sebagian besar pengguna, perubahan ini mungkin tidak benar-benar memengaruhi Anda. Namun jika Anda mencetak konten di luar callable dan controller (misalnya dalam hook), Anda kemungkinan akan menghadapi masalah. Mencetak konten dalam hook, dan sebelum framework benar-benar mengeksekusi mungkin berfungsi di masa lalu, tetapi tidak akan berfungsi ke depan.
Di mana Anda mungkin mengalami masalah
// index.php
require 'vendor/autoload.php';
// hanya contoh
define('START_TIME', microtime(true));
function hello() {
echo 'Hello World';
}
Flight::map('hello', 'hello');
Flight::after('hello', function(){
// ini sebenarnya baik-baik saja
echo '<p>Frasa Hello World ini dibawakan kepada Anda oleh huruf "H"</p>';
});
Flight::before('start', function(){
// hal-hal seperti ini akan menyebabkan kesalahan
echo '<html><head><title>Halaman Saya</title></head><body>';
});
Flight::route('/', function(){
// ini sebenarnya baik-baik saja
echo 'Hello World';
// Ini juga seharusnya baik-baik saja
Flight::hello();
});
Flight::after('start', function(){
// ini akan menyebabkan kesalahan
echo '<div>Halaman Anda dimuat dalam '.(microtime(true) - START_TIME).' detik</div></body></html>';
});
Mengaktifkan Perilaku Rendering v2
Apakah Anda masih bisa menjaga kode lama Anda seperti semula tanpa melakukan penulisan ulang untuk membuatnya berfungsi dengan v3? Ya, Anda bisa! Anda dapat mengaktifkan
perilaku rendering v2 dengan mengatur opsi konfigurasi flight.v2.output_buffering
menjadi true
. Ini akan memungkinkan Anda untuk terus menggunakan
perilaku rendering lama, tetapi disarankan untuk memperbaikinya ke depan. Di v4 dari framework, ini akan dihapus.
// index.php
require 'vendor/autoload.php';
Flight::set('flight.v2.output_buffering', true);
Flight::before('start', function(){
// Sekarang ini akan baik-baik saja
echo '<html><head><title>Halaman Saya</title></head><body>';
});
// lebih banyak kode
Perubahan Dispatcher (3.7.0)
Jika Anda langsung memanggil metode statis untuk Dispatcher
seperti Dispatcher::invokeMethod()
, Dispatcher::execute()
, dll.
Anda perlu memperbarui kode Anda agar tidak langsung memanggil metode ini. Dispatcher
telah diubah menjadi lebih berorientasi objek sehingga
Container Penyuntikan Ketergantungan dapat digunakan dengan cara yang lebih mudah. Jika Anda perlu memanggil metode mirip seperti yang dilakukan Dispatcher, Anda
dapat menggunakan sesuatu seperti $result = $class->$method(...$params);
atau call_user_func_array()
sebagai gantinya.
Perubahan halt()
stop()
redirect()
dan error()
(3.10.0)
Perilaku default sebelum 3.10.0 adalah untuk menghapus baik header maupun body respons. Ini diubah hanya untuk menghapus body respons.
Jika Anda perlu menghapus header juga, Anda bisa menggunakan Flight::response()->clear()
.
Learn/configuration
Konfigurasi
Anda dapat menyesuaikan perilaku tertentu dari Flight dengan menetapkan nilai konfigurasi melalui metode set
.
Flight::set('flight.log_errors', true);
Pengaturan Konfigurasi Tersedia
Berikut adalah daftar semua pengaturan konfigurasi yang tersedia:
- flight.base_url
?string
- Gantilah URL dasar dari permintaan. (default: null) - flight.case_sensitive
bool
- Pencocokan sensitif terhadap huruf untuk URL. (default: false) - flight.handle_errors
bool
- Izinkan Flight menangani semua kesalahan secara internal. (default: true) - flight.log_errors
bool
- Catat kesalahan ke file log kesalahan server web. (default: false) - flight.views.path
string
- Direktori yang berisi file template tampilan. (default: ./views) - flight.views.extension
string
- Ekstensi file template tampilan. (default: .php) - flight.content_length
bool
- Atur headerContent-Length
. (default: true) - flight.v2.output_buffering
bool
- Gunakan buffering output tradisional. Lihat migrasi ke v3. (default: false)
Konfigurasi Loader
Selain itu, ada pengaturan konfigurasi lain untuk loader. Ini akan memungkinkan Anda
untuk memuat kelas secara otomatis dengan _
dalam nama kelas.
// Aktifkan pemuatan kelas dengan garis bawah
// Defaultnya adalah true
Loader::$v2ClassLoading = false;
Variabel
Flight memungkinkan Anda untuk menyimpan variabel sehingga dapat digunakan di mana saja dalam aplikasi Anda.
// Simpan variabel Anda
Flight::set('id', 123);
// Di tempat lain dalam aplikasi Anda
$id = Flight::get('id');
Untuk melihat apakah sebuah variabel telah disetel, Anda dapat melakukan:
if (Flight::has('id')) {
// Lakukan sesuatu
}
Anda dapat menghapus variabel dengan melakukan:
// Menghapus variabel id
Flight::clear('id');
// Menghapus semua variabel
Flight::clear();
Flight juga menggunakan variabel untuk tujuan konfigurasi.
Flight::set('flight.log_errors', true);
Penanganan Kesalahan
Kesalahan dan Pengecualian
Semua kesalahan dan pengecualian ditangkap oleh Flight dan diteruskan ke metode error
.
Perilaku default adalah mengirimkan respons HTTP 500 Internal Server Error
dengan beberapa informasi kesalahan.
Anda dapat mengganti perilaku ini sesuai kebutuhan Anda:
Flight::map('error', function (Throwable $error) {
// Tangani kesalahan
echo $error->getTraceAsString();
});
Secara default kesalahan tidak dicatat ke server web. Anda dapat mengaktifkan ini dengan mengubah konfigurasi:
Flight::set('flight.log_errors', true);
Tidak Ditemukan
Ketika sebuah URL tidak dapat ditemukan, Flight memanggil metode notFound
. Perilaku default
adalah mengirimkan respons HTTP 404 Not Found
dengan pesan sederhana.
Anda dapat mengganti perilaku ini sesuai kebutuhan Anda:
Flight::map('notFound', function () {
// Tangani tidak ditemukan
});
Learn/security
Keamanan
Keamanan adalah hal yang penting ketika berhubungan dengan aplikasi web. Anda ingin memastikan bahwa aplikasi Anda aman dan data pengguna Anda terlindungi. Flight menyediakan sejumlah fitur untuk membantu Anda mengamankan aplikasi web Anda.
Header
Header HTTP adalah salah satu cara termudah untuk mengamankan aplikasi web Anda. Anda dapat menggunakan header untuk mencegah clickjacking, XSS, dan serangan lainnya. Ada beberapa cara yang dapat Anda lakukan untuk menambahkan header ini ke aplikasi Anda.
Dua situs web yang bagus untuk memeriksa keamanan header Anda adalah securityheaders.com dan observatory.mozilla.org.
Tambah Secara Manual
Anda dapat menambahkan header ini secara manual dengan menggunakan metode header
pada objek Flight\Response
.
// Atur header X-Frame-Options untuk mencegah clickjacking
Flight::response()->header('X-Frame-Options', 'SAMEORIGIN');
// Atur header Content-Security-Policy untuk mencegah XSS
// Catatan: header ini bisa menjadi sangat kompleks, jadi Anda akan
// ingin berkonsultasi dengan contoh di internet untuk aplikasi Anda
Flight::response()->header("Content-Security-Policy", "default-src 'self'");
// Atur header X-XSS-Protection untuk mencegah XSS
Flight::response()->header('X-XSS-Protection', '1; mode=block');
// Atur header X-Content-Type-Options untuk mencegah sniffing MIME
Flight::response()->header('X-Content-Type-Options', 'nosniff');
// Atur header Referrer-Policy untuk mengontrol seberapa banyak informasi referer yang dikirim
Flight::response()->header('Referrer-Policy', 'no-referrer-when-downgrade');
// Atur header Strict-Transport-Security untuk memaksakan HTTPS
Flight::response()->header('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload');
// Atur header Permissions-Policy untuk mengontrol fitur dan API apa yang dapat digunakan
Flight::response()->header('Permissions-Policy', 'geolocation=()');
Header ini dapat ditambahkan di atas file bootstrap.php
atau index.php
Anda.
Tambah sebagai Filter
Anda juga dapat menambahkannya dalam filter/hook seperti berikut:
// Tambahkan header dalam filter
Flight::before('start', function() {
Flight::response()->header('X-Frame-Options', 'SAMEORIGIN');
Flight::response()->header("Content-Security-Policy", "default-src 'self'");
Flight::response()->header('X-XSS-Protection', '1; mode=block');
Flight::response()->header('X-Content-Type-Options', 'nosniff');
Flight::response()->header('Referrer-Policy', 'no-referrer-when-downgrade');
Flight::response()->header('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload');
Flight::response()->header('Permissions-Policy', 'geolocation=()');
});
Tambah sebagai Middleware
Anda juga dapat menambahkannya sebagai kelas middleware. Ini adalah cara yang baik untuk menjaga kode Anda tetap bersih dan terorganisir.
// app/middleware/SecurityHeadersMiddleware.php
namespace app\middleware;
class SecurityHeadersMiddleware
{
public function before(array $params): void
{
Flight::response()->header('X-Frame-Options', 'SAMEORIGIN');
Flight::response()->header("Content-Security-Policy", "default-src 'self'");
Flight::response()->header('X-XSS-Protection', '1; mode=block');
Flight::response()->header('X-Content-Type-Options', 'nosniff');
Flight::response()->header('Referrer-Policy', 'no-referrer-when-downgrade');
Flight::response()->header('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload');
Flight::response()->header('Permissions-Policy', 'geolocation=()');
}
}
// index.php atau di mana pun Anda memiliki rute Anda
// FYI, grup string kosong ini bertindak sebagai middleware global untuk
// semua rute. Tentu saja Anda dapat melakukan hal yang sama dan hanya menambah
// ini hanya di rute tertentu.
Flight::group('', function(Router $router) {
$router->get('/users', [ 'UserController', 'getUsers' ]);
// lebih banyak rute
}, [ new SecurityHeadersMiddleware() ]);
Serangan Permintaan Lintas Situs (CSRF)
Serangan Permintaan Lintas Situs (CSRF) adalah jenis serangan di mana situs web jahat dapat membuat browser pengguna mengirim permintaan ke situs web Anda. Ini dapat digunakan untuk melakukan tindakan di situs web Anda tanpa sepengetahuan pengguna. Flight tidak menyediakan mekanisme perlindungan CSRF bawaan, tetapi Anda dapat dengan mudah mengimplementasikan sendiri menggunakan middleware.
Setup
Pertama Anda perlu menghasilkan token CSRF dan menyimpannya di sesi pengguna. Anda kemudian dapat menggunakan token ini dalam formulir Anda dan memeriksanya saat formulir diserahkan.
// Menghasilkan token CSRF dan menyimpannya di sesi pengguna
// (asumsikan Anda telah membuat objek sesi dan mengaitkannya dengan Flight)
// lihat dokumentasi sesi untuk informasi lebih lanjut
Flight::register('session', \Ghostff\Session\Session::class);
// Anda hanya perlu menghasilkan satu token per sesi (agar berfungsi
// di beberapa tab dan permintaan untuk pengguna yang sama)
if(Flight::session()->get('csrf_token') === null) {
Flight::session()->set('csrf_token', bin2hex(random_bytes(32)) );
}
<!-- Gunakan token CSRF di formulir Anda -->
<form method="post">
<input type="hidden" name="csrf_token" value="<?= Flight::session()->get('csrf_token') ?>">
<!-- field formulir lainnya -->
</form>
Menggunakan Latte
Anda juga dapat mengatur fungsi kustom untuk menampilkan token CSRF dalam template Latte Anda.
// Atur fungsi kustom untuk menampilkan token CSRF
// Catatan: View telah dikonfigurasi dengan Latte sebagai mesin tampilan
Flight::view()->addFunction('csrf', function() {
$csrfToken = Flight::session()->get('csrf_token');
return new \Latte\Runtime\Html('<input type="hidden" name="csrf_token" value="' . $csrfToken . '">');
});
Dan sekarang di template Latte Anda, Anda dapat menggunakan fungsi csrf()
untuk menampilkan token CSRF.
<form method="post">
{csrf()}
<!-- field formulir lainnya -->
</form>
Singkat dan sederhana, bukan?
Periksa Token CSRF
Anda dapat memeriksa token CSRF menggunakan filter peristiwa:
// Middleware ini memeriksa apakah permintaan adalah permintaan POST dan jika iya, memeriksa apakah token CSRF valid
Flight::before('start', function() {
if(Flight::request()->method == 'POST') {
// tangkap token csrf dari nilai formulir
$token = Flight::request()->data->csrf_token;
if($token !== Flight::session()->get('csrf_token')) {
Flight::halt(403, 'Token CSRF tidak valid');
// atau untuk respons JSON
Flight::jsonHalt(['error' => 'Token CSRF tidak valid'], 403);
}
}
});
Atau Anda dapat menggunakan kelas middleware:
// app/middleware/CsrfMiddleware.php
namespace app\middleware;
class CsrfMiddleware
{
public function before(array $params): void
{
if(Flight::request()->method == 'POST') {
$token = Flight::request()->data->csrf_token;
if($token !== Flight::session()->get('csrf_token')) {
Flight::halt(403, 'Token CSRF tidak valid');
}
}
}
}
// index.php atau di mana pun Anda memiliki rute Anda
Flight::group('', function(Router $router) {
$router->get('/users', [ 'UserController', 'getUsers' ]);
// lebih banyak rute
}, [ new CsrfMiddleware() ]);
Serangan Skrip Lintas Situs (XSS)
Serangan Skrip Lintas Situs (XSS) adalah jenis serangan di mana situs web jahat dapat menyuntikkan kode ke situs web Anda. Sebagian besar peluang ini datang dari nilai formulir yang akan diisi oleh pengguna akhir Anda. Anda tidak pernah mempercayai output dari pengguna Anda! Selalu anggap semua dari mereka adalah hacker terbaik di dunia. Mereka dapat menyuntikkan JavaScript atau HTML berbahaya ke halaman Anda. Kode ini dapat digunakan untuk mencuri informasi dari pengguna Anda atau melakukan tindakan di situs web Anda. Dengan menggunakan kelas view dari Flight, Anda dapat dengan mudah melarikan output untuk mencegah serangan XSS.
// Mari kita anggap pengguna cerdas dan mencoba menggunakan ini sebagai nama mereka
$name = '<script>alert("XSS")</script>';
// Ini akan melarikan output
Flight::view()->set('name', $name);
// Ini akan menampilkan: <script>alert("XSS")</script>
// Jika Anda menggunakan sesuatu seperti Latte yang terdaftar sebagai kelas view Anda, ini juga akan otomatis melarikan ini.
Flight::view()->render('template', ['name' => $name]);
SQL Injection
SQL Injection adalah jenis serangan di mana pengguna jahat dapat menyuntikkan kode SQL ke dalam database Anda. Ini dapat digunakan untuk mencuri informasi
dari database Anda atau melakukan tindakan di database Anda. Sekali lagi Anda tidak pernah mempercayai input dari pengguna Anda! Selalu anggap mereka
berniat buruk. Anda dapat menggunakan pernyataan terprepared dalam objek PDO
Anda untuk mencegah SQL injection.
// Menganggap Anda memiliki Flight::db() terdaftar sebagai objek PDO Anda
$statement = Flight::db()->prepare('SELECT * FROM users WHERE username = :username');
$statement->execute([':username' => $username]);
$users = $statement->fetchAll();
// Jika Anda menggunakan kelas PdoWrapper, ini dapat dengan mudah dilakukan dalam satu baris
$users = Flight::db()->fetchAll('SELECT * FROM users WHERE username = :username', [ 'username' => $username ]);
// Anda dapat melakukan hal yang sama dengan objek PDO dengan placeholder ?
$statement = Flight::db()->fetchAll('SELECT * FROM users WHERE username = ?', [ $username ]);
// Janji Anda tidak akan pernah MELAKUKAN sesuatu seperti ini...
$users = Flight::db()->fetchAll("SELECT * FROM users WHERE username = '{$username}' LIMIT 5");
// karena bagaimana jika $username = "' OR 1=1; -- ";
// Setelah kueri dibangun, terlihat seperti ini
// SELECT * FROM users WHERE username = '' OR 1=1; -- LIMIT 5
// Ini terlihat aneh, tetapi ini adalah kueri yang valid yang akan berfungsi.
// Faktanya,
// ini adalah serangan SQL injection yang sangat umum yang akan mengembalikan semua pengguna.
CORS
Cross-Origin Resource Sharing (CORS) adalah mekanisme yang memungkinkan banyak sumber daya (misalnya, font, JavaScript, dll.) di halaman web untuk
diminta dari domain lain di luar domain tempat sumber daya tersebut berasal. Flight tidak memiliki fungsi bawaan,
tetapi ini dapat dengan mudah ditangani dengan hook untuk dijalankan sebelum metode Flight::start()
dipanggil.
// app/utils/CorsUtil.php
namespace app\utils;
class CorsUtil
{
public function set(array $params): void
{
$request = Flight::request();
$response = Flight::response();
if ($request->getVar('HTTP_ORIGIN') !== '') {
$this->allowOrigins();
$response->header('Access-Control-Allow-Credentials', 'true');
$response->header('Access-Control-Max-Age', '86400');
}
if ($request->method === 'OPTIONS') {
if ($request->getVar('HTTP_ACCESS_CONTROL_REQUEST_METHOD') !== '') {
$response->header(
'Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD'
);
}
if ($request->getVar('HTTP_ACCESS_CONTROL_REQUEST_HEADERS') !== '') {
$response->header(
"Access-Control-Allow-Headers",
$request->getVar('HTTP_ACCESS_CONTROL_REQUEST_HEADERS')
);
}
$response->status(200);
$response->send();
exit;
}
}
private function allowOrigins(): void
{
// sesuaikan host yang diizinkan Anda di sini.
$allowed = [
'capacitor://localhost',
'ionic://localhost',
'http://localhost',
'http://localhost:4200',
'http://localhost:8080',
'http://localhost:8100',
];
$request = Flight::request();
if (in_array($request->getVar('HTTP_ORIGIN'), $allowed, true) === true) {
$response = Flight::response();
$response->header("Access-Control-Allow-Origin", $request->getVar('HTTP_ORIGIN'));
}
}
}
// index.php atau di mana pun Anda memiliki rute Anda
$CorsUtil = new CorsUtil();
// Ini perlu dijalankan sebelum start dijalankan.
Flight::before('start', [ $CorsUtil, 'setupCors' ]);
Penanganan Kesalahan
Sembunyikan detail kesalahan sensitif di produksi untuk menghindari kebocoran informasi kepada penyerang.
// Di bootstrap.php atau index.php Anda
// di flightphp/skeleton, ini ada di app/config/config.php
$environment = ENVIRONMENT;
if ($environment === 'production') {
ini_set('display_errors', 0); // Nonaktifkan tampilan error
ini_set('log_errors', 1); // Catat kesalahan sebagai gantinya
ini_set('error_log', '/path/to/error.log');
}
// Di rute atau pengontrol Anda
// Gunakan Flight::halt() untuk respons kesalahan yang terkendali
Flight::halt(403, 'Akses ditolak');
Sanitasi Input
Jangan pernah mempercayai input pengguna. Sanitasi sebelum memproses untuk mencegah data berbahaya masuk.
// Menganggap permintaan $_POST dengan $_POST['input'] dan $_POST['email']
// Sanitasi input string
$clean_input = filter_var(Flight::request()->data->input, FILTER_SANITIZE_STRING);
// Sanitasi email
$clean_email = filter_var(Flight::request()->data->email, FILTER_SANITIZE_EMAIL);
Hashing Password
Simpan password dengan aman dan verifikasi dengan aman menggunakan fungsi bawaan PHP.
$password = Flight::request()->data->password;
// Hash password saat menyimpan (misalnya, saat pendaftaran)
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
// Verifikasi password (misalnya, saat login)
if (password_verify($password, $stored_hash)) {
// Password cocok
}
Pembatasan Kecepatan
Lindungi terhadap serangan brute force dengan membatasi laju permintaan menggunakan cache.
// Menganggap Anda telah menginstal dan mendaftarkan flightphp/cache
// Menggunakan flightphp/cache dalam middleware
Flight::before('start', function() {
$cache = Flight::cache();
$ip = Flight::request()->ip;
$key = "rate_limit_{$ip}";
$attempts = (int) $cache->retrieve($key);
if ($attempts >= 10) {
Flight::halt(429, 'Terlalu banyak permintaan');
}
$cache->set($key, $attempts + 1, 60); // Reset setelah 60 detik
});
Kesimpulan
Keamanan adalah hal yang penting dan penting untuk memastikan aplikasi web Anda aman. Flight menyediakan sejumlah fitur untuk membantu Anda mengamankan aplikasi web Anda, tetapi penting untuk selalu waspada dan memastikan Anda melakukan segala sesuatu yang Anda bisa untuk menjaga data pengguna Anda tetap aman. Selalu anggap yang terburuk dan jangan pernah mempercayai input dari pengguna Anda. Selalu melarikan output dan gunakan pernyataan terprepared untuk mencegah SQL injection. Selalu gunakan middleware untuk melindungi rute Anda dari serangan CSRF dan CORS. Jika Anda melakukan semua hal ini, Anda akan berada di jalur yang tepat untuk membangun aplikasi web yang aman.
Learn/routing
Routing
Catatan: Ingin memahami lebih lanjut tentang routing? Periksa halaman "mengapa sebuah framework?" untuk penjelasan yang lebih mendalam.
Routing dasar di Flight dilakukan dengan mencocokkan pola URL dengan fungsi callback atau sebuah array dari sebuah kelas dan metode.
Flight::route('/', function(){
echo 'hello world!';
});
Rute dicocokkan dalam urutan mereka didefinisikan. Rute pertama yang mencocokkan permintaan akan dipanggil.
Callback/Fungsi
Callback dapat berupa objek apa pun yang dapat dipanggil. Jadi Anda dapat menggunakan fungsi biasa:
function hello() {
echo 'hello world!';
}
Flight::route('/', 'hello');
Kelas
Anda juga dapat menggunakan metode statis dari sebuah kelas:
class Greeting {
public static function hello() {
echo 'hello world!';
}
}
Flight::route('/', [ 'Greeting','hello' ]);
Atau dengan membuat objek terlebih dahulu dan kemudian memanggil metode:
// Greeting.php
class Greeting
{
public function __construct() {
$this->name = 'John Doe';
}
public function hello() {
echo "Hello, {$this->name}!";
}
}
// index.php
$greeting = new Greeting();
Flight::route('/', [ $greeting, 'hello' ]);
// Anda juga dapat melakukan ini tanpa membuat objek terlebih dahulu
// Catatan: Tidak ada argumen yang akan disuntikkan ke konstruktor
Flight::route('/', [ 'Greeting', 'hello' ]);
// Selain itu, Anda dapat menggunakan sintaks lebih pendek ini
Flight::route('/', 'Greeting->hello');
// atau
Flight::route('/', Greeting::class.'->hello');
Dependency Injection melalui DIC (Dependency Injection Container)
Jika Anda ingin menggunakan dependency injection melalui sebuah container (PSR-11, PHP-DI, Dice, dll), satu-satunya jenis rute yang tersedia adalah langsung membuat objek sendiri dan menggunakan container untuk membuat objek Anda atau Anda dapat menggunakan string untuk mendefinisikan kelas dan metode yang akan dipanggil. Anda dapat pergi ke halaman Dependency Injection untuk informasi lebih lanjut.
Berikut adalah contoh cepat:
use flight\database\PdoWrapper;
// Greeting.php
class Greeting
{
protected PdoWrapper $pdoWrapper;
public function __construct(PdoWrapper $pdoWrapper) {
$this->pdoWrapper = $pdoWrapper;
}
public function hello(int $id) {
// lakukan sesuatu dengan $this->pdoWrapper
$name = $this->pdoWrapper->fetchField("SELECT name FROM users WHERE id = ?", [ $id ]);
echo "Hello, world! Nama saya adalah {$name}!";
}
}
// index.php
// Siapkan container dengan parameter apa pun yang Anda butuhkan
// Lihat halaman Dependency Injection untuk informasi lebih lanjut tentang PSR-11
$dice = new \Dice\Dice();
// Jangan lupa untuk menetapkan kembali variabel dengan '$dice = '!!!!!
$dice = $dice->addRule('flight\database\PdoWrapper', [
'shared' => true,
'constructParams' => [
'mysql:host=localhost;dbname=test',
'root',
'password'
]
]);
// Daftarkan pengendali container
Flight::registerContainerHandler(function($class, $params) use ($dice) {
return $dice->create($class, $params);
});
// Rute seperti biasa
Flight::route('/hello/@id', [ 'Greeting', 'hello' ]);
// atau
Flight::route('/hello/@id', 'Greeting->hello');
// atau
Flight::route('/hello/@id', 'Greeting::hello');
Flight::start();
Metode Routing
Secara default, pola rute dicocokkan dengan semua metode permintaan. Anda dapat merespons metode tertentu dengan menempatkan pengenal sebelum URL.
Flight::route('GET /', function () {
echo 'Saya menerima permintaan GET.';
});
Flight::route('POST /', function () {
echo 'Saya menerima permintaan POST.';
});
// Anda tidak dapat menggunakan Flight::get() untuk rute karena itu adalah metode
// untuk mendapatkan variabel, tidak membuat rute.
// Flight::post('/', function() { /* kode */ });
// Flight::patch('/', function() { /* kode */ });
// Flight::put('/', function() { /* kode */ });
// Flight::delete('/', function() { /* kode */ });
Anda juga dapat memetakan beberapa metode ke satu callback dengan menggunakan pemisah |
:
Flight::route('GET|POST /', function () {
echo 'Saya menerima baik permintaan GET atau POST.';
});
Selain itu, Anda dapat mengambil objek Router yang memiliki beberapa metode pembantu untuk Anda gunakan:
$router = Flight::router();
// memetakan semua metode
$router->map('/', function() {
echo 'hello world!';
});
// permintaan GET
$router->get('/users', function() {
echo 'users';
});
// $router->post();
// $router->put();
// $router->delete();
// $router->patch();
Ekspresi Reguler
Anda dapat menggunakan ekspresi reguler dalam rute Anda:
Flight::route('/user/[0-9]+', function () {
// Ini akan mencocokkan /user/1234
});
Meskipun metode ini tersedia, disarankan untuk menggunakan parameter bernama, atau parameter bernama dengan ekspresi reguler, karena lebih mudah dibaca dan lebih mudah untuk dipelihara.
Parameter Bernama
Anda dapat menentukan parameter bernama dalam rute Anda yang akan diteruskan ke fungsi callback Anda. Ini lebih untuk keterbacaan rute daripada yang lain . Silakan lihat bagian di bawah tentang caveat penting.
Flight::route('/@name/@id', function (string $name, string $id) {
echo "hello, $name ($id)!";
});
Anda juga dapat menyertakan ekspresi reguler dengan parameter bernama Anda menggunakan
pemisah :
:
Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) {
// Ini akan mencocokkan /bob/123
// Tetapi tidak akan mencocokkan /bob/12345
});
Catatan: Mencocokkan grup regex
()
dengan parameter posisi tidak didukung. :'(
Caveat Penting
Meskipun dalam contoh di atas, tampaknya @name
terikat langsung pada variabel $name
, itu tidak. Urutan parameter dalam fungsi callback yang menentukan apa yang diteruskan ke dalamnya. Jadi jika Anda membalik urutan parameter dalam fungsi callback, variabel juga akan dibalik. Berikut adalah contohnya:
Flight::route('/@name/@id', function (string $id, string $name) {
echo "hello, $name ($id)!";
});
Dan jika Anda mengunjungi URL berikut: /bob/123
, hasilnya akan menjadi hello, 123 (bob)!
.
Silakan berhati-hati saat Anda menetapkan rute dan fungsi callback Anda.
Parameter Opsional
Anda dapat menentukan parameter bernama yang bersifat opsional untuk pencocokan dengan membungkus segmen dalam tanda kurung.
Flight::route(
'/blog(/@year(/@month(/@day)))',
function(?string $year, ?string $month, ?string $day) {
// Ini akan mencocokkan URL berikut:
// /blog/2012/12/10
// /blog/2012/12
// /blog/2012
// /blog
}
);
Parameter opsional yang tidak dicocokkan akan diteruskan sebagai NULL
.
Wildcards
Pencocokan hanya dilakukan pada segmen URL individu. Jika Anda ingin mencocokkan beberapa
segmen Anda dapat menggunakan wildcard *
.
Flight::route('/blog/*', function () {
// Ini akan mencocokkan /blog/2000/02/01
});
Untuk merutekan semua permintaan ke satu callback, Anda dapat melakukan:
Flight::route('*', function () {
// Lakukan sesuatu
});
Menyampaikan
Anda dapat meneruskan eksekusi ke rute berikutnya yang cocok dengan mengembalikan true
dari
fungsi callback Anda.
Flight::route('/user/@name', function (string $name) {
// Periksa beberapa kondisi
if ($name !== "Bob") {
// Lanjutkan ke rute berikutnya
return true;
}
});
Flight::route('/user/*', function () {
// Ini akan dipanggil
});
Aliasing Rute
Anda dapat menetapkan alias ke sebuah rute, sehingga URL dapat dibuat secara dinamis dilanjutkan dalam kode Anda (seperti template misalnya).
Flight::route('/users/@id', function($id) { echo 'user:'.$id; }, false, 'user_view');
// nanti dalam kode di suatu tempat
Flight::getUrl('user_view', [ 'id' => 5 ]); // akan mengembalikan '/users/5'
Ini sangat membantu jika URL Anda kebetulan berubah. Dalam contoh di atas, katakanlah bahwa pengguna dipindahkan ke /admin/users/@id
alih-alih.
Dengan aliasing di tempat, Anda tidak perlu mengubah di mana pun Anda merujuk alias karena alias sekarang akan mengembalikan /admin/users/5
seperti dalam
contoh di atas.
Aliasing rute masih berfungsi dalam grup juga:
Flight::group('/users', function() {
Flight::route('/@id', function($id) { echo 'user:'.$id; }, false, 'user_view');
});
// nanti dalam kode di suatu tempat
Flight::getUrl('user_view', [ 'id' => 5 ]); // akan mengembalikan '/users/5'
Informasi Rute
Jika Anda ingin memeriksa informasi rute yang cocok, Anda dapat meminta objek rute
untuk diteruskan ke fungsi callback Anda dengan meneruskan true
sebagai parameter ketiga di metode rute. Objek rute akan selalu menjadi parameter terakhir yang diteruskan ke fungsi callback Anda.
Flight::route('/', function(\flight\net\Route $route) {
// Array metode HTTP yang dicocokkan
$route->methods;
// Array parameter bernama
$route->params;
// Ekspresi reguler yang cocok
$route->regex;
// Berisi konten dari setiap '*' yang digunakan dalam pola URL
$route->splat;
// Menunjukkan jalur url....jika Anda benar-benar membutuhkannya
$route->pattern;
// Menunjukkan middleware apa yang ditugaskan untuk ini
$route->middleware;
// Menunjukkan alias yang ditugaskan untuk rute ini
$route->alias;
}, true);
Pengelompokan Rute
Mungkin ada waktu ketika Anda ingin mengelompokkan rute-rute terkait bersama (seperti /api/v1
).
Anda dapat melakukan ini dengan menggunakan metode group
:
Flight::group('/api/v1', function () {
Flight::route('/users', function () {
// Mencocokkan /api/v1/users
});
Flight::route('/posts', function () {
// Mencocokkan /api/v1/posts
});
});
Anda bahkan dapat menelurkan grup dari grup:
Flight::group('/api', function () {
Flight::group('/v1', function () {
// Flight::get() mendapatkan variabel, itu tidak menetapkan rute! Lihat konteks objek di bawah
Flight::route('GET /users', function () {
// Mencocokkan GET /api/v1/users
});
Flight::post('/posts', function () {
// Mencocokkan POST /api/v1/posts
});
Flight::put('/posts/1', function () {
// Mencocokkan PUT /api/v1/posts
});
});
Flight::group('/v2', function () {
// Flight::get() mendapatkan variabel, itu tidak menetapkan rute! Lihat konteks objek di bawah
Flight::route('GET /users', function () {
// Mencocokkan GET /api/v2/users
});
});
});
Pengelompokan dengan Konteks Objek
Anda masih dapat menggunakan pengelompokan rute dengan objek Engine
dengan cara berikut:
$app = new \flight\Engine();
$app->group('/api/v1', function (Router $router) {
// gunakan variabel $router
$router->get('/users', function () {
// Mencocokkan GET /api/v1/users
});
$router->post('/posts', function () {
// Mencocokkan POST /api/v1/posts
});
});
Resource Routing
Anda dapat membuat serangkaian rute untuk sebuah sumber daya menggunakan metode resource
. Ini akan membuat
serangkaian rute untuk sumber daya yang mengikuti konvensi RESTful.
Untuk membuat sumber daya, lakukan hal berikut:
Flight::resource('/users', UsersController::class);
Dan yang akan terjadi di latar belakang adalah ini akan membuat rute berikut:
[
'index' => 'GET ',
'create' => 'GET /create',
'store' => 'POST ',
'show' => 'GET /@id',
'edit' => 'GET /@id/edit',
'update' => 'PUT /@id',
'destroy' => 'DELETE /@id'
]
Dan controller Anda akan terlihat seperti ini:
class UsersController
{
public function index(): void
{
}
public function show(string $id): void
{
}
public function create(): void
{
}
public function store(): void
{
}
public function edit(string $id): void
{
}
public function update(string $id): void
{
}
public function destroy(string $id): void
{
}
}
Catatan: Anda dapat melihat rute yang baru ditambahkan dengan
runway
dengan menjalankanphp runway routes
.
Menyesuaikan Rute Sumber Daya
Ada beberapa opsi untuk mengonfigurasi rute sumber daya.
Alias Basis
Anda dapat mengonfigurasi aliasBase
. Secara default, alias adalah bagian terakhir dari URL yang ditentukan.
Misalnya /users/
akan menghasilkan aliasBase
menjadi users
. Ketika rute ini dibuat,
alias adalah users.index
, users.create
, dst. Jika Anda ingin mengubah alias, atur aliasBase
ke nilai yang Anda inginkan.
Flight::resource('/users', UsersController::class, [ 'aliasBase' => 'user' ]);
Hanya dan Kecuali
Anda juga dapat menentukan rute mana yang ingin Anda buat dengan menggunakan opsi only
dan except
.
Flight::resource('/users', UsersController::class, [ 'only' => [ 'index', 'show' ] ]);
Flight::resource('/users', UsersController::class, [ 'except' => [ 'create', 'store', 'edit', 'update', 'destroy' ] ]);
Ini pada dasarnya adalah opsi daftar putih dan daftar hitam sehingga Anda dapat menentukan rute mana yang ingin Anda buat.
Middleware
Anda juga dapat menentukan middleware yang akan dijalankan di setiap rute yang dibuat oleh metode resource
.
Flight::resource('/users', UsersController::class, [ 'middleware' => [ MyAuthMiddleware::class ] ]);
Streaming
Anda sekarang dapat melakukan streaming respons ke klien menggunakan metode streamWithHeaders()
.
Ini berguna untuk mengirim file besar, proses yang memakan waktu lama, atau menghasilkan respons besar.
Streaming rute ditangani sedikit berbeda dari rute biasa.
Catatan: Streaming respons hanya tersedia jika Anda memiliki
flight.v2.output_buffering
disetel ke false.
Stream dengan Header Manual
Anda dapat melakukan streaming respons ke klien dengan menggunakan metode stream()
pada sebuah rute. Jika Anda
melakukan ini, Anda harus menetapkan semua metode secara manual sebelum Anda mengeluarkan apapun kepada klien.
Ini dilakukan dengan fungsi header()
php atau metode Flight::response()->setRealHeader()
.
Flight::route('/@filename', function($filename) {
// jelas Anda akan menyaring jalur dan lain-lain.
$fileNameSafe = basename($filename);
// Jika Anda memiliki header tambahan untuk diatur di sini setelah rute dieksekusi
// Anda harus mendefinisikannya sebelum ada yang di-echo keluar.
// Mereka semua harus merupakan panggilan mentah ke fungsi header()
// atau panggilan ke Flight::response()->setRealHeader()
header('Content-Disposition: attachment; filename="'.$fileNameSafe.'"');
// atau
Flight::response()->setRealHeader('Content-Disposition', 'attachment; filename="'.$fileNameSafe.'"');
$fileData = file_get_contents('/some/path/to/files/'.$fileNameSafe);
// Penanganan kesalahan dan lain-lain
if(empty($fileData)) {
Flight::halt(404, 'File tidak ditemukan');
}
// set panjang konten secara manual jika Anda suka
header('Content-Length: '.filesize($filename));
// Streaming data ke klien
echo $fileData;
// Ini adalah baris ajaib di sini
})->stream();
Stream dengan Header
Anda juga dapat menggunakan metode streamWithHeaders()
untuk mengatur header sebelum Anda mulai streaming.
Flight::route('/stream-users', function() {
// Anda dapat menambahkan header tambahan apa pun yang Anda inginkan di sini
// Anda hanya harus menggunakan header() atau Flight::response()->setRealHeader()
// namun cara Anda menarik data Anda, hanya sebagai contoh...
$users_stmt = Flight::db()->query("SELECT id, first_name, last_name FROM users");
echo '{';
$user_count = count($users);
while($user = $users_stmt->fetch(PDO::FETCH_ASSOC)) {
echo json_encode($user);
if(--$user_count > 0) {
echo ',';
}
// Ini diperlukan untuk mengirim data ke klien
ob_flush();
}
echo '}';
// Ini adalah bagaimana Anda mengatur header sebelum Anda mulai streaming.
})->streamWithHeaders([
'Content-Type' => 'application/json',
'Content-Disposition' => 'attachment; filename="users.json"',
// kode status opsional, default ke 200
'status' => 200
]);
Learn/flight_vs_symfony
Flight vs Symfony
Apa itu Symfony?
Symfony adalah sekumpulan komponen PHP yang dapat digunakan kembali dan framework PHP untuk proyek web.
Landasan standar di mana aplikasi PHP terbaik dibangun. Pilih salah satu dari 50 komponen mandiri yang tersedia untuk aplikasi Anda sendiri.
Percepat pembuatan dan pemeliharaan aplikasi web PHP Anda. Akhiri tugas pengkodean yang repetitif dan nikmati kekuatan mengendalikan kode Anda.
Kelebihan dibandingkan Flight
- Symfony memiliki ekosistem yang besar dari pengembang dan modul yang dapat digunakan untuk menyelesaikan masalah umum.
- Symfony memiliki ORM yang dilengkapi dengan fitur lengkap (Doctrine) yang dapat digunakan untuk berinteraksi dengan basis data Anda.
- Symfony memiliki banyak dokumentasi dan tutorial yang dapat digunakan untuk mempelajari framework.
- Symfony memiliki podcast, konferensi, pertemuan, video, dan sumber daya lainnya yang dapat digunakan untuk mempelajari framework.
- Symfony ditujukan untuk pengembang berpengalaman yang ingin membangun aplikasi web perusahaan yang kaya fitur.
Kekurangan dibandingkan Flight
- Symfony memiliki lebih banyak yang terjadi di bawah permukaan dibandingkan dengan Flight. Ini datang dengan biaya dramatis dalam hal kinerja. Lihat pengujian TechEmpower untuk informasi lebih lanjut.
- Flight ditujukan untuk pengembang yang ingin membangun aplikasi web yang ringan, cepat, dan mudah digunakan.
- Flight ditujukan untuk kesederhanaan dan kemudahan penggunaan.
- Salah satu fitur inti Flight adalah bahwa ia melakukan yang terbaik untuk mempertahankan kompatibilitas mundur.
- Flight tidak memiliki ketergantungan, sementara Symfony memiliki sejumlah ketergantungan
- Flight ditujukan untuk pengembang yang baru memasuki dunia framework untuk pertama kalinya.
- Flight juga dapat digunakan untuk aplikasi tingkat enterprise, tetapi tidak memiliki sebanyak contoh dan tutorial seperti Symfony. Ini juga akan memerlukan lebih banyak disiplin dari pihak pengembang untuk menjaga agar segala sesuatunya terorganisir dan terstruktur dengan baik.
- Flight memberikan pengembang lebih banyak kontrol atas aplikasi, sementara Symfony dapat menyisipkan sedikit keajaiban di belakang layar.
Learn/flight_vs_another_framework
Membandingkan Flight dengan Framework Lain
Jika Anda bermigrasi dari framework lain seperti Laravel, Slim, Fat-Free, atau Symfony ke Flight, halaman ini akan membantu Anda memahami perbedaan antara keduanya.
Laravel
Laravel adalah framework yang penuh fitur yang memiliki segala fasilitas dan ekosistem yang menakjubkan yang berfokus pada pengembang, tetapi dengan biaya dalam kinerja dan kompleksitas.
Lihat perbandingan antara Laravel dan Flight.
Slim
Slim adalah micro-framework yang mirip dengan Flight. Ini dirancang agar ringan dan mudah digunakan, tetapi bisa sedikit lebih kompleks daripada Flight.
Lihat perbandingan antara Slim dan Flight.
Fat-Free
Fat-Free adalah framework full-stack dalam paket yang jauh lebih kecil. Meskipun memiliki semua alat dalam kotak perkakas, ia memiliki arsitektur data yang dapat membuat beberapa proyek menjadi lebih kompleks daripada yang seharusnya.
Lihat perbandingan antara Fat-Free dan Flight.
Symfony
Symfony adalah framework modular tingkat perusahaan yang dirancang untuk fleksibel dan skalabel. Untuk proyek yang lebih kecil atau pengembang yang lebih baru, Symfony bisa sedikit membingungkan.
Lihat perbandingan antara Symfony dan Flight.
Learn/dependency_injection_container
Kontainer Penyuntikan Ketergantungan
Pengenalan
Kontainer Penyuntikan Ketergantungan (DIC) adalah alat yang kuat yang memungkinkan Anda untuk mengelola ketergantungan aplikasi Anda. Ini adalah konsep kunci dalam kerangka PHP modern dan digunakan untuk mengelola instansiasi dan konfigurasi objek. Beberapa contoh pustaka DIC adalah: Dice, Pimple, PHP-DI, dan league/container.
DIC adalah cara mewah untuk mengatakan bahwa ia memungkinkan Anda untuk membuat dan mengelola kelas Anda di lokasi terpusat. Ini berguna ketika Anda perlu mengoper objek yang sama ke beberapa kelas (seperti pengontrol Anda). Contoh sederhana mungkin membantu ini menjadi lebih jelas.
Contoh Dasar
Cara lama dalam melakukan sesuatu mungkin terlihat seperti ini:
require 'vendor/autoload.php';
// kelas untuk mengelola pengguna dari database
class UserController {
protected PDO $pdo;
public function __construct(PDO $pdo) {
$this->pdo = $pdo;
}
public function view(int $id) {
$stmt = $this->pdo->prepare('SELECT * FROM users WHERE id = :id');
$stmt->execute(['id' => $id]);
print_r($stmt->fetch());
}
}
$User = new UserController(new PDO('mysql:host=localhost;dbname=test', 'user', 'pass'));
Flight::route('/user/@id', [ $UserController, 'view' ]);
Flight::start();
Anda dapat melihat dari kode di atas bahwa kami membuat objek PDO
baru dan mengoperasikan
ke kelas UserController
kami. Ini baik untuk aplikasi kecil, tetapi seiring pertumbuhan aplikasi Anda,
Anda akan menemukan bahwa Anda membuat objek PDO
yang sama di beberapa tempat. Inilah saatnya DIC berguna.
Berikut adalah contoh yang sama menggunakan DIC (menggunakan Dice):
require 'vendor/autoload.php';
// kelas yang sama seperti di atas. Tidak ada yang berubah
class UserController {
protected PDO $pdo;
public function __construct(PDO $pdo) {
$this->pdo = $pdo;
}
public function view(int $id) {
$stmt = $this->pdo->prepare('SELECT * FROM users WHERE id = :id');
$stmt->execute(['id' => $id]);
print_r($stmt->fetch());
}
}
// buat kontainer baru
$container = new \Dice\Dice;
// jangan lupa untuk menetapkannya kembali ke dirinya sendiri seperti di bawah ini!
$container = $container->addRule('PDO', [
// dibagikan berarti objek yang sama akan dikembalikan setiap kali
'shared' => true,
'constructParams' => ['mysql:host=localhost;dbname=test', 'user', 'pass' ]
]);
// Ini mendaftarkan penangan kontainer sehingga Flight tahu untuk menggunakannya.
Flight::registerContainerHandler(function($class, $params) use ($container) {
return $container->create($class, $params);
});
// sekarang kita bisa menggunakan kontainer untuk membuat UserController kita
Flight::route('/user/@id', [ 'UserController', 'view' ]);
// atau alternatifnya, Anda dapat mendefinisikan rute seperti ini
Flight::route('/user/@id', 'UserController->view');
// atau
Flight::route('/user/@id', 'UserController::view');
Flight::start();
Saya yakin Anda mungkin berpikir bahwa banyak kode tambahan ditambahkan ke contoh ini.
Keajaiban datang ketika Anda memiliki pengontrol lain yang membutuhkan objek PDO
.
// Jika semua pengontrol Anda memiliki konstruktor yang membutuhkan objek PDO
// masing-masing rute di bawah ini akan secara otomatis menginjeksikannya!!!
Flight::route('/company/@id', 'CompanyController->view');
Flight::route('/organization/@id', 'OrganizationController->view');
Flight::route('/category/@id', 'CategoryController->view');
Flight::route('/settings', 'SettingsController->view');
Bonus tambahan dari memanfaatkan DIC adalah bahwa pengujian unit menjadi jauh lebih mudah. Anda dapat membuat objek tiruan dan mengoperasikannya ke kelas Anda. Ini adalah manfaat besar ketika Anda menulis tes untuk aplikasi Anda!
PSR-11
Flight juga dapat menggunakan kontainer yang sesuai dengan PSR-11. Ini berarti Anda dapat menggunakan kontainer apa pun yang mengimplementasikan antarmuka PSR-11. Berikut adalah contoh menggunakan kontainer PSR-11 dari League:
require 'vendor/autoload.php';
// kelas UserController yang sama seperti di atas
$container = new \League\Container\Container();
$container->add(UserController::class)->addArgument(PdoWrapper::class);
$container->add(PdoWrapper::class)
->addArgument('mysql:host=localhost;dbname=test')
->addArgument('user')
->addArgument('pass');
Flight::registerContainerHandler($container);
Flight::route('/user', [ 'UserController', 'view' ]);
Flight::start();
Ini mungkin sedikit lebih panjang daripada contoh Dice sebelumnya, tetapi tetap menyelesaikan pekerjaan dengan keuntungan yang sama!
Penangan DIC Kustom
Anda juga dapat membuat penangan DIC Anda sendiri. Ini berguna jika Anda memiliki kontainer kustom yang ingin Anda gunakan yang bukan PSR-11 (Dice). Lihat contoh dasar untuk cara melakukannya.
Selain itu, ada beberapa default yang berguna yang akan membuat hidup Anda lebih mudah saat menggunakan Flight.
Instance Engine
Jika Anda menggunakan instance Engine
di pengontrol/middleware Anda, inilah cara Anda mengkonfigurasinya:
// Di suatu tempat di file bootstrap Anda
$engine = Flight::app();
$container = new \Dice\Dice;
$container = $container->addRule('*', [
'substitutions' => [
// Ini adalah tempat Anda mengoper instance
Engine::class => $engine
]
]);
$engine->registerContainerHandler(function($class, $params) use ($container) {
return $container->create($class, $params);
});
// Sekarang Anda dapat menggunakan instance Engine di pengontrol/middleware Anda
class MyController {
public function __construct(Engine $app) {
$this->app = $app;
}
public function index() {
$this->app->render('index');
}
}
Menambahkan Kelas Lain
Jika Anda memiliki kelas lain yang ingin Anda tambahkan ke kontainer, dengan Dice sangat mudah karena mereka akan secara otomatis diselesaikan oleh kontainer. Berikut adalah contohnya:
$container = new \Dice\Dice;
// Jika Anda tidak perlu menyuntikkan apa pun ke dalam kelas Anda
// Anda tidak perlu mendefinisikan apa pun!
Flight::registerContainerHandler(function($class, $params) use ($container) {
return $container->create($class, $params);
});
class MyCustomClass {
public function parseThing() {
return 'thing';
}
}
class UserController {
protected MyCustomClass $MyCustomClass;
public function __construct(MyCustomClass $MyCustomClass) {
$this->MyCustomClass = $MyCustomClass;
}
public function index() {
echo $this->MyCustomClass->parseThing();
}
}
Flight::route('/user', 'UserController->index');
Learn/middleware
Middleware Rute
Flight mendukung middleware rute dan group rute. Middleware adalah fungsi yang dijalankan sebelum (atau setelah) callback rute. Ini adalah cara yang bagus untuk menambahkan pemeriksaan otentikasi API dalam kode Anda, atau untuk memvalidasi bahwa pengguna memiliki izin untuk mengakses rute tersebut.
Middleware Dasar
Berikut adalah contoh dasar:
// Jika Anda hanya menyediakan fungsi anonim, itu akan dieksekusi sebelum callback rute.
// tidak ada fungsi middleware "setelah" kecuali untuk kelas (lihat di bawah)
Flight::route('/path', function() { echo ' Di sini saya!'; })->addMiddleware(function() {
echo 'Middleware pertama!';
});
Flight::start();
// Ini akan menghasilkan "Middleware pertama! Di sini saya!"
Ada beberapa catatan yang sangat penting tentang middleware yang harus Anda ketahui sebelum menggunakannya:
- Fungsi middleware dieksekusi dalam urutan mereka ditambahkan ke rute. Eksekusi mirip dengan bagaimana Slim Framework menangani ini.
- Sebelum dieksekusi dalam urutan ditambahkan, dan Setelah dieksekusi dalam urutan terbalik.
- Jika fungsi middleware Anda mengembalikan false, semua eksekusi dihentikan dan kesalahan 403 Forbidden akan dibuang. Anda mungkin ingin menangani ini secara lebih halus dengan
Flight::redirect()
atau sesuatu yang serupa. - Jika Anda perlu parameter dari rute Anda, mereka akan diteruskan dalam satu array ke fungsi middleware Anda. (
function($params) { ... }
ataupublic function before($params) {}
). Alasan untuk ini adalah Anda dapat menyusun parameter Anda dalam kelompok dan dalam beberapa kelompok tersebut, parameter Anda mungkin sebenarnya muncul dalam urutan yang berbeda yang akan merusak fungsi middleware dengan merujuk pada parameter yang salah. Dengan cara ini, Anda dapat mengaksesnya berdasarkan nama alih-alih posisi. - Jika Anda hanya memberikan nama middleware, itu akan secara otomatis dieksekusi oleh kontainer injeksi ketergantungan dan middleware akan dieksekusi dengan parameter yang dibutuhkannya. Jika Anda tidak memiliki kontainer injeksi ketergantungan yang terdaftar, itu akan meneruskan instance
flight\Engine
ke__construct()
.
Kelas Middleware
Middleware dapat terdaftar sebagai kelas juga. Jika Anda perlu fungsi "setelah", Anda harus menggunakan kelas.
class MyMiddleware {
public function before($params) {
echo 'Middleware pertama!';
}
public function after($params) {
echo 'Middleware terakhir!';
}
}
$MyMiddleware = new MyMiddleware();
Flight::route('/path', function() { echo ' Di sini saya! '; })->addMiddleware($MyMiddleware); // juga ->addMiddleware([ $MyMiddleware, $MyMiddleware2 ]);
Flight::start();
// Ini akan menampilkan "Middleware pertama! Di sini saya! Middleware terakhir!"
Menangani Kesalahan Middleware
Misalkan Anda memiliki middleware otentikasi dan Anda ingin mengalihkan pengguna ke halaman login jika mereka tidak terautentikasi. Anda memiliki beberapa opsi di tangan Anda:
- Anda dapat mengembalikan false dari fungsi middleware dan Flight akan secara otomatis mengembalikan kesalahan 403 Forbidden, tetapi tidak ada kustomisasi.
- Anda dapat mengalihkan pengguna ke halaman login menggunakan
Flight::redirect()
. - Anda dapat membuat kesalahan kustom dalam middleware dan menghentikan eksekusi rute.
Contoh Dasar
Ini adalah contoh sederhana return false;:
class MyMiddleware {
public function before($params) {
if (isset($_SESSION['user']) === false) {
return false;
}
// karena ini benar, semuanya akan terus berjalan
}
}
Contoh Redirect
Ini adalah contoh mengalihkan pengguna ke halaman login:
class MyMiddleware {
public function before($params) {
if (isset($_SESSION['user']) === false) {
Flight::redirect('/login');
exit;
}
}
}
Contoh Kesalahan Kustom
Misalkan Anda perlu membuang kesalahan JSON karena Anda sedang membangun API. Anda dapat melakukannya seperti ini:
class MyMiddleware {
public function before($params) {
$authorization = Flight::request()->headers['Authorization'];
if(empty($authorization)) {
Flight::jsonHalt(['error' => 'Anda harus masuk untuk mengakses halaman ini.'], 403);
// atau
Flight::json(['error' => 'Anda harus masuk untuk mengakses halaman ini.'], 403);
exit;
// atau
Flight::halt(403, json_encode(['error' => 'Anda harus masuk untuk mengakses halaman ini.']));
}
}
}
Pengelompokan Middleware
Anda dapat menambahkan grup rute, dan kemudian setiap rute dalam grup itu akan memiliki middleware yang sama juga. Ini berguna jika Anda perlu mengelompokkan sejumlah rute dengan misalnya middleware Auth untuk memeriksa kunci API di header.
// ditambahkan di akhir metode grup
Flight::group('/api', function() {
// Rute yang "kosong" ini sebenarnya akan mencocokkan /api
Flight::route('', function() { echo 'api'; }, false, 'api');
// Ini akan mencocokkan /api/users
Flight::route('/users', function() { echo 'users'; }, false, 'users');
// Ini akan mencocokkan /api/users/1234
Flight::route('/users/@id', function($id) { echo 'user:'.$id; }, false, 'user_view');
}, [ new ApiAuthMiddleware() ]);
Jika Anda ingin menerapkan middleware global ke semua rute Anda, Anda dapat menambahkan grup "kosong":
// ditambahkan di akhir metode grup
Flight::group('', function() {
// Ini masih /users
Flight::route('/users', function() { echo 'users'; }, false, 'users');
// Dan ini masih /users/1234
Flight::route('/users/@id', function($id) { echo 'user:'.$id; }, false, 'user_view');
}, [ new ApiAuthMiddleware() ]);
Learn/filtering
Penyaringan
Flight memungkinkan Anda untuk menyaring metode sebelum dan setelah mereka dipanggil. Tidak ada hook yang telah ditentukan sebelumnya yang perlu Anda ingat. Anda dapat menyaring salah satu dari metode kerangka kerja default serta metode kustom apa pun yang telah Anda peta.
Fungsi filter terlihat seperti ini:
function (array &$params, string &$output): bool {
// Kode penyaring
}
Dengan menggunakan variabel yang diteruskan, Anda dapat memanipulasi parameter input dan/atau output.
Anda dapat menjalankan filter sebelum sebuah metode dengan melakukan:
Flight::before('start', function (array &$params, string &$output): bool {
// Lakukan sesuatu
});
Anda dapat menjalankan filter setelah sebuah metode dengan melakukan:
Flight::after('start', function (array &$params, string &$output): bool {
// Lakukan sesuatu
});
Anda dapat menambahkan sebanyak mungkin filter yang Anda inginkan ke metode mana pun. Mereka akan dipanggil dalam urutan di mana mereka dideklarasikan.
Berikut adalah contoh proses penyaringan:
// Peta metode kustom
Flight::map('hello', function (string $name) {
return "Halo, $name!";
});
// Tambahkan filter sebelum
Flight::before('hello', function (array &$params, string &$output): bool {
// Manipulasi parameter
$params[0] = 'Fred';
return true;
});
// Tambahkan filter setelah
Flight::after('hello', function (array &$params, string &$output): bool {
// Manipulasi output
$output .= " Semoga harimu menyenangkan!";
return true;
});
// Panggil metode kustom
echo Flight::hello('Bob');
Ini seharusnya menampilkan:
Halo Fred! Semoga harimu menyenangkan!
Jika Anda telah mendefinisikan beberapa filter, Anda dapat memutus rantai dengan mengembalikan false
di salah satu fungsi filter Anda:
Flight::before('start', function (array &$params, string &$output): bool {
echo 'satu';
return true;
});
Flight::before('start', function (array &$params, string &$output): bool {
echo 'dua';
// Ini akan mengakhiri rantai
return false;
});
// Ini tidak akan dipanggil
Flight::before('start', function (array &$params, string &$output): bool {
echo 'tiga';
return true;
});
Catatan, metode inti seperti map
dan register
tidak dapat disaring karena mereka
dipanggil secara langsung dan tidak dipanggil secara dinamis.
Learn/requests
Permintaan
Flight mengenkapsulasi permintaan HTTP ke dalam satu objek, yang dapat diakses dengan melakukan:
$request = Flight::request();
Kasus Penggunaan Umum
Ketika Anda sedang bekerja dengan permintaan di aplikasi web, biasanya Anda ingin mengambil header, atau parameter $_GET
atau $_POST
, atau mungkin bahkan body permintaan mentah. Flight menyediakan antarmuka sederhana untuk melakukan semua hal ini.
Berikut adalah contoh mengambil parameter string kueri:
Flight::route('/search', function(){
$keyword = Flight::request()->query['keyword'];
echo "Anda sedang mencari: $keyword";
// kueri database atau sesuatu lainnya dengan $keyword
});
Berikut adalah contoh dari mungkin sebuah formulir dengan metode POST:
Flight::route('POST /submit', function(){
$name = Flight::request()->data['name'];
$email = Flight::request()->data['email'];
echo "Anda mengirim: $name, $email";
// simpan ke dalam database atau sesuatu lainnya dengan $name dan $email
});
Properti Objek Permintaan
Objek permintaan menyediakan properti berikut:
- body - Body permintaan HTTP mentah
- url - URL yang diminta
- base - Subdirektori induk dari URL
- method - Metode permintaan (GET, POST, PUT, DELETE)
- referrer - URL referer
- ip - Alamat IP dari klien
- ajax - Apakah permintaan adalah permintaan AJAX
- scheme - Protokol server (http, https)
- user_agent - Informasi browser
- type - Tipe konten
- length - Panjang konten
- query - Parameter string kueri
- data - Data post atau data JSON
- cookies - Data cookie
- files - File yang diunggah
- secure - Apakah koneksi aman
- accept - Parameter HTTP accept
- proxy_ip - Alamat IP proxy dari klien. Memindai array
$_SERVER
untukHTTP_CLIENT_IP
,HTTP_X_FORWARDED_FOR
,HTTP_X_FORWARDED
,HTTP_X_CLUSTER_CLIENT_IP
,HTTP_FORWARDED_FOR
,HTTP_FORWARDED
dalam urutan itu. - host - Nama host permintaan
Anda dapat mengakses properti query
, data
, cookies
, dan files
sebagai array atau objek.
Jadi, untuk mendapatkan parameter string kueri, Anda dapat melakukan:
$id = Flight::request()->query['id'];
Atau Anda dapat melakukan:
$id = Flight::request()->query->id;
Body Permintaan RAW
Untuk mendapatkan body permintaan HTTP mentah, misalnya saat menangani permintaan PUT, Anda dapat melakukan:
$body = Flight::request()->getBody();
Input JSON
Jika Anda mengirimkan permintaan dengan tipe application/json
dan data {"id": 123}
itu akan tersedia dari properti data
:
$id = Flight::request()->data->id;
$_GET
Anda dapat mengakses array $_GET
melalui properti query
:
$id = Flight::request()->query['id'];
$_POST
Anda dapat mengakses array $_POST
melalui properti data
:
$id = Flight::request()->data['id'];
$_COOKIE
Anda dapat mengakses array $_COOKIE
melalui properti cookies
:
$myCookieValue = Flight::request()->cookies['myCookieName'];
$_SERVER
Ada pintasan yang tersedia untuk mengakses array $_SERVER
melalui metode getVar()
:
$host = Flight::request()->getVar['HTTP_HOST'];
Mengakses File yang Diunggah melalui $_FILES
Anda dapat mengakses file yang diunggah melalui properti files
:
$uploadedFile = Flight::request()->files['myFile'];
Memproses Unggahan File (v3.12.0)
Anda dapat memproses unggahan file menggunakan framework dengan beberapa metode pembantu. Secara dasar, ini menyangkut mengambil data file dari permintaan, dan memindahkannya ke lokasi baru.
Flight::route('POST /upload', function(){
// Jika Anda memiliki field input seperti <input type="file" name="myFile">
$uploadedFileData = Flight::request()->getUploadedFiles();
$uploadedFile = $uploadedFileData['myFile'];
$uploadedFile->moveTo('/path/to/uploads/' . $uploadedFile->getClientFilename());
});
Jika Anda memiliki beberapa file yang diunggah, Anda dapat melakukan pengulangan melalui mereka:
Flight::route('POST /upload', function(){
// Jika Anda memiliki field input seperti <input type="file" name="myFiles[]">
$uploadedFiles = Flight::request()->getUploadedFiles()['myFiles'];
foreach ($uploadedFiles as $uploadedFile) {
$uploadedFile->moveTo('/path/to/uploads/' . $uploadedFile->getClientFilename());
}
});
Catatan Keamanan: Selalu validasi dan bersihkan input pengguna, terutama saat menangani unggahan file. Selalu validasi tipe ekstensi yang akan Anda izinkan untuk diunggah, tetapi Anda juga harus memvalidasi "magic bytes" dari file untuk memastikan file tersebut sebenarnya adalah tipe file yang diklaim pengguna. Terdapat artikel dan perpustakaan yang tersedia untuk membantu dengan ini.
Header Permintaan
Anda dapat mengakses header permintaan menggunakan metode getHeader()
atau getHeaders()
:
// Mungkin Anda membutuhkan header Authorization
$host = Flight::request()->getHeader('Authorization');
// atau
$host = Flight::request()->header('Authorization');
// Jika Anda perlu mengambil semua header
$headers = Flight::request()->getHeaders();
// atau
$headers = Flight::request()->headers();
Body Permintaan
Anda dapat mengakses body permintaan mentah menggunakan metode getBody()
:
$body = Flight::request()->getBody();
Metode Permintaan
Anda dapat mengakses metode permintaan menggunakan properti method
atau metode getMethod()
:
$method = Flight::request()->method; // sebenarnya memanggil getMethod()
$method = Flight::request()->getMethod();
Catatan: Metode getMethod()
pertama-tama menarik metode dari $_SERVER['REQUEST_METHOD']
, kemudian bisa ditimpa oleh $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']
jika ada atau $_REQUEST['_method']
jika ada.
URL Permintaan
Terdapat beberapa metode pembantu untuk menyusun bagian dari URL demi kenyamanan Anda.
URL Lengkap
Anda dapat mengakses URL permintaan penuh menggunakan metode getFullUrl()
:
$url = Flight::request()->getFullUrl();
// https://example.com/some/path?foo=bar
URL Dasar
Anda dapat mengakses URL dasar menggunakan metode getBaseUrl()
:
$url = Flight::request()->getBaseUrl();
// Perhatikan, tidak ada garis miring di akhir.
// https://example.com
Penguraian Kueri
Anda dapat mengoper URL ke metode parseQuery()
untuk menguraikan string kueri menjadi array asosiatif:
$query = Flight::request()->parseQuery('https://example.com/some/path?foo=bar');
// ['foo' => 'bar']
Learn/api
Metode API Framework
Flight dirancang untuk mudah digunakan dan dipahami. Berikut adalah set lengkap metode untuk framework. Ini terdiri dari metode inti, yang merupakan metode statis biasa, dan metode yang dapat diperluas, yang merupakan metode yang dipetakan yang dapat disaring atau ditimpa.
Metode Inti
Metode-metode ini adalah inti dari framework dan tidak dapat ditimpa.
Flight::map(string $name, callable $callback, bool $pass_route = false) // Membuat metode framework khusus.
Flight::register(string $name, string $class, array $params = [], ?callable $callback = null) // Mendaftarkan kelas ke metode framework.
Flight::unregister(string $name) // Menghapus pendaftaran kelas pada metode framework.
Flight::before(string $name, callable $callback) // Menambahkan filter sebelum metode framework.
Flight::after(string $name, callable $callback) // Menambahkan filter setelah metode framework.
Flight::path(string $path) // Menambahkan jalur untuk memuat kelas secara otomatis.
Flight::get(string $key) // Mengambil variabel yang disetel oleh Flight::set().
Flight::set(string $key, mixed $value) // Menyetel variabel dalam mesin Flight.
Flight::has(string $key) // Memeriksa apakah sebuah variabel disetel.
Flight::clear(array|string $key = []) // Menghapus sebuah variabel.
Flight::init() // Menginisialisasi framework ke pengaturan defaultnya.
Flight::app() // Mengambil instance objek aplikasi.
Flight::request() // Mengambil instance objek permintaan.
Flight::response() // Mengambil instance objek respons.
Flight::router() // Mengambil instance objek router.
Flight::view() // Mengambil instance objek tampilan.
Metode yang Dapat Diperluas
Flight::start() // Memulai framework.
Flight::stop() // Menghentikan framework dan mengirimkan respons.
Flight::halt(int $code = 200, string $message = '') // Menghentikan framework dengan kode status dan pesan opsional.
Flight::route(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') // Memetakan pola URL ke callback.
Flight::post(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') // Memetakan pola URL permintaan POST ke callback.
Flight::put(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') // Memetakan pola URL permintaan PUT ke callback.
Flight::patch(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') // Memetakan pola URL permintaan PATCH ke callback.
Flight::delete(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') // Memetakan pola URL permintaan DELETE ke callback.
Flight::group(string $pattern, callable $callback) // Membuat pengelompokan untuk URL, pola harus berupa string.
Flight::getUrl(string $name, array $params = []) // Menghasilkan URL berdasarkan alias rute.
Flight::redirect(string $url, int $code) // Mengalihkan ke URL lain.
Flight::download(string $filePath) // Mengunduh sebuah file.
Flight::render(string $file, array $data, ?string $key = null) // Merender file template.
Flight::error(Throwable $error) // Mengirimkan respons HTTP 500.
Flight::notFound() // Mengirimkan respons HTTP 404.
Flight::etag(string $id, string $type = 'string') // Melakukan caching HTTP ETag.
Flight::lastModified(int $time) // Melakukan caching HTTP terakhir dimodifikasi.
Flight::json(mixed $data, int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // Mengirimkan respons JSON.
Flight::jsonp(mixed $data, string $param = 'jsonp', int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // Mengirimkan respons JSONP.
Flight::jsonHalt(mixed $data, int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // Mengirimkan respons JSON dan menghentikan framework.
Flight::onEvent(string $event, callable $callback) // Mendaftarkan pendengar acara.
Flight::triggerEvent(string $event, ...$args) // Memicu sebuah acara.
Metode kustom apa pun yang ditambahkan dengan map
dan register
juga dapat disaring. Untuk contoh tentang bagaimana memetakan metode ini, lihat panduan Memperluas Flight.
Learn/why_frameworks
Mengapa Kerangka?
Beberapa pemrogram sangat menentang penggunaan kerangka. Mereka berpendapat bahwa kerangka itu berlebihan, lambat, dan sulit dipelajari. Mereka mengatakan bahwa kerangka tidak diperlukan dan bahwa Anda dapat menulis kode yang lebih baik tanpa mereka. Tentu ada beberapa poin yang valid mengenai kekurangan menggunakan kerangka. Namun, ada juga banyak keuntungan dalam menggunakan kerangka.
Alasan untuk Menggunakan Kerangka
Berikut adalah beberapa alasan mengapa Anda mungkin ingin mempertimbangkan untuk menggunakan kerangka:
- Pengembangan Cepat: Kerangka menyediakan banyak fungsionalitas langsung dari kotaknya. Ini berarti Anda dapat membangun aplikasi web lebih cepat. Anda tidak perlu menulis sebanyak itu karena kerangka menyediakan banyak fungsionalitas yang Anda butuhkan.
- Konsistensi: Kerangka menyediakan cara yang konsisten untuk melakukan hal-hal. Ini memudahkan Anda untuk memahami cara kerja kode dan memudahkan pengembang lain untuk memahami kode Anda. Jika Anda memiliki skrip demi skrip, Anda mungkin kehilangan konsistensi antara skrip, terutama jika Anda bekerja dengan tim pengembang.
- Keamanan: Kerangka menyediakan fitur keamanan yang membantu melindungi aplikasi web Anda dari ancaman keamanan umum. Ini berarti Anda tidak perlu khawatir sebanyak itu tentang keamanan karena kerangka mengurus banyak hal untuk Anda.
- Komunitas: Kerangka memiliki komunitas besar pengembang yang berkontribusi pada kerangka. Ini berarti Anda dapat mendapatkan bantuan dari pengembang lain ketika Anda memiliki pertanyaan atau masalah. Ini juga berarti bahwa ada banyak sumber daya yang tersedia untuk membantu Anda belajar cara menggunakan kerangka.
- Praktik Terbaik: Kerangka dibangun menggunakan praktik terbaik. Ini berarti Anda dapat belajar dari kerangka dan menggunakan praktik terbaik yang sama dalam kode Anda sendiri. Ini dapat membantu Anda menjadi pemrogram yang lebih baik. Kadang-kadang Anda tidak tahu apa yang tidak Anda ketahui dan itu dapat merugikan Anda pada akhirnya.
- Ekstensibilitas: Kerangka dirancang untuk diperluas. Ini berarti Anda dapat menambahkan fungsionalitas Anda sendiri ke dalam kerangka. Ini memungkinkan Anda untuk membangun aplikasi web yang disesuaikan dengan kebutuhan spesifik Anda.
Flight adalah micro-framework. Ini berarti bahwa ia kecil dan ringan. Ia tidak menyediakan sebanyak fungsionalitas seperti kerangka besar seperti Laravel atau Symfony. Namun, ia menyediakan banyak fungsionalitas yang Anda butuhkan untuk membangun aplikasi web. Ini juga mudah dipelajari dan digunakan. Ini membuatnya menjadi pilihan yang baik untuk membangun aplikasi web dengan cepat dan mudah. Jika Anda baru mengenal kerangka, Flight adalah kerangka pemula yang hebat untuk mulai digunakan. Ini akan membantu Anda belajar tentang keuntungan menggunakan kerangka tanpa membebani Anda dengan terlalu banyak kompleksitas. Setelah Anda memiliki beberapa pengalaman dengan Flight, akan lebih mudah untuk beralih ke kerangka yang lebih kompleks seperti Laravel atau Symfony, namun Flight masih dapat membuat aplikasi yang berhasil dan tangguh.
Apa itu Routing?
Routing adalah inti dari kerangka Flight, tetapi apa itu sebenarnya? Routing adalah proses mengambil URL dan mencocokkannya dengan fungsi tertentu di kode Anda.
Inilah cara Anda dapat membuat situs web Anda melakukan hal-hal yang berbeda berdasarkan URL yang diminta. Misalnya, Anda mungkin ingin menampilkan profil pengguna ketika mereka
mengunjungi /user/1234
, tetapi menampilkan daftar semua pengguna ketika mereka mengunjungi /users
. Semua ini dilakukan melalui routing.
Ini mungkin bekerja seperti ini:
- Seorang pengguna pergi ke peramban Anda dan mengetik
http://example.com/user/1234
. - Server menerima permintaan dan melihat URL dan meneruskannya ke kode aplikasi Flight Anda.
- Katakanlah di kode Flight Anda Anda memiliki sesuatu seperti
Flight::route('/user/@id', [ 'UserController', 'viewUserProfile' ]);
. Kode aplikasi Flight Anda melihat URL dan melihat bahwa itu cocok dengan jalur yang telah Anda definisikan, dan kemudian menjalankan kode yang telah Anda definisikan untuk jalur tersebut. - Router Flight kemudian akan dijalankan dan memanggil metode
viewUserProfile($id)
dalam kelasUserController
, dengan melewatkan1234
sebagai argumen$id
dalam metode tersebut. - Kode dalam metode
viewUserProfile()
Anda kemudian akan dijalankan dan melakukan apa yang telah Anda katakan untuk dilakukan. Anda mungkin akan mengeluarkan beberapa HTML untuk halaman profil pengguna, atau jika ini adalah API RESTful, Anda mungkin akan mengeluarkan respons JSON dengan informasi pengguna. - Flight membungkus ini dengan rapi, menghasilkan header respons dan mengirimkannya kembali ke peramban pengguna.
- Pengguna merasa senang dan memberi diri mereka pelukan hangat!
Dan Mengapa Ini Penting?
Memiliki router terpusat yang baik sebenarnya dapat membuat hidup Anda jauh lebih mudah! Ini mungkin sulit dilihat pada awalnya. Berikut adalah beberapa alasan mengapa:
- Routing Terpusat: Anda dapat menyimpan semua jalur Anda di satu tempat. Ini memudahkan untuk melihat jalur mana yang Anda miliki dan apa yang mereka lakukan. Ini juga memudahkan untuk mengubahnya jika Anda perlu.
- Parameter Jalur: Anda dapat menggunakan parameter jalur untuk melewatkan data ke metode jalur Anda. Ini adalah cara yang bagus untuk menjaga kode Anda tetap bersih dan teratur.
- Kelompok Jalur: Anda dapat mengelompokkan jalur bersama. Ini bagus untuk menjaga kode Anda teratur dan untuk menerapkan middleware ke sekelompok jalur.
- Alias Jalur: Anda dapat menetapkan alias ke sebuah jalur, sehingga URL dapat dibuat secara dinamis nanti di kode Anda (seperti template misalnya). Contoh: alih-alih menghardcode
/user/1234
di kode Anda, Anda bisa merujuk ke aliasuser_view
dan melewatkanid
sebagai parameter. Ini sangat memudahkan jika Anda memutuskan untuk mengubahnya menjadi/admin/user/1234
nanti. Anda tidak perlu mengubah semua URL yang Anda hardcode, cukup URL yang terhubung ke jalur. - Middleware Jalur: Anda dapat menambahkan middleware ke jalur Anda. Middleware sangat kuat dalam menambahkan perilaku tertentu ke aplikasi Anda, seperti mengotentikasi bahwa pengguna tertentu dapat mengakses jalur atau kelompok jalur.
Saya yakin Anda sudah familiar dengan cara skrip demi skrip untuk membuat situs web. Anda mungkin memiliki file bernama index.php
yang memiliki banyak pernyataan if
untuk memeriksa URL dan kemudian menjalankan fungsi tertentu berdasarkan URL tersebut. Ini adalah bentuk routing, tetapi tidak sangat teratur dan dapat
menjadi tidak terkendali dengan cepat. Sistem routing Flight adalah cara yang jauh lebih teratur dan kuat untuk menangani routing.
Ini?
// /user/view_profile.php?id=1234
if ($_GET['id']) {
$id = $_GET['id'];
viewUserProfile($id);
}
// /user/edit_profile.php?id=1234
if ($_GET['id']) {
$id = $_GET['id'];
editUserProfile($id);
}
// dll...
Atau ini?
// index.php
Flight::route('/user/@id', [ 'UserController', 'viewUserProfile' ]);
Flight::route('/user/@id/edit', [ 'UserController', 'editUserProfile' ]);
// Mungkin di dalam app/controllers/UserController.php Anda
class UserController {
public function viewUserProfile($id) {
// lakukan sesuatu
}
public function editUserProfile($id) {
// lakukan sesuatu
}
}
Semoga Anda mulai melihat manfaat menggunakan sistem routing terpusat. Ini jauh lebih mudah untuk dikelola dan dipahami dalam jangka panjang!
Permintaan dan Respons
Flight menyediakan cara yang sederhana dan mudah untuk menangani permintaan dan respons. Ini adalah inti dari apa yang dilakukan kerangka web. Ini menerima permintaan dari peramban pengguna, memprosesnya, dan kemudian mengirim kembali respons. Ini adalah cara Anda dapat membangun aplikasi web yang melakukan hal-hal seperti menampilkan profil pengguna, memungkinkan pengguna masuk, atau memungkinkan pengguna membuat posting blog baru.
Permintaan
Permintaan adalah apa yang dikirim peramban pengguna ke server Anda ketika mereka mengunjungi situs web Anda. Permintaan ini mengandung informasi tentang apa yang ingin dilakukan pengguna. Misalnya, mungkin berisi informasi tentang URL apa yang ingin dikunjungi pengguna, data apa yang ingin dikirim pengguna ke server Anda, atau jenis data apa yang ingin diterima pengguna dari server Anda. Penting untuk diketahui bahwa permintaan bersifat read-only. Anda tidak dapat mengubah permintaan, tetapi Anda dapat membacanya.
Flight menyediakan cara yang sederhana untuk mengakses informasi tentang permintaan tersebut. Anda dapat mengakses informasi tentang permintaan menggunakan metode Flight::request()
. Metode ini mengembalikan objek Request
yang berisi informasi tentang permintaan. Anda dapat menggunakan objek ini untuk mengakses informasi tentang
permintaan, seperti URL, metode, atau data yang dikirim pengguna ke server Anda.
Respons
Respons adalah apa yang dikirim server Anda kembali ke peramban pengguna ketika mereka mengunjungi situs web Anda. Respons ini berisi informasi tentang apa yang ingin dilakukan server Anda. Misalnya, mungkin berisi informasi tentang jenis data apa yang ingin dikirim server Anda kepada pengguna, jenis data apa yang ingin diterima server Anda dari pengguna, atau jenis data apa yang ingin disimpan server Anda di komputer pengguna.
Flight menyediakan cara yang sederhana untuk mengirim respons ke peramban pengguna. Anda dapat mengirim respons menggunakan metode Flight::response()
. Metode ini
mengambil objek Response
sebagai argumen dan mengirimkan respons ke peramban pengguna. Anda dapat menggunakan objek ini untuk mengirim respons kepada peramban pengguna,
seperti HTML, JSON, atau file. Flight membantu Anda secara otomatis menghasilkan beberapa bagian dari respons untuk mempermudah, tetapi pada akhirnya Anda memiliki
kendali atas apa yang Anda kirim kembali kepada pengguna.
Learn/responses
Respons
Flight membantu menghasilkan sebagian header respons untuk Anda, tetapi Anda memiliki sebagian besar kontrol atas apa yang Anda kirim kembali kepada pengguna. Terkadang Anda dapat mengakses objek Response
secara langsung, tetapi sebagian besar waktu Anda akan menggunakan instance Flight
untuk mengirim respons.
Mengirim Respons Dasar
Flight menggunakan ob_start() untuk menampung output. Ini berarti Anda dapat menggunakan echo
atau print
untuk mengirim respons kepada pengguna dan Flight akan menangkapnya dan mengirimkannya kembali kepada pengguna dengan header yang sesuai.
// Ini akan mengirim "Hello, World!" ke browser pengguna
Flight::route('/', function() {
echo "Hello, World!";
});
// HTTP/1.1 200 OK
// Content-Type: text/html
//
// Hello, World!
Sebagai alternatif, Anda dapat memanggil metode write()
untuk menambahkan ke tubuh juga.
// Ini akan mengirim "Hello, World!" ke browser pengguna
Flight::route('/', function() {
// verbose, tetapi berhasil menyelesaikan pekerjaan kadang-kadang saat Anda membutuhkannya
Flight::response()->write("Hello, World!");
// jika Anda ingin mengambil tubuh yang telah Anda atur pada titik ini
// Anda dapat melakukannya seperti ini
$body = Flight::response()->getBody();
});
Kode Status
Anda dapat mengatur kode status respons dengan menggunakan metode status
:
Flight::route('/@id', function($id) {
if($id == 123) {
Flight::response()->status(200);
echo "Hello, World!";
} else {
Flight::response()->status(403);
echo "Dilarang";
}
});
Jika Anda ingin mendapatkan kode status saat ini, Anda dapat menggunakan metode status
tanpa argumen:
Flight::response()->status(); // 200
Mengatur Tubuh Respons
Anda dapat mengatur tubuh respons dengan menggunakan metode write
, namun, jika Anda echo atau print sesuatu,
itu akan ditangkap dan dikirim sebagai tubuh respons melalui penampungan output.
Flight::route('/', function() {
Flight::response()->write("Hello, World!");
});
// sama dengan
Flight::route('/', function() {
echo "Hello, World!";
});
Menghapus Tubuh Respons
Jika Anda ingin menghapus tubuh respons, Anda dapat menggunakan metode clearBody
:
Flight::route('/', function() {
if($someCondition) {
Flight::response()->write("Hello, World!");
} else {
Flight::response()->clearBody();
}
});
Menjalankan Callback pada Tubuh Respons
Anda dapat menjalankan callback pada tubuh respons dengan menggunakan metode addResponseBodyCallback
:
Flight::route('/users', function() {
$db = Flight::db();
$users = $db->fetchAll("SELECT * FROM users");
Flight::render('users_table', ['users' => $users]);
});
// Ini akan gzip semua respons untuk rute mana pun
Flight::response()->addResponseBodyCallback(function($body) {
return gzencode($body, 9);
});
Anda dapat menambahkan beberapa callback dan mereka akan dijalankan dalam urutan mereka ditambahkan. Karena ini dapat menerima callable, itu dapat menerima array kelas [ $class, 'method' ]
, closure $strReplace = function($body) { str_replace('hi', 'there', $body); };
, atau nama fungsi 'minify'
jika Anda memiliki fungsi untuk meminify kode html Anda misalnya.
Catatan: Callback rute tidak akan berfungsi jika Anda menggunakan opsi konfigurasi flight.v2.output_buffering
.
Callback Rute Khusus
Jika Anda ingin ini hanya berlaku untuk rute tertentu, Anda dapat menambahkan callback di dalam rute itu sendiri:
Flight::route('/users', function() {
$db = Flight::db();
$users = $db->fetchAll("SELECT * FROM users");
Flight::render('users_table', ['users' => $users]);
// Ini akan gzip hanya respons untuk rute ini
Flight::response()->addResponseBodyCallback(function($body) {
return gzencode($body, 9);
});
});
Opsi Middleware
Anda juga dapat menggunakan middleware untuk menerapkan callback ke semua rute melalui middleware:
// MinifyMiddleware.php
class MinifyMiddleware {
public function before() {
// Terapkan callback di sini pada objek response().
Flight::response()->addResponseBodyCallback(function($body) {
return $this->minify($body);
});
}
protected function minify(string $body): string {
// meminify tubuh entah bagaimana
return $body;
}
}
// index.php
Flight::group('/users', function() {
Flight::route('', function() { /* ... */ });
Flight::route('/@id', function($id) { /* ... */ });
}, [ new MinifyMiddleware() ]);
Mengatur Header Respons
Anda dapat mengatur header seperti jenis konten dari respons dengan menggunakan metode header
:
// Ini akan mengirim "Hello, World!" ke browser pengguna dalam teks biasa
Flight::route('/', function() {
Flight::response()->header('Content-Type', 'text/plain');
// atau
Flight::response()->setHeader('Content-Type', 'text/plain');
echo "Hello, World!";
});
JSON
Flight menyediakan dukungan untuk mengirim respons JSON dan JSONP. Untuk mengirim respons JSON Anda mengirimkan beberapa data untuk di-JSON-kan:
Flight::json(['id' => 123]);
Catatan: Secara default, Flight akan mengirimkan header
Content-Type: application/json
bersamaan dengan respons. Ini juga akan menggunakan konstantaJSON_THROW_ON_ERROR
danJSON_UNESCAPED_SLASHES
saat mengkodekan JSON.
JSON dengan Kode Status
Anda juga dapat memasukkan kode status sebagai argumen kedua:
Flight::json(['id' => 123], 201);
JSON dengan Pretty Print
Anda juga dapat memasukkan argumen di posisi terakhir untuk mengaktifkan pencetakan yang indah:
Flight::json(['id' => 123], 200, true, 'utf-8', JSON_PRETTY_PRINT);
Jika Anda mengubah opsi yang diteruskan ke Flight::json()
dan ingin sintaks yang lebih sederhana, Anda dapat
mengganti metode JSON:
Flight::map('json', function($data, $code = 200, $options = 0) {
Flight::_json($data, $code, true, 'utf-8', $options);
}
// Dan sekarang bisa digunakan seperti ini
Flight::json(['id' => 123], 200, JSON_PRETTY_PRINT);
JSON dan Hentikan Eksekusi (v3.10.0)
Jika Anda ingin mengirim respons JSON dan menghentikan eksekusi, Anda dapat menggunakan metode jsonHalt
.
Ini berguna untuk kasus di mana Anda memeriksa mungkin beberapa jenis otorisasi dan jika
pengguna tidak diotorisasi, Anda bisa segera mengirim respons JSON, membersihkan konten tubuh yang ada
dan menghentikan eksekusi.
Flight::route('/users', function() {
$authorized = someAuthorizationCheck();
// Periksa apakah pengguna diotorisasi
if($authorized === false) {
Flight::jsonHalt(['error' => 'Unauthorized'], 401);
}
// Melanjutkan dengan sisa rute
});
Sebelum v3.10.0, Anda harus melakukan sesuatu seperti ini:
Flight::route('/users', function() {
$authorized = someAuthorizationCheck();
// Periksa apakah pengguna diotorisasi
if($authorized === false) {
Flight::halt(401, json_encode(['error' => 'Unauthorized']));
}
// Melanjutkan dengan sisa rute
});
JSONP
Untuk permintaan JSONP, Anda dapat secara opsional memasukkan nama parameter kueri yang Anda gunakan untuk mendefinisikan fungsi callback Anda:
Flight::jsonp(['id' => 123], 'q');
Jadi, ketika melakukan permintaan GET menggunakan ?q=my_func
, Anda harus menerima output:
my_func({"id":123});
Jika Anda tidak memasukkan nama parameter kueri, itu akan default ke jsonp
.
Mengalihkan ke URL lain
Anda dapat mengalihkan permintaan saat ini dengan menggunakan metode redirect()
dan memasukkan
URL baru:
Flight::redirect('/new/location');
Secara default, Flight mengirimkan status kode HTTP 303 ("Lihat Lain"). Anda juga dapat mengatur kode kustom:
Flight::redirect('/new/location', 401);
Menghentikan
Anda dapat menghentikan framework kapan saja dengan memanggil metode halt
:
Flight::halt();
Anda juga dapat menentukan status kode dan pesan HTTP
opsional:
Flight::halt(200, 'Be right back...');
Memanggil halt
akan membuang konten respons apapun hingga saat itu. Jika Anda ingin menghentikan
framework dan menampilkan respons saat ini, gunakan metode stop
:
Flight::stop();
Menghapus Data Respons
Anda dapat menghapus tubuh dan header respons dengan menggunakan metode clear()
. Ini akan menghapus
header apapun yang ditetapkan pada respons, menghapus tubuh respons, dan mengatur kode status menjadi 200
.
Flight::response()->clear();
Menghapus Hanya Tubuh Respons
Jika Anda hanya ingin menghapus tubuh respons, Anda dapat menggunakan metode clearBody()
:
// Ini masih akan mempertahankan header apapun yang diatur pada objek response().
Flight::response()->clearBody();
Caching HTTP
Flight menyediakan dukungan bawaan untuk caching level HTTP. Jika kondisi caching
terpenuhi, Flight akan mengembalikan respons HTTP 304 Not Modified
. Waktu berikutnya klien
meminta sumber daya yang sama, mereka akan diminta untuk menggunakan versi lokal yang telah mereka
cache.
Caching Level Rute
Jika Anda ingin menyimpan cache seluruh respons Anda, Anda dapat menggunakan metode cache()
dan memasukkan waktu untuk disimpan dalam cache.
// Ini akan menyimpan cache respons selama 5 menit
Flight::route('/news', function () {
Flight::response()->cache(time() + 300);
echo 'Konten ini akan disimpan dalam cache.';
});
// Atau, Anda dapat menggunakan string yang akan Anda kirim
// ke metode strtotime()
Flight::route('/news', function () {
Flight::response()->cache('+5 minutes');
echo 'Konten ini akan disimpan dalam cache.';
});
Last-Modified
Anda dapat menggunakan metode lastModified
dan memasukkan timestamp UNIX untuk mengatur tanggal
dan waktu halaman terakhir dimodifikasi. Klien akan terus menggunakan cache mereka sampai
nilai terakhir dimodifikasi diubah.
Flight::route('/news', function () {
Flight::lastModified(1234567890);
echo 'Konten ini akan disimpan dalam cache.';
});
ETag
Caching ETag
mirip dengan Last-Modified
, kecuali Anda dapat menentukan id apa pun yang
Anda inginkan untuk sumber daya:
Flight::route('/news', function () {
Flight::etag('my-unique-id');
echo 'Konten ini akan disimpan dalam cache.';
});
Perlu diingat bahwa memanggil lastModified
atau etag
akan mengatur dan memeriksa
nilai cache. Jika nilai cache sama antara permintaan, Flight akan segera
mengirim respons HTTP 304
dan menghentikan pemrosesan.
Mengunduh File (v3.12.0)
Ada metode pembantu untuk mengunduh file. Anda dapat menggunakan metode download
dan memasukkan path.
Flight::route('/download', function () {
Flight::download('/path/to/file.txt');
});
Learn/events
Sistem Acara di Flight PHP (v3.15.0+)
Flight PHP memperkenalkan sistem acara yang ringan dan intuitif yang memungkinkan Anda mendaftar dan memicu acara kustom di aplikasi Anda. Dengan penambahan Flight::onEvent()
dan Flight::triggerEvent()
, Anda sekarang dapat terhubung ke momen-momen penting dalam siklus hidup aplikasi Anda atau mendefinisikan acara Anda sendiri untuk membuat kode Anda lebih modular dan dapat diperluas. Metode ini adalah bagian dari metode yang dapat dipetakan Flight, yang berarti Anda dapat mengganti perilaku mereka sesuai dengan kebutuhan Anda.
Panduan ini mencakup semuanya yang perlu Anda ketahui untuk memulai dengan acara, termasuk mengapa mereka berharga, bagaimana cara menggunakannya, dan contoh praktis untuk membantu pemula memahami kekuatannya.
Mengapa Menggunakan Acara?
Acara memungkinkan Anda untuk memisahkan bagian-bagian berbeda dari aplikasi Anda sehingga mereka tidak terlalu bergantung satu sama lain. Pemisahan ini—sering disebut decoupling—memudahkan kode Anda untuk diperbarui, diperluas, atau di-debug. Alih-alih menulis semuanya dalam satu blok besar, Anda dapat memecah logika Anda menjadi potongan-potongan kecil yang independen yang merespons tindakan spesifik (acara).
Bayangkan Anda sedang membangun aplikasi blog:
- Ketika seorang pengguna mengirimkan komentar, Anda mungkin ingin:
- Menyimpan komentar ke dalam basis data.
- Mengirim email kepada pemilik blog.
- Mencatat tindakan untuk keamanan.
Tanpa acara, Anda akan memasukkan semua ini ke dalam satu fungsi. Dengan acara, Anda dapat memecahnya: satu bagian menyimpan komentar, bagian lain memicu acara seperti 'comment.posted'
, dan pendengar terpisah menangani email dan pencatatan. Ini menjaga kode Anda lebih bersih dan memungkinkan Anda menambah atau menghapus fitur (seperti notifikasi) tanpa menyentuh logika inti.
Penggunaan Umum
- Pencatatan: Mencatat tindakan seperti login atau kesalahan tanpa mengacaukan kode utama Anda.
- Notifikasi: Mengirim email atau peringatan ketika sesuatu terjadi.
- Pembaruan: Menyegarkan cache atau memberi tahu sistem lain tentang perubahan.
Mendaftar Pendengar Acara
Untuk mendengarkan sebuah acara, gunakan Flight::onEvent()
. Metode ini memungkinkan Anda menentukan apa yang harus terjadi ketika sebuah acara terjadi.
Sintaks
Flight::onEvent(string $event, callable $callback): void
$event
: Nama untuk acara Anda (misalnya,'user.login'
).$callback
: Fungsi yang dijalankan ketika acara dipicu.
Cara Kerjanya
Anda "berlangganan" ke sebuah acara dengan memberi tahu Flight apa yang harus dilakukan ketika acara itu terjadi. Callback dapat menerima argumen yang diteruskan dari pemicu acara.
Sistem acara Flight bersifat sinkron, yang berarti setiap pendengar acara dieksekusi secara berurutan, satu setelah yang lain. Ketika Anda memicu sebuah acara, semua pendengar terdaftar untuk acara itu akan dijalankan hingga selesai sebelum kode Anda dilanjutkan. Ini penting untuk dipahami karena berbeda dari sistem acara asinkron di mana pendengar mungkin dijalankan secara paralel atau pada waktu yang lebih lambat.
Contoh Sederhana
Flight::onEvent('user.login', function ($username) {
echo "Selamat datang kembali, $username!";
});
Di sini, ketika acara 'user.login'
dipicu, ia akan menyapa pengguna dengan nama.
Poin Utama
- Anda dapat menambahkan beberapa pendengar ke acara yang sama—mereka akan dijalankan dalam urutan Anda mendaftarkannya.
- Callback dapat berupa fungsi, fungsi anonim, atau metode dari sebuah kelas.
Memicu Acara
Untuk membuat sebuah acara terjadi, gunakan Flight::triggerEvent()
. Ini memberi tahu Flight untuk menjalankan semua pendengar yang terdaftar untuk acara tersebut, meneruskan data yang Anda berikan.
Sintaks
Flight::triggerEvent(string $event, ...$args): void
$event
: Nama acara yang Anda picu (harus cocok dengan acara terdaftar)....$args
: Argumen opsional untuk dikirim ke pendengar (dapat berupa jumlah argumen apa pun).
Contoh Sederhana
$username = 'alice';
Flight::triggerEvent('user.login', $username);
Ini memicu acara 'user.login'
dan mengirimkan 'alice'
kepada pendengar yang telah kita definisikan sebelumnya, yang akan menghasilkan: Selamat datang kembali, alice!
.
Poin Utama
- Jika tidak ada pendengar yang terdaftar, tidak ada yang terjadi—aplikasi Anda tidak akan rusak.
- Gunakan operator spread (
...
) untuk meneruskan beberapa argumen dengan fleksibel.
Mendaftar Pendengar Acara
...
Menghentikan Pendengar Selanjutnya:
Jika sebuah pendengar mengembalikan false
, pendengar tambahan untuk acara itu tidak akan dieksekusi. Ini memungkinkan Anda untuk menghentikan rantai acara berdasarkan kondisi tertentu. Ingat, urutan pendengar itu penting, karena pendengar pertama yang mengembalikan false
akan menghentikan yang lainnya dari berjalan.
Contoh:
Flight::onEvent('user.login', function ($username) {
if (isBanned($username)) {
logoutUser($username);
return false; // Menghentikan pendengar berikutnya
}
});
Flight::onEvent('user.login', function ($username) {
sendWelcomeEmail($username); // ini tidak pernah dikirim
});
Mengganti Metode Acara
Flight::onEvent()
dan Flight::triggerEvent()
tersedia untuk diperluas, yang berarti Anda dapat mendefinisikan ulang bagaimana mereka bekerja. Ini sangat baik untuk pengguna tingkat lanjut yang ingin menyesuaikan sistem acara, seperti menambahkan pencatatan atau mengubah cara acara dikirimkan.
Contoh: Menyesuaikan onEvent
Flight::map('onEvent', function (string $event, callable $callback) {
// Mencatat setiap pendaftaran acara
error_log("Pendengar acara baru ditambahkan untuk: $event");
// Panggil perilaku default (mengasumsikan ada sistem acara internal)
Flight::_onEvent($event, $callback);
});
Sekarang, setiap kali Anda mendaftarkan sebuah acara, ia akan mencatatnya sebelum melanjutkan.
Mengapa Mengganti?
- Menambahkan debugging atau pemantauan.
- Membatasi acara di lingkungan tertentu (misalnya, menonaktifkan saat pengujian).
- Mengintegrasikan dengan pustaka acara yang berbeda.
Di Mana Menempatkan Acara Anda
Sebagai pemula, Anda mungkin bertanya: di mana saya mendaftarkan semua acara ini di aplikasi saya? Kesederhanaan Flight berarti tidak ada aturan ketat—Anda dapat menempatkannya di mana pun terasa tepat untuk proyek Anda. Namun, menjaga mereka terorganisir membantu Anda mempertahankan kode Anda seiring pertumbuhan aplikasi Anda. Berikut adalah beberapa opsi praktis dan praktik terbaik, disesuaikan dengan sifat ringan Flight:
Opsi 1: Di index.php
Utama Anda
Untuk aplikasi kecil atau prototipe cepat, Anda dapat mendaftarkan acara langsung di file index.php
Anda bersamaan dengan rute Anda. Ini menjaga semuanya di satu tempat, yang baik ketika kesederhanaan adalah prioritas Anda.
require 'vendor/autoload.php';
// Mendaftarkan acara
Flight::onEvent('user.login', function ($username) {
error_log("$username login pada " . date('Y-m-d H:i:s'));
});
// Mendefinisikan rute
Flight::route('/login', function () {
$username = 'bob';
Flight::triggerEvent('user.login', $username);
echo "Telah login!";
});
Flight::start();
- Pro: Sederhana, tidak ada file tambahan, bagus untuk proyek kecil.
- Kontra: Dapat menjadi berantakan seiring pertumbuhan aplikasi Anda dengan lebih banyak acara dan rute.
Opsi 2: File events.php
Terpisah
Untuk aplikasi yang sedikit lebih besar, pertimbangkan untuk memindahkan pendaftaran acara ke dalam file khusus seperti app/config/events.php
. Sertakan file ini di index.php
Anda sebelum rute Anda. Ini meniru cara rute sering diorganisir dalam app/config/routes.php
di proyek Flight.
// app/config/events.php
Flight::onEvent('user.login', function ($username) {
error_log("$username login pada " . date('Y-m-d H:i:s'));
});
Flight::onEvent('user.registered', function ($email, $name) {
echo "Email dikirim ke $email: Selamat datang, $name!";
});
// index.php
require 'vendor/autoload.php';
require 'app/config/events.php';
Flight::route('/login', function () {
$username = 'bob';
Flight::triggerEvent('user.login', $username);
echo "Telah login!";
});
Flight::start();
- Pro: Menjaga
index.php
terfokus pada routing, mengorganisir acara secara logis, mudah ditemukan dan diedit. - Kontra: Menambahkan sedikit struktur, yang mungkin terasa berlebihan untuk aplikasi yang sangat kecil.
Opsi 3: Dekat Tempat Acara Dipicu
Pendekatan lain adalah mendaftarkan acara dekat tempat mereka dipicu, seperti di dalam kontroler atau definisi rute. Ini bekerja dengan baik jika sebuah acara khusus untuk satu bagian aplikasi Anda.
Flight::route('/signup', function () {
// Mendaftarkan acara di sini
Flight::onEvent('user.registered', function ($email) {
echo "Email selamat datang dikirim ke $email!";
});
$email = 'jane@example.com';
Flight::triggerEvent('user.registered', $email);
echo "Telah mendaftar!";
});
- Pro: Menjaga kode terkait bersama, baik untuk fitur terisolasi.
- Kontra: Menyebar pendaftaran acara, membuatnya lebih sulit untuk melihat semua acara sekaligus; berisiko pendaftaran duplikat jika tidak hati-hati.
Praktik Terbaik untuk Flight
- Mulailah Sederhana: Untuk aplikasi kecil, letakkan acara di
index.php
. Ini cepat dan selaras dengan minimalisme Flight. - Bertumbuh dengan Cerdas: Saat aplikasi Anda berkembang (misalnya, lebih dari 5-10 acara), gunakan file
app/config/events.php
. Ini adalah langkah alami ke atas, seperti mengorganisir rute, dan menjaga kode Anda rapi tanpa menambahkan framework yang kompleks. - Hindari Over-Engineering: Jangan membuat kelas atau direktori "manajer acara" yang besar kecuali aplikasi Anda sangat besar—Flight berkembang dalam kesederhanaan, jadi jaga tetap ringan.
Tip: Kelompokkan Berdasarkan Tujuan
Di events.php
, kelompokkan acara terkait (misalnya, semua acara terkait pengguna bersama) dengan komentar untuk kejelasan:
// app/config/events.php
// Acara Pengguna
Flight::onEvent('user.login', function ($username) {
error_log("$username login");
});
Flight::onEvent('user.registered', function ($email) {
echo "Selamat datang di $email!";
});
// Acara Halaman
Flight::onEvent('page.updated', function ($pageId) {
unset($_SESSION['pages'][$pageId]);
});
Struktur ini berkembang dengan baik dan tetap ramah pemula.
Contoh untuk Pemula
Mari kita lihat beberapa skenario dunia nyata untuk menunjukkan bagaimana acara bekerja dan mengapa mereka berguna.
Contoh 1: Mencatat Login Pengguna
// Langkah 1: Mendaftarkan pendengar
Flight::onEvent('user.login', function ($username) {
$time = date('Y-m-d H:i:s');
error_log("$username login pada $time");
});
// Langkah 2: Memicu di aplikasi Anda
Flight::route('/login', function () {
$username = 'bob'; // Asumsikan ini berasal dari formulir
Flight::triggerEvent('user.login', $username);
echo "Hai, $username!";
});
Mengapa Ini Berguna: Kode login tidak perlu tahu tentang pencatatan—hanya memicu acara. Anda bisa menambahkan lebih banyak pendengar (misalnya, mengirim email selamat datang) tanpa mengubah rute.
Contoh 2: Memberi Tahu tentang Pengguna Baru
// Pendengar untuk pendaftaran baru
Flight::onEvent('user.registered', function ($email, $name) {
// Mensimulasikan mengirim email
echo "Email dikirim ke $email: Selamat datang, $name!";
});
// Memicu ketika seseorang mendaftar
Flight::route('/signup', function () {
$email = 'jane@example.com';
$name = 'Jane';
Flight::triggerEvent('user.registered', $email, $name);
echo "Terima kasih telah mendaftar!";
});
Mengapa Ini Berguna: Logika pendaftaran fokus pada pembuatan pengguna, sementara acara menangani notifikasi. Anda dapat menambahkan lebih banyak pendengar (misalnya, mencatat pendaftaran) nanti.
Contoh 3: Menghapus Cache
// Pendengar untuk menghapus cache
Flight::onEvent('page.updated', function ($pageId) {
unset($_SESSION['pages'][$pageId]); // Menghapus cache sesi jika berlaku
echo "Cache dihapus untuk halaman $pageId.";
});
// Memicu saat halaman diedit
Flight::route('/edit-page/(@id)', function ($pageId) {
// Asumsikan kami memperbarui halaman
Flight::triggerEvent('page.updated', $pageId);
echo "Halaman $pageId diperbarui.";
});
Mengapa Ini Berguna: Kode pengeditan tidak peduli tentang caching—hanya memberi sinyal pembaruan. Bagian lain dari aplikasi dapat bereaksi sesuai kebutuhan.
Praktik Terbaik
- Berikan Nama Acara dengan Jelas: Gunakan nama spesifik seperti
'user.login'
atau'page.updated'
agar jelas apa fungsinya. - Simpan Pendengar Sederhana: Jangan letakkan tugas lambat atau kompleks dalam pendengar—jaga aplikasi Anda cepat.
- Uji Acara Anda: Picu secara manual untuk memastikan pendengar berfungsi seperti yang diharapkan.
- Gunakan Acara dengan Bijak: Mereka hebat untuk pemisahan, tetapi terlalu banyak bisa membuat kode Anda sulit diikuti—gunakan ketika masuk akal.
Sistem acara di Flight PHP, dengan Flight::onEvent()
dan Flight::triggerEvent()
, memberi Anda cara yang sederhana namun kuat untuk membangun aplikasi yang fleksibel. Dengan membiarkan bagian-bagian berbeda dari aplikasi Anda berkomunikasi melalui acara, Anda dapat menjaga kode Anda terorganisir, dapat digunakan kembali, dan mudah untuk diperluas. Apakah Anda sedang mencatat tindakan, mengirim notifikasi, atau mengelola pembaruan, acara membantu Anda melakukannya tanpa merumitkan logika Anda. Ditambah dengan kemampuan untuk menimpa metode-metode ini, Anda memiliki kebebasan untuk menyesuaikan sistem dengan kebutuhan Anda. Mulailah kecil dengan satu acara, dan saksikan bagaimana hal itu mengubah struktur aplikasi Anda!
Acara Bawaan
Flight PHP dilengkapi dengan beberapa acara bawaan yang dapat Anda gunakan untuk terhubung ke siklus hidup framework. Acara ini dipicu pada titik tertentu dalam siklus permintaan/respons, memungkinkan Anda untuk mengeksekusi logika kustom saat tindakan tertentu terjadi.
Daftar Acara Bawaan
flight.request.received
: Dipicu saat permintaan diterima, diparsing, dan diproses.flight.route.middleware.before
: Dipicu setelah middleware sebelum dieksekusi.flight.route.middleware.after
: Dipicu setelah middleware setelah dieksekusi.flight.route.executed
: Dipicu setelah sebuah rute dieksekusi dan diproses.flight.response.sent
: Dipicu setelah respons dikirim ke klien.
Learn/templates
Tampilan HTML dan Template
Flight menyediakan beberapa fungsionalitas templating dasar secara default.
Flight memungkinkan Anda untuk mengganti mesin tampilan default hanya dengan mendaftarkan kelas tampilan Anda sendiri. Gulir ke bawah untuk melihat contoh cara menggunakan Smarty, Latte, Blade, dan lainnya!
Mesin Tampilan Bawaan
Untuk menampilkan sebuah template tampilan, panggil metode render
dengan nama file template dan data template opsional:
Flight::render('hello.php', ['name' => 'Bob']);
Data template yang Anda masukkan secara otomatis disuntikkan ke dalam template dan dapat dirujuk seperti variabel lokal. File template hanyalah file PHP. Jika konten dari file template hello.php
adalah:
Hello, <?= $name ?>!
Outputnya adalah:
Hello, Bob!
Anda juga dapat secara manual mengatur variabel tampilan dengan menggunakan metode set:
Flight::view()->set('name', 'Bob');
Variabel name
kini tersedia di semua tampilan Anda. Jadi Anda dapat dengan mudah melakukan:
Flight::render('hello');
Perhatikan bahwa saat menentukan nama template dalam metode render, Anda dapat menghilangkan ekstensi .php
.
Secara default, Flight akan mencari direktori views
untuk file template. Anda dapat menetapkan jalur alternatif untuk template Anda dengan mengatur konfigurasi berikut:
Flight::set('flight.views.path', '/path/to/views');
Tata Letak
Adalah hal yang umum untuk situs web memiliki satu file template tata letak dengan konten yang saling bertukar. Untuk merender konten yang digunakan dalam tata letak, Anda dapat memasukkan parameter opsional ke dalam metode render
.
Flight::render('header', ['heading' => 'Hello'], 'headerContent');
Flight::render('body', ['body' => 'World'], 'bodyContent');
Tampilan Anda kemudian akan memiliki variabel yang disimpan yang disebut headerContent
dan bodyContent
. Anda kemudian dapat merender tata letak Anda dengan melakukan:
Flight::render('layout', ['title' => 'Home Page']);
Jika file template terlihat seperti ini:
header.php
:
<h1><?= $heading ?></h1>
body.php
:
<div><?= $body ?></div>
layout.php
:
<html>
<head>
<title><?= $title ?></title>
</head>
<body>
<?= $headerContent ?>
<?= $bodyContent ?>
</body>
</html>
Outputnya adalah:
<html>
<head>
<title>Home Page</title>
</head>
<body>
<h1>Hello</h1>
<div>World</div>
</body>
</html>
Smarty
Berikut cara menggunakan mesin template Smarty untuk tampilan Anda:
// Muat pustaka Smarty
require './Smarty/libs/Smarty.class.php';
// Daftarkan Smarty sebagai kelas tampilan
// Juga lewati fungsi callback untuk mengonfigurasi Smarty saat dimuat
Flight::register('view', Smarty::class, [], function (Smarty $smarty) {
$smarty->setTemplateDir('./templates/');
$smarty->setCompileDir('./templates_c/');
$smarty->setConfigDir('./config/');
$smarty->setCacheDir('./cache/');
});
// Tetapkan data template
Flight::view()->assign('name', 'Bob');
// Tampilkan template
Flight::view()->display('hello.tpl');
Untuk kelengkapan, Anda juga harus menimpa metode render default Flight:
Flight::map('render', function(string $template, array $data): void {
Flight::view()->assign($data);
Flight::view()->display($template);
});
Latte
Berikut cara menggunakan mesin template Latte untuk tampilan Anda:
// Daftarkan Latte sebagai kelas tampilan
// Juga lewati fungsi callback untuk mengonfigurasi Latte saat dimuat
Flight::register('view', Latte\Engine::class, [], function (Latte\Engine $latte) {
// Di sinilah Latte akan menyimpan cache template Anda untuk mempercepat segalanya
// Satu hal menarik tentang Latte adalah bahwa ia secara otomatis menyegarkan
// cache saat Anda melakukan perubahan pada template Anda!
$latte->setTempDirectory(__DIR__ . '/../cache/');
// Beri tahu Latte di mana direktori akar untuk tampilan Anda akan berada.
$latte->setLoader(new \Latte\Loaders\FileLoader(__DIR__ . '/../views/'));
});
// Dan akhiri sehingga Anda dapat menggunakan Flight::render() dengan benar
Flight::map('render', function(string $template, array $data): void {
// Ini seperti $latte_engine->render($template, $data);
echo Flight::view()->render($template, $data);
});
Blade
Berikut cara menggunakan mesin template Blade untuk tampilan Anda:
Pertama, Anda perlu menginstal pustaka BladeOne melalui Composer:
composer require eftec/bladeone
Kemudian, Anda dapat mengonfigurasi BladeOne sebagai kelas tampilan di Flight:
<?php
// Muat pustaka BladeOne
use eftec\bladeone\BladeOne;
// Daftarkan BladeOne sebagai kelas tampilan
// Juga lewati fungsi callback untuk mengonfigurasi BladeOne saat dimuat
Flight::register('view', BladeOne::class, [], function (BladeOne $blade) {
$views = __DIR__ . '/../views';
$cache = __DIR__ . '/../cache';
$blade->setPath($views);
$blade->setCompiledPath($cache);
});
// Tetapkan data template
Flight::view()->share('name', 'Bob');
// Tampilkan template
echo Flight::view()->run('hello', []);
Untuk kelengkapan, Anda juga harus menimpa metode render default Flight:
<?php
Flight::map('render', function(string $template, array $data): void {
echo Flight::view()->run($template, $data);
});
Dalam contoh ini, file template hello.blade.php mungkin terlihat seperti ini:
<?php
Hello, {{ $name }}!
Outputnya adalah:
Hello, Bob!
Dengan mengikuti langkah-langkah ini, Anda dapat mengintegrasikan mesin template Blade dengan Flight dan menggunakannya untuk merender tampilan Anda.
Learn/flight_vs_fat_free
Flight vs Fat-Free
Apa itu Fat-Free?
Fat-Free (dikenal dengan penuh kasih sebagai F3) adalah sebuah mikro-framework PHP yang kuat namun mudah digunakan, dirancang untuk membantu Anda membangun aplikasi web yang dinamis dan tangguh - dengan cepat!
Flight dibandingkan dengan Fat-Free dalam banyak hal dan mungkin merupakan kerabat terdekat dalam hal fitur dan kesederhanaan. Fat-Free memiliki banyak fitur yang tidak dimiliki oleh Flight, tetapi juga memiliki banyak fitur yang dimiliki oleh Flight. Fat-Free mulai menunjukkan usianya dan tidak sepopuler dulu.
Pembaruan menjadi semakin jarang dan komunitas tidak seaktif dulu. Kode ini cukup sederhana, tetapi terkadang kurangnya disiplin sintaks dapat membuatnya sulit untuk dibaca dan dipahami. Ini berfungsi untuk PHP 8.3, tetapi kode itu sendiri masih terlihat seolah-olah berada di PHP 5.3.
Kelebihan dibandingkan Flight
- Fat-Free memiliki beberapa bintang lebih banyak di GitHub dibandingkan Flight.
- Fat-Free memiliki dokumentasi yang cukup baik, tetapi kurang jelas di beberapa area.
- Fat-Free memiliki beberapa sumber daya yang jarang seperti tutorial YouTube dan artikel online yang dapat digunakan untuk mempelajari framework.
- Fat-Free memiliki beberapa plugin yang berguna yang terkadang bermanfaat.
- Fat-Free memiliki ORM bawaan yang disebut Mapper yang dapat digunakan untuk berinteraksi dengan database Anda. Flight memiliki active-record.
- Fat-Free memiliki sesi, caching, dan lokalisasi bawaan. Flight mengharuskan Anda untuk menggunakan pustaka pihak ketiga, tetapi dijelaskan dalam dokumentasi.
- Fat-Free memiliki sekelompok plugin yang dibuat oleh komunitas yang dapat digunakan untuk memperluas framework. Flight memiliki beberapa yang dijelaskan dalam halaman dokumentasi dan contoh.
- Fat-Free seperti Flight tidak memiliki ketergantungan.
- Fat-Free seperti Flight ditujukan untuk memberikan kontrol kepada pengembang atas aplikasi mereka dan pengalaman pengembang yang sederhana.
- Fat-Free mempertahankan kompatibilitas ke belakang seperti halnya Flight (sebagian karena pembaruan semakin jarang).
- Fat-Free seperti Flight ditujukan untuk pengembang yang menjelajah ke dunia framework untuk pertama kalinya.
- Fat-Free memiliki mesin template bawaan yang lebih kuat dibandingkan dengan mesin template Flight. Flight merekomendasikan Latte untuk mencapai ini.
- Fat-Free memiliki perintah CLI tipe "route" unik di mana Anda dapat membangun aplikasi CLI di dalam Fat-Free itu sendiri dan memperlakukannya seperti permintaan
GET
. Flight mencapainya dengan runway.
Kekurangan dibandingkan Flight
- Fat-Free memiliki beberapa pengujian implementasi dan bahkan memiliki kelas test sendiri yang sangat dasar. Namun, tidak 100% diuji unit seperti Flight.
- Anda harus menggunakan mesin pencari seperti Google untuk benar-benar mencari situs dokumentasi.
- Flight memiliki mode gelap di situs dokumentasi mereka. (mic drop)
- Fat-Free memiliki beberapa modul yang sangat kurang terawat.
- Flight memiliki PdoWrapper yang sedikit lebih sederhana dibandingkan kelas
DB\SQL
bawaan Fat-Free. - Flight memiliki plugin izin yang dapat digunakan untuk mengamankan aplikasi Anda. Slim mengharuskan Anda untuk menggunakan pustaka pihak ketiga.
- Flight memiliki ORM yang disebut active-record yang terasa lebih seperti ORM dibandingkan dengan Mapper Fat-Free.
Manfaat tambahan dari
active-record
adalah Anda dapat mendefinisikan hubungan antara catatan untuk penggabungan otomatis di mana Mapper Fat-Free mengharuskan Anda untuk membuat tampilan SQL. - Yang mengejutkan, Fat-Free tidak memiliki namespace akar. Flight memiliki namespace yang lengkap untuk tidak bertabrakan dengan kode Anda sendiri.
kelas
Cache
adalah pelanggar terbesar di sini. - Fat-Free tidak memiliki middleware. Sebaliknya, ada hook
beforeroute
danafterroute
yang dapat digunakan untuk memfilter permintaan dan respons di dalam kontroler. - Fat-Free tidak dapat mengelompokkan routes.
- Fat-Free memiliki penangan kontainer injeksi ketergantungan, tetapi dokumentasinya sangat jarang tentang cara menggunakannya.
- Penggunaan debugging bisa sedikit rumit karena pada dasarnya semuanya disimpan dalam apa yang disebut
HIVE
.
Learn/extending
Memperluas
Flight dirancang untuk menjadi kerangka kerja yang dapat diperluas. Kerangka kerja ini dilengkapi dengan serangkaian metode dan komponen default, tetapi memungkinkan Anda untuk memetakan metode Anda sendiri, mendaftarkan kelas Anda sendiri, atau bahkan mengganti kelas dan metode yang sudah ada.
Jika Anda mencari DIC (Dependency Injection Container), silakan kunjungi halaman Dependency Injection Container.
Memetakan Metode
Untuk memetakan metode kustom sederhana Anda sendiri, Anda menggunakan fungsi map
:
// Pemetakan metode Anda
Flight::map('hello', function (string $name) {
echo "halo $name!";
});
// Panggil metode kustom Anda
Flight::hello('Bob');
Meskipun mungkin untuk membuat metode kustom sederhana, disarankan untuk hanya membuat fungsi standar di PHP. Ini memiliki autocompletion di IDE dan lebih mudah dibaca. Padanan dari kode di atas adalah:
function hello(string $name) {
echo "halo $name!";
}
hello('Bob');
Ini lebih sering digunakan ketika Anda perlu mengoper variabel ke metode Anda untuk mendapatkan nilai yang diharapkan. Menggunakan metode register()
seperti di bawah ini lebih untuk mengoper konfigurasi dan kemudian memanggil kelas yang sudah dikonfigurasi sebelumnya.
Mendaftarkan Kelas
Untuk mendaftarkan kelas Anda sendiri dan mengkonfigurasinya, Anda menggunakan fungsi register
:
// Daftarkan kelas Anda
Flight::register('user', User::class);
// Ambil instance dari kelas Anda
$user = Flight::user();
Metode register juga memungkinkan Anda untuk mengoper parameter ke konstruktor kelas Anda. Jadi, ketika Anda memuat kelas kustom Anda, itu akan datang dengan inisialisasi awal. Anda dapat menentukan parameter konstruktor dengan mengoper array tambahan. Berikut adalah contoh memuat koneksi database:
// Daftarkan kelas dengan parameter konstruktor
Flight::register('db', PDO::class, ['mysql:host=localhost;dbname=test', 'user', 'pass']);
// Ambil instance dari kelas Anda
// Ini akan membuat objek dengan parameter yang ditentukan
//
// new PDO('mysql:host=localhost;dbname=test','user','pass');
//
$db = Flight::db();
// dan jika Anda membutuhkannya nanti dalam kode Anda, Anda cukup memanggil metode yang sama lagi
class SomeController {
public function __construct() {
$this->db = Flight::db();
}
}
Jika Anda mengoper parameter callback tambahan, itu akan dieksekusi segera setelah konstruktor kelas. Ini memungkinkan Anda untuk melakukan prosedur penyiapan untuk objek baru Anda. Fungsi callback mengambil satu parameter, sebuah instance dari objek baru.
// Callback akan menerima objek yang telah dibangun
Flight::register(
'db',
PDO::class,
['mysql:host=localhost;dbname=test', 'user', 'pass'],
function (PDO $db) {
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
);
Secara default, setiap kali Anda memuat kelas Anda, Anda akan mendapatkan instance yang dibagikan. Untuk mendapatkan instance baru dari kelas, cukup oper false
sebagai parameter:
// Instance bersama dari kelas
$shared = Flight::db();
// Instance baru dari kelas
$new = Flight::db(false);
Ingat bahwa metode yang dipetakan memiliki prioritas atas kelas yang terdaftar. Jika Anda mendeklarasikan keduanya menggunakan nama yang sama, hanya metode yang dipetakan yang akan dipanggil.
Logging
Flight tidak memiliki sistem logging bawaan, namun, sangat mudah untuk menggunakan pustaka logging dengan Flight. Berikut adalah contoh menggunakan pustaka Monolog:
// index.php atau bootstrap.php
// Daftarkan logger dengan Flight
Flight::register('log', Monolog\Logger::class, [ 'name' ], function(Monolog\Logger $log) {
$log->pushHandler(new Monolog\Handler\StreamHandler('path/to/your.log', Monolog\Logger::WARNING));
});
Sekarang setelah terdaftar, Anda dapat menggunakannya di aplikasi Anda:
// Di controller atau route Anda
Flight::log()->warning('Ini adalah pesan peringatan');
Ini akan mencatat pesan ke file log yang Anda tentukan. Bagaimana jika Anda ingin mencatat sesuatu saat terjadi kesalahan? Anda dapat menggunakan metode error
:
// Di controller atau route Anda
Flight::map('error', function(Throwable $ex) {
Flight::log()->error($ex->getMessage());
// Tampilkan halaman kesalahan kustom Anda
include 'errors/500.html';
});
Anda juga bisa membuat sistem APM (Application Performance Monitoring) dasar menggunakan metode before
dan after
:
// Di file bootstrap Anda
Flight::before('start', function() {
Flight::set('start_time', microtime(true));
});
Flight::after('start', function() {
$end = microtime(true);
$start = Flight::get('start_time');
Flight::log()->info('Permintaan '.Flight::request()->url.' memakan waktu ' . round($end - $start, 4) . ' detik');
// Anda juga bisa menambahkan header permintaan atau respons Anda
// untuk mencatatnya juga (hati-hati karena ini akan jadi
// banyak data jika Anda memiliki banyak permintaan)
Flight::log()->info('Header Permintaan: ' . json_encode(Flight::request()->headers));
Flight::log()->info('Header Respons: ' . json_encode(Flight::response()->headers));
});
Mengganti Metode Framework
Flight memungkinkan Anda untuk mengganti fungsionalitas bawaannya agar sesuai dengan kebutuhan Anda, tanpa harus memodifikasi kode apa pun. Anda dapat melihat semua metode yang dapat Anda ganti di sini.
Sebagai contoh, ketika Flight tidak dapat mencocokkan URL dengan rute, ia memanggil metode notFound
yang mengirimkan tanggapan HTTP 404
umum. Anda dapat mengganti perilaku ini dengan menggunakan metode map
:
Flight::map('notFound', function() {
// Tampilkan halaman kustom 404
include 'errors/404.html';
});
Flight juga memungkinkan Anda untuk mengganti komponen inti dari kerangka kerja. Sebagai contoh, Anda dapat mengganti kelas Router default dengan kelas kustom Anda sendiri:
// Daftarkan kelas kustom Anda
Flight::register('router', MyRouter::class);
// Ketika Flight memuat instance Router, itu akan memuat kelas Anda
$myrouter = Flight::router();
Namun, metode kerangka kerja seperti map
dan register
tidak dapat diganti. Anda akan mendapatkan kesalahan jika Anda mencoba melakukannya.
Learn/flight_vs_slim
Flight vs Slim
Apa itu Slim?
Slim adalah kerangka mikro PHP yang membantu Anda dengan cepat menulis aplikasi web dan API yang sederhana namun kuat.
Banyak inspirasi untuk beberapa fitur v3 dari Flight sebenarnya datang dari Slim. Pengelompokan rute, dan menjalankan middleware dalam urutan tertentu adalah dua fitur yang terinspirasi oleh Slim. Slim v3 diluncurkan dengan mengutamakan kesederhanaan, tetapi terdapat ulasan campuran mengenai v4.
Kelebihan dibandingkan Flight
- Slim memiliki komunitas pengembang yang lebih besar, yang pada gilirannya membuat modul-modul berguna untuk membantu Anda tidak menciptakan kembali roda.
- Slim mengikuti banyak antarmuka dan standar yang umum di komunitas PHP, yang meningkatkan interoperabilitas.
- Slim memiliki dokumentasi dan tutorial yang baik yang dapat digunakan untuk mempelajari kerangka kerja (tidak ada yang sebanding dengan Laravel atau Symfony).
- Slim memiliki berbagai sumber daya seperti tutorial YouTube dan artikel online yang dapat digunakan untuk mempelajari kerangka kerja.
- Slim memungkinkan Anda menggunakan komponen apa pun yang Anda inginkan untuk menangani fitur routing inti karena memenuhi standar PSR-7.
Kekurangan dibandingkan Flight
- Secara mengejutkan, Slim tidak secepat yang Anda kira untuk sebuah mikro-kerangka. Lihat benchmark TechEmpower untuk informasi lebih lanjut.
- Flight ditujukan untuk pengembang yang ingin membangun aplikasi web yang ringan, cepat, dan mudah digunakan.
- Flight tidak memiliki ketergantungan, sedangkan Slim memiliki beberapa ketergantungan yang harus Anda instal.
- Flight ditujukan untuk kesederhanaan dan kemudahan penggunaan.
- Salah satu fitur inti dari Flight adalah bahwa ia melakukan yang terbaik untuk mempertahankan kompatibilitas mundur. Perubahan dari Slim v3 ke v4 adalah perubahan yang merusak.
- Flight dimaksudkan untuk pengembang yang memasuki dunia kerangka kerja untuk pertama kalinya.
- Flight juga dapat melakukan aplikasi tingkat perusahaan, tetapi tidak memiliki sebanyak contoh dan tutorial seperti yang dimiliki Slim. Ini juga akan memerlukan lebih banyak disiplin dari pihak pengembang untuk menjaga semuanya tetap teratur dan terstruktur dengan baik.
- Flight memberikan pengembang lebih banyak kontrol atas aplikasi, sedangkan Slim dapat menyisipkan beberapa sihir di balik layar.
- Flight memiliki PdoWrapper yang sederhana yang dapat digunakan untuk berinteraksi dengan basis data Anda. Slim mengharuskan Anda menggunakan perpustakaan pihak ketiga.
- Flight memiliki plugin izin yang dapat digunakan untuk mengamankan aplikasi Anda. Slim mengharuskan Anda menggunakan perpustakaan pihak ketiga.
- Flight memiliki ORM yang disebut active-record yang dapat digunakan untuk berinteraksi dengan basis data Anda. Slim mengharuskan Anda menggunakan perpustakaan pihak ketiga.
- Flight memiliki aplikasi CLI yang disebut runway yang dapat digunakan untuk menjalankan aplikasi Anda dari command line. Slim tidak memiliki.
Learn/autoloading
Autoloading
Autoloading adalah konsep dalam PHP di mana Anda menentukan satu direktori atau beberapa direktori untuk memuat kelas. Ini jauh lebih menguntungkan daripada menggunakan require
atau include
untuk memuat kelas. Ini juga merupakan persyaratan untuk menggunakan paket Composer.
Secara default, setiap kelas Flight
dimuat otomatis untuk Anda berkat composer. Namun, jika Anda ingin memuat otomatis kelas Anda sendiri, Anda dapat menggunakan metode Flight::path()
untuk menentukan direktori yang akan memuat kelas.
Contoh Dasar
Mari kita anggap kita memiliki pohon direktori seperti berikut:
# Contoh path
/home/user/project/my-flight-project/
├── app
│ ├── cache
│ ├── config
│ ├── controllers - berisi kontroler untuk proyek ini
│ ├── translations
│ ├── UTILS - berisi kelas untuk aplikasi ini saja (ini huruf kapital semua dengan tujuan sebagai contoh nanti)
│ └── views
└── public
└── css
└── js
└── index.php
Anda mungkin telah memperhatikan bahwa ini adalah struktur file yang sama dengan situs dokumentasi ini.
Anda dapat menentukan setiap direktori untuk dimuat dari seperti ini:
/**
* public/index.php
*/
// Tambahkan path ke autoloader
Flight::path(__DIR__.'/../app/controllers/');
Flight::path(__DIR__.'/../app/utils/');
/**
* app/controllers/MyController.php
*/
// tidak ada namespace yang diperlukan
// Semua kelas yang dimuat otomatis disarankan untuk menggunakan Pascal Case (setiap kata dengan huruf kapital, tanpa spasi)
// Mulai dari 3.7.2, Anda dapat menggunakan Pascal_Snake_Case untuk nama kelas Anda dengan menjalankan Loader::setV2ClassLoading(false);
class MyController {
public function index() {
// lakukan sesuatu
}
}
Namespace
Jika Anda memiliki namespace, sebenarnya menjadi sangat mudah untuk menerapkan ini. Anda harus menggunakan metode Flight::path()
untuk menentukan direktori root (bukan document root atau folder public/
) aplikasi Anda.
/**
* public/index.php
*/
// Tambahkan path ke autoloader
Flight::path(__DIR__.'/../');
Sekarang inilah yang mungkin terlihat seperti kontroler Anda. Lihat contoh di bawah ini, tetapi perhatikan komentar untuk informasi penting.
/**
* app/controllers/MyController.php
*/
// namespace diperlukan
// namespace sama dengan struktur direktori
// namespace harus mengikuti huruf besar yang sama dengan struktur direktori
// namespace dan direktori tidak dapat memiliki garis bawah (kecuali Loader::setV2ClassLoading(false) diset)
namespace app\controllers;
// Semua kelas yang dimuat otomatis disarankan untuk menggunakan Pascal Case (setiap kata dengan huruf kapital, tanpa spasi)
// Mulai dari 3.7.2, Anda dapat menggunakan Pascal_Snake_Case untuk nama kelas Anda dengan menjalankan Loader::setV2ClassLoading(false);
class MyController {
public function index() {
// lakukan sesuatu
}
}
Dan jika Anda ingin memuat otomatis kelas di direktori utilitas Anda, Anda akan melakukan hal yang hampir sama:
/**
* app/UTILS/ArrayHelperUtil.php
*/
// namespace harus cocok dengan struktur direktori dan huruf besar (perhatikan direktori UTILS semua huruf kapital
// seperti pada pohon file di atas)
namespace app\UTILS;
class ArrayHelperUtil {
public function changeArrayCase(array $array) {
// lakukan sesuatu
}
}
Garis Bawah dalam Nama Kelas
Mulai dari 3.7.2, Anda dapat menggunakan Pascal_Snake_Case untuk nama kelas Anda dengan menjalankan Loader::setV2ClassLoading(false);
.
Ini akan memungkinkan Anda untuk menggunakan garis bawah dalam nama kelas Anda.
Ini tidak disarankan, tetapi tersedia untuk mereka yang membutuhkannya.
/**
* public/index.php
*/
// Tambahkan path ke autoloader
Flight::path(__DIR__.'/../app/controllers/');
Flight::path(__DIR__.'/../app/utils/');
Loader::setV2ClassLoading(false);
/**
* app/controllers/My_Controller.php
*/
// tidak ada namespace yang diperlukan
class My_Controller {
public function index() {
// lakukan sesuatu
}
}
Learn/troubleshooting
Pemecahan Masalah
Halaman ini akan membantu Anda memecahkan masalah umum yang mungkin Anda temui saat menggunakan Flight.
Masalah Umum
404 Tidak Ditemukan atau Perilaku Rute Tak Terduga
Jika Anda melihat kesalahan 404 Tidak Ditemukan (tetapi Anda bersumpah bahwa itu benar-benar ada dan bukan kesalahan ketik) ini sebenarnya bisa menjadi masalah dengan Anda yang mengembalikan nilai di titik akhir rute Anda alih-alih hanya mencetaknya. Alasan untuk ini adalah disengaja tetapi bisa mengganggu beberapa pengembang.
Flight::route('/hello', function(){
// Ini mungkin menyebabkan kesalahan 404 Tidak Ditemukan
return 'Hello World';
});
// Apa yang mungkin Anda inginkan
Flight::route('/hello', function(){
echo 'Hello World';
});
Alasan untuk ini adalah karena mekanisme khusus yang dibangun ke dalam router yang menangani keluaran pengembalian sebagai sinyal untuk "melanjutkan ke rute berikutnya". Anda dapat melihat perilaku ini didokumentasikan di bagian Routing.
Kelas Tidak Ditemukan (autoloading tidak bekerja)
Ada beberapa alasan mengapa ini tidak terjadi. Di bawah ini adalah beberapa contoh tetapi pastikan Anda juga memeriksa bagian autoloading.
Nama File yang Salah
Yang paling umum adalah bahwa nama kelas tidak cocok dengan nama file.
Jika Anda memiliki kelas bernama MyClass
maka file tersebut harus dinamai MyClass.php
. Jika Anda memiliki kelas bernama MyClass
dan file tersebut dinamai myclass.php
maka autoloader tidak akan dapat menemukannya.
Namespace yang Salah
Jika Anda menggunakan namespace, maka namespace harus cocok dengan struktur direktori.
// kode
// jika MyController Anda berada di direktori app/controllers dan memiliki namespace
// ini tidak akan berfungsi.
Flight::route('/hello', 'MyController->hello');
// Anda perlu memilih salah satu dari opsi ini
Flight::route('/hello', 'app\controllers\MyController->hello');
// atau jika Anda memiliki pernyataan use di atas
use app\controllers\MyController;
Flight::route('/hello', [ MyController::class, 'hello' ]);
// juga bisa ditulis
Flight::route('/hello', MyController::class.'->hello');
// juga...
Flight::route('/hello', [ 'app\controllers\MyController', 'hello' ]);
path()
tidak didefinisikan
Dalam aplikasi kerangka kerja, ini didefinisikan di dalam file config.php
, tetapi agar kelas Anda dapat ditemukan, Anda perlu memastikan bahwa metode path()
didefinisikan (kemungkinan ke root direktori Anda) sebelum Anda mencoba menggunakannya.
// Tambahkan path ke autoloader
Flight::path(__DIR__.'/../');
Guides/blog
Membangun Blog Sederhana dengan Flight PHP
Panduan ini memandu Anda melalui pembuatan blog dasar menggunakan framework Flight PHP. Anda akan mengatur proyek, mendefinisikan rute, mengelola pos dengan JSON, dan merendernya dengan mesin templating Latte—semuanya menunjukkan kesederhanaan dan fleksibilitas Flight. Pada akhir panduan, Anda akan memiliki blog fungsional dengan halaman utama, halaman pos individu, dan formulir pembuatan.
Prasyarat
- PHP 7.4+: Terinstal di sistem Anda.
- Composer: Untuk manajemen ketergantungan.
- Editor Teks: Editor apa pun seperti VS Code atau PHPStorm.
- Pengetahuan dasar tentang PHP dan pengembangan web.
Langkah 1: Siapkan Proyek Anda
Mulailah dengan membuat direktori proyek baru dan menginstal Flight melalui Composer.
-
Buat Direktori:
mkdir flight-blog cd flight-blog
-
Instal Flight:
composer require flightphp/core
-
Buat Direktori Publik: Flight menggunakan titik masuk tunggal (
index.php
). Buat folderpublic/
untuk itu:mkdir public
-
index.php
Dasar: Buatpublic/index.php
dengan rute "hello world" yang sederhana:<?php require '../vendor/autoload.php'; Flight::route('/', function () { echo 'Halo, Flight!'; }); Flight::start();
-
Jalankan Server Bawaan: Uji pengaturan Anda dengan server pengembangan PHP:
php -S localhost:8000 -t public/
Kunjungi
http://localhost:8000
untuk melihat "Halo, Flight!".
Langkah 2: Atur Struktur Proyek Anda
Untuk pengaturan yang bersih, struktur proyek Anda seperti ini:
flight-blog/
├── app/
│ ├── config/
│ └── views/
├── data/
├── public/
│ └── index.php
├── vendor/
└── composer.json
app/config/
: File konfigurasi (misalnya, acara, rute).app/views/
: Template untuk merender halaman.data/
: File JSON untuk menyimpan pos blog.public/
: Root web denganindex.php
.
Langkah 3: Instal dan Konfigurasi Latte
Latte adalah mesin templating ringan yang terintegrasi dengan baik dengan Flight.
-
Instal Latte:
composer require latte/latte
-
Konfigurasikan Latte di Flight: Perbarui
public/index.php
untuk mendaftarkan Latte sebagai mesin tampilan:<?php require '../vendor/autoload.php'; use Latte\Engine; Flight::register('view', Engine::class, [], function ($latte) { $latte->setTempDirectory(__DIR__ . '/../cache/'); $latte->setLoader(new \Latte\Loaders\FileLoader(__DIR__ . '/../app/views/')); }); Flight::route('/', function () { Flight::view()->render('home.latte', ['title' => 'Blog Saya']); }); Flight::start();
-
Buat Template Layout: Di
app/views/layout.latte
:<!DOCTYPE html> <html> <head> <title>{$title}</title> </head> <body> <header> <h1>Blog Saya</h1> <nav> <a href="/">Beranda</a> | <a href="/create">Buat Pos</a> </nav> </header> <main> {block content}{/block} </main> <footer> <p>© {date('Y')} Blog Flight</p> </footer> </body> </html>
-
Buat Template Beranda: Di
app/views/home.latte
:{extends 'layout.latte'} {block content} <h2>{$title}</h2> <ul> {foreach $posts as $post} <li><a href="/post/{$post['slug']}">{$post['title']}</a></li> {/foreach} </ul> {/block}
Mulai ulang server jika Anda keluar dan kunjungi
http://localhost:8000
untuk melihat halaman yang dirender. -
Buat File Data:
Gunakan file JSON untuk mensimulasikan database untuk kesederhanaan.
Di
data/posts.json
:[ { "slug": "first-post", "title": "Pos Pertama Saya", "content": "Ini adalah pos blog pertama saya dengan Flight PHP!" } ]
Langkah 4: Definisikan Rute
Pisahkan rute Anda ke dalam file konfigurasi untuk organisasi yang lebih baik.
-
Buat
routes.php
: Diapp/config/routes.php
:<?php Flight::route('/', function () { Flight::view()->render('home.latte', ['title' => 'Blog Saya']); }); Flight::route('/post/@slug', function ($slug) { Flight::view()->render('post.latte', ['title' => 'Pos: ' . $slug, 'slug' => $slug]); }); Flight::route('GET /create', function () { Flight::view()->render('create.latte', ['title' => 'Buat Pos']); });
-
Perbarui
index.php
: Termasuk file rute:<?php require '../vendor/autoload.php'; use Latte\Engine; Flight::register('view', Engine::class, [], function ($latte) { $latte->setTempDirectory(__DIR__ . '/../cache/'); $latte->setLoader(new \Latte\Loaders\FileLoader(__DIR__ . '/../app/views/')); }); require '../app/config/routes.php'; Flight::start();
Langkah 5: Simpan dan Ambil Pos Blog
Tambahkan metode untuk memuat dan menyimpan pos.
-
Tambahkan Metode Pos: Di
index.php
, tambahkan metode untuk memuat pos:Flight::map('posts', function () { $file = __DIR__ . '/../data/posts.json'; return json_decode(file_get_contents($file), true); });
-
Perbarui Rute: Modifikasi
app/config/routes.php
untuk menggunakan pos:<?php Flight::route('/', function () { $posts = Flight::posts(); Flight::view()->render('home.latte', [ 'title' => 'Blog Saya', 'posts' => $posts ]); }); Flight::route('/post/@slug', function ($slug) { $posts = Flight::posts(); $post = array_filter($posts, fn($p) => $p['slug'] === $slug); $post = reset($post) ?: null; if (!$post) { Flight::notFound(); return; } Flight::view()->render('post.latte', [ 'title' => $post['title'], 'post' => $post ]); }); Flight::route('GET /create', function () { Flight::view()->render('create.latte', ['title' => 'Buat Pos']); });
Langkah 6: Buat Template
Perbarui template Anda untuk menampilkan pos.
-
Halaman Pos (
app/views/post.latte
):{extends 'layout.latte'} {block content} <h2>{$post['title']}</h2> <div class="post-content"> <p>{$post['content']}</p> </div> {/block}
Langkah 7: Tambahkan Pembuatan Pos
Tangani pengiriman formulir untuk menambahkan pos baru.
-
Formulir Buat (
app/views/create.latte
):{extends 'layout.latte'} {block content} <h2>{$title}</h2> <form method="POST" action="/create"> <div class="form-group"> <label for="title">Judul:</label> <input type="text" name="title" id="title" required> </div> <div class="form-group"> <label for="content">Konten:</label> <textarea name="content" id="content" required></textarea> </div> <button type="submit">Simpan Pos</button> </form> {/block}
-
Tambahkan Rute POST: Di
app/config/routes.php
:Flight::route('POST /create', function () { $request = Flight::request(); $title = $request->data['title']; $content = $request->data['content']; $slug = strtolower(str_replace(' ', '-', $title)); $posts = Flight::posts(); $posts[] = ['slug' => $slug, 'title' => $title, 'content' => $content]; file_put_contents(__DIR__ . '/../../data/posts.json', json_encode($posts, JSON_PRETTY_PRINT)); Flight::redirect('/'); });
-
Uji Coba:
- Kunjungi
http://localhost:8000/create
. - Kirim pos baru (misalnya, “Pos Kedua” dengan beberapa konten).
- Periksa halaman utama untuk melihatnya terdaftar.
- Kunjungi
Langkah 8: Perbaiki dengan Penanganan Kesalahan
Timpakan metode notFound
untuk pengalaman 404 yang lebih baik.
Di index.php
:
Flight::map('notFound', function () {
Flight::view()->render('404.latte', ['title' => 'Halaman Tidak Ditemukan']);
});
Buat app/views/404.latte
:
{extends 'layout.latte'}
{block content}
<h2>404 - {$title}</h2>
<p>Maaf, halaman tersebut tidak ada!</p>
{/block}
Langkah Selanjutnya
- Tambahkan Gaya: Gunakan CSS di template Anda untuk tampilan yang lebih baik.
- Database: Ganti
posts.json
dengan database seperti SQLite menggunakanPdoWrapper
. - Validasi: Tambahkan cek untuk slug duplikat atau input kosong.
- Middleware: Implementasikan autentikasi untuk pembuatan pos.
Kesimpulan
Anda telah membangun blog sederhana dengan Flight PHP! Panduan ini menunjukkan fitur inti seperti routing, templating dengan Latte, dan menangani pengiriman formulir—semuanya tetap ringan. Jelajahi dokumentasi Flight untuk fitur-fitur lebih lanjut untuk membawa blog Anda lebih jauh!
License
Lisensi MIT (MIT)
Hak Cipta © 2024
@mikecao, @n0nag0n
Izin diberikan di sini, tanpa biaya, kepada setiap orang yang mendapatkan salinan perangkat lunak ini dan dokumentasi terkait (disebut "Perangkat Lunak"), untuk berurusan dengan Perangkat Lunak tanpa pembatasan, termasuk tanpa batasan hak untuk menggunakan, menyalin, memodifikasi, menggabungkan, menerbitkan, mendistribusikan, sublisensikan, dan/atau menjual salinan Perangkat Lunak, dan untuk mengizinkan orang-orang yang menerima Perangkat Lunak untuk melakukannya, dengan syarat berikut:
Pemberitahuan hak cipta di atas dan pemberitahuan izin ini harus disertakan dalam semua salinan atau bagian substansial dari Perangkat Lunak.
PERANGKAT LUNAK DIBERIKAN "SEBAGAIMANA ADANYA", TANPA JAMINAN DALAM BENTUK APAPUN, TERSURAT ATAU TERSIRAT, TERMASUK NAMUN TIDAK TERBATAS PADA JAMINAN KELAYAKAN PERDAGANGAN, KECOCOKAN UNTUK TUJUAN TERTENTU DAN TIDAK MELANGGAR. DALAM HAL APA PUN PENULIS ATAU PEMEGANG HAK CIPTA TIDAK BERTANGGUNG JAWAB ATAS CLAIM, KERUSAKAN ATAU TANGGUNG JAWAB LAINNYA, BAIK DALAM TINDAKAN KONTRAK, TORT ATAU SEBALIKNYA, YANG TIMBUL DARI, DARI ATAU SEHUBUNGAN DENGAN PERANGKAT LUNAK ATAU PENGGUNAAN ATAU TRANSAKSI LAINNYA DALAM PERANGKAT LUNAK.
About
Apa itu Flight?
Flight adalah framework PHP yang cepat, sederhana, dan dapat diperluas. Ini cukup serbaguna dan dapat digunakan untuk membangun berbagai jenis aplikasi web. Dibangun dengan pemikiran kesederhanaan dan ditulis dengan cara yang mudah dipahami dan digunakan.
Flight adalah framework yang hebat untuk pemula yang baru mengenal PHP dan ingin belajar bagaimana membangun aplikasi web. Ini juga merupakan framework yang hebat untuk pengembang berpengalaman yang ingin lebih mengontrol aplikasi web mereka. Ini dirancang untuk dengan mudah membangun RESTful API, aplikasi web sederhana, atau aplikasi web yang kompleks.
Mulai Cepat
Pertama, instal dengan Composer
composer require flightphp/core
atau Anda bisa mengunduh zip dari repositori di sini. Kemudian Anda akan memiliki file dasar index.php
seperti berikut:
<?php
// jika diinstal dengan composer
require 'vendor/autoload.php';
// atau jika diinstal secara manual dengan file zip
// require 'flight/Flight.php';
Flight::route('/', function() {
echo 'halo dunia!';
});
Flight::route('/json', function() {
Flight::json(['halo' => 'dunia']);
});
Flight::start();
Itu saja! Anda memiliki aplikasi dasar Flight. Anda sekarang dapat menjalankan file ini dengan php -S localhost:8000
dan kunjungi http://localhost:8000
di browser Anda untuk melihat output.
Apakah ini cepat?
Ya! Flight cepat. Ini adalah salah satu framework PHP tercepat yang tersedia. Anda dapat melihat semua tolok ukur di TechEmpower
Lihat tolok ukur di bawah ini dengan beberapa framework PHP populer lainnya.
Framework | Permintaan Teks Biasa/detik | Permintaan JSON/detik |
---|---|---|
Flight | 190.421 | 182.491 |
Yii | 145.749 | 131.434 |
Fat-Free | 139.238 | 133.952 |
Slim | 89.588 | 87.348 |
Phalcon | 95.911 | 87.675 |
Symfony | 65.053 | 63.237 |
Lumen | 40.572 | 39.700 |
Laravel | 26.657 | 26.901 |
CodeIgniter | 20.628 | 19.901 |
Aplikasi Skeleton/Boilerplate
Ada aplikasi contoh yang dapat membantu Anda memulai dengan Framework Flight. Kunjungi flightphp/skeleton untuk instruksi tentang cara memulai! Anda juga dapat mengunjungi halaman contoh untuk inspirasi tentang beberapa hal yang dapat Anda lakukan dengan Flight.
Komunitas
Kami ada di Matrix Chat
Dan Discord
Kontribusi
Ada dua cara Anda dapat berkontribusi pada Flight:
- Anda dapat berkontribusi pada framework inti dengan mengunjungi repositori inti.
- Anda dapat berkontribusi pada dokumentasi. Situs web dokumentasi ini dihosting di Github. Jika Anda menemukan kesalahan atau ingin memperbaiki sesuatu menjadi lebih baik, silakan perbaiki dan kirim permintaan tarik! Kami berusaha untuk tetap mengikuti hal-hal, tetapi pembaruan dan terjemahan bahasa sangat diterima.
Persyaratan
Flight memerlukan PHP 7.4 atau lebih tinggi.
Catatan: PHP 7.4 didukung karena pada saat penulisan ini (2024) PHP 7.4 adalah versi default untuk beberapa distribusi Linux LTS. Memaksa pindah ke PHP >8 akan menyebabkan banyak masalah bagi pengguna tersebut. Framework ini juga mendukung PHP >8.
Lisensi
Flight dirilis di bawah lisensi MIT.
Awesome-plugins/php_cookie
Cookies
overclokk/cookie adalah perpustakaan sederhana untuk mengelola cookie dalam aplikasi Anda.
Instalasi
Instalasi sangat sederhana dengan composer.
composer require overclokk/cookie
Penggunaan
Penggunaan semudah mendaftarkan metode baru pada kelas Flight.
use Overclokk\Cookie\Cookie;
/*
* Set di file bootstrap atau public/index.php Anda
*/
Flight::register('cookie', Cookie::class);
/**
* ExampleController.php
*/
class ExampleController {
public function login() {
// Set sebuah cookie
// Anda ingin ini menjadi false agar Anda mendapatkan instance baru
// gunakan komentar di bawah jika Anda ingin autocomplete
/** @var \Overclokk\Cookie\Cookie $cookie */
$cookie = Flight::cookie(false);
$cookie->set(
'stay_logged_in', // nama cookie
'1', // nilai yang ingin Anda atur
86400, // jumlah detik cookie harus bertahan
'/', // jalur yang akan tersedia untuk cookie
'example.com', // domain yang akan tersedia untuk cookie
true, // cookie hanya akan ditransmisikan melalui koneksi HTTPS yang aman
true // cookie hanya akan tersedia melalui protokol HTTP
);
// opsional, jika Anda ingin mempertahankan nilai default
// dan memiliki cara cepat untuk mengatur cookie untuk waktu yang lama
$cookie->forever('stay_logged_in', '1');
}
public function home() {
// Periksa apakah Anda memiliki cookie
if (Flight::cookie()->has('stay_logged_in')) {
// tempatkan mereka di area dasbor misalnya.
Flight::redirect('/dashboard');
}
}
}
Awesome-plugins/php_encryption
Enkripsi PHP
defuse/php-encryption adalah perpustakaan yang dapat digunakan untuk mengenkripsi dan mendekripsi data. Memulai dan menjalankan cukup sederhana untuk mulai mengenkripsi dan mendekripsi data. Mereka memiliki tutorial yang sangat membantu menjelaskan dasar-dasar cara menggunakan perpustakaan serta implikasi keamanan penting terkait enkripsi.
Instalasi
Instalasi sangat sederhana dengan composer.
composer require defuse/php-encryption
Pengaturan
Kemudian Anda perlu menghasilkan kunci enkripsi.
vendor/bin/generate-defuse-key
Ini akan menghasilkan kunci yang perlu Anda simpan dengan aman. Anda bisa menyimpan kunci di file app/config/config.php
Anda di array di bagian bawah file. Meskipun itu bukan tempat yang sempurna, paling tidak itu adalah sesuatu.
Penggunaan
Sekarang Anda memiliki perpustakaan dan kunci enkripsi, Anda dapat mulai mengenkripsi dan mendekripsi data.
use Defuse\Crypto\Crypto;
use Defuse\Crypto\Key;
/*
* Tetapkan di file bootstrap atau public/index.php Anda
*/
// Metode enkripsi
Flight::map('encrypt', function($raw_data) {
$encryption_key = /* $config['encryption_key'] atau file_get_contents tempat Anda meletakkan kunci */;
return Crypto::encrypt($raw_data, Key::loadFromAsciiSafeString($encryption_key));
});
// Metode dekripsi
Flight::map('decrypt', function($encrypted_data) {
$encryption_key = /* $config['encryption_key'] atau file_get_contents tempat Anda meletakkan kunci */;
try {
$raw_data = Crypto::decrypt($encrypted_data, Key::loadFromAsciiSafeString($encryption_key));
} catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
// Sebuah serangan! Entah kunci yang salah dimuat, atau ciphertext telah
// berubah sejak dibuat -- baik rusak di database atau
// sengaja dimodifikasi oleh Eve yang mencoba melakukan serangan.
// ... tangani kasus ini dengan cara yang sesuai untuk aplikasi Anda ...
}
return $raw_data;
});
Flight::route('/encrypt', function() {
$encrypted_data = Flight::encrypt('Ini adalah rahasia');
echo $encrypted_data;
});
Flight::route('/decrypt', function() {
$encrypted_data = '...'; // Ambil data terenkripsi dari suatu tempat
$decrypted_data = Flight::decrypt($encrypted_data);
echo $decrypted_data;
});
Awesome-plugins/php_file_cache
flightphp/cache
Kelas caching PHP di-file yang ringan, sederhana, dan mandiri
Keuntungan
- Ringan, mandiri, dan sederhana
- Semua kode dalam satu file - tidak ada driver yang tidak berguna.
- Aman - setiap file cache yang dihasilkan memiliki header php dengan die, sehingga akses langsung tidak mungkin dilakukan meskipun seseorang mengetahui jalur dan server Anda tidak dikonfigurasi dengan benar
- Didokumentasikan dengan baik dan diuji
- Menangani konkurensi dengan benar melalui flock
- Mendukung PHP 7.4+
- Gratis di bawah lisensi MIT
Situs dokumen ini menggunakan perpustakaan ini untuk menyimpan cache setiap halaman!
Klik di sini untuk melihat kodenya.
Instalasi
Instal melalui composer:
composer require flightphp/cache
Penggunaan
Penggunaannya cukup sederhana. Ini menyimpan file cache di direktori cache.
use flight\Cache;
$app = Flight::app();
// Anda memasukkan direktori tempat cache akan disimpan ke dalam konstruktor
$app->register('cache', Cache::class, [ __DIR__ . '/../cache/' ], function(Cache $cache) {
// Ini memastikan bahwa cache hanya digunakan saat dalam mode produksi
// ENVIRONMENT adalah konstanta yang diatur dalam file bootstrap Anda atau di tempat lain dalam aplikasi Anda
$cache->setDevMode(ENVIRONMENT === 'development');
});
Kemudian Anda dapat menggunakannya di kode Anda seperti ini:
// Dapatkan instance cache
$cache = Flight::cache();
$data = $cache->refreshIfExpired('simple-cache-test', function () {
return date("H:i:s"); // kembalikan data untuk disimpan di cache
}, 10); // 10 detik
// atau
$data = $cache->retrieve('simple-cache-test');
if(empty($data)) {
$data = date("H:i:s");
$cache->store('simple-cache-test', $data, 10); // 10 detik
}
Dokumentasi
Kunjungi https://github.com/flightphp/cache untuk dokumentasi lengkap dan pastikan Anda melihat folder contoh.
Awesome-plugins/permissions
FlightPHP/Permissions
Ini adalah modul izin yang dapat digunakan dalam proyek Anda jika Anda memiliki beberapa peran di aplikasi Anda dan setiap peran memiliki sedikit fungsi yang berbeda. Modul ini memungkinkan Anda untuk mendefinisikan izin untuk setiap peran dan kemudian memeriksa apakah pengguna saat ini memiliki izin untuk mengakses halaman tertentu atau melakukan tindakan tertentu.
Klik di sini untuk repositori di GitHub.
Instalasi
Jalankan composer require flightphp/permissions
dan Anda sudah siap!
Penggunaan
Pertama, Anda perlu mengatur izin Anda, lalu Anda memberi tahu aplikasi Anda apa arti izin tersebut. Pada akhirnya, Anda akan memeriksa izin Anda dengan $Permissions->has()
, ->can()
, atau is()
. has()
dan can()
memiliki fungsionalitas yang sama, tetapi dinamai berbeda untuk membuat kode Anda lebih mudah dibaca.
Contoh Dasar
Mari kita anggap Anda memiliki fitur dalam aplikasi Anda yang memeriksa apakah seorang pengguna sudah masuk. Anda dapat membuat objek izin seperti ini:
// index.php
require 'vendor/autoload.php';
// beberapa kode
// lalu Anda mungkin memiliki sesuatu yang memberi tahu Anda siapa peran saat ini dari orang tersebut
// kemungkinan Anda memiliki sesuatu di mana Anda mengambil peran saat ini
// dari variabel sesi yang mendefinisikan ini
// setelah seseorang masuk, jika tidak, mereka akan memiliki peran 'tamu' atau 'publik'.
$current_role = 'admin';
// mengatur izin
$permission = new \flight\Permission($current_role);
$permission->defineRule('loggedIn', function($current_role) {
return $current_role !== 'guest';
});
// Anda mungkin ingin menyimpan objek ini di Flight di suatu tempat
Flight::set('permission', $permission);
Kemudian di dalam controller di suatu tempat, Anda mungkin memiliki sesuatu seperti ini.
<?php
// beberapa controller
class SomeController {
public function someAction() {
$permission = Flight::get('permission');
if ($permission->has('loggedIn')) {
// lakukan sesuatu
} else {
// lakukan sesuatu yang lain
}
}
}
Anda juga dapat menggunakan ini untuk melacak apakah mereka memiliki izin untuk melakukan sesuatu dalam aplikasi Anda. Sebagai contoh, jika Anda memiliki cara bagi pengguna untuk berinteraksi dengan posting di perangkat lunak Anda, Anda dapat memeriksa apakah mereka memiliki izin untuk melakukan tindakan tertentu.
$current_role = 'admin';
// mengatur izin
$permission = new \flight\Permission($current_role);
$permission->defineRule('post', function($current_role) {
if($current_role === 'admin') {
$permissions = ['create', 'read', 'update', 'delete'];
} else if($current_role === 'editor') {
$permissions = ['create', 'read', 'update'];
} else if($current_role === 'author') {
$permissions = ['create', 'read'];
} else if($current_role === 'contributor') {
$permissions = ['create'];
} else {
$permissions = [];
}
return $permissions;
});
Flight::set('permission', $permission);
Kemudian di dalam controller di suatu tempat...
class PostController {
public function create() {
$permission = Flight::get('permission');
if ($permission->can('post.create')) {
// lakukan sesuatu
} else {
// lakukan sesuatu yang lain
}
}
}
Menginjeksi ketergantungan
Anda dapat menginjeksi ketergantungan ke dalam closure yang mendefinisikan izin. Ini berguna jika Anda memiliki semacam toggle, id, atau titik data lain yang ingin Anda periksa. Hal ini juga berlaku untuk panggilan jenis Class->Method, kecuali Anda mendefinisikan argumen dalam metode tersebut.
Closure
$Permission->defineRule('order', function(string $current_role, MyDependency $MyDependency = null) {
// ... kode
});
// di file controller Anda
public function createOrder() {
$MyDependency = Flight::myDependency();
$permission = Flight::get('permission');
if ($permission->can('order.create', $MyDependency)) {
// lakukan sesuatu
} else {
// lakukan sesuatu yang lain
}
}
Kelas
namespace MyApp;
class Permissions {
public function order(string $current_role, MyDependency $MyDependency = null) {
// ... kode
}
}
Pintasan untuk mengatur izin dengan kelas
Anda juga dapat menggunakan kelas untuk mendefinisikan izin Anda. Ini berguna jika Anda memiliki banyak izin dan Anda ingin menjaga kode Anda tetap bersih. Anda bisa melakukan sesuatu seperti ini:
<?php
// kode bootstrap
$Permissions = new \flight\Permission($current_role);
$Permissions->defineRule('order', 'MyApp\Permissions->order');
// myapp/Permissions.php
namespace MyApp;
class Permissions {
public function order(string $current_role, int $user_id) {
// Mengasumsikan Anda telah mengatur ini sebelumnya
/** @var \flight\database\PdoWrapper $db */
$db = Flight::db();
$allowed_permissions = [ 'read' ]; // semua orang dapat melihat sebuah pesanan
if($current_role === 'manager') {
$allowed_permissions[] = 'create'; // manajer dapat membuat pesanan
}
$some_special_toggle_from_db = $db->fetchField('SELECT some_special_toggle FROM settings WHERE id = ?', [ $user_id ]);
if($some_special_toggle_from_db) {
$allowed_permissions[] = 'update'; // jika pengguna memiliki toggle khusus, mereka dapat memperbarui pesanan
}
if($current_role === 'admin') {
$allowed_permissions[] = 'delete'; // admin dapat menghapus pesanan
}
return $allowed_permissions;
}
}
Bagian yang keren adalah bahwa ada juga pintasan yang dapat Anda gunakan (yang juga dapat dicache!!!) di mana Anda cukup memberi tahu kelas izin untuk memetakan semua metode dalam sebuah kelas ke dalam izin. Jadi jika Anda memiliki metode bernama order()
dan metode bernama company()
, ini akan secara otomatis dipetakan sehingga Anda cukup menjalankan $Permissions->has('order.read')
atau $Permissions->has('company.read')
dan itu akan berhasil. Mendefinisikan ini sangat sulit, jadi ikutlah bersama saya di sini. Anda hanya perlu melakukan ini:
Buat kelas izin yang ingin Anda kelompokkan bersama.
class MyPermissions {
public function order(string $current_role, int $order_id = 0): array {
// kode untuk menentukan izin
return $permissions_array;
}
public function company(string $current_role, int $company_id): array {
// kode untuk menentukan izin
return $permissions_array;
}
}
Kemudian buat izin tersebut dapat ditemukan menggunakan pustaka ini.
$Permissions = new \flight\Permission($current_role);
$Permissions->defineRulesFromClassMethods(MyApp\Permissions::class);
Flight::set('permissions', $Permissions);
Akhirnya, panggil izin di basis kode Anda untuk memeriksa apakah pengguna diizinkan untuk melakukan izin tertentu.
class SomeController {
public function createOrder() {
if(Flight::get('permissions')->can('order.create') === false) {
die('Anda tidak bisa membuat sebuah pesanan. Maaf!');
}
}
}
Cache
Untuk mengaktifkan caching, lihat pustaka sederhana wruczak/phpfilecache. Contoh untuk mengaktifkannya ada di bawah ini.
// $app ini bisa menjadi bagian dari kode Anda, atau
// Anda bisa langsung meneruskan null dan itu akan
// mengambil dari Flight::app() di dalam konstruktor
$app = Flight::app();
// Untuk saat ini, ini menerima sebagai cache file. Lainnya dapat dengan mudah
// ditambahkan di masa depan.
$Cache = new Wruczek\PhpFileCache\PhpFileCache;
$Permissions = new \flight\Permission($current_role, $app, $Cache);
$Permissions->defineRulesFromClassMethods(MyApp\Permissions::class, 3600); // 3600 adalah berapa detik untuk menyimpan cache ini. Biarkan ini kosong untuk tidak menggunakan caching
Dan Anda sudah siap!
Awesome-plugins/simple_job_queue
Antrean Pekerjaan Sederhana
Antrean Pekerjaan Sederhana adalah sebuah pustaka yang dapat digunakan untuk memproses pekerjaan secara asinkron. Ini dapat digunakan dengan beanstalkd, MySQL/MariaDB, SQLite, dan PostgreSQL.
Instal
composer require n0nag0n/simple-job-queue
Penggunaan
Agar ini dapat berfungsi, Anda memerlukan cara untuk menambahkan pekerjaan ke antrean dan cara untuk memproses pekerjaan (pekerja). Berikut adalah contoh tentang cara menambahkan pekerjaan ke antrean dan cara memproses pekerjaan.
Menambahkan ke Flight
Menambahkan ini ke Flight sangat sederhana dan dilakukan dengan menggunakan metode register()
. Berikut adalah contoh cara menambahkan ini ke Flight.
<?php
require 'vendor/autoload.php';
// Ubah ['mysql'] menjadi ['beanstalkd'] jika Anda ingin menggunakan beanstalkd
Flight::register('queue', n0nag0n\Job_Queue::class, ['mysql'], function($Job_Queue) {
// jika Anda sudah memiliki koneksi PDO di Flight::db();
$Job_Queue->addQueueConnection(Flight::db());
// atau jika Anda menggunakan beanstalkd/Pheanstalk
$pheanstalk = Pheanstalk\Pheanstalk::create('127.0.0.1');
$Job_Queue->addQueueConnection($pheanstalk);
});
Menambahkan pekerjaan baru
Saat Anda menambahkan pekerjaan, Anda perlu menentukan sebuah pipeline (antrean). Ini sebanding dengan sebuah saluran di RabbitMQ atau sebuah tabung di beanstalkd.
<?php
Flight::queue()->selectPipeline('send_important_emails');
Flight::queue()->addJob(json_encode([ 'something' => 'that', 'ends' => 'up', 'a' => 'string' ]));
Menjalankan seorang pekerja
Berikut adalah contoh file tentang cara menjalankan seorang pekerja.
<?php
require 'vendor/autoload.php';
$Job_Queue = new n0nag0n\Job_Queue('mysql');
// Koneksi PDO
$PDO = new PDO('mysql:dbname=testdb;host=127.0.0.1', 'user', 'pass');
$Job_Queue->addQueueConnection($PDO);
// atau jika Anda menggunakan beanstalkd/Pheanstalk
$pheanstalk = Pheanstalk\Pheanstalk::create('127.0.0.1');
$Job_Queue->addQueueConnection($pheanstalk);
$Job_Queue->watchPipeline('send_important_emails');
while(true) {
$job = $Job_Queue->getNextJobAndReserve();
// sesuaikan dengan apa pun yang membuat Anda tidur lebih nyenyak di malam hari (hanya untuk antrean basis data, beanstalkd tidak memerlukan pernyataan if ini)
if(empty($job)) {
usleep(500000);
continue;
}
echo "Memproses {$job['id']}\n";
$payload = json_decode($job['payload'], true);
try {
$result = doSomethingThatDoesSomething($payload);
if($result === true) {
$Job_Queue->deleteJob($job);
} else {
// ini mengeluarkannya dari antrean siap dan menempatkannya dalam antrean lain yang dapat diambil dan "dikejutkan" nanti.
$Job_Queue->buryJob($job);
}
} catch(Exception $e) {
$Job_Queue->buryJob($job);
}
}
Menangani Proses Panjang dengan Supervisord
Supervisord adalah sistem kontrol proses yang memastikan bahwa proses pekerja Anda tetap berjalan terus-menerus. Berikut adalah panduan yang lebih lengkap tentang cara mengaturnya dengan pekerja Antrean Pekerjaan Sederhana Anda:
Menginstal Supervisord
# Di Ubuntu/Debian
sudo apt-get install supervisor
# Di CentOS/RHEL
sudo yum install supervisor
# Di macOS dengan Homebrew
brew install supervisor
Membuat Skrip Pekerja
Pertama, simpan kode pekerja Anda ke dalam file PHP yang didedikasikan:
<?php
require 'vendor/autoload.php';
$Job_Queue = new n0nag0n\Job_Queue('mysql');
// Koneksi PDO
$PDO = new PDO('mysql:dbname=your_database;host=127.0.0.1', 'username', 'password');
$Job_Queue->addQueueConnection($PDO);
// Tentukan pipeline untuk diawasi
$Job_Queue->watchPipeline('send_important_emails');
// Catat awal pekerja
echo date('Y-m-d H:i:s') . " - Pekerja dimulai\n";
while(true) {
$job = $Job_Queue->getNextJobAndReserve();
if(empty($job)) {
usleep(500000); // Tidur selama 0.5 detik
continue;
}
echo date('Y-m-d H:i:s') . " - Memproses pekerjaan {$job['id']}\n";
$payload = json_decode($job['payload'], true);
try {
$result = doSomethingThatDoesSomething($payload);
if($result === true) {
$Job_Queue->deleteJob($job);
echo date('Y-m-d H:i:s') . " - Pekerjaan {$job['id']} berhasil diselesaikan\n";
} else {
$Job_Queue->buryJob($job);
echo date('Y-m-d H:i:s') . " - Pekerjaan {$job['id']} gagal, dibuang\n";
}
} catch(Exception $e) {
$Job_Queue->buryJob($job);
echo date('Y-m-d H:i:s') . " - Pengecualian saat memproses pekerjaan {$job['id']}: {$e->getMessage()}\n";
}
}
Mengkonfigurasi Supervisord
Buat file konfigurasi untuk pekerja Anda:
[program:email_worker]
command=php /path/to/worker.php
directory=/path/to/project
autostart=true
autorestart=true
startretries=3
stderr_logfile=/var/log/simple_job_queue_err.log
stdout_logfile=/var/log/simple_job_queue.log
user=www-data
numprocs=2
process_name=%(program_name)s_%(process_num)02d
Opsi Konfigurasi Utama:
command
: Perintah untuk menjalankan pekerja Andadirectory
: Direktori kerja untuk pekerjaautostart
: Mulai secara otomatis saat supervisord dimulaiautorestart
: Mulai ulang secara otomatis jika proses keluarstartretries
: Jumlah kali untuk mencoba memulai jika gagalstderr_logfile
/stdout_logfile
: Lokasi file loguser
: Pengguna sistem untuk menjalankan prosesnumprocs
: Jumlah instance pekerja yang akan dijalankanprocess_name
: Format penamaan untuk beberapa proses pekerja
Mengelola Pekerja dengan Supervisorctl
Setelah membuat atau mengubah konfigurasi:
# Muat ulang konfigurasi supervisor
sudo supervisorctl reread
sudo supervisorctl update
# Kontrol proses pekerja tertentu
sudo supervisorctl start email_worker:*
sudo supervisorctl stop email_worker:*
sudo supervisorctl restart email_worker:*
sudo supervisorctl status email_worker:*
Menjalankan Beberapa Pipeline
Untuk beberapa pipeline, buat file pekerja dan konfigurasi terpisah:
[program:email_worker]
command=php /path/to/email_worker.php
# ... konfigurasi lainnya ...
[program:notification_worker]
command=php /path/to/notification_worker.php
# ... konfigurasi lainnya ...
Memantau dan Log
Periksa log untuk memantau aktivitas pekerja:
# Lihat log
sudo tail -f /var/log/simple_job_queue.log
# Periksa status
sudo supervisorctl status
Pengaturan ini memastikan pekerja pekerjaan Anda terus berjalan meskipun setelah kerusakan, reboot server, atau masalah lainnya, menjadikan sistem antrean Anda andal untuk lingkungan produksi.
Awesome-plugins/ghost_session
Ghostff/Session
Pengelola Sesi PHP (non-blocking, flash, segment, enkripsi sesi). Menggunakan PHP open_ssl untuk enkripsi/dekripsi data sesi secara opsional. Mendukung File, MySQL, Redis, dan Memcached.
Klik di sini untuk melihat kode.
Instalasi
Instal dengan composer.
composer require ghostff/session
Konfigurasi Dasar
Anda tidak perlu mengirimkan apa pun untuk menggunakan pengaturan default dengan sesi Anda. Anda bisa membaca lebih lanjut tentang pengaturan lainnya di Github Readme.
use Ghostff\Session\Session;
require 'vendor/autoload.php';
$app = Flight::app();
$app->register('session', Session::class);
// satu hal yang perlu diingat adalah bahwa Anda harus mengkomit sesi Anda di setiap muatan halaman
// atau Anda perlu menjalankan auto_commit dalam konfigurasi Anda.
Contoh Sederhana
Berikut adalah contoh sederhana tentang bagaimana Anda mungkin menggunakan ini.
Flight::route('POST /login', function() {
$session = Flight::session();
// lakukan logika login Anda di sini
// validasi kata sandi, dll.
// jika login berhasil
$session->set('is_logged_in', true);
$session->set('user', $user);
// setiap kali Anda menulis ke sesi, Anda harus mengkomitnya dengan sengaja.
$session->commit();
});
// Pemeriksaan ini bisa ada dalam logika halaman terbatas, atau dibungkus dengan middleware.
Flight::route('/some-restricted-page', function() {
$session = Flight::session();
if(!$session->get('is_logged_in')) {
Flight::redirect('/login');
}
// lakukan logika halaman terbatas Anda di sini
});
// versi middleware
Flight::route('/some-restricted-page', function() {
// logika halaman biasa
})->addMiddleware(function() {
$session = Flight::session();
if(!$session->get('is_logged_in')) {
Flight::redirect('/login');
}
});
Contoh yang Lebih Kompleks
Berikut adalah contoh yang lebih kompleks tentang bagaimana Anda mungkin menggunakan ini.
use Ghostff\Session\Session;
require 'vendor/autoload.php';
$app = Flight::app();
// setel jalur kustom ke file konfigurasi sesi Anda dan berikan string acak untuk id sesi
$app->register('session', Session::class, [ 'path/to/session_config.php', bin2hex(random_bytes(32)) ], function(Session $session) {
// atau Anda dapat secara manual menimpa opsi konfigurasi
$session->updateConfiguration([
// jika Anda ingin menyimpan data sesi Anda dalam basis data (baik jika Anda menginginkan sesuatu seperti, "keluar dari semua perangkat")
Session::CONFIG_DRIVER => Ghostff\Session\Drivers\MySql::class,
Session::CONFIG_ENCRYPT_DATA => true,
Session::CONFIG_SALT_KEY => hash('sha256', 'my-super-S3CR3T-salt'), // silakan ubah ini menjadi sesuatu yang lain
Session::CONFIG_AUTO_COMMIT => true, // hanya lakukan ini jika memerlukannya dan/atau sulit untuk mengkomit sesi Anda.
// selain itu Anda bisa melakukan Flight::after('start', function() { Flight::session()->commit(); });
Session::CONFIG_MYSQL_DS => [
'driver' => 'mysql', # Driver basis data untuk dns PDO misal(mysql:host=...;dbname=...)
'host' => '127.0.0.1', # Host basis data
'db_name' => 'my_app_database', # Nama basis data
'db_table' => 'sessions', # Tabel basis data
'db_user' => 'root', # Nama pengguna basis data
'db_pass' => '', # Kata sandi basis data
'persistent_conn'=> false, # Hindari overhead dari pembuatan koneksi baru setiap kali skrip perlu berbicara dengan basis data, yang menghasilkan aplikasi web yang lebih cepat. TEMUKAN BELAKANG SENDIRI
]
]);
}
);
Bantu! Data Sesi Saya Tidak Bertahan!
Apakah Anda mengatur data sesi Anda dan itu tidak bertahan antar permintaan? Anda mungkin telah lupa untuk mengkomit data sesi Anda. Anda dapat melakukannya dengan memanggil $session->commit()
setelah Anda mengatur data sesi Anda.
Flight::route('POST /login', function() {
$session = Flight::session();
// lakukan logika login Anda di sini
// validasi kata sandi, dll.
// jika login berhasil
$session->set('is_logged_in', true);
$session->set('user', $user);
// setiap kali Anda menulis ke sesi, Anda harus mengkomitnya dengan sengaja.
$session->commit();
});
Cara lain untuk mengatasi ini adalah ketika Anda mengatur layanan sesi Anda, Anda harus mengatur auto_commit
ke true
dalam konfigurasi Anda. Ini akan secara otomatis mengkomit data sesi Anda setelah setiap permintaan.
$app->register('session', Session::class, [ 'path/to/session_config.php', bin2hex(random_bytes(32)) ], function(Session $session) {
$session->updateConfiguration([
Session::CONFIG_AUTO_COMMIT => true,
]);
}
);
Selain itu, Anda dapat melakukan Flight::after('start', function() { Flight::session()->commit(); });
untuk mengkomit data sesi Anda setelah setiap permintaan.
Dokumentasi
Kunjungi Github Readme untuk dokumentasi lengkap. Opsi konfigurasi dijelaskan secara rinci dalam default_config.php file itu sendiri. Kodenya mudah dipahami jika Anda ingin menelusuri paket ini sendiri.
Awesome-plugins/pdo_wrapper
Kelas Pembantu PDO PdoWrapper
Flight hadir dengan kelas pembantu untuk PDO. Kelas ini memungkinkan Anda untuk dengan mudah melakukan kueri ke basis data Anda dengan semua persiapan/eksekusi/fetchAll() yang membingungkan. Ini sangat menyederhanakan cara Anda dapat melakukan kueri ke basis data Anda. Setiap hasil baris dikembalikan sebagai kelas Koleksi Flight yang memungkinkan Anda mengakses data Anda melalui sintaks array atau sintaks objek.
Mendaftar Kelas Pembantu PDO
// Daftarkan kelas pembantu PDO
Flight::register('db', \flight\database\PdoWrapper::class, ['mysql:host=localhost;dbname=cool_db_name', 'user', 'pass', [
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'utf8mb4\'',
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_STRINGIFY_FETCHES => false,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
]
]);
Penggunaan
Objek ini memperluas PDO sehingga semua metode PDO normal tersedia. Metode berikut ditambahkan untuk mempermudah kueri ke basis data:
runQuery(string $sql, array $params = []): PDOStatement
Gunakan ini untuk INSERTS, UPDATES, atau jika Anda berencana menggunakan SELECT dalam loop while
$db = Flight::db();
$statement = $db->runQuery("SELECT * FROM table WHERE something = ?", [ $something ]);
while($row = $statement->fetch()) {
// ...
}
// Atau menulis ke basis data
$db->runQuery("INSERT INTO table (name) VALUES (?)", [ $name ]);
$db->runQuery("UPDATE table SET name = ? WHERE id = ?", [ $name, $id ]);
fetchField(string $sql, array $params = []): mixed
Mengambil field pertama dari kueri
$db = Flight::db();
$count = $db->fetchField("SELECT COUNT(*) FROM table WHERE something = ?", [ $something ]);
fetchRow(string $sql, array $params = []): array
Mengambil satu baris dari kueri
$db = Flight::db();
$row = $db->fetchRow("SELECT id, name FROM table WHERE id = ?", [ $id ]);
echo $row['name'];
// atau
echo $row->name;
fetchAll(string $sql, array $params = []): array
Mengambil semua baris dari kueri
$db = Flight::db();
$rows = $db->fetchAll("SELECT id, name FROM table WHERE something = ?", [ $something ]);
foreach($rows as $row) {
echo $row['name'];
// atau
echo $row->name;
}
Catatan dengan sintaks IN()
Ini juga memiliki pembungkus yang berguna untuk pernyataan IN()
. Anda cukup memasukkan tanda tanya tunggal sebagai placeholder untuk IN()
dan kemudian array nilai. Berikut adalah contoh seperti apa itu:
$db = Flight::db();
$name = 'Bob';
$company_ids = [1,2,3,4,5];
$rows = $db->fetchAll("SELECT id, name FROM table WHERE name = ? AND company_id IN (?)", [ $name, $company_ids ]);
Contoh Lengkap
// Contoh rute dan cara Anda akan menggunakan pembungkus ini
Flight::route('/users', function () {
// Dapatkan semua pengguna
$users = Flight::db()->fetchAll('SELECT * FROM users');
// Streaming semua pengguna
$statement = Flight::db()->runQuery('SELECT * FROM users');
while ($user = $statement->fetch()) {
echo $user['name'];
// atau echo $user->name;
}
// Dapatkan satu pengguna
$user = Flight::db()->fetchRow('SELECT * FROM users WHERE id = ?', [123]);
// Dapatkan satu nilai
$count = Flight::db()->fetchField('SELECT COUNT(*) FROM users');
// Sintaks IN() khusus untuk membantu (pastikan IN ditulis dengan huruf kapital)
$users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [[1,2,3,4,5]]);
// Anda juga dapat melakukan ini
$users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [ '1,2,3,4,5']);
// Memasukkan pengguna baru
Flight::db()->runQuery("INSERT INTO users (name, email) VALUES (?, ?)", ['Bob', 'bob@example.com']);
$insert_id = Flight::db()->lastInsertId();
// Memperbarui pengguna
Flight::db()->runQuery("UPDATE users SET name = ? WHERE id = ?", ['Bob', 123]);
// Menghapus pengguna
Flight::db()->runQuery("DELETE FROM users WHERE id = ?", [123]);
// Dapatkan jumlah baris yang terpengaruh
$statement = Flight::db()->runQuery("UPDATE users SET name = ? WHERE name = ?", ['Bob', 'Sally']);
$affected_rows = $statement->rowCount();
});
Awesome-plugins/migrations
Migrations
Migrasi untuk proyek Anda menjaga semua perubahan basis data yang terlibat dalam proyek Anda.
byjg/php-migration adalah pustaka inti yang sangat membantu untuk memulai.
Menginstal
Pustaka PHP
Jika Anda ingin menggunakan hanya Pustaka PHP di proyek Anda:
composer require "byjg/migration"
Antarmuka Baris Perintah
Antarmuka baris perintah berdiri sendiri dan tidak memerlukan Anda menginstalnya bersama proyek Anda.
Anda dapat menginstalnya secara global dan membuat tautan simbolis
composer require "byjg/migration-cli"
Silakan kunjungi byjg/migration-cli untuk mendapatkan lebih banyak informasi tentang Migration CLI.
Basis data yang didukung
Basis Data | Driver | String Koneksi |
---|---|---|
Sqlite | pdo_sqlite | sqlite:///path/to/file |
MySql/MariaDb | pdo_mysql | mysql://username:password@hostname:port/database |
Postgres | pdo_pgsql | pgsql://username:password@hostname:port/database |
Sql Server | pdo_dblib, pdo_sysbase Linux | dblib://username:password@hostname:port/database |
Sql Server | pdo_sqlsrv Windows | sqlsrv://username:password@hostname:port/database |
Bagaimana Ini Bekerja?
Migrasi Basis Data menggunakan SQL MURNI untuk mengelola versi basis data.
Untuk dapat berfungsi, Anda perlu:
- Membuat Skrip SQL
- Mengelola menggunakan Baris Perintah atau API.
Skrip SQL
Skrip dibagi menjadi tiga set skrip:
- Skrip BASIS berisi SEMUA perintah SQL untuk membuat basis data yang baru;
- Skrip UP berisi semua perintah migrasi SQL untuk "naik" versi basis data;
- Skrip DOWN berisi semua perintah migrasi SQL untuk "turun" atau mengembalikan versi basis data;
Direktori skrip adalah:
<root dir>
|
+-- base.sql
|
+-- /migrations
|
+-- /up
|
+-- 00001.sql
+-- 00002.sql
+-- /down
|
+-- 00000.sql
+-- 00001.sql
- "base.sql" adalah skrip dasar
- Folder "up" berisi skrip untuk migrasi naik versi. Sebagai contoh: 00002.sql adalah skrip untuk mengubah basis data dari versi '1' ke '2'.
- Folder "down" berisi skrip untuk migrasi turun versi. Sebagai contoh: 00001.sql adalah skrip untuk mengubah basis data dari versi '2' ke '1'. Folder "down" adalah opsional.
Lingkungan Pengembangan Multi
Jika Anda bekerja dengan beberapa pengembang dan beberapa cabang, sulit untuk menentukan nomor berikutnya.
Dalam kasus itu, Anda mempunyai akhiran "-dev" setelah nomor versi.
Lihat skenarionya:
- Pengembang 1 membuat cabang dan versi terbaru misalnya 42.
- Pengembang 2 membuat cabang pada saat yang sama dan memiliki nomor versi basis data yang sama.
Dalam kedua kasus, para pengembang akan membuat file bernama 43-dev.sql. Kedua pengembang akan bermigrasi NAIK dan TURUN tanpa masalah dan versi lokal Anda akan menjadi 43.
Namun pengembang 1 menggabungkan perubahan Anda dan membuat versi akhir 43.sql (git mv 43-dev.sql 43.sql
). Jika pengembang 2 memperbarui cabang lokal Anda, dia akan memiliki file 43.sql (dari dev 1) dan file Anda 43-dev.sql.
Jika dia mencoba untuk bermigrasi NAIK atau TURUN, skrip migrasi akan turun dan memberi tahu bahwa terdapat DUA versi 43. Dalam kasus ini, pengembang 2 harus memperbarui file-nya menjadi 44-dev.sql dan melanjutkan bekerja hingga menggabungkan perubahan Anda dan menghasilkan versi akhir.
Menggunakan API PHP dan Mengintegrasikannya ke dalam Proyek Anda
Penggunaan dasar adalah
- Membuat koneksi objek ConnectionManagement. Untuk informasi lebih lanjut, lihat komponen "byjg/anydataset".
- Membuat objek Migrasi dengan koneksi ini dan folder tempat skrip SQL berada.
- Gunakan perintah yang sesuai untuk "reset", "up", atau "down" skrip migrasi.
Lihat contohnya:
<?php
// Membuat URI Koneksi
// Lihat lebih lanjut: https://github.com/byjg/anydataset#connection-based-on-uri
$connectionUri = new \ByJG\Util\Uri('mysql://migrateuser:migratepwd@localhost/migratedatabase');
// Daftarkan Database atau Basis Data yang dapat menangani URI tersebut:
\ByJG\DbMigration\Migration::registerDatabase(\ByJG\DbMigration\Database\MySqlDatabase::class);
// Membuat instance Migrasi
$migration = new \ByJG\DbMigration\Migration($connectionUri, '.');
// Tambahkan fungsi progres callback untuk menerima info dari eksekusi
$migration->addCallbackProgress(function ($action, $currentVersion, $fileInfo) {
echo "$action, $currentVersion, ${fileInfo['description']}\n";
});
// Mengembalikan basis data menggunakan skrip "base.sql"
// dan menjalankan SEMUA skrip yang ada untuk menaikkan versi basis data ke versi terbaru
$migration->reset();
// Jalankan SEMUA skrip yang ada untuk naik atau turun versi basis data
// dari versi sekarang hingga nomor $version;
// Jika nomor versi tidak ditentukan, migrasi hingga versi basis data terakhir
$migration->update($version = null);
Objek Migrasi mengontrol versi basis data.
Membuat kontrol versi di proyek Anda
<?php
// Daftarkan Database atau Basis Data yang dapat menangani URI tersebut:
\ByJG\DbMigration\Migration::registerDatabase(\ByJG\DbMigration\Database\MySqlDatabase::class);
// Membuat instance Migrasi
$migration = new \ByJG\DbMigration\Migration($connectionUri, '.');
// Perintah ini akan membuat tabel versi di basis data Anda
$migration->createVersion();
Mendapatkan versi saat ini
<?php
$migration->getCurrentVersion();
Menambahkan Callback untuk mengontrol progres
<?php
$migration->addCallbackProgress(function ($command, $version, $fileInfo) {
echo "Melakukan Perintah: $command di versi $version - ${fileInfo['description']}, ${fileInfo['exists']}, ${fileInfo['file']}, ${fileInfo['checksum']}\n";
});
Mendapatkan instance Driver Db
<?php
$migration->getDbDriver();
Untuk menggunakannya, silakan kunjungi: https://github.com/byjg/anydataset-db
Menghindari Migrasi Parsial (tidak tersedia untuk MySQL)
Migrasi parsial adalah ketika skrip migrasi terhenti di tengah proses karena kesalahan atau penghentian manual.
Tabel migrasi akan memiliki status partial up
atau partial down
dan perlu diperbaiki secara manual sebelum dapat bermigrasi lagi.
Untuk menghindari situasi ini, Anda dapat menentukan migrasi akan dijalankan dalam konteks transaksional.
Jika skrip migrasi gagal, transaksi akan dibatalkan dan tabel migrasi akan ditandai sebagai complete
dan versi akan menjadi versi sebelumnya yang segera sebelum skrip yang menyebabkan kesalahan.
Untuk mengaktifkan fitur ini, Anda perlu memanggil metode withTransactionEnabled
dengan melewatkan true
sebagai parameter:
<?php
$migration->withTransactionEnabled(true);
CATATAN: Fitur ini tidak tersedia untuk MySQL karena tidak mendukung perintah DDL di dalam transaksi.
Jika Anda menggunakan metode ini dengan MySQL, Migrasi akan mengabaikannya tanpa pemberitahuan.
Info lebih lanjut: https://dev.mysql.com/doc/refman/8.0/en/cannot-roll-back.html
Tips dalam menulis migrasi SQL untuk Postgres
Saat membuat trigger dan fungsi SQL
-- Lakukan
CREATE FUNCTION emp_stamp() RETURNS trigger AS $emp_stamp$
BEGIN
-- Periksa bahwa empname dan salary diberikan
IF NEW.empname IS NULL THEN
RAISE EXCEPTION 'empname tidak boleh null'; -- tidak masalah apakah komentar ini kosong atau tidak
END IF; --
IF NEW.salary IS NULL THEN
RAISE EXCEPTION '% tidak dapat memiliki salary null', NEW.empname; --
END IF; --
-- Siapa yang bekerja untuk kita ketika mereka harus membayar untuk itu?
IF NEW.salary < 0 THEN
RAISE EXCEPTION '% tidak dapat memiliki salary negatif', NEW.empname; --
END IF; --
-- Ingat siapa yang mengubah gaji ketika
NEW.last_date := current_timestamp; --
NEW.last_user := current_user; --
RETURN NEW; --
END; --
$emp_stamp$ LANGUAGE plpgsql;
-- JANGAN
CREATE FUNCTION emp_stamp() RETURNS trigger AS $emp_stamp$
BEGIN
-- Periksa bahwa empname dan salary diberikan
IF NEW.empname IS NULL THEN
RAISE EXCEPTION 'empname tidak boleh null';
END IF;
IF NEW.salary IS NULL THEN
RAISE EXCEPTION '% tidak dapat memiliki salary null', NEW.empname;
END IF;
-- Siapa yang bekerja untuk kita ketika mereka harus membayar untuk itu?
IF NEW.salary < 0 THEN
RAISE EXCEPTION '% tidak dapat memiliki salary negatif', NEW.empname;
END IF;
-- Ingat siapa yang mengubah gaji ketika
NEW.last_date := current_timestamp;
NEW.last_user := current_user;
RETURN NEW;
END;
$emp_stamp$ LANGUAGE plpgsql;
Karena lapisan abstraksi basis data PDO
tidak dapat menjalankan kelompok pernyataan SQL,
ketika byjg/migration
membaca file migrasi, itu harus memisahkan seluruh isi file SQL pada titik koma, dan menjalankan pernyataan satu per satu. Namun, ada satu jenis pernyataan yang dapat memiliki beberapa titik koma di antara tubuhnya: fungsi.
Agar dapat mem-parsing fungsi dengan benar, byjg/migration
2.1.0 mulai memisahkan file migrasi pada urutan semicolon + EOL
bukannya hanya titik koma. Dengan cara ini, jika Anda menambahkan komentar kosong setelah setiap titik koma dalam definisi fungsi, byjg/migration
akan dapat mem-parsingnya.
Sayangnya, jika Anda lupa menambahkan salah satu komentar ini, pustaka akan memisahkan pernyataan CREATE FUNCTION
menjadi beberapa bagian dan migrasi akan gagal.
Hindari karakter titik dua (:
)
-- Lakukan
CREATE TABLE bookings (
booking_id UUID PRIMARY KEY,
booked_at TIMESTAMPTZ NOT NULL CHECK (CAST(booked_at AS DATE) <= check_in),
check_in DATE NOT NULL
);
-- JANGAN
CREATE TABLE bookings (
booking_id UUID PRIMARY KEY,
booked_at TIMESTAMPTZ NOT NULL CHECK (booked_at::DATE <= check_in),
check_in DATE NOT NULL
);
Karena PDO
menggunakan karakter titik dua untuk menjelaskan parameter bernama dalam pernyataan yang sudah disiapkan, penggunaannya akan menyebabkan kesalahan dalam konteks lain.
Misalnya, pernyataan PostgreSQL dapat menggunakan ::
untuk mengonversi nilai antar tipe. Di sisi lain, PDO
akan membaca ini sebagai parameter bernama yang tidak valid dalam konteks yang tidak valid dan gagal ketika mencoba menjalankannya.
Satu-satunya cara untuk memperbaiki ketidakkonsistenan ini adalah dengan menghindari titik dua sama sekali (dalam hal ini, PostgreSQL juga memiliki sintaks alternatif: CAST(value AS type)
).
Gunakan editor SQL
Akhirnya, menulis migrasi SQL manual bisa melelahkan, tetapi jauh lebih mudah jika Anda menggunakan editor yang mampu memahami sintaks SQL, menyediakan autocompletion, mengintrospeksi skema basis data Anda saat ini dan/atau memformat kode Anda secara otomatis.
Menangani berbagai migrasi di dalam satu skema
Jika Anda perlu membuat skrip migrasi yang berbeda dan versi di dalam skema yang sama, itu mungkin
tetapi terlalu berisiko dan saya tidak merekomendasikannya sama sekali.
Untuk melakukan ini, Anda perlu membuat "tabel migrasi" yang berbeda dengan mengoper parameter pada konstruktor.
<?php
$migration = new \ByJG\DbMigration\Migration("db:/uri", "/path", true, "NEW_MIGRATION_TABLE_NAME");
Untuk alasan keamanan, fitur ini tidak tersedia di baris perintah, tetapi Anda dapat menggunakan variabel lingkungan
MIGRATION_VERSION
untuk menyimpan namanya.
Kami sangat merekomendasikan untuk tidak menggunakan fitur ini. Rekomendasi adalah satu migrasi untuk satu skema.
Menjalankan Uji Unit
Uji unit dasar dapat dijalankan dengan:
vendor/bin/phpunit
Menjalankan uji basis data
Menjalankan uji integrasi memerlukan Anda untuk memiliki basis data yang aktif dan berjalan. Kami menyediakan docker-compose.yml
dasar dan Anda
dapat menggunakannya untuk memulai basis data untuk pengujian.
Menjalankan basis data
docker-compose up -d postgres mysql mssql
Menjalankan uji
vendor/bin/phpunit
vendor/bin/phpunit tests/SqliteDatabase*
vendor/bin/phpunit tests/MysqlDatabase*
vendor/bin/phpunit tests/PostgresDatabase*
vendor/bin/phpunit tests/SqlServerDblibDatabase*
vendor/bin/phpunit tests/SqlServerSqlsrvDatabase*
Opsional Anda dapat mengatur host dan kata sandi yang digunakan oleh uji unit
export MYSQL_TEST_HOST=localhost # default ke localhost
export MYSQL_PASSWORD=newpassword # gunakan '.' jika ingin memiliki kata sandi null
export PSQL_TEST_HOST=localhost # default ke localhost
export PSQL_PASSWORD=newpassword # gunakan '.' jika ingin memiliki kata sandi null
export MSSQL_TEST_HOST=localhost # default ke localhost
export MSSQL_PASSWORD=Pa55word
export SQLITE_TEST_HOST=/tmp/test.db # default ke /tmp/test.db
Awesome-plugins/session
FlightPHP Sesi - Pengelola Sesi Berbasis File yang Ringan
Ini adalah plugin pengelola sesi berbasis file yang ringan untuk Flight PHP Framework. Ini memberikan solusi sederhana namun kuat untuk mengelola sesi, dengan fitur seperti pembacaan sesi non-blocking, enkripsi opsional, fungsionalitas auto-commit, dan mode uji untuk pengembangan. Data sesi disimpan dalam file, menjadikannya ideal untuk aplikasi yang tidak memerlukan basis data.
Jika Anda ingin menggunakan basis data, periksa plugin ghostff/session dengan banyak fitur yang sama tetapi dengan backend basis data.
Kunjungi repositori Github untuk kode sumber lengkap dan detailnya.
Instalasi
Instal plugin melalui Composer:
composer require flightphp/session
Penggunaan Dasar
Berikut adalah contoh sederhana tentang cara menggunakan plugin flightphp/session
dalam aplikasi Flight Anda:
require 'vendor/autoload.php';
use flight\Session;
$app = Flight::app();
// Daftarkan layanan sesi
$app->register('session', Session::class);
// Contoh rute dengan penggunaan sesi
Flight::route('/login', function() {
$session = Flight::session();
$session->set('user_id', 123);
$session->set('username', 'johndoe');
$session->set('is_admin', false);
echo $session->get('username'); // Menghasilkan: johndoe
echo $session->get('preferences', 'default_theme'); // Menghasilkan: default_theme
if ($session->get('user_id')) {
Flight::json(['message' => 'Pengguna sudah login!', 'user_id' => $session->get('user_id')]);
}
});
Flight::route('/logout', function() {
$session = Flight::session();
$session->clear(); // Hapus semua data sesi
Flight::json(['message' => 'Berhasil keluar']);
});
Flight::start();
Poin Kunci
- Non-Blocking: Menggunakan
read_and_close
untuk memulai sesi secara default, mencegah masalah penguncian sesi. - Auto-Commit: Diaktifkan secara default, sehingga perubahan disimpan secara otomatis saat dimatikan kecuali dinonaktifkan.
- Penyimpanan File: Sesi disimpan di direktori temp sistem di bawah
/flight_sessions
secara default.
Konfigurasi
Anda dapat menyesuaikan pengelola sesi dengan melewatkan array opsi saat mendaftar:
$app->register('session', Session::class, [
'save_path' => '/custom/path/to/sessions', // Direktori untuk file sesi
'encryption_key' => 'a-secure-32-byte-key-here', // Aktifkan enkripsi (32 byte disarankan untuk AES-256-CBC)
'auto_commit' => false, // Nonaktifkan auto-commit untuk kontrol manual
'start_session' => true, // Mulai sesi secara otomatis (default: true)
'test_mode' => false // Aktifkan mode uji untuk pengembangan
]);
Opsi Konfigurasi
Opsi | Deskripsi | Nilai Default |
---|---|---|
save_path |
Direktori tempat file sesi disimpan | sys_get_temp_dir() . '/flight_sessions' |
encryption_key |
Kunci untuk enkripsi AES-256-CBC (opsional) | null (tidak ada enkripsi) |
auto_commit |
Simpan data sesi secara otomatis saat dimatikan | true |
start_session |
Mulai sesi secara otomatis | true |
test_mode |
Jalankan dalam mode uji tanpa mempengaruhi sesi PHP | false |
test_session_id |
ID sesi kustom untuk mode uji (opsional) | Dihasilkan secara acak jika tidak disetel |
Penggunaan Lanjut
Manual Commit
Jika Anda menonaktifkan auto-commit, Anda harus melakukan commit perubahan secara manual:
$app->register('session', Session::class, ['auto_commit' => false]);
Flight::route('/update', function() {
$session = Flight::session();
$session->set('key', 'value');
$session->commit(); // Simpan perubahan secara eksplisit
});
Keamanan Sesi dengan Enkripsi
Aktifkan enkripsi untuk data sensitif:
$app->register('session', Session::class, [
'encryption_key' => 'your-32-byte-secret-key-here'
]);
Flight::route('/secure', function() {
$session = Flight::session();
$session->set('credit_card', '4111-1111-1111-1111'); // Dienkripsi secara otomatis
echo $session->get('credit_card'); // Didekripsi saat diambil
});
Regenerasi Sesi
Regenerasi ID sesi untuk keamanan (misalnya, setelah login):
Flight::route('/post-login', function() {
$session = Flight::session();
$session->regenerate(); // ID baru, pertahankan data
// ATAU
$session->regenerate(true); // ID baru, hapus data lama
});
Contoh Middleware
Lindungi rute dengan otentikasi berbasis sesi:
Flight::route('/admin', function() {
Flight::json(['message' => 'Selamat datang di panel admin']);
})->addMiddleware(function() {
$session = Flight::session();
if (!$session->get('is_admin')) {
Flight::halt(403, 'Akses ditolak');
}
});
Ini hanyalah contoh sederhana tentang cara menggunakan ini dalam middleware. Untuk contoh yang lebih mendalam, lihat dokumentasi middleware.
Metode
Kelas Session
menyediakan metode ini:
set(string $key, $value)
: Menyimpan sebuah nilai dalam sesi.get(string $key, $default = null)
: Mengambil sebuah nilai, dengan nilai default opsional jika kunci tidak ada.delete(string $key)
: Menghapus kunci tertentu dari sesi.clear()
: Menghapus semua data sesi.commit()
: Menyimpan data sesi saat ini ke sistem file.id()
: Mengembalikan ID sesi saat ini.regenerate(bool $deleteOld = false)
: Regenerasi ID sesi, pilihan untuk menghapus data lama.
Semua metode kecuali get()
dan id()
mengembalikan instance Session
untuk chaining.
Mengapa Menggunakan Plugin Ini?
- Ringan: Tidak ada dependensi eksternal—hanya file.
- Non-Blocking: Menghindari penguncian sesi dengan
read_and_close
secara default. - Aman: Mendukung enkripsi AES-256-CBC untuk data sensitif.
- Fleksibel: Opsi auto-commit, mode uji, dan kontrol manual.
- Flight-Native: Dibangun khusus untuk framework Flight.
Detail Teknis
- Format Penyimpanan: File sesi diawali dengan
sess_
dan disimpan disave_path
yang dikonfigurasi. Data terenkripsi menggunakan awalanE
, data teks biasa menggunakanP
. - Enkripsi: Menggunakan AES-256-CBC dengan IV acak per penulisan sesi saat kunci
encryption_key
disediakan. - Pengumpulan Sampah: Mengimplementasikan
SessionHandlerInterface::gc()
PHP untuk membersihkan sesi yang telah kedaluwarsa.
Berkontribusi
Kontribusi sangat diterima! Fork repositori, lakukan perubahan Anda, dan kirim pull request. Laporkan bug atau sarankan fitur melalui pelacak masalah Github.
Lisensi
Plugin ini dilisensikan di bawah Lisensi MIT. Lihat repositori Github untuk detailnya.
Awesome-plugins/runway
Jalur
Jalur adalah aplikasi CLI yang membantu Anda mengelola aplikasi Flight Anda. Ini dapat menghasilkan pengontrol, menampilkan semua rute, dan banyak lagi. Ini didasarkan pada pustaka adhocore/php-cli yang sangat baik.
Klik di sini untuk melihat kodenya.
Instalasi
Instal dengan composer.
composer require flightphp/runway
Konfigurasi Dasar
Kali pertama Anda menjalankan Jalur, itu akan memandu Anda melalui proses pengaturan dan membuat file konfigurasi .runway.json
di akar proyek Anda. File ini akan berisi beberapa konfigurasi yang diperlukan agar Jalur berfungsi dengan baik.
Penggunaan
Jalur memiliki sejumlah perintah yang dapat Anda gunakan untuk mengelola aplikasi Flight Anda. Ada dua cara mudah untuk menggunakan Jalur.
- Jika Anda menggunakan proyek tulang, Anda dapat menjalankan
php runway [command]
dari akar proyek Anda. - Jika Anda menggunakan Jalur sebagai paket yang diinstal melalui composer, Anda dapat menjalankan
vendor/bin/runway [command]
dari akar proyek Anda.
Untuk setiap perintah, Anda dapat melewatkan bendera --help
untuk mendapatkan informasi lebih lanjut tentang cara menggunakan perintah tersebut.
php runway routes --help
Berikut adalah beberapa contoh:
Menghasilkan Pengontrol
Berdasarkan konfigurasi dalam file .runway.json
Anda, lokasi default akan menghasilkan pengontrol untuk Anda di direktori app/controllers/
.
php runway make:controller MyController
Menghasilkan Model Rekaman Aktif
Berdasarkan konfigurasi dalam file .runway.json
Anda, lokasi default akan menghasilkan pengontrol untuk Anda di direktori app/records/
.
php runway make:record users
Jika misalnya Anda memiliki tabel users
dengan skema berikut: id
, name
, email
, created_at
, updated_at
, sebuah file yang mirip dengan yang berikut akan dibuat di file app/records/UserRecord.php
:
<?php
declare(strict_types=1);
namespace app\records;
/**
* Kelas ActiveRecord untuk tabel users.
* @link https://docs.flightphp.com/awesome-plugins/active-record
*
* @property int $id
* @property string $name
* @property string $email
* @property string $created_at
* @property string $updated_at
* // Anda juga bisa menambahkan hubungan di sini setelah Anda mendefinisikannya di array $relations
* @property CompanyRecord $company Contoh hubungan
*/
class UserRecord extends \flight\ActiveRecord
{
/**
* @var array $relations Tetapkan hubungan untuk model
* https://docs.flightphp.com/awesome-plugins/active-record#relationships
*/
protected array $relations = [];
/**
* Konstruktor
* @param mixed $databaseConnection Koneksi ke database
*/
public function __construct($databaseConnection)
{
parent::__construct($databaseConnection, 'users');
}
}
Tampilkan Semua Rute
Ini akan menampilkan semua rute yang saat ini terdaftar dengan Flight.
php runway routes
Jika Anda ingin hanya melihat rute tertentu, Anda dapat melewatkan bendera untuk menyaring rute.
# Tampilkan hanya rute GET
php runway routes --get
# Tampilkan hanya rute POST
php runway routes --post
# dll.
Menyesuaikan Jalur
Jika Anda membuat paket untuk Flight, atau ingin menambahkan perintah kustom Anda sendiri ke dalam proyek Anda, Anda dapat melakukannya dengan membuat direktori src/commands/
, flight/commands/
, app/commands/
, atau commands/
untuk proyek/paket Anda. Jika Anda memerlukan penyesuaian lebih lanjut, lihat bagian di bawah tentang Konfigurasi.
Untuk membuat perintah, Anda cukup memperluas kelas AbstractBaseCommand
, dan menerapkan setidaknya metode __construct
dan metode execute
.
<?php
declare(strict_types=1);
namespace flight\commands;
class ExampleCommand extends AbstractBaseCommand
{
/**
* Konstruktor
*
* @param array<string,mixed> $config Konfigurasi JSON dari .runway-config.json
*/
public function __construct(array $config)
{
parent::__construct('make:example', 'Buat contoh untuk dokumentasi', $config);
$this->argument('<funny-gif>', 'Nama gif lucu');
}
/**
* Menjalankan fungsi
*
* @return void
*/
public function execute(string $controller)
{
$io = $this->app()->io();
$io->info('Membuat contoh...');
// Lakukan sesuatu di sini
$io->ok('Contoh dibuat!');
}
}
Lihat adhocore/php-cli Documentation untuk informasi lebih lanjut tentang cara membangun perintah kustom Anda sendiri ke dalam aplikasi Flight Anda!
Konfigurasi
Jika Anda perlu menyesuaikan konfigurasi untuk Jalur, Anda dapat membuat file .runway-config.json
di akar proyek Anda. Di bawah ini adalah beberapa konfigurasi tambahan yang dapat Anda tetapkan:
{
// Ini adalah tempat direktori aplikasi Anda berada
"app_root": "app/",
// Ini adalah direktori tempat file indeks akar Anda berada
"index_root": "public/",
// Ini adalah jalur ke akar proyek lainnya
"root_paths": [
"/home/user/different-project",
"/var/www/another-project"
],
// Jalur dasar kemungkinan besar tidak perlu dikonfigurasi, tapi ada di sini jika Anda menginginkannya
"base_paths": {
"/includes/libs/vendor", // jika Anda memiliki jalur yang sangat unik untuk direktori vendor Anda atau sesuatu
},
// Jalur akhir adalah lokasi dalam proyek untuk mencari file perintah
"final_paths": {
"src/diff-path/commands",
"app/module/admin/commands",
},
// Jika Anda ingin hanya menambahkan jalur lengkap, silakan saja (absolut atau relatif terhadap akar proyek)
"paths": [
"/home/user/different-project/src/diff-path/commands",
"/var/www/another-project/app/module/admin/commands",
"app/my-unique-commands"
]
}
Awesome-plugins/tracy_extensions
Tracy Flight Panel Extensions
Ini adalah serangkaian ekstensi untuk membuat kerja dengan Flight sedikit lebih kaya.
- Flight - Analisis semua variabel Flight.
- Database - Analisis semua kueri yang telah dijalankan di halaman (jika Anda benar-benar memulai koneksi database)
- Request - Analisis semua variabel
$_SERVER
dan periksa semua payload global ($_GET
,$_POST
,$_FILES
) - Session - Analisis semua variabel
$_SESSION
jika sesi aktif.
Ini adalah Panel
Dan setiap panel menampilkan informasi yang sangat berguna tentang aplikasi Anda!
Klik di sini untuk melihat kode.
Instalasi
Jalankan composer require flightphp/tracy-extensions --dev
dan Anda sudah siap!
Konfigurasi
Ada sangat sedikit konfigurasi yang perlu Anda lakukan untuk memulai ini. Anda perlu memulai debugger Tracy sebelum menggunakan ini https://tracy.nette.org/en/guide:
<?php
use Tracy\Debugger;
use flight\debug\tracy\TracyExtensionLoader;
// kode bootstrap
require __DIR__ . '/vendor/autoload.php';
Debugger::enable();
// Anda mungkin perlu menentukan lingkungan Anda dengan Debugger::enable(Debugger::DEVELOPMENT)
// jika Anda menggunakan koneksi database dalam aplikasi Anda, ada
// pembungkus PDO yang diperlukan untuk digunakan HANYA DI PENGEMBANGAN (bukan produksi, tolong!)
// Ini memiliki parameter yang sama dengan koneksi PDO biasa
$pdo = new PdoQueryCapture('sqlite:test.db', 'user', 'pass');
// atau jika Anda melampirkan ini ke framework Flight
Flight::register('db', PdoQueryCapture::class, ['sqlite:test.db', 'user', 'pass']);
// sekarang setiap kali Anda melakukan kueri, akan menangkap waktu, kueri, dan parameter
// Ini menghubungkan titik-titik
if(Debugger::$showBar === true) {
// Ini perlu false atau Tracy tidak bisa benar-benar merender :(
Flight::set('flight.content_length', false);
new TracyExtensionLoader(Flight::app());
}
// lebih banyak kode
Flight::start();
Konfigurasi Tambahan
Data Sesi
Jika Anda memiliki pengendali sesi kustom (seperti ghostff/session), Anda dapat meneruskan array data sesi apa pun ke Tracy dan secara otomatis akan mengeluarkannya untuk Anda. Anda mengirimkannya dengan kunci session_data
di parameter kedua konstruktor TracyExtensionLoader
.
use Ghostff\Session\Session;
require 'vendor/autoload.php';
$app = Flight::app();
$app->register('session', Session::class);
if(Debugger::$showBar === true) {
// Ini perlu false atau Tracy tidak bisa benar-benar merender :(
Flight::set('flight.content_length', false);
new TracyExtensionLoader(Flight::app(), [ 'session_data' => Flight::session()->getAll() ]);
}
// rute dan hal-hal lain...
Flight::start();
Latte
Jika Anda telah menginstal Latte di proyek Anda, Anda dapat menggunakan panel Latte untuk menganalisis template Anda. Anda dapat meneruskan instance Latte ke konstruktor TracyExtensionLoader
dengan kunci latte
di parameter kedua.
use Latte\Engine;
require 'vendor/autoload.php';
$app = Flight::app();
$app->register('latte', Engine::class, [], function($latte) {
$latte->setTempDirectory(__DIR__ . '/temp');
// di sinilah Anda menambahkan Panel Latte ke Tracy
$latte->addExtension(new Latte\Bridges\Tracy\TracyExtension);
});
if(Debugger::$showBar === true) {
// Ini perlu false atau Tracy tidak bisa benar-benar merender :(
Flight::set('flight.content_length', false);
new TracyExtensionLoader(Flight::app());
}
Awesome-plugins/tracy
Tracy
Tracy adalah penangan kesalahan yang luar biasa yang dapat digunakan dengan Flight. Ia memiliki sejumlah panel yang dapat membantu Anda dalam mendebug aplikasi Anda. Ini juga sangat mudah untuk diperluas dan menambahkan panel Anda sendiri. Tim Flight telah membuat beberapa panel khusus untuk proyek Flight dengan plugin flightphp/tracy-extensions.
Instalasi
Instal dengan composer. Dan Anda akan ingin menginstal ini tanpa versi dev karena Tracy dilengkapi dengan komponen penanganan kesalahan produksi.
composer require tracy/tracy
Konfigurasi Dasar
Ada beberapa opsi konfigurasi dasar untuk memulai. Anda dapat membaca lebih lanjut tentang mereka di Dokumentasi Tracy.
require 'vendor/autoload.php';
use Tracy\Debugger;
// Mengaktifkan Tracy
Debugger::enable();
// Debugger::enable(Debugger::DEVELOPMENT) // kadang-kadang Anda harus eksplisit (juga Debugger::PRODUCTION)
// Debugger::enable('23.75.345.200'); // Anda juga dapat menyediakan array alamat IP
// Di sinilah kesalahan dan pengecualian akan dicatat. Pastikan direktori ini ada dan dapat ditulisi.
Debugger::$logDirectory = __DIR__ . '/../log/';
Debugger::$strictMode = true; // tampilkan semua kesalahan
// Debugger::$strictMode = E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED; // semua kesalahan kecuali pemberitahuan kadaluarsa
if (Debugger::$showBar) {
$app->set('flight.content_length', false); // jika bilah Debugger terlihat, maka panjang konten tidak dapat diatur oleh Flight
// Ini khusus untuk Ekstensi Tracy untuk Flight jika Anda telah menyertakannya
// jika tidak, silakan komentari ini.
new TracyExtensionLoader($app);
}
Tips Berguna
Saat Anda mendebug kode Anda, ada beberapa fungsi yang sangat berguna untuk mengeluarkan data untuk Anda.
bdump($var)
- Ini akan mencetak variabel ke Tracy Bar di panel terpisah.dumpe($var)
- Ini akan mencetak variabel dan kemudian mati segera.
Awesome-plugins/active_record
Flight Active Record
Sebuah active record adalah pemetaan entitas basis data ke objek PHP. Sederhananya, jika Anda memiliki tabel pengguna di basis data Anda, Anda dapat "menerjemahkan" sebuah baris di tabel tersebut ke dalam kelas User
dan objek $user
dalam kode Anda. Lihat contoh dasar.
Klik di sini untuk repositori di GitHub.
Contoh Dasar
Mari kita asumsikan Anda memiliki tabel berikut:
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT,
password TEXT
);
Sekarang Anda dapat mengatur kelas baru untuk mewakili tabel ini:
/**
* Sebuah kelas ActiveRecord biasanya tunggal
*
* Sangat disarankan untuk menambahkan properti tabel sebagai komentar di sini
*
* @property int $id
* @property string $name
* @property string $password
*/
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
// Anda dapat mengatur ini dengan cara ini
parent::__construct($database_connection, 'users');
// atau dengan cara ini
parent::__construct($database_connection, null, [ 'table' => 'users']);
}
}
Sekarang saksikan sihir terjadi!
// untuk sqlite
$database_connection = new PDO('sqlite:test.db'); // ini hanya untuk contoh, Anda mungkin akan menggunakan koneksi basis data yang nyata
// untuk mysql
$database_connection = new PDO('mysql:host=localhost;dbname=test_db&charset=utf8bm4', 'username', 'password');
// atau mysqli
$database_connection = new mysqli('localhost', 'username', 'password', 'test_db');
// atau mysqli dengan pembuatan yang tidak berdasarkan objek
$database_connection = mysqli_connect('localhost', 'username', 'password', 'test_db');
$user = new User($database_connection);
$user->name = 'Bobby Tables';
$user->password = password_hash('some cool password');
$user->insert();
// atau $user->save();
echo $user->id; // 1
$user->name = 'Joseph Mamma';
$user->password = password_hash('some cool password again!!!');
$user->insert();
// tidak dapat menggunakan $user->save() di sini, atau itu akan mengira ini adalah pembaruan!
echo $user->id; // 2
Dan itu sangat mudah untuk menambahkan pengguna baru! Sekarang setelah ada baris pengguna di basis data, bagaimana cara Anda mengeluarkannya?
$user->find(1); // cari id = 1 dalam basis data dan kembalikan.
echo $user->name; // 'Bobby Tables'
Dan bagaimana jika Anda ingin menemukan semua pengguna?
$users = $user->findAll();
Bagaimana dengan kondisi tertentu?
$users = $user->like('name', '%mamma%')->findAll();
Lihat betapa menyenangkannya ini? Mari kita instal dan mulai!
Instalasi
Cukup instal dengan Composer
composer require flightphp/active-record
Penggunaan
Ini dapat digunakan sebagai pustaka mandiri atau dengan Flight PHP Framework. Sepenuhnya terserah Anda.
Mandiri
Pastikan Anda mengoper koneksi PDO ke konstruktor.
$pdo_connection = new PDO('sqlite:test.db'); // ini hanya untuk contoh, Anda mungkin akan menggunakan koneksi basis data yang nyata
$User = new User($pdo_connection);
Tidak ingin selalu mengatur koneksi basis data Anda di konstruktor? Lihat Manajemen Koneksi Basis Data untuk ide lainnya!
Daftarkan sebagai metode dalam Flight
Jika Anda menggunakan Flight PHP Framework, Anda dapat mendaftarkan kelas ActiveRecord sebagai layanan, tetapi sejujurnya Anda tidak harus melakukannya.
Flight::register('user', 'User', [ $pdo_connection ]);
// kemudian Anda dapat menggunakannya seperti ini di pengontrol, fungsi, dll.
Flight::user()->find(1);
Metode runway
runway adalah alat CLI untuk Flight yang memiliki perintah khusus untuk pustaka ini.
# Penggunaan
php runway make:record database_table_name [class_name]
# Contoh
php runway make:record users
Ini akan membuat kelas baru di direktori app/records/
sebagai UserRecord.php
dengan konten berikut:
<?php
declare(strict_types=1);
namespace app\records;
/**
* Kelas ActiveRecord untuk tabel pengguna.
* @link https://docs.flightphp.com/awesome-plugins/active-record
*
* @property int $id
* @property string $username
* @property string $email
* @property string $password_hash
* @property string $created_dt
*/
class UserRecord extends \flight\ActiveRecord
{
/**
* @var array $relations Menetapkan hubungan untuk model
* https://docs.flightphp.com/awesome-plugins/active-record#relationships
*/
protected array $relations = [
// 'relation_name' => [ self::HAS_MANY, 'RelatedClass', 'foreign_key' ],
];
/**
* Konstruktor
* @param mixed $databaseConnection Koneksi ke basis data
*/
public function __construct($databaseConnection)
{
parent::__construct($databaseConnection, 'users');
}
}
Fungsi CRUD
find($id = null) : boolean|ActiveRecord
Mencari satu catatan dan menetapkannya pada objek saat ini. Jika Anda mengoper $id
dari jenis tertentu, itu akan melakukan pencarian pada kunci utama dengan nilai itu. Jika tidak ada yang dipassing, ini hanya akan menemukan catatan pertama di tabel.
Selain itu, Anda dapat mengoper metode pembantu lainnya untuk menanyakan tabel Anda.
// mencari catatan dengan beberapa kondisi terlebih dahulu
$user->notNull('password')->orderBy('id DESC')->find();
// mencari catatan berdasarkan id tertentu
$id = 123;
$user->find($id);
findAll(): array<int,ActiveRecord>
Menemukan semua catatan di tabel yang Anda tentukan.
$user->findAll();
isHydrated(): boolean
(v0.4.0)
Mengembalikan true
jika catatan saat ini telah terhidrat (diambil dari database).
$user->find(1);
// jika catatan ditemukan dengan data...
$user->isHydrated(); // true
insert(): boolean|ActiveRecord
Menyisipkan catatan saat ini ke dalam basis data.
$user = new User($pdo_connection);
$user->name = 'demo';
$user->password = md5('demo');
$user->insert();
Kunci Utama berbasis Teks
Jika Anda memiliki kunci utama berbasis teks (seperti UUID), Anda dapat mengatur nilai kunci utama sebelum menyisipkan dalam dua cara.
$user = new User($pdo_connection, [ 'primaryKey' => 'uuid' ]);
$user->uuid = 'some-uuid';
$user->name = 'demo';
$user->password = md5('demo');
$user->insert(); // atau $user->save();
atau Anda dapat membiarkan kunci utama dihasilkan secara otomatis untuk Anda melalui peristiwa.
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users', [ 'primaryKey' => 'uuid' ]);
// Anda juga dapat mengatur primaryKey ini alih-alih array di atas.
$this->primaryKey = 'uuid';
}
protected function beforeInsert(self $self) {
$self->uuid = uniqid(); // atau sesuaikan bagaimana Anda perlu menghasilkan id unik Anda
}
}
Jika Anda tidak mengatur kunci utama sebelum menyisipkan, itu akan diatur ke rowid
dan basis data akan menghasilkan untuk Anda, tetapi tidak akan dipertahankan karena bidang itu mungkin tidak ada dalam tabel Anda. Inilah sebabnya mengapa disarankan untuk menggunakan peristiwa untuk menangani ini secara otomatis untuk Anda.
update(): boolean|ActiveRecord
Memperbarui catatan saat ini ke dalam basis data.
$user->greaterThan('id', 0)->orderBy('id desc')->find();
$user->email = 'test@example.com';
$user->update();
save(): boolean|ActiveRecord
Menyisipkan atau memperbarui catatan saat ini ke dalam basis data. Jika catatan memiliki id, itu akan memperbarui, jika tidak, itu akan menyisipkan.
$user = new User($pdo_connection);
$user->name = 'demo';
$user->password = md5('demo');
$user->save();
Catatan: Jika Anda memiliki hubungan yang ditentukan dalam kelas, itu akan menyimpan hubungan tersebut secara rekursif juga jika telah ditentukan, diinstansiasi, dan memiliki data yang perlu diperbarui. (v0.4.0 dan lebih baru)
delete(): boolean
Menghapus catatan saat ini dari basis data.
$user->gt('id', 0)->orderBy('id desc')->find();
$user->delete();
Anda juga dapat menghapus beberapa catatan dengan mengeksekusi pencarian terlebih dahulu.
$user->like('name', 'Bob%')->delete();
dirty(array $dirty = []): ActiveRecord
Data "dirty" merujuk pada data yang telah diubah dalam sebuah catatan.
$user->greaterThan('id', 0)->orderBy('id desc')->find();
// tidak ada yang "dirty" pada titik ini.
$user->email = 'test@example.com'; // sekarang email dianggap "dirty" karena telah diubah.
$user->update();
// sekarang tidak ada data yang dirty karena telah diperbarui dan dipertahankan dalam basis data
$user->password = password_hash('newpassword'); // sekarang ini kotor
$user->dirty(); // melewatkan apa pun akan membersihkan semua entri yang kotor.
$user->update(); // tidak ada yang akan diperbarui karena tidak ada yang ditangkap sebagai kotor.
$user->dirty([ 'name' => 'sesuatu', 'password' => password_hash('password yang berbeda') ]);
$user->update(); // baik nama dan kata sandi diperbarui.
copyFrom(array $data): ActiveRecord
(v0.4.0)
Ini adalah alias untuk metode dirty()
. Ini sedikit lebih jelas tentang apa yang Anda lakukan.
$user->copyFrom([ 'name' => 'sesuatu', 'password' => password_hash('password yang berbeda') ]);
$user->update(); // baik nama dan kata sandi diperbarui.
isDirty(): boolean
(v0.4.0)
Mengembalikan true
jika catatan saat ini telah diubah.
$user->greaterThan('id', 0)->orderBy('id desc')->find();
$user->email = 'test@email.com';
$user->isDirty(); // true
reset(bool $include_query_data = true): ActiveRecord
Mereset catatan saat ini ke keadaan awalnya. Ini sangat baik digunakan dalam perilaku tipe loop.
Jika Anda mengoper true
, itu juga akan mereset data kueri yang digunakan untuk menemukan objek saat ini (perilaku default).
$users = $user->greaterThan('id', 0)->orderBy('id desc')->find();
$user_company = new UserCompany($pdo_connection);
foreach($users as $user) {
$user_company->reset(); // mulai dengan slate yang bersih
$user_company->user_id = $user->id;
$user_company->company_id = $some_company_id;
$user_company->insert();
}
getBuiltSql(): string
(v0.4.1)
Setelah Anda menjalankan metode find()
, findAll()
, insert()
, update()
, atau save()
, Anda dapat memperoleh SQL yang dibangun dan menggunakannya untuk tujuan debugging.
Metode Kuery SQL
select(string $field1 [, string $field2 ... ])
Anda dapat memilih hanya beberapa kolom di tabel jika Anda mau (ini lebih efisien pada tabel yang sangat lebar dengan banyak kolom)
$user->select('id', 'name')->find();
from(string $table)
Anda dapat memilih tabel lain juga! Untuk apa tidak?!
$user->select('id', 'name')->from('user')->find();
join(string $table_name, string $join_condition)
Anda bahkan dapat bergabung dengan tabel lain di basis data.
$user->join('contacts', 'contacts.user_id = users.id')->find();
where(string $where_conditions)
Anda dapat menetapkan beberapa argumen where kustom (Anda tidak dapat mengatur parameter dalam pernyataan where ini)
$user->where('id=1 AND name="demo"')->find();
Catatan Keamanan - Anda mungkin terdorong untuk melakukan sesuatu seperti $user->where("id = '{$id}' AND name = '{$name}'")->find();
. Tolong JANGAN LAKUKAN INI!!! Ini rentan terhadap apa yang dikenal sebagai serangan SQL Injection. Ada banyak artikel di internet, silakan Google "sql injection attacks php" dan Anda akan menemukan banyak artikel tentang subjek ini. Cara yang tepat untuk menangani ini dengan perpustakaan ini adalah alih-alih metode where()
ini, Anda akan melakukan sesuatu yang lebih seperti $user->eq('id', $id)->eq('name', $name)->find();
Jika Anda harus melakukan ini, pustaka PDO
memiliki $pdo->quote($var)
untuk menghindarinya untuk Anda. Hanya setelah Anda menggunakan quote()
Anda dapat menggunakannya dalam pernyataan where()
.
group(string $group_by_statement)/groupBy(string $group_by_statement)
Kelompokkan hasil Anda berdasarkan kondisi tertentu.
$user->select('COUNT(*) as count')->groupBy('name')->findAll();
order(string $order_by_statement)/orderBy(string $order_by_statement)
Urutkan kueri yang dikembalikan dengan cara tertentu.
$user->orderBy('name DESC')->find();
limit(string $limit)/limit(int $offset, int $limit)
Batasi jumlah rekaman yang dikembalikan. Jika bilangan kedua diberikan, itu akan di-offset, batasi saja seperti di SQL.
$user->orderby('name DESC')->limit(0, 10)->findAll();
Kondisi WHERE
equal(string $field, mixed $value) / eq(string $field, mixed $value)
Di mana field = $value
$user->eq('id', 1)->find();
notEqual(string $field, mixed $value) / ne(string $field, mixed $value)
Di mana field <> $value
$user->ne('id', 1)->find();
isNull(string $field)
Di mana field IS NULL
$user->isNull('id')->find();
isNotNull(string $field) / notNull(string $field)
Di mana field IS NOT NULL
$user->isNotNull('id')->find();
greaterThan(string $field, mixed $value) / gt(string $field, mixed $value)
Di mana field > $value
$user->gt('id', 1)->find();
lessThan(string $field, mixed $value) / lt(string $field, mixed $value)
Di mana field < $value
$user->lt('id', 1)->find();
greaterThanOrEqual(string $field, mixed $value) / ge(string $field, mixed $value) / gte(string $field, mixed $value)
Di mana field >= $value
$user->ge('id', 1)->find();
lessThanOrEqual(string $field, mixed $value) / le(string $field, mixed $value) / lte(string $field, mixed $value)
Di mana field <= $value
$user->le('id', 1)->find();
like(string $field, mixed $value) / notLike(string $field, mixed $value)
Di mana field LIKE $value
atau field NOT LIKE $value
$user->like('name', 'de')->find();
in(string $field, array $values) / notIn(string $field, array $values)
Di mana field IN($value)
atau field NOT IN($value)
$user->in('id', [1, 2])->find();
between(string $field, array $values)
Di mana field BETWEEN $value AND $value1
$user->between('id', [1, 2])->find();
Kondisi OR
Dimungkinkan untuk membungkus kondisi Anda dalam pernyataan OR. Ini dilakukan dengan metode startWrap()
dan endWrap()
atau dengan mengisi parameter ke-3 dari kondisi setelah bidang dan nilai.
// Metode 1
$user->eq('id', 1)->startWrap()->eq('name', 'demo')->or()->eq('name', 'test')->endWrap('OR')->find();
// Ini akan dievaluasi menjadi `id = 1 AND (name = 'demo' OR name = 'test')`
// Metode 2
$user->eq('id', 1)->eq('name', 'demo', 'OR')->find();
// Ini akan dievaluasi menjadi `id = 1 OR name = 'demo'`
Hubungan
Anda dapat mengatur beberapa jenis hubungan menggunakan pustaka ini. Anda dapat mengatur hubungan satu->banyak dan satu->satu antara tabel. Ini membutuhkan pengaturan ekstra dalam kelas sebelumnya.
Mengatur array $relations
tidaklah sulit, tetapi menebak sintaks yang benar bisa membingungkan.
protected array $relations = [
// Anda dapat memberi nama kuncinya dengan cara apa pun yang Anda suka. Nama ActiveRecord mungkin bagus. Mis: user, contact, client
'user' => [
// wajib
// self::HAS_MANY, self::HAS_ONE, self::BELONGS_TO
self::HAS_ONE, // ini adalah jenis hubungan
// wajib
'Some_Class', // ini adalah kelas ActiveRecord "lain" yang akan direferensikan
// wajib
// tergantung pada jenis hubungan
// self::HAS_ONE = kunci asing yang mereferensikan gabungan
// self::HAS_MANY = kunci asing yang mereferensikan gabungan
// self::BELONGS_TO = kunci lokal yang mereferensikan gabungan
'local_or_foreign_key',
// hanya FYI, ini juga hanya bergabung dengan kunci utama model "lain"
// opsional
[ 'eq' => [ 'client_id', 5 ], 'select' => 'COUNT(*) as count', 'limit' 5 ], // kondisi tambahan yang Anda inginkan ketika menggabungkan hubungan
// $record->eq('client_id', 5)->select('COUNT(*) as count')->limit(5))
// opsional
'nama_referensi_kembali' // ini jika Anda ingin merujuk kembali hubungan ini kembali ke dirinya sendiri Mis: $user->contact->user;
];
]
class User extends ActiveRecord{
protected array $relations = [
'contacts' => [ self::HAS_MANY, Contact::class, 'user_id' ],
'contact' => [ self::HAS_ONE, Contact::class, 'user_id' ],
];
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
}
class Contact extends ActiveRecord{
protected array $relations = [
'user' => [ self::BELONGS_TO, User::class, 'user_id' ],
'user_with_backref' => [ self::BELONGS_TO, User::class, 'user_id', [], 'contact' ],
];
public function __construct($database_connection)
{
parent::__construct($database_connection, 'contacts');
}
}
Sekarang kita telah mengatur referensi sehingga kita dapat menggunakannya dengan sangat mudah!
$user = new User($pdo_connection);
// cari pengguna terbaru.
$user->notNull('id')->orderBy('id desc')->find();
// ambil kontak dengan menggunakan hubungan:
foreach($user->contacts as $contact) {
echo $contact->id;
}
// atau kita bisa pergi ke arah yang lain.
$contact = new Contact();
// cari satu kontak
$contact->find();
// dapatkan pengguna dengan menggunakan hubungan:
echo $contact->user->name; // ini adalah nama pengguna
Keren kan?
Mengatur Data Kustom
Terkadang Anda mungkin perlu melampirkan sesuatu yang unik pada ActiveRecord Anda seperti perhitungan khusus yang mungkin lebih mudah untuk dilampirkan pada objek yang kemudian akan diteruskan ke template.
setCustomData(string $field, mixed $value)
Anda melampirkan data kustom dengan metode setCustomData()
.
$user->setCustomData('page_view_count', $page_view_count);
Dan kemudian Anda cukup merujuknya seperti properti objek biasa.
echo $user->page_view_count;
Peristiwa
Satu fitur luar biasa lainnya tentang pustaka ini adalah tentang peristiwa. Peristiwa dipicu pada saat tertentu berdasarkan metode tertentu yang Anda panggil. Mereka sangat membantu dalam menyiapkan data untuk Anda secara otomatis.
onConstruct(ActiveRecord $ActiveRecord, array &config)
Ini sangat membantu jika Anda perlu mengatur koneksi default atau sesuatu seperti itu.
// index.php atau bootstrap.php
Flight::register('db', 'PDO', [ 'sqlite:test.db' ]);
//
//
//
// User.php
class User extends flight\ActiveRecord {
protected function onConstruct(self $self, array &$config) { // jangan lupa referensi &
// Anda bisa melakukan ini untuk secara otomatis mengatur koneksi
$config['connection'] = Flight::db();
// atau ini
$self->transformAndPersistConnection(Flight::db());
// Anda juga dapat mengatur nama tabel dengan cara ini.
$config['table'] = 'users';
}
}
beforeFind(ActiveRecord $ActiveRecord)
Ini mungkin hanya berguna jika Anda perlu manipulasi kueri setiap kali.
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
protected function beforeFind(self $self) {
// selalu jalankan id >= 0 jika itu adalah yang Anda inginkan
$self->gte('id', 0);
}
}
afterFind(ActiveRecord $ActiveRecord)
Yang ini mungkin lebih berguna jika Anda selalu perlu menjalankan beberapa logika setiap kali catatan ini diambil. Apakah Anda perlu mendekripsi sesuatu? Apakah Anda perlu menjalankan kueri hitung kustom setiap kali (tidak efisien tetapi tidak apa-apa)?
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
protected function afterFind(self $self) {
// mendekripsi sesuatu
$self->secret = yourDecryptFunction($self->secret, $some_key);
// mungkin menyimpan sesuatu yang kustom seperti kueri???
$self->setCustomData('view_count', $self->select('COUNT(*) count')->from('user_views')->eq('user_id', $self->id)['count']);
}
}
beforeFindAll(ActiveRecord $ActiveRecord)
Ini mungkin hanya berguna jika Anda perlu manipulasi kueri setiap kali.
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
protected function beforeFindAll(self $self) {
// selalu jalankan id >= 0 jika itu adalah yang Anda inginkan
$self->gte('id', 0);
}
}
afterFindAll(array<int,ActiveRecord> $results)
Mirip dengan afterFind()
tetapi Anda bisa melakukannya ke semua catatan!
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
protected function afterFindAll(array $results) {
foreach($results as $self) {
// lakukan sesuatu yang keren seperti afterFind()
}
}
}
beforeInsert(ActiveRecord $ActiveRecord)
Sangat berguna jika Anda perlu menetapkan beberapa nilai default setiap kali.
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
protected function beforeInsert(self $self) {
// menetapkan beberapa default yang baik
if(!$self->created_date) {
$self->created_date = gmdate('Y-m-d');
}
if(!$self->password) {
$self->password = password_hash((string) microtime(true));
}
}
}
afterInsert(ActiveRecord $ActiveRecord)
Mungkin Anda memiliki skenario untuk mengubah data setelah disisipkan?
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
protected function afterInsert(self $self) {
// Anda melakukan Anda
Flight::cache()->set('most_recent_insert_id', $self->id);
// atau apa pun....
}
}
beforeUpdate(ActiveRecord $ActiveRecord)
Sangat berguna jika Anda perlu menetapkan beberapa nilai default setiap kali ada pembaruan.
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
protected function beforeInsert(self $self) {
// menetapkan beberapa default yang baik
if(!$self->updated_date) {
$self->updated_date = gmdate('Y-m-d');
}
}
}
afterUpdate(ActiveRecord $ActiveRecord)
Mungkin Anda memiliki skenario untuk mengubah data setelah diperbarui?
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
protected function afterInsert(self $self) {
// Anda melakukan Anda
Flight::cache()->set('most_recently_updated_user_id', $self->id);
// atau apa pun....
}
}
beforeSave(ActiveRecord $ActiveRecord)/afterSave(ActiveRecord $ActiveRecord)
Ini berguna jika Anda ingin peristiwa terjadi baik saat sisip atau pembaruan terjadi. Saya akan menghemat penjelasan panjangnya, tetapi saya yakin Anda bisa menebak apa itu.
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
protected function beforeSave(self $self) {
$self->last_updated = gmdate('Y-m-d H:i:s');
}
}
beforeDelete(ActiveRecord $ActiveRecord)/afterDelete(ActiveRecord $ActiveRecord)
Tidak yakin apa yang ingin Anda lakukan di sini, tetapi tidak ada penilaian di sini! Ayo lakukan!
class User extends flight\ActiveRecord {
public function __construct($database_connection)
{
parent::__construct($database_connection, 'users');
}
protected function beforeDelete(self $self) {
echo 'Dia adalah seorang prajurit yang berani... :cry-face:';
}
}
Manajemen Koneksi Basis Data
Ketika Anda menggunakan pustaka ini, Anda dapat mengatur koneksi basis data dengan beberapa cara berbeda. Anda dapat mengatur koneksi di konstruktor, Anda dapat mengatur melalui variabel konfigurasi $config['connection']
atau Anda dapat mengatur melalui setDatabaseConnection()
(v0.4.1).
$pdo_connection = new PDO('sqlite:test.db'); // untuk contoh
$user = new User($pdo_connection);
// atau
$user = new User(null, [ 'connection' => $pdo_connection ]);
// atau
$user = new User();
$user->setDatabaseConnection($pdo_connection);
Jika Anda ingin menghindari selalu mengatur $database_connection
setiap kali Anda memanggil record aktif, ada cara untuk mengatasinya!
// index.php atau bootstrap.php
// Set ini sebagai kelas terdaftar di Flight
Flight::register('db', 'PDO', [ 'sqlite:test.db' ]);
// User.php
class User extends flight\ActiveRecord {
public function __construct(array $config = [])
{
$database_connection = $config['connection'] ?? Flight::db();
parent::__construct($database_connection, 'users', $config);
}
}
// Dan sekarang, tidak ada argumen yang diperlukan!
$user = new User();
Catatan: Jika Anda berencana untuk melakukan pengujian unit, melakukan ini dapat menambah beberapa tantangan untuk pengujian unit, tetapi secara keseluruhan karena Anda dapat menyuntikkan koneksi Anda dengan
setDatabaseConnection()
atau$config['connection']
, ini tidak terlalu buruk.
Jika Anda perlu menyegarkan koneksi basis data, misalnya jika Anda menjalankan skrip CLI yang berjalan lama dan perlu menyegarkan koneksi setiap saat, Anda dapat mengatur ulang koneksi dengan $your_record->setDatabaseConnection($pdo_connection)
.
Kontribusi
Silakan lakukan. :D
Pengaturan
Saat Anda berkontribusi, pastikan Anda menjalankan composer test-coverage
untuk mempertahankan 100% cakupan pengujian (ini bukan cakupan pengujian unit yang sebenarnya, lebih seperti pengujian integrasi).
Juga pastikan Anda menjalankan composer beautify
dan composer phpcs
untuk memperbaiki kesalahan linting.
Lisensi
MIT
Awesome-plugins/latte
Latte
Latte adalah mesin templating dengan fitur lengkap yang sangat mudah digunakan dan terasa lebih dekat dengan sintaks PHP dibandingkan Twig atau Smarty. Ini juga sangat mudah untuk diperluas dan menambahkan filter serta fungsi Anda sendiri.
Instalasi
Instal dengan composer.
composer require latte/latte
Konfigurasi Dasar
Ada beberapa opsi konfigurasi dasar untuk memulai. Anda dapat membaca lebih lanjut tentang mereka di Dokumentasi Latte.
use Latte\Engine as LatteEngine;
require 'vendor/autoload.php';
$app = Flight::app();
$app->register('latte', LatteEngine::class, [], function(LatteEngine $latte) use ($app) {
// Di sinilah Latte akan menyimpan cache untuk template Anda untuk mempercepat proses
// Satu hal menarik tentang Latte adalah bahwa ia secara otomatis menyegarkan
// cache saat Anda membuat perubahan pada template Anda!
$latte->setTempDirectory(__DIR__ . '/../cache/');
// Beri tahu Latte di mana direktori root untuk tampilan Anda akan berada.
// $app->get('flight.views.path') diatur di file config.php
// Anda juga bisa melakukan sesuatu seperti `__DIR__ . '/../views/'`
$latte->setLoader(new \Latte\Loaders\FileLoader($app->get('flight.views.path')));
});
Contoh Layout Sederhana
Ini adalah contoh sederhana dari file layout. Ini adalah file yang akan digunakan untuk membungkus semua tampilan Anda yang lain.
<!-- app/views/layout.latte -->
<!doctype html>
<html lang="en">
<head>
<title>{$title ? $title . ' - '}Aplikasi Saya</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<nav>
<!-- elemen navigasi Anda di sini -->
</nav>
</header>
<div id="content">
<!-- Ini adalah keajaiban yang terjadi di sini -->
{block content}{/block}
</div>
<div id="footer">
© Hak Cipta
</div>
</body>
</html>
Dan sekarang kita memiliki file Anda yang akan dirender di dalam blok konten tersebut:
<!-- app/views/home.latte -->
<!-- Ini memberi tahu Latte bahwa file ini "di dalam" file layout.latte -->
{extends layout.latte}
<!-- Ini adalah konten yang akan dirender di dalam layout di dalam blok konten -->
{block content}
<h1>Halaman Utama</h1>
<p>Selamat datang di aplikasi saya!</p>
{/block}
Kemudian saat Anda pergi untuk merender ini di dalam fungsi atau kontroler Anda, Anda akan melakukan sesuatu seperti ini:
// rute sederhana
Flight::route('/', function () {
Flight::latte()->render('home.latte', [
'title' => 'Halaman Utama'
]);
});
// atau jika Anda menggunakan kontroler
Flight::route('/', [HomeController::class, 'index']);
// HomeController.php
class HomeController
{
public function index()
{
Flight::latte()->render('home.latte', [
'title' => 'Halaman Utama'
]);
}
}
Lihat Dokumentasi Latte untuk informasi lebih lanjut tentang cara menggunakan Latte untuk potensi penuh!
Awesome-plugins/awesome_plugins
Plugin Luar Biasa
Flight sangat dapat diperluas. Ada sejumlah plugin yang dapat digunakan untuk menambahkan fungsionalitas ke aplikasi Flight Anda. Beberapa didukung secara resmi oleh Tim Flight dan lainnya adalah pustaka mikro/lite untuk membantu Anda memulai.
Dokumentasi API
Dokumentasi API sangat penting untuk API apa pun. Ini membantu pengembang memahami cara berinteraksi dengan API Anda dan apa yang diharapkan sebagai balasan. Ada beberapa alat yang tersedia untuk membantu Anda menghasilkan dokumentasi API untuk Proyek Flight Anda.
- FlightPHP OpenAPI Generator - Pos blog yang ditulis oleh Daniel Schreiber tentang cara menggunakan Spesifikasi OpenAPI dengan FlightPHP untuk membangun API Anda menggunakan pendekatan API pertama.
- SwaggerUI - Swagger UI adalah alat hebat untuk membantu Anda menghasilkan dokumentasi API untuk proyek Flight Anda. Ini sangat mudah digunakan dan dapat disesuaikan agar sesuai dengan kebutuhan Anda. Ini adalah pustaka PHP untuk membantu Anda menghasilkan dokumentasi Swagger.
Autentikasi/Otorisasi
Autentikasi dan Otorisasi sangat penting untuk setiap aplikasi yang memerlukan kontrol untuk siapa yang dapat mengakses apa.
- resmi flightphp/permissions - Pustaka Izin Flight resmi. Pustaka ini adalah cara sederhana untuk menambahkan izin tingkat pengguna dan aplikasi ke aplikasi Anda.
Cache
Cache adalah cara yang bagus untuk mempercepat aplikasi Anda. Ada sejumlah pustaka caching yang dapat digunakan dengan Flight.
- resmi flightphp/cache - Kelas caching PHP dalam file yang ringan, sederhana, dan mandiri.
CLI
Aplikasi CLI adalah cara yang bagus untuk berinteraksi dengan aplikasi Anda. Anda dapat menggunakannya untuk menghasilkan pengontrol, menampilkan semua rute, dan lainnya.
- resmi flightphp/runway - Runway adalah aplikasi CLI yang membantu Anda mengelola aplikasi Flight Anda.
Cookies
Cookies adalah cara yang bagus untuk menyimpan sedikit data di sisi klien. Ini dapat digunakan untuk menyimpan preferensi pengguna, pengaturan aplikasi, dan lainnya.
- overclokk/cookie - PHP Cookie adalah pustaka PHP yang menyediakan cara sederhana dan efektif untuk mengelola cookies.
Debugging
Debugging sangat penting ketika Anda sedang mengembangkan di lingkungan lokal Anda. Ada beberapa plugin yang dapat meningkatkan pengalaman debugging Anda.
- tracy/tracy - Ini adalah pengendali kesalahan dengan fitur lengkap yang dapat digunakan dengan Flight. Ini memiliki sejumlah panel yang dapat membantu Anda melakukan debug aplikasi Anda. Ini juga sangat mudah untuk diperluas dan menambahkan panel Anda sendiri.
- flightphp/tracy-extensions - Digunakan dengan Tracy pengendali kesalahan, plugin ini menambahkan beberapa panel ekstra untuk membantu dengan debugging khusus untuk proyek Flight.
Basis Data
Basis data adalah inti dari sebagian besar aplikasi. Ini adalah cara Anda menyimpan dan mengambil data. Beberapa pustaka basis data hanyalah pembungkus untuk menulis kueri dan beberapa adalah ORM lengkap.
- resmi flightphp/core PdoWrapper - Pembungkus PDO resmi Flight yang merupakan bagian dari inti. Ini adalah pembungkus sederhana untuk membantu menyederhanakan proses menulis kueri dan mengeksekusinya. Ini bukan ORM.
- resmi flightphp/active-record - ORM/Pemetaan ActiveRecord resmi Flight. Pustaka kecil yang hebat untuk dengan mudah mengambil dan menyimpan data di basis data Anda.
- byjg/php-migration - Plugin untuk melacak semua perubahan basis data untuk proyek Anda.
Enkripsi
Enkripsi sangat penting untuk aplikasi apa pun yang menyimpan data sensitif. Mengenskripsi dan mendekripsi data tidak terlalu sulit, tetapi menyimpan kunci enkripsi dengan benar dapat menjadi sulit. Hal yang paling penting adalah tidak pernah menyimpan kunci enkripsi Anda di direktori publik atau mengkomitnya ke repositori kode Anda.
- defuse/php-encryption - Ini adalah pustaka yang dapat digunakan untuk mengenkripsi dan mendekripsi data. Memulai dan berjalan cukup mudah untuk mulai mengenkripsi dan mendekripsi data.
Antrian Pekerjaan
Antrian pekerjaan sangat membantu untuk memproses tugas secara asinkron. Ini dapat berupa mengirim email, memproses gambar, atau apa pun yang tidak perlu dilakukan secara waktu nyata.
- n0nag0n/simple-job-queue - Antrian Pekerjaan Sederhana adalah pustaka yang dapat digunakan untuk memproses pekerjaan secara asinkron. Ini dapat digunakan dengan beanstalkd, MySQL/MariaDB, SQLite, dan PostgreSQL.
Sesi
Sesi tidak terlalu berguna untuk API, tetapi untuk membangun aplikasi web, sesi dapat sangat penting untuk memelihara status dan informasi login.
- resmi flightphp/session - Pustaka Sesi resmi Flight. Ini adalah pustaka sesi sederhana yang dapat digunakan untuk menyimpan dan mengambil data sesi. Ini menggunakan penanganan sesi bawaan PHP.
- Ghostff/Session - Pengelola Sesi PHP (non-blocking, flash, segment, enkripsi sesi). Menggunakan open_ssl PHP untuk enkripsi/dekripsi opsional data sesi.
Templating
Templating adalah inti dari setiap aplikasi web dengan UI. Ada sejumlah mesin templating yang dapat digunakan dengan Flight.
- ditinggalkan flightphp/core View - Ini adalah mesin templating yang sangat dasar yang merupakan bagian dari inti. Ini tidak dianjurkan digunakan jika Anda memiliki lebih dari beberapa halaman dalam proyek Anda.
- latte/latte - Latte adalah mesin templating dengan fitur lengkap yang sangat mudah digunakan dan terasa lebih dekat dengan sintaks PHP dibandingkan Twig atau Smarty. Ini juga sangat mudah untuk diperluas dan menambahkan filter serta fungsi Anda sendiri.
Kontribusi
Apakah Anda memiliki plugin yang ingin Anda bagikan? Kirim permohonan tarik untuk menambahkannya ke daftar!
Media
Media
Kami telah berusaha untuk melacak apa yang kami bisa tentang berbagai jenis media di internet seputar Flight. Lihat di bawah untuk berbagai sumber yang dapat Anda gunakan untuk mempelajari lebih lanjut tentang Flight.
Artikel dan Tulisannya
- Define, Generate, and Implement: An API-First Approach with OpenAPI Generator and FlightPHP oleh Daniel Schreiber (2025)
- Best PHP Micro Frameworks for 2024 oleh n0nag0n (2024)
- Creating a RESTful API with Flight Framework oleh n0nag0n (2024)
- Building a Simple Blog with Flight Part 2 oleh n0nag0n (2024)
- Building a Simple Blog with Flight Part 1 oleh n0nag0n (2024)
- 🚀 Build a Simple CRUD API in PHP with the Flight Framework oleh soheil-khaledabadi (2024)
- Building a PHP Web Application with the Flight Micro-framework oleh Arthur C. Codex (2023)
- Best PHP Frameworks for Web Development in 2024 oleh Ravikiran A S (2023)
- Top 12 PHP Frameworks: A Comprehensive Guide for 2023 oleh marketing kbk (2023)
- 5 PHP Frameworks You've (Probably) Never Heard of oleh n0nag0n (2022)
- 12 top PHP frameworks for web developers to consider in 2023 oleh Anna Monus (2022)
- The Best PHP Microframeworks on a Cloud Server oleh Shahzeb Ahmed (2021)
- PHP framework: Top 15 powerful ones for your web development oleh AHT Tech (2020)
- Easy PHP Routing with FlightPHP oleh Lucas Conceição (2019)
- Trying Out New PHP Framework (Flight) oleh Leon (2017)
- Setting up FlightPHP to work with Backbonejs oleh Timothy Tocci (2015)
Video dan Tutorial
- Create a REST API for IoT Devices Using PHP & FlightPHP - ESP32 API oleh IoT Craft Hub (2024)
- PHP Flight Framework Simple Introductory Video oleh n0nag0n (2024)
- Set header HTTP code in Flightphp (3 Solutions!!) oleh Roel Van de Paar (2024)
- PHP Flight Framework Tutorial. Super easy API Project! oleh n0nag0n (2022)
- Aplicación web CRUD con php y mysql y bootstrap usando flight oleh Devlopteca - Oscar Uh (2021)
- DevOps & SysAdmins: Lighttpd rewrite rule for Flight PHP microframework oleh Roel Van de Paar (2021)
- Tutorial REST API Flight PHP #PART2 INSERT TABLE Info #Code (Tagalog) oleh Info Singkat Official (2020)
- Tutorial REST API Flight PHP #PART1 Info #Code (Tagalog) oleh Info Singkat Official (2020)
- How To Create JSON REST API IN PHP - Part 2 oleh Codewife (2018)
- How To Create JSON REST API IN PHP - Part 1 oleh Codewife (2018)
- Teste Micro Frameworks PHP - Flight PHP, Lumen, Slim 3 e Laravel oleh Codemarket (2016)
- Tutorial 1 Flight PHP - Instalación oleh absagg (2014)
- Tutorial 2 Flight PHP - Route parte 1 oleh absagg (2014)
Examples
Butuh permulaan yang cepat?
Anda memiliki dua opsi untuk memulai proyek Flight baru:
- Full Skeleton Boilerplate: Contoh yang lebih lengkap dengan pengontrol dan tampilan.
- Single File Skeleton Boilerplate: Satu file yang mencakup semua yang Anda butuhkan untuk menjalankan aplikasi Anda dalam satu file sederhana.
Contoh yang disumbangkan oleh komunitas:
- flightravel: FlightPHP dengan direktori Laravel, dengan alat PHP + GH Actions
- fleact - Kit pemula FlightPHP dengan integrasi ReactJS.
- flastro - Kit pemula FlightPHP dengan integrasi Astro.
- velt - Velt adalah templat pemula Svelte yang cepat dan mudah dengan backend FlightPHP.
Butuh Beberapa Inspirasi?
Meskipun ini tidak secara resmi disponsori oleh Tim Flight, ini bisa memberi Anda ide tentang cara menyusun proyek Anda sendiri yang dibangun dengan Flight!
- Decay - Flight v3 dengan HTMX dan SleekDB semuanya tentang zombie! (Demo)
- Flight Example Blog - Flight v3 dengan Middleware, Pengontrol, Active Record, dan Latte.
- Flight CRUD RESTful API - Proyek API CRUD sederhana menggunakan framework Flight, yang menyediakan struktur dasar bagi pengguna baru untuk dengan cepat menyiapkan aplikasi PHP dengan operasi CRUD dan konektivitas database. Proyek ini mendemonstrasikan cara menggunakan Flight untuk pengembangan API RESTful, menjadikannya alat belajar yang ideal untuk pemula dan kit pemula yang berguna bagi pengembang yang lebih berpengalaman.
- Flight School Management System - Flight v3
- Paste Bin with Comments - Flight v3
- Basic Skeleton App
- Example Wiki
- The IT-Innovator PHP Framework Application
- LittleEducationalCMS (Spanyol)
- API Halaman Kuning Italia
- Sistem Manajemen Konten Generik (dengan....sangat sedikit dokumentasi)
- Framework php kecil yang berbasis pada Flight dan medoo.
- Contoh Aplikasi MVC
Ingin Membagikan Contoh Anda Sendiri?
Jika Anda memiliki proyek yang ingin Anda bagikan, silakan kirim permintaan tarik untuk menambahkannya ke daftar ini!
Install/install
Instalasi
Unduh berkas
Pastikan Anda memiliki PHP terinstal di sistem Anda. Jika tidak, klik di sini untuk petunjuk tentang cara menginstalnya di sistem Anda.
Jika Anda menggunakan Composer, Anda dapat menjalankan perintah berikut:
composer require flightphp/core
ATAU Anda dapat mengunduh berkas langsung dan mengekstraknya ke direktori web Anda.
Konfigurasikan Server Web Anda
Server Pengembangan PHP Bawaan
Ini adalah cara termudah untuk memulai dan menjalankan aplikasi. Anda dapat menggunakan server bawaan untuk menjalankan aplikasi Anda dan bahkan menggunakan SQLite untuk basis data (selama sqlite3 terinstal di sistem Anda) dan tidak memerlukan banyak hal! Jalankan perintah berikut setelah PHP terinstal:
php -S localhost:8000
Kemudian buka browser Anda dan pergi ke http://localhost:8000
.
Jika Anda ingin membuat akar dokumen proyek Anda ke direktori yang berbeda (Mis: proyek Anda adalah ~/myproject
, tetapi akar dokumen Anda adalah ~/myproject/public/
), Anda dapat menjalankan perintah berikut setelah Anda berada di direktori ~/myproject
:
php -S localhost:8000 -t public/
Kemudian buka browser Anda dan pergi ke http://localhost:8000
.
Apache
Pastikan Apache sudah terinstal di sistem Anda. Jika tidak, cari tahu cara menginstal Apache di sistem Anda.
Untuk Apache, edit file .htaccess
Anda dengan yang berikut:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]
Catatan: Jika Anda perlu menggunakan flight di subdirektori, tambahkan baris
RewriteBase /subdir/
tepat setelahRewriteEngine On
.Catatan: Jika Anda ingin melindungi semua berkas server, seperti berkas db atau env. Tempatkan ini di file
.htaccess
Anda:
RewriteEngine On
RewriteRule ^(.*)$ index.php
Nginx
Pastikan Nginx sudah terinstal di sistem Anda. Jika tidak, cari tahu cara menginstal Nginx di sistem Anda.
Untuk Nginx, tambahkan yang berikut ke deklarasi server Anda:
server {
location / {
try_files $uri $uri/ /index.php;
}
}
Buat file index.php
Anda
<?php
// Jika Anda menggunakan Composer, persyaratan autoloader.
require 'vendor/autoload.php';
// jika Anda tidak menggunakan Composer, muat kerangka kerja secara langsung
// require 'flight/Flight.php';
// Kemudian tetapkan rute dan tetapkan fungsi untuk menangani permintaan.
Flight::route('/', function () {
echo 'hello world!';
});
// Akhirnya, mulai kerangka kerja.
Flight::start();
Instalasi PHP
Jika Anda sudah memiliki php
terinstal di sistem Anda, silakan lewati petunjuk ini dan lanjut ke bagian unduh
macOS
Menginstal PHP menggunakan Homebrew
-
Instal Homebrew (jika belum terinstal):
- Buka Terminal dan jalankan:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
- Buka Terminal dan jalankan:
-
Instal PHP:
- Instal versi terbaru:
brew install php
- Untuk menginstal versi tertentu, misalnya, PHP 8.1:
brew tap shivammathur/php brew install shivammathur/php/php@8.1
- Instal versi terbaru:
-
Beralih antara versi PHP:
- Lepaskan versi saat ini dan tautkan versi yang diinginkan:
brew unlink php brew link --overwrite --force php@8.1
- Verifikasi versi yang diinstal:
php -v
- Lepaskan versi saat ini dan tautkan versi yang diinginkan:
Windows 10/11
Menginstal PHP secara manual
-
Unduh PHP:
- Kunjungi PHP untuk Windows dan unduh versi terbaru atau versi tertentu (misalnya, 7.4, 8.0) sebagai berkas zip yang tidak aman untuk thread.
-
Ekstrak PHP:
- Ekstrak berkas zip yang diunduh ke
C:\php
.
- Ekstrak berkas zip yang diunduh ke
-
Tambahkan PHP ke PATH sistem:
- Masuk ke Properti Sistem > Variabel Lingkungan.
- Di bawah variabel sistem, cari Path dan klik Edit.
- Tambahkan jalur
C:\php
(atau di mana pun Anda mengekstrak PHP). - Klik OK untuk menutup semua jendela.
-
Konfigurasi PHP:
- Salin
php.ini-development
kephp.ini
. - Edit
php.ini
untuk mengonfigurasi PHP sesuai kebutuhan (misalnya, mengaturextension_dir
, mengaktifkan ekstensi).
- Salin
-
Verifikasi instalasi PHP:
- Buka Command Prompt dan jalankan:
php -v
- Buka Command Prompt dan jalankan:
Menginstal Beberapa Versi PHP
-
Ulangi langkah di atas untuk setiap versi, menempatkan masing-masing di direktori terpisah (misalnya,
C:\php7
,C:\php8
). -
Beralih antara versi dengan menyesuaikan variabel PATH sistem untuk menunjuk ke direktori versi yang diinginkan.
Ubuntu (20.04, 22.04, dll.)
Menginstal PHP menggunakan apt
-
Perbarui daftar paket:
- Buka Terminal dan jalankan:
sudo apt update
- Buka Terminal dan jalankan:
-
Instal PHP:
- Instal versi PHP terbaru:
sudo apt install php
- Untuk menginstal versi tertentu, misalnya, PHP 8.1:
sudo apt install php8.1
- Instal versi PHP terbaru:
-
Instal modul tambahan (opsional):
- Misalnya, untuk menginstal dukungan MySQL:
sudo apt install php8.1-mysql
- Misalnya, untuk menginstal dukungan MySQL:
-
Beralih antara versi PHP:
- Gunakan
update-alternatives
:sudo update-alternatives --set php /usr/bin/php8.1
- Gunakan
-
Verifikasi versi yang diinstal:
- Jalankan:
php -v
- Jalankan:
Rocky Linux
Menginstal PHP menggunakan yum/dnf
-
Aktifkan repositori EPEL:
- Buka Terminal dan jalankan:
sudo dnf install epel-release
- Buka Terminal dan jalankan:
-
Instal repositori Remi:
- Jalankan:
sudo dnf install https://rpms.remirepo.net/enterprise/remi-release-8.rpm sudo dnf module reset php
- Jalankan:
-
Instal PHP:
- Untuk menginstal versi default:
sudo dnf install php
- Untuk menginstal versi tertentu, misalnya, PHP 7.4:
sudo dnf module install php:remi-7.4
- Untuk menginstal versi default:
-
Beralih antara versi PHP:
- Gunakan perintah modul
dnf
:sudo dnf module reset php sudo dnf module enable php:remi-8.0 sudo dnf install php
- Gunakan perintah modul
-
Verifikasi versi yang diinstal:
- Jalankan:
php -v
- Jalankan:
Catatan Umum
- Untuk lingkungan pengembangan, penting untuk mengonfigurasi pengaturan PHP sesuai dengan kebutuhan proyek Anda.
- Saat beralih antara versi PHP, pastikan semua ekstensi PHP yang relevan terinstal untuk versi tertentu yang ingin Anda gunakan.
- Restart server web Anda (Apache, Nginx, dll.) setelah beralih versi PHP atau memperbarui konfigurasi untuk menerapkan perubahan.
Guides
Panduan
Flight PHP dirancang untuk menjadi sederhana namun kuat, dan panduan kami akan membantu Anda membangun aplikasi dunia nyata langkah demi langkah. Tutorial praktis ini membawa Anda melalui proyek lengkap untuk menunjukkan bagaimana Flight dapat digunakan secara efektif.
Panduan Resmi
Membangun Blog
Pelajari cara membuat aplikasi blog fungsional dengan Flight PHP. Panduan ini membawa Anda melalui:
- Menyusun struktur proyek
- Bekerja dengan template menggunakan Latte
- Mengimplementasikan rute untuk pos
- Menyimpan dan mengambil data
- Menangani pengiriman formulir
- Penanganan kesalahan dasar
Tutorial ini sempurna untuk pemula yang ingin melihat bagaimana semua bagian cocok bersama dalam aplikasi nyata.
Panduan Tidak Resmi
Meskipun panduan ini tidak secara resmi dikelola oleh tim Flight, mereka adalah sumber daya berharga yang dibuat oleh komunitas. Mereka mencakup berbagai topik dan kasus penggunaan, memberikan wawasan tambahan tentang penggunaan Flight PHP.
Membuat API RESTful dengan Flight Framework
Panduan ini membawa Anda melalui cara membuat API RESTful menggunakan framework Flight PHP. Ini mencakup dasar-dasar pengaturan API, mendefinisikan rute, dan mengembalikan respons JSON.
Membangun Blog Sederhana
Panduan ini membawa Anda melalui cara membuat blog dasar menggunakan framework Flight PHP. Sebenarnya, ini memiliki 2 bagian: satu untuk mencakup dasar-dasar dan yang lainnya untuk mencakup topik yang lebih maju dan perbaikan untuk blog yang siap digunakan di produksi.
- Membangun Blog Sederhana dengan Flight - Bagian 1 - Memulai dengan blog sederhana.
- Membangun Blog Sederhana dengan Flight - Bagian 2 - Memperbaiki blog untuk produksi.
Membangun API Pokémon di PHP: Panduan untuk Pemula
Panduan menyenangkan ini membawa Anda melalui cara membuat API Pokémon sederhana menggunakan Flight PHP. Ini mencakup dasar-dasar pengaturan API, mendefinisikan rute, dan mengembalikan respons JSON.
Kontribusi
Ada ide untuk panduan? Menemukan kesalahan? Kami menyambut kontribusi! Panduan kami dikelola dalam repositori dokumentasi FlightPHP.
Jika Anda telah membuat sesuatu yang menarik dengan Flight dan ingin membagikannya sebagai panduan, silakan ajukan permintaan tarik. Membagikan pengetahuan Anda membantu komunitas Flight berkembang.
Mencari Dokumentasi API?
Jika Anda mencari informasi spesifik tentang fitur dan metode inti dari Flight, periksa bagian Belajar dari dokumentasi kami.