Elemental adalah kerangka kerja PHP yang dikembangkan dari awal untuk pengalaman pengkodean yang dinamis dan ramah pengguna. Ini menggabungkan fitur -fitur seperti injeksi ketergantungan dan mengikuti arsitektur MVC untuk merampingkan pengembangan web dan meningkatkan organisasi kode. Direkayasa dengan hasrat untuk kesederhanaan dan fleksibilitas, itu mengundang pengembang ke ranah di mana mereka dapat menggunakan kontrol yang tak tertandingi dan mendapatkan pemahaman yang mendalam tentang alat yang mereka miliki.
Untuk memamerkan kemampuan Elemental, platform yang bekerja sepenuhnya bernama Inkwell telah dikembangkan menggunakan Elemental. Inkwell adalah ruang unik yang didedikasikan untuk esensi murni dari bercerita. Sejalan dengan tujuan Elemental untuk tidak memiliki dependensi eksternal, Inkwell telah dibuat menggunakan HTML biasa, CSS, JS, dan PHP saja.
Jangan ragu untuk mempelajari platform langsung dan basis kode yang sesuai. Jelajahi fitur Inkwell untuk memahami bagaimana unsur dapat dimanfaatkan untuk proyek Anda sendiri.
Lihat inspirasi di balik penciptaan Elemental .
Elemental telah dirancang dengan tujuan tidak ada string yang terpasang. Tidak ada dependensi pada perpustakaan atau kerangka kerja eksternal. Tujuannya adalah untuk memberi para pengembang rasa kontrol yang tulus - pintu terbuka untuk mengeksplorasi dan memahami hal -hal magis secara mandiri yang memberi kekuatan kerangka kerja.
Tujuan menyeluruh? Biarkan pengembang sepenuhnya merangkul dan memanfaatkan keanggunan abstraksi yang kuat seperti wadah DI, ORM, Middleware, dan banyak lagi. Tapi inilah kickernya - Elemental tidak hanya mengarahkan jalan. Ini memberi Anda kunci untuk mengungkap misteri, memberdayakan Anda untuk mengeksplorasi bagaimana abstraksi ini diletakkan dalam kode.
Bahkan, Anda didorong tidak hanya untuk mengikuti jalan tetapi untuk menjelajah dari jalur yang dipukuli. Selami basis kode, membedah abstraksi, dan pahami pekerjaan batin mereka. Jangan ragu untuk mengubah dan bereksperimen, karena Elemental bukan hanya kerangka kerja - ini adalah undangan terbuka untuk membentuk dan membentuk alat yang Anda inginkan. Karena pengkodean seharusnya tidak menjadi labirin; itu harus menjadi perjalanan. Mari kita lakukan perjalanan itu bersama.
Tidak seperti kerangka kerja lainnya, Elemental tidak mengandalkan pustaka komposer atau eksternal. Ini sesederhana mengkloning repositori dan memulai dengan PHP yang baik dipasang di sistem Anda.
Buka terminal Anda dan jalankan perintah berikut:
git clone https://github.com/aneesmuzzafer/elemental.gitJangan khawatir tentang manajer paket atau dependensi - Elemental dibangun dari awal untuk membebaskan Anda dari masalah tersebut.
Bagi mereka yang lebih suka rute komposer, membuat aplikasi elemental baru hanyalah sebuah perintah yang jauh:
composer create-project fragment/elemental sample-app Ini akan menghasilkan proyek dengan file composer.json .
Setelah proyek Anda siap, kickstart server pengembangan lokal Elemental dengan perintah ignite menggunakan mesin baris perintah kami, lilin :
cd sample-app
php candle igniteVoila! Aplikasi Anda sekarang dapat diakses di http://127.0.0.1:8000.
Kami telah mengurus pengaturan dasar sehingga Anda dapat fokus pada keajaiban.
Biarkan pesona dimulai!
Fitur terpenting dari unsur adalah wadah injeksi ketergantungannya yang digunakannya untuk mengelola ketergantungan kelas dan melakukan injeksi ketergantungan.
Injeksi ketergantungan adalah pola desain dalam pengembangan perangkat lunak yang berkaitan dengan bagaimana komponen mendapatkan ketergantungan mereka. Dalam sistem tradisional, kelas bertanggung jawab untuk menciptakan ketergantungannya sendiri. Dengan DI, tanggung jawab menciptakan dan memberikan ketergantungan dipindahkan di luar kelas. Alih -alih kelas yang menciptakan ketergantungannya, mereka "disuntikkan" ke dalam kelas dari sumber eksternal.
Di membantu dalam mencapai kode yang digabungkan secara longgar dan lebih dapat dipelihara. Ini mempromosikan pemisahan kekhawatiran dengan memungkinkan setiap kelas untuk fokus pada fungsi spesifiknya tanpa khawatir tentang cara membuat atau mendapatkan ketergantungannya.
Injeksi ketergantungan adalah implementasi spesifik dari konsep yang lebih luas yang dikenal sebagai inversi kontrol (IOC). IOC mewakili paradigma desain di mana aliran kontrol suatu program terbalik atau diserahkan ke entitas eksternal, wadah atau kerangka kerja.
Di Elemental, ketika Anda menggunakan Injeksi Ketergantungan (DI), jika suatu kelas tidak bergantung pada kelas lain atau hanya bergantung pada kelas konkret (bukan antarmuka abstrak), Anda tidak perlu secara eksplisit memberi tahu wadah DI cara membuat instance dari kelas itu. Wadah DI akan secara otomatis mengetahuinya.
Wadah akan berusaha membuat instance kelas, dan jika kelas itu memiliki ketergantungan pada kelas lain, wadah akan secara rekursif mencoba untuk menyelesaikan dependensi tersebut juga. Proses ini berlanjut sampai semua kelas yang diperlukan berhasil diselesaikan. Jadi, Anda tidak perlu secara manual menentukan cara membuat setiap kelas - wadah DI mengurusnya untuk Anda.
<?php
class MailService {
public function __construct ( private MailerAgent $ mailer ) {
}
}
// Inside some other class
class UserController {
public function sendMail ( MailService $ mailService )
{
$ mailService -> sendMail ();
}
} Di sini, dengan tipe-menampilkan MailService di dalam argumen metode, Elemental dapat menyelesaikan kelas dan membuat instance dari kelas ini dan meneruskannya ke sendMail sehingga Anda dapat menggunakannya tanpa khawatir tentang dependensi apa yang diperlukan oleh kelas MailService . Seperti yang Anda lihat, MailService itu sendiri tergantung pada beberapa MailerAgent kelas lainnya, namun, Elemental berusaha menyelesaikan kelas MailerAgent di belakang layar, meneruskannya ke MailService saat membuat contohnya dan memberikan contoh itu untuk Anda gunakan.
"Jadi, di mana semacam itu akan menyuntikkan dependensi hanya dengan tipe-menangani nama kelas bekerja di Elemental?" Semua fungsi constructor kelas, semua controller methods , dan metode handle kelas pembuatan perintah.
Di belakang layar, Elemental menyelesaikan kelas atau antarmuka menjadi instance konkret dengan melihat ikatan apa pun yang telah terdaftar. Dengan kata lain, untuk secara eksplisit memberi tahu kerangka kerja tentang cara menyelesaikan contoh kelas atau antarmuka tertentu, Anda perlu mendaftarkan ikatan kelas atau antarmuka tersebut menggunakan metode bind pada instance Application , meneruskan kelas atau antarmuka yang ingin kami daftarkan bersama dengan penutupan yang mengembalikan contoh kelas:
app ()-> bind (MailService::class, function () {
// Run some logic, for example, decide on the mail agent to be passed to its constructor depending on some factors.
return new MailService ( app ()-> make (MailAgent::class));
});Perhatikan bahwa Anda biasanya perlu mengikat kelas hanya ketika Anda perlu menjalankan beberapa logika tambahan untuk menyelesaikan kelas, atau Anda perlu mengikat antarmuka ke implementasi konkret. Jika tidak, Elemental akan menyelesaikan kelas tanpa secara eksplisit mengharuskan Anda untuk mengikatnya.
Metode singleton mengikat kelas atau antarmuka dengan wadah, memastikan bahwa itu diselesaikan hanya sekali. Setelah resolusi awal, setiap panggilan berikutnya ke wadah untuk ikatan yang sama akan mengembalikan instance objek yang sama.
app ()-> singleton (DatabaseConnection::class, function () {
return new DatabaseConnection ( ' localhost ' , ' username ' , ' password ' );
});
// Later in the code
$ databaseConnection1 = app ()-> make (DatabaseConnection::class);
$ databaseConnection2 = app ()-> make (DatabaseConnection::class);
// $databaseConnection1 and $databaseConnection2 will reference the same instance Meskipun baik -baik saja untuk mendaftarkan ikatan di mana saja di aplikasi, sering kali diperlukan untuk mengikatnya saat aplikasi bootstrap, sehingga komponen aplikasi lain dapat mulai menggunakannya. Elemental menyediakan tempat khusus untuk mendaftarkan semua binding aplikasi dan melakukan logika bootstrap lain yang diperlukan oleh aplikasi Anda. Ini adalah AppBootstrapAppServiceProvider . Penyedia layanan aplikasi berisi register dan metode boot .
Dalam metode register , Anda harus mengikat hal -hal ke dalam wadah injeksi ketergantungan. Namun, Anda tidak boleh mencoba menyelesaikan ikatan apa pun. rute, atau jalankan fungsionalitas lain dalam metode register . Kalau tidak, Anda dapat secara tidak sengaja menggunakan layanan di dalam wadah yang belum dimuat.
Metode ini dipanggil setelah semua penyedia layanan lainnya telah terdaftar, memberikan akses ke semua layanan yang terdaftar oleh kerangka kerja. Logika inisialisasi apa pun yang ingin Anda jalankan harus ditempatkan di sini.
<?php
namespace App Bootstrap ;
use App Services Auth ;
class AppServiceProvider
{
public function register (): void
{
app ()-> singleton (Auth::class, function () {
return new Auth ();
});
}
public function boot (): void
{
// Additional initialization logic can be placed here
}
} Anda dapat menggunakan metode make untuk menyelesaikan instance kelas dari wadah DI. Metode make pada contoh aplikasi menerima nama kelas atau antarmuka yang ingin Anda selesaikan:
use App Services MailService ;
$ mailService = app ()-> make (MailService::class); Anda juga dapat memperoleh instance aplikasi menggunakan instance metode statis secara langsung di kelas Application .
use Core Main Application ;
use App Services MailService ;
$ mailService = Application:: instance ()-> make (MailService::class); Metode make sangat berguna ketika mencoba untuk menyelesaikan kelas dari dalam komponen kode di mana tidak praktis untuk menyuntikkan ketergantungan menggunakan tipe-hinting. Dalam skenario seperti itu, Anda dapat secara eksplisit meminta wadah injeksi ketergantungan aplikasi untuk menyelesaikan instance untuk Anda.
Rute didefinisikan dalam file approutes.php , memungkinkan pengembang untuk dengan mudah mendaftarkan berbagai rute untuk menangani berbagai permintaan HTTP.
Rute didaftarkan dengan memohon metode yang relevan pada fasad rute, seperti Route::get() , dan melibatkan menentukan pola URI sebagai argumen pertama. Argumen kedua dapat berupa penutupan atau array yang mendefinisikan pengontrol dan metode yang bertanggung jawab untuk menangani permintaan tersebut.
Misalnya:
<?php
use App Controllers AuthController ;
use Core Facade Route ;
Route:: get ( " /settings " , function () {
// handling logic goes here
});
Route:: post ( " /register " , [AuthController::class, " register " ]);Setiap kali permintaan URI dicocokkan, metode penutupan atau pengontrol yang sesuai dieksekusi, dan respons dihasilkan dan dikirim kembali ke browser.
Anda dapat mendaftarkan rute yang menanggapi kata kerja HTTP menggunakan metode berikut:
Route::get($uri, $callback);Route::post($uri, $callback);Route::put($uri, $callback);Route::patch($uri, $callback);Route::delete($uri, $callback);Route::options($uri, $callback); Terkadang Anda perlu menangkap segmen URI di dalam rute Anda. Misalnya, Anda mungkin perlu menangkap ID pengguna dari URL. Anda dapat melakukannya dengan mendefinisikan parameter rute:
Route:: get ( ' /user/{id} ' , function ( string $ id ) {
return ' User ' . $ id ;
});
Route:: get ( " /story/{id} " , function ( $ id ) { /*...*/ });Anda dapat mendefinisikan sebanyak mungkin parameter rute seperti yang dipersyaratkan oleh rute Anda:
Route:: post ( " story/edit/{id} " , [StoryController::class, " edit " ]);
Route:: get ( " story/{story_id}/comment/{comment_id} " , [StoryController::class, " comment " ]);Ini akan diteruskan ke metode pengontrol juga.
Elemental dengan mulus menangani injeksi dependensi yang diperlukan untuk metode pengontrol Anda. Ini memungkinkan Anda untuk menentukan ketergantungan yang diperlukan oleh rute Anda di tanda tangan callback menggunakan tipe-hinting. Elemental menangani penyelesaian otomatis dan menyuntikkan dependensi yang dinyatakan ke dalam panggilan balik.
Misalnya, jika Anda mengetikkan CoreRequestRequest di dalam panggilan balik, Elemental memastikan bahwa permintaan HTTP saat ini secara otomatis disuntikkan ke dalam panggilan balik rute Anda:
<?php
use Core Request Request ;
Route:: get ( ' /users ' , function ( Request $ request ) {
// ...
});Anda dapat meletakkan dependensi yang diketik dan parameter rute dalam urutan apa pun.
Saat Anda melewati ID model sebagai parameter ke rute atau tindakan pengontrol, pendekatan tipikal melibatkan permintaan database untuk mengambil model yang sesuai berdasarkan ID itu. Elemental menyederhanakan proses ini melalui pengikatan model rute, menawarkan cara yang nyaman untuk secara otomatis menyuntikkan contoh model langsung ke rute Anda.
Misalnya, alih -alih menyuntikkan ID pengguna ke dalam rute Anda, Anda memiliki opsi untuk menyuntikkan seluruh contoh model pengguna yang sesuai dengan ID yang diberikan.
Dalam konteks rute atau tindakan pengontrol, model didefinisikan menggunakan nama variabel tipe yang cocok yang cocok dengan segmen tertentu dalam rute. Misalnya:
use App Models User ;
Route:: get ( ' /users/{user} ' , function ( User $ user ) {
return $ user -> email ;
}); Terkadang Anda mungkin ingin menyelesaikan model menggunakan kolom selain id . Untuk melakukannya, Anda dapat menentukan kolom dalam definisi parameter rute:
use App Models User ;
Route:: get ( ' /users/{user:email} ' , function ( User $ user ) {
return $ user ;
});Dalam skenario ini, Elemental akan dengan mulus menyuntikkan contoh model yang memiliki email yang cocok dengan nilai yang sesuai dari permintaan URI.
Tentu saja, pengikatan model rute juga bekerja dengan metode pengontrol.
Jika contoh model pencocokan tidak ditemukan dalam database, ModelNotFoundException akan dilemparkan oleh aplikasi. Anda dapat menangani pengecualian tersebut dan mengendalikan perilaku pengecualian tersebut dan lainnya yang dilemparkan oleh aplikasi di kelas ExceptionsHandler . Lebih lanjut tentang itu nanti.
Menggunakan Route::fallback Metode, Anda dapat mendefinisikan rute yang akan dieksekusi ketika tidak ada rute lain yang cocok dengan permintaan yang masuk.
Route:: fallback ( function () {
// ...
}); Perintah route:list Candle akan memberikan daftar semua rute yang ditentukan dalam aplikasi:
php candle route:list Daripada mengkonsolidasikan semua logika penanganan permintaan dalam penutupan dalam file rute Anda, pertimbangkan untuk menyusun perilaku ini melalui kelas "pengontrol". Pengontrol memungkinkan Anda untuk mengatur logika penanganan permintaan terkait ke dalam kelas kohesif. Misalnya, kelas UserController dapat mengelola berbagai permintaan yang masuk yang terkait dengan pengguna, seperti menampilkan, membuat, memperbarui, dan menghapus pengguna. Kelas pengontrol ini disimpan secara konvensional di direktori app/Controllers .
Untuk menghasilkan pengontrol baru, Anda dapat menjalankan perintah build:controller lilin.
php candle build:controller UserController Ini akan menghasilkan file baru bernama "usercontroller.php" di dalam direktori app/Controllers .
Pengontrol mungkin memiliki sejumlah metode publik yang akan menanggapi permintaan HTTP yang masuk:
<?php
use App Services Auth ;
namespace App Controllers ;
class AuthController
{
public function showRegister ()
{
return view ( " Register " )-> withLayout ( " layouts.DashboardLayout " );
}
public function logout ()
{
Auth:: logout ();
redirect ( " / " );
}
}Setelah membuat kelas pengontrol dan metodenya, Anda dapat menentukan rute ke metode pengontrol sebagai berikut:
use App Controllers UserController ;
Route:: get ( " /register " , [AuthController::class, " showRegister " ]); Ketika permintaan yang diterima cocok dengan rute yang ditunjuk URI, metode showRegister dalam kelas AppControllersUserController akan dipanggil, dan metode ini akan menerima parameter rute yang sesuai.
Wadah Layanan Elemental bertanggung jawab untuk menyelesaikan contoh semua pengontrol. Akibatnya, Anda dapat menggunakan tipe-penampilan dalam konstruktor pengontrol Anda untuk menentukan dependensi yang mungkin diperlukan. Ketergantungan yang dinyatakan akan secara otomatis diselesaikan dan disuntikkan ke instance controller
<?php
namespace App Controllers ;
use Core Database Database ;
class UserController
{
/**
* Create a new controller instance.
*/
public function __construct (
public Database $ db ,
) {}
} Selain menyuntikkan ketergantungan melalui konstruktor, Anda juga dapat menggunakan tipe-menampilkan ketergantungan dalam metode pengontrol Anda. Kasus penggunaan umum untuk injeksi metode adalah menyuntikkan CoreRequestRequest atau instance layanan apa pun ke dalam metode pengontrol Anda:
Buat dan kelola pengontrol untuk menangani permintaan secara efektif.
<?php
namespace App Controllers ;
use Core Request Request ;
use App Services Auth ;
class StoryController
{
public function create ( Request $ request )
{
$ data = $ request -> data ();
$ user = Auth:: user ();
$ story = Story:: create ([...]);
return redirect ( " /story/ $ story -> id " );
}
}f Metode pengontrol Anda mengantisipasi input dari parameter rute, Anda memiliki fleksibilitas untuk mendaftarkan argumen Anda dalam urutan apa pun. Misalnya, pertimbangkan definisi rute berikut:
Route:: post ( " story/update/{id} " , [StoryController::class, " update " ]); Anda masih dapat mengetikkan CoreRequestRequest dan mengakses parameter id Anda dengan mendefinisikan metode pengontrol Anda sebagai berikut:
<?php
namespace App Controllers ;
use Core Request Request ;
class StoryController
{
public function update ( string $ id , Request $ request )
{
// Update $story
return redirect ( " /story/ $ story -> id " );
}
} Kelas CoreRequestRequest di Elemental menawarkan pendekatan berorientasi objek untuk terlibat dengan permintaan HTTP ini yang dikelola oleh aplikasi Anda. Ini memfasilitasi pengambilan input, cookie, dan file yang dikirimkan bersama dengan permintaan tersebut.
Untuk memperoleh instance permintaan HTTP saat ini melalui injeksi ketergantungan, Anda dapat memanfaatkan tipe-penempatan untuk kelas CoreRequestRequest dalam penutupan rute atau metode pengontrol Anda. Wadah Layanan akan secara otomatis menyuntikkan instance permintaan yang masuk.
<?php
namespace App Controllers ;
use App Models Category ;
use Core Request Request ;
class CategoryController
{
public function store ( Request $ request )
{
$ name = $ request -> data ()[ " name " ];
$ category = Category:: where ([ " name " => $ name ]);
if ( $ category ) {
return view ( " Category " , [ " categories " => Category:: all (), " msg " => " Category already exists! " ])-> withLayout ( " layouts.DashboardLayout " );
}
Category:: create ( $ request -> data ());
redirect ( " /category " );
}
}Wadah layanan akan secara otomatis menyuntikkan permintaan yang masuk ke penutupan rute juga.
Jika metode pengontrol Anda mengantisipasi input dari parameter rute, Anda memiliki fleksibilitas untuk mendaftar argumen Anda dalam urutan apa pun. Misalnya, pertimbangkan definisi rute berikut:
Route:: post ( " story/update/{id} " , [StoryController::class, " update " ]); Anda masih dapat mengetikkan CoreRequestRequest dan mengakses parameter id Anda dengan mendefinisikan metode pengontrol Anda sebagai berikut:
<?php
namespace App Controllers ;
use Core Request Request ;
class StoryController
{
public function update ( string $ id , Request $ request )
{
// Update $story
return redirect ( " /story/ $ story -> id " );
}
} Anda dapat memperoleh semua data input permintaan yang masuk sebagai array menggunakan metode data() . Metode ini dapat digunakan terlepas dari apakah permintaan yang masuk berasal dari formulir HTML atau merupakan permintaan XHR:
$ data = $ request -> data (); Anda dapat mengakses semua input pengguna dari instance Request Anda tanpa khawatir tentang kata kerja HTTP mana yang digunakan untuk permintaan tersebut. Terlepas dari kata kerja HTTP, metode data dapat digunakan untuk mengambil input pengguna:
$ name = $ request -> data ()[ " name " ]; Instance CoreRequestRequest menyediakan berbagai metode untuk memeriksa permintaan HTTP yang masuk. Mari kita bahas beberapa metode terpenting di bawah ini.
Anda dapat mengambil header permintaan dari instance CoreRequestRequest menggunakan metode headers .
$ headers = $ request -> headers (); Anda dapat mengambil metode permintaan dengan memanggil method pada instance CoreRequestRequest .
$ method = $ request -> method (); Anda dapat mengambil permintaan URI dari instance CoreRequestRequest menggunakan metode uri .
$ uri = $ request -> uri (); Anda dapat mengambil cookie permintaan dari instance CoreRequestRequest menggunakan metode cookies .
$ cookies = $ request -> cookies (); Anda dapat mengambil konten mentah dari instance CoreRequestRequest menggunakan metode rawContent .
$ content = $ request -> rawContent ();Berhati -hatilah saat berhadapan dengan konten mentah dari suatu permintaan.
Anda dapat mengambil file dari instance CoreRequestRequest menggunakan metode files .
$ files = $ request -> files (); Metode ip dapat digunakan untuk mengambil alamat IP klien yang mengajukan permintaan ke aplikasi Anda:
$ ipAddress = $ request -> ip (); Metode port dapat digunakan untuk mengambil alamat port klien yang mengajukan permintaan ke aplikasi Anda:
$ port = $ request -> port (); Anda dapat mengambil tipe konten dari instance CoreRequestRequest menggunakan metode contentType .
$ contentType = $ request -> contentType (); Anda dapat mengambil string kueri permintaan menggunakan metode queryString .
$ query = $ request -> queryString (); Anda dapat mengambil konten teks dari permintaan menggunakan metode text asalkan tipe konten diatur ke text/plain
$ text = $ request -> text (); Anda dapat mengambil konten JS dari permintaan menggunakan metode js asalkan tipe konten diatur ke application/javascript
$ js = $ request -> js (); Anda dapat mengambil konten HTML dari permintaan menggunakan metode html asalkan tipe konten diatur ke text/html
$ js = $ request -> html (); Anda dapat mengambil konten JSON dari permintaan menggunakan metode json asalkan tipe konten diatur ke application/json The $request->data() mengembalikan semua data JSON yang diteruskan ke permintaan. Namun,
$ jsonData = $ request -> json (); $request->data() berisi semua data JSON bersama dengan input yang dilewati Params kueri dalam permintaan. Namun, $request->json() dapat digunakan untuk mengambil hanya konten JSON.
Anda dapat mengambil konten XML dari permintaan menggunakan metode xml asalkan tipe konten diatur ke application/json
$ xmlData = $ request -> xml ();Setiap rute dan pengontrol diharapkan menghasilkan respons untuk pengiriman ke browser pengguna. Elemental menawarkan berbagai metode untuk menghasilkan respons. Bentuk respons paling sederhana melibatkan pengembalian string langsung dari rute atau pengontrol. Kerangka kerja ini akan dengan mulus mengubah string ini menjadi respons HTTP yang lengkap.
Route:: get ( ' / ' , function () {
return ' Hello World ' ;
});Selain mengembalikan string dari rute dan pengontrol Anda, Anda juga dapat mengembalikan array atau objek. Kerangka kerja akan secara otomatis mengubahnya menjadi respons JSON:
Route:: get ( ' / ' , function () {
return [ 1 , 2 , 3 ];
}); Biasanya, Anda tidak akan hanya mengembalikan string atau array langsung dari tindakan rute Anda. Sebaliknya, Anda akan sering mengembalikan instance lengkap dari CoreResponseResponse atau tampilan.
Mengembalikan instance Response penuh memungkinkan Anda untuk menyesuaikan kode dan header status HTTP respons. Anda dapat menyuntikkan instance respons dengan tipe-menangani instance respons di dalam pengontrol atau penutupan rute Anda.
use Core Response Response ;
Route:: get ( ' /home ' , function ( Response $ response ) {
$ response -> setHeader ( " content-type " , " text/plain " )
-> setStatusCode ( 200 )
-> setContent ( " Hello World " );
return $ response ;
}); Anda tentu saja dapat mengembalikan view dari pengontrol. Namun, jika Anda membutuhkan kendali atas status dan header respons tetapi juga perlu mengembalikan view sebagai konten respons, Anda dapat melakukannya sebagai berikut:
use Core Response Response ;
class UserController {
public function register ( Response $ response ){
$ response -> setHeader ( " x-is_register " , " true " );
return view ( " Register " );
}
}Ini akan secara otomatis mengatur header pada respons tampilan yang akan dikirim ke browser.
Perlu diingat bahwa sebagian besar metode respons dapat diikat, memungkinkan untuk konstruksi lancar dari instance respons.
Anda dapat mengatur konten respons dengan menggunakan metode setContent pada instance respons.
$ response -> setContent ( " ... " ); Namun, jika Anda ingin menambahkan konten respons, Anda dapat melakukannya dengan menggunakan metode appendContent pada instance respons.
$ response -> appendContent ( " ... " ); Anda dapat mengatur header pada instance respons dengan menggunakan metode setHeader
$ response -> setHeader ( " content-type " , " text/plain " ); Namun, jika Anda ingin mengatur beberapa header secara bersamaan, Anda dapat melakukannya dengan menggunakan metode setHeaders dan melewati berbagai header.
$ response -> setHeaders ([ " content-type " => " text/html " , ...]); Anda dapat secara langsung mengatur kode status respons dengan menggunakan metode setHeader pada instance respons.
$ response -> setStatusCode ( 301 );Teks status akan ditetapkan secara default untuk kode status umum.
Anda dapat menghasilkan respons pengalihan yang berisi header yang tepat yang diperlukan untuk mengarahkan pengguna ke URL lain dengan memohon metode statis redirect pada kelas CoreResponseResponse .
use Core Response Response ;
Route:: get ( ' /dashboard ' , function () {
return Response:: redirect ( ' home/dashboard ' );
}); Namun, untuk kesederhanaan metode helper redirect() juga tersedia secara global untuk mencapai fungsionalitas yang sama.
use Core Response Response ;
Route:: post ( ' /story/create ' , function () {
if (! $ someCondition )
return redirect ( ' /story ' , 204 );
}); Anda juga dapat menghasilkan respons JSON dengan memanggil metode statis JSON pada kelas CoreResponseResponse . Data yang diteruskan ke metode ini akan dikonversi ke JSON yang tepat. Anda juga dapat secara opsional meneruskan kode status dan header array sebagai argumen kedua dan ketiga untuk fungsi tersebut.
use Core Response Response ;
Route:: post ( ' /post ' , function () {
$ post = ( . . . );
return Response:: JSON ( $ post , 201 , [ " header " => " value " ]);
});Middleware menawarkan mekanisme yang nyaman untuk memeriksa dan memfilter permintaan HTTP yang masuk ke aplikasi Anda. Misalnya, Anda dapat mengembangkan middleware untuk memvalidasi status otentikasi pengguna aplikasi Anda. Jika pengguna tidak diautentikasi, middleware akan mengarahkan mereka ke layar login. Sebaliknya, jika pengguna diautentikasi, middleware akan mengizinkan permintaan untuk maju lebih dalam ke aplikasi.
Anda memiliki fleksibilitas untuk membuat middleware tambahan untuk menjalankan beragam tugas di luar otentikasi. Sebagai ilustrasi, middleware logging dapat merekam semua permintaan yang masuk ke aplikasi Anda. Komponen middleware ini ditempatkan di dalam direktori app/middlewares .
Untuk membuat middleware baru, gunakan perintah build:middleware Candle:
php candle build:middleware IsAuthenticated Melaksanakan perintah ini akan menghasilkan kelas middleware baru bernama "isAuthenticated" di direktori app/middlewares . Di dalam kelas ini, handle bernama dibuat di mana Anda dapat mengartikulasikan logika untuk middleware.
Di sini, kami hanya akan mengizinkan akses ke rute jika pengguna diautentikasi, jika tidak, kami akan mengarahkan kembali pengguna kembali ke login URI:
<?php
namespace App Middlewares ;
use App Services Auth ;
use Closure ;
use Core Request Request ;
class IsAuthenticated
{
public function handle ( Request $ request , Closure $ next )
{
if (!( /* authentication logic */ )) {
return redirect ( " /login " );
}
return $ next ( $ request );
}
} Untuk meneruskan permintaan lebih dalam ke aplikasi, Anda harus menghubungi panggilan balik $next dengan $request .
Pertimbangkan Middleware sebagai urutan "lapisan" yang meminta HTTP melintasi sebelum mencapai aplikasi Anda. Setiap lapisan memiliki kemampuan untuk meneliti permintaan dan berpotensi menolaknya.
Tentu saja, middleware dapat melakukan tugas sebelum atau setelah meneruskan permintaan lebih dalam ke aplikasi. Misalnya, middleware ini akan melakukan tugasnya setelah permintaan ditangani oleh aplikasi:
<?php
namespace App Middlewares ;
use Closure ;
use Core Request Request ;
class AfterMiddleware
{
public function handle ( Request $ request , Closure $ next )
{
$ response = $ next ( $ request );
// Perform action
return $ response ;
}
} Jika Anda ingin menetapkan middleware ke rute tertentu, Anda dapat memohon metode middleware saat mendefinisikan rute:
Route:: get ( ' /profile ' , function () {
// ...
})-> middleware (IsAuthenticated::class); Anda dapat menetapkan beberapa middleware ke rute dengan meneruskan array nama middleware ke metode middleware :
Route:: get ( ' / ' , function () {
// ...
})-> middleware ([First::class, Second::class]); Anda dapat menugaskan Middlewares ke grup rute dengan meneruskan array nama middleware ke atribut middlewares saat mendefinisikan grup:
Route:: group ([ " middleware " => [HasSession::class]], function () {
Route:: get ( " / " , [StoryController::class, " index " ]);
Route:: get ( " /story/{story} " , [StoryController::class, " show " ]);
}); Anda dapat menggunakan kelompok rute bersarang untuk menggabungkan tudung dengan kelompok induknya. Dalam contoh selanjutnya, middleware "Hassession" diterapkan pada rute "/" dan "/story/{story}" , sedangkan "Hassession," "Isauth," dan "log" Middlewares diterapkan pada sisa rute:
Route:: group ([ " middleware " => [HasSession::class]], function () {
Route:: get ( " / " , [StoryController::class, " index " ]);
Route:: get ( " /story/{story} " , [StoryController::class, " show " ]);
Route:: group ([ " middleware " => [IsAuth::class, Log::class]], function () {
Route:: get ( " /compose " , [StoryController::class, " compose " ]);
Route:: post ( " /compose " , [StoryController::class, " create " ]);
});
});Dalam kerangka PHP unsur, tidak praktis untuk mengembalikan seluruh string dokumen HTML langsung dari rute dan pengontrol. Tampilan memberikan cara yang nyaman untuk menempatkan semua HTML di file terpisah.
Tampilan memainkan peran penting dalam memisahkan pengontrol/logika aplikasi dari masalah presentasi dan disimpan dalam direktori app/views . File tampilan ini, ditulis dalam PHP, merangkum markup. Pertimbangkan contoh dasar tampilan:
<html>
<body>
<h1>Hello, <?= $ name ?> </h1>
</body>
</html> Jika tampilan ini disimpan di app/views/Welcome.php , itu dapat dikembalikan menggunakan Helper view Global dalam rute:
Route:: get ( ' / ' , function () {
return view ( ' Welcome ' , [ ' name ' => ' Ahmed ' ]);
}); Argumen pertama yang diteruskan ke penampung view sesuai dengan nama file tampilan di direktori resources/views . Argumen kedua dapat berupa array pasangan nilai kunci yang dilewatkan ke pandangan. Misalnya, dalam kode di atas, $name akan dapat diakses secara langsung dan berisi nilai 'Ahmed'.
Tampilan juga dapat dikembalikan menggunakan metode statis make pada kelas CoreViewView :
Route:: get ( ' / ' , function () {
return View:: make ( " Post " , $ params );
}); Tampilan dapat bersarang di dalam subdirektori direktori app/views . Notasi "DOT" dapat digunakan untuk merujuk pandangan bersarang. Misalnya, jika tampilan Anda disimpan di app/views/layouts/MainLayout.php , Anda dapat mengembalikannya dari rute/pengontrol seperti itu:
return view ( ' layouts.MainLayout ' , $ data ); Elemental menyediakan cara yang nyaman untuk mempertahankan tata letak yang sama di berbagai tampilan, mengurangi duplikasi kode. Tata letak itu sendiri merupakan file tampilan yang berisi placeholder {{ content }} . Ketika tampilan dikembalikan dengan tata letak, tampilan terakhir disusun dengan meletakkan tampilan di dalam konten tata letak.
Elemental menyediakan cara yang nyaman untuk mempertahankan tata letak yang sama di berbagai tampilan, mengurangi duplikasi kode. Tata letak adalah file tampilan yang menggabungkan placeholder yang ditunjuk, dilambangkan dengan {{ content }} . Ketika sebuah tampilan dikembalikan menggunakan tata letak tertentu, komposisi dicapai dengan menanamkan konten tampilan di dalam placeholder yang ditunjuk dalam tata letak. Pendekatan ini merampingkan organisasi pandangan dan meningkatkan pemeliharaan kode dengan memusatkan elemen tata letak umum.
Di bawah ini adalah contoh dasar:
<!DOCTYPE html >
< html lang =" en " >
< head >
<!-- Head content -->
</ head >
< body >
< ?= component("components.Navbar") ? >
< div style =" min-height: calc(100vh - 140px); " >
{{ content }}
</ div >
</ body >
</ html >Tampilan dapat dikembalikan dengan tata letak seperti ini:
public function compose ()
{
return view ( " Compose " )-> withLayout ( " layouts.DashboardLayout " );
}Elemental menawarkan pendekatan yang kuat untuk membuat pandangan. Setiap tampilan pada dasarnya adalah komponen, dan setiap tampilan dapat dirakit dari komponen lain. Ini adalah simfoni komposisi, di mana masing -masing bagian berkontribusi pada penciptaan keseluruhan yang harmonis dan dinamis.
Contoh file komponen ( views/components/Logo.php ):
<a class="logo" href="/ " >
<span class= " logo-img">
<img src="logo.png" class ="logo-text">
LOGO
</span>
</a> Komponen ini dapat digunakan di dalam file tampilan lainnya. Misalnya, di views/Login.php :
<div>
<?= component ( " components.Logo " ) ?>
<p>Welcome Back!</p>
<!-- Other login form elements -->
</div>Dengan demikian, Elemental memberdayakan Anda dengan konstruksi tata letak dan komponen, memungkinkan Anda untuk menyusun pandangan Anda dengan kemahiran dari pendekatan top-down dan bottom-up. Fleksibilitas ini memungkinkan fusi yang mulus, di mana Anda dapat dengan mudah mencampur dan menggabungkan elemen untuk membuat antarmuka pengguna yang elegan dan canggih untuk aplikasi Anda.
Dalam aplikasi web modern, interaksi basis data adalah aspek mendasar. Elemental telah dirancang untuk merampingkan interaksi ini dengan mulus di beragam database yang didukung, memanfaatkan kemampuan inheren PHP PDO. Dengan Elemental, Anda memiliki fleksibilitas untuk menjalankan kueri atau transaksi kompleks menggunakan kelas CoreDatabaseDatabase .
Elemental menawarkan mapper objek-relasional (ORM) yang kuat yang secara efektif mengabstraksi banyak seluk-beluk, terbukti sangat berharga bagi sebagian besar kueri basis data. Namun, CoreDatabaseDatabase dapat digunakan untuk menjalankan kueri SQL yang lebih canggih.
Semua konfigurasi untuk aplikasi elemen Anda berada di app/config/config.php Anda. Di sini Anda dapat mendefinisikan semua koneksi database Anda, serta menentukan koneksi mana yang harus digunakan secara default. Sebagian besar opsi konfigurasi dalam file ini didorong oleh nilai -nilai variabel lingkungan aplikasi Anda.
Semua konfigurasi untuk aplikasi elemen Anda berada di app/config/config.php Anda. Di sini Anda dapat mendefinisikan semua koneksi database Anda, serta menentukan koneksi mana yang harus digunakan secara default. Sebagian besar opsi konfigurasi dalam file ini didorong oleh nilai -nilai variabel lingkungan aplikasi Anda.
<?php
return [
" db " => [
" driver " => getenv ( " DB_DRIVER " ) ?? " mysql " ,
" host " => getenv ( " DB_HOST " ) ?? $ _SERVER [ ' SERVER_ADDR ' ],
" port " => getenv ( " DB_PORT " ) ?? " 3306 " ,
" database " => getenv ( " DB_DATABASE " ) ?? " elemental " ,
" username " => getenv ( " DB_USERNAME " ) ?? " root " ,
" password " => getenv ( " DB_PASSWORD " ) ?? "" ,
],
]; Elemental menggunakan PDO sebagai kelas penanganan database yang mendasarinya. Semua fungsi PDO secara langsung tersedia di kelas CoreDatabaseDatabase . Anda dapat menyuntikkan instance dari CoreDatabaseDatabase ke dalam metode konstruktor atau pengontrol untuk memanggil metode PDO. Konfigurasi default untuk Elemental diatur untuk database MySQL, tetapi Anda dapat mengubah driver di dalam file konfigurasi.
Berikut adalah contoh menjalankan kueri melalui instance Database :
public function tokens ( Database $ db ) {
$ user_id = 1 ;
$ sql = " SELECT * FROM access_tokens WHERE user_id = :user_id " ;
$ stmt = $ db -> prepare ( $ sql );
$ stmt -> bindValue ( " :user_id " , $ user_id );
$ stmt -> execute ();
$ tokens = $ stmt -> fetchAll ();
}Untuk informasi lebih lanjut tentang PDO, Anda dapat merujuk pada dokumentasi PDO PHP
Elemental mencakup mapper (ORM) objek yang dibuat khusus yang membuatnya menyenangkan untuk berinteraksi dengan database. Saat menggunakan ORM, setiap tabel database memiliki "model" yang sesuai yang digunakan untuk berinteraksi dengan tabel itu. Selain mengambil catatan dari tabel database, model memungkinkan Anda untuk memasukkan, memperbarui, dan menghapus catatan dari tabel juga.
Model hadir dalam direktori app/models dan memperluas kelas CoreModelModel . Anda dapat menghasilkan model baru dengan menggunakan perintah build:model lilin.
php candle build:model Post Model yang dihasilkan oleh build:model akan ditempatkan di direktori app/Models . Model yang sangat mendasar memiliki struktur berikut:
<?php
namespace App Models ;
use Core Model Model ;
class Post extends Model
{
// ...
} Nama Tabel: Dengan konvensi, "Kasus Ular," nama jamak kelas akan digunakan sebagai nama tabel kecuali nama lain ditentukan secara eksplisit. Jadi, dalam hal ini, Elemental akan mengasumsikan Catatan Post Model Menyimpan dalam tabel posts .
Anda dapat secara manual menentukan nama tabel model dengan mendefinisikan properti tableName pada model:
<?php
namespace App Models ;
use Core Model Model ;
class Post extends Model
{
protected $ tableName = ' elemental_posts ' ;
}Kunci utama:
Elemental juga akan mengasumsikan bahwa tabel database yang sesuai setiap model memiliki kolom kunci utama bernama id . Jika perlu, Anda dapat mendefinisikan properti $primaryKey yang dilindungi pada model Anda untuk menentukan kolom berbeda yang berfungsi sebagai kunci utama model Anda:
<?php
namespace App Models ;
use Core Model Model ;
class Post extends Model
{
protected $ primaryKey = ' elemental_id ' ;
}Anda dapat menganggap setiap model sebagai pembangun kueri yang kuat yang memungkinkan Anda untuk meminta tabel basis data yang terkait dengan model.
Metode all model akan mengambil semua catatan dari tabel database terkait model:
use App Models Story ;
foreach (Story:: all () as $ story ) {
echo $ story [ " content " ];
}Secara default, catatan yang diambil diwakili sebagai array. Namun, Anda dapat melewati argumen mode yang mengontrol bagaimana setiap catatan diwakili. Argumen mode mengambil salah satu mode pengambilan PDO. Misalnya,
use App Models Story ;
foreach (Story:: all () as $ story ) {
echo $ story -> content ;
} Metode allWhere adalah abstraksi yang kuat dalam model yang memungkinkan mengeksekusi kueri yang kompleks. Metode ini membutuhkan tiga argumen: conditions , options , dan fetchMode .
public static function allWhere( array $ conditions , array $ options = [], int $ fetchMode = PDO :: FETCH_ASSOC ) Kondisi: Parameter conditions adalah array klausa yang harus dipenuhi catatan untuk diambil. Setiap kondisi dapat berupa pasangan [key => value] atau pasangan [key => [operator, value]] .
key sesuai dengan kolom tertentu dalam tabel.[key => value] , operator default adalah = dan value adalah data di dalam kolom itu untuk catatan.[key => [operator, value]] , Anda dapat menentukan operator untuk setiap kondisi. Operator yang didukung adalah:['=', '!=', '<', '>', '<=', '>=', 'LIKE', 'IS NULL', 'IS NOT NULL'] . Opsi: Parameter options adalah array yang menentukan argumen kueri tambahan, seperti order by , limit , dll. Konstruksi yang didukung dalam argumen opsi meliputi:
"orderBy""limit""offset""sortDir" FetchMode: Parameter fetchMode mengontrol bagaimana setiap catatan yang diambil diwakili. Argumen mode mengambil salah satu mode pengambilan PDO:
PDO::FETCH_ASSOCPDO::FETCH_NUMPDO::FETCH_BOTHPDO::FETCH_OBJPDO::FETCH_CLASSPDO::FETCH_INTOPDO::FETCH_LAZYPDO::FETCH_KEY_PAIRContoh akan membuatnya lebih jelas:
use Core Request Request ;
class StoryController {
const PAGE_SIZE = 10 ;
public function index ( Request $ request )
{
$ search = $ request -> search ;
$ categoryId = $ request -> category_id ;
$ sortBy = $ request -> sort_by ; // ASC or DESC, Default = ASC
$ page = $ request -> page ;
$ orderBy = $ request -> order_by ;
return Story:: allWhere (
[
" category_id " => $ categoryId ,
" title " => [ " LIKE " , " % $ search $ " ],
],
[
" limit " => static :: PAGE_SIZE ,
" orderBy " => $ orderBy ,
" sortDir " => $ sortBy ,
" offset " => ( $ page - 1 ) * static :: PAGE_SIZE ,
],
PDO :: FETCH_OBJ
);
}
} Selain mengambil semua catatan yang cocok dengan kueri yang diberikan, Anda juga dapat mengambil catatan tunggal menggunakan metode find and where . Alih -alih mengembalikan array catatan, metode ini mengembalikan contoh model tunggal:
Temukan: Ini akan mengambil catatan pertama yang cocok dengan kunci utama tabel.
$ flight = Story:: find ( 1 ); Di mana: Metode di mana mengambil serangkaian kondisi yang harus dipenuhi catatan untuk diambil. Setiap kondisi dapat berupa pasangan [key => value] atau pasangan [key => [operator, value]] .
key corresponds to a specific column in the table.[key => value] , the default operator is = and the value is the data inside that column for the record.[key => [operator, value]] , you can specify the operator for each condition. The supported operators are:['=', '!=', '<', '>', '<=', '>=', 'LIKE', 'IS NULL', 'IS NOT NULL'] .Misalnya
$ user = User:: where ([ " email " => $ email ]);
$ liked = Like:: where ([ " user_id " => $ user -> id , " story_id " => $ story_id ]); To insert a new record into the database, you can instantiate a new model instance and set attributes on the model. Then, call the save method on the model instance:
<?php
namespace App Controllers ;
use App Models Story ;
use Core Request Request ;
class StoryController
{
public function store ( Request $ request )
{
$ story = new Story ;
$ story -> name = $ request -> name ;
$ story -> save ();
return redirect ( ' /story ' );
}
} In this example, we assign the name field from the incoming HTTP request to the name attribute of the AppModelsStory model instance. When we call the save method, a record will be inserted into the database. The model's created_at timestamp will automatically be set when the save method is called, so there is no need to set it manually.
Alternatively, you may use the static create method to "save" a new model using a single PHP statement. The inserted model instance will be returned to you by the create method:
use App Models Story ;
$ story = Story:: create ([
' name ' => ' A tale of elemental magic ' ,
]); The save method may also be used to update models that already exist in the database. To update a model, you should retrieve it and set any attributes you wish to update. Then, you should call the model's save method.
use App Models Story ;
$ story = Story:: find ( 10 );
$ story -> name = ' An elemental tale of magic ' ;
$ story -> save (); Alternatively, you may use the static update method to update a model instance. The first argument is the id of the model, and the second argument needs to be the array of column value pair.
use App Models Story ;
$ story = Story:: update ( 10 , [ " name " => " A tale " , " content " => " Once upon a time .... " ]); To delete a model, you may call the destroy method on the model instance:
use App Models Story ;
$ story = Story:: find ( 12 );
$ story -> destroy (); However, if you know the primary key of the model, you may delete the model without explicitly retrieving it by calling the delete method. The id of the deleted record is returned.
use App Models Story ;
Story:: delete ( 12 ); You may call the data method on the model to retrieve all the attributes of a modal instance in an array form.
$ user = User:: find ( 10 );
$ user_data = $ user -> data (); Candle is the command line engine of the Elemental. Candle exists at the root of your application as the candle script and provides a number of helpful commands designed to aid you in the development process of your application. To view a list of all available Candle commands, you may use the help command:
php candle helpThis will also display the custom commands that you may have created yourself.
By now, you must have already ignited the the Elemental's candle to run your app. This ignite command serves the app at the IP Address 127.0.0.1, searching for a free port starting from 8000. If Port 8000 is occupied, Elemental automatically attempts to bind to the next available port (eg, 8001) and so forth.
php candle igniteYou have the flexibility to customize the server setup according to your requirements.
Custom Host Specify a specific IP address using the --host argument. Misalnya:
php candle ingite --host=192.168.1.10 Custom Port If you prefer binding to a specific port, use the --port argument:
php candle ingite --port=8080 To serve your application at a custom IP and port simultaneously, provide both the --host and --port arguments:
php candle ingite --host=192.168.1.10 --port=8080 The --host and --port arguments can be placed in any order.
To obtain a comprehensive view of all registered routes within your application, utilize the route:list command provided by Candle:
pesta
php candle route:list You can use the Candle build command to generate files for your models, controllers, middleware and commands.
To create a model, execute the following command:
php candle build:model Story This command will generate a file named Story.php within the appmodels directory, containing the Story class.
For generating a controller, the build command is similarly employed:
php candle build:controller StoryController Executing this command will generate a file named StoryController.php in the appcontrollers directory, featuring the MyController class.
To generate a middleware, utilize the build command as follows:
php candle build:middleware HasSession This will create a file named HasSession.php within the appmiddleware directory, housing the handle method.
For command generation, execute the build command with the appropriate arguments:
php candle build:command Migration Executing this command will generate a file named Migration.php in the appcommands directory, containing the Migration class and the handle method.
Generating custom commands is where the Candle's power can be experienced. Commands are stored in the app/commands directory, and it's essential to load them inside the array returned in appcommandsCommands.php for proper registration within the app.
After generating a command, define values for the key and description properties of the class. The key is used as the argument for the command, while description will be displayed in the help screen. The handle method will be called when the command is executed, and you can place your command logic in this method.
You can type-hint any dependencies required for your command handling. Elemental's DI Container will automatically inject all dependencies type-hinted in the handle method's signature.
Let's take a look at an example command:
<?php
namespace App Commands ;
use App Models User ;
use App Service MailService ;
use Core Console Command ;
class SendEmails extends Command
{
protected $ key = ' mail:send ' ;
protected $ description = ' Send mails to all users ' ;
public function handle ( MailService $ mailService ): void
{
$ mailService -> send (User:: all ());
}
}To execute the command in the command line:
php candle mail:send You can use Elemental's CoreConsoleCommander to retrieve any inputs passed through the command line. The CoreConsoleCommander provides a method named getArgs that returns an array of inputs passed from the command line. The Commander instance can be type-hinted through the handler method and used as required.
A concrete example will make it clear:
<?php
namespace App Commands ;
use Core Console Command ;
use Core Console Commander ;
class Migration extends Command
{
protected $ key = " migrate " ;
protected $ description = " Custom migration handler. " ;
private $ commander ;
public function handle ( Commander $ commander , Database $ db )
{
$ args = $ commander -> getArgs ();
if (! isset ( $ args [ 1 ])) {
$ this -> up ();
return ;
}
switch ( $ args [ 1 ]) {
case " fresh " :
$ this -> downThenUp ();
break ;
case " delete " :
$ this -> down ();
break ;
default :
$ this -> up ();
}
}
public function up ()
{
$ sql = " CREATE TABLE IF NOT EXISTS users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
bio TEXT,
image VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) " ;
try {
$ db -> exec ( $ sql );
console_log ( " Table 'users' created successfully! " );
} catch ( PDOException $ e ) {
console_log ( " Table creation error: " . $ e -> getMessage ());
}
}
public function down ()
{
$ sql = " DROP TABLE IF EXISTS users " ;
try {
$ db -> exec ( $ sql );
console_log ( " Table 'users' deleted successfully! " );
} catch ( PDOException $ e ) {
console_log ( " Table deletion error: " . $ e -> getMessage ());
}
}
public function downThenUp ()
{
$ this -> down ();
$ this -> up ();
}
}It is recommended to type-hint dependencies inside the handle method as opposed to inside the constructor of the command class.
To execute these migration commands in the command line:
php candle migrate
php candle migrate fresh
php candle migrate deleteAs you can see, generating commands are very powerful and can be helpful to achieve a variety of functionalities. Here, a custom migration handler has been built. You can expand and organize the above structure or create a custom Migration Service that can handle your migration logic.
Commands can also be used for handling task scheduling. You may create a command that executes some logic, and then pass the command to your operating systems CRON handler.
Elemental includes a variety of global "helper" PHP functions. You can use these functions in any way that is convenient to you.
The app function returns the Application instance:
$ app = app ();This is pretty useful when you want to register your own services as well as resolve any framework or custom service.
app ()-> bind (CustomService::class, function () {
return new CustomService ( new anotherService ());
});
$ service = app ()- make (CustomService::class); The dump function dumps the variable passed as the first argument. You can also pass an additional second argument that can serve as the identifier on screen:
dump ( $ value );
dump ( $ user , " user " ); The dd function dumps the given variable and ends the execution of the script:
dd ( $ value );
dd ( $ user , " user " ); The console_log function serves as a unique tool for logging variables, distinct from the dump function. Notably, it doesn't return output to the browser; instead, it directs information to the console initiated by the script. You can pass any variable number of arguments to the console_log function.
console_log ( $ value );
console_log ( $ user , $ post , $ image , $ comment ); The router function returns the returns the Router instance.
The view function is used to return a view from the controller method:
return view ( ' Login ' ); The component function is used to return a view as a component to be used inside another view:
<body>
<?= component ( " Logo " ) ?>
//...
</body> The redirect function returns a redirect HTTP response and is used to redirect to any other route.
return redirect ( ' /home ' );Elemental provides a convenient way to handle all the exceptions thrown by the app.
The handle method of AppExceptionsHandler class is where all exceptions thrown by your application pass through before being rendered to the user. By default, exceptions thrown by the app will be formatted, and a structured response will be sent back to the browser. However, inside the handle method, you can intercept any exception and perform custom logic before the response is sent back.
You can even send back a custom view or a response.
<?php
namespace App Exceptions ;
use Core Exception ExceptionHandler ;
class Handler extends ExceptionHandler
{
public function handle ( $ e )
{
// Perform some processing here
// You can customize the handling of exceptions based on your requirements
}
}Elemental has defined some specific exception classes by default:
AppExceptionModelNotFoundExceptionRouteNotFoundExceptionRouterExceptionViewNotFoundException If you need to handle different types of exceptions in different ways, you can modify the handle method accordingly:
<?php
class Handler extends ExceptionHandler
{
public function handle ( $ e )
{
if ( $ e instanceof ModelNotFoundException || $ e instanceof RouteNotFoundException) {
return view ( " 404 " )-> withLayout ( " layouts.DashboardLayout " );
}
if ( $ e instanceof ViewNotFoundException) {
return view ( " Home " );
}
// Handle other specific exceptions as needed
}
} You are free to create your own exception classes by extending from the base Exception class, which can then be handled as required.
Feel free to customize the handle method based on your application's specific needs.
All configuration settings for the application are centralized in the appconfigconfig.php file. These configurations cover various aspects such as database connection information and other core settings essential for your app.
To cater to different environments where the application might run, a .env.example file is provided in the root directory. This file outlines common environment variables that can be configured. If you are working in a team, it's recommended to include the .env.example file with placeholder values. This makes it clear to other developers which environment variables are required to run the application.
When your application receives a request, all the variables listed in the .env file will be loaded into the $_ENV PHP super-global. You can then use the getenv function to retrieve values from these variables in your configuration files.
$ appName = getenv ( " APP_NAME " ); To access configuration values, you can use type-hinting and inject the CoreConfigConfig class into your constructors, controller methods, or route closures.
use Core Config Config ;
class YourClass {
public function __construct ( Config $ config ) {
$ driver = $ config -> db [ " driver " ];
$ host = $ config -> db [ " host " ];
$ port = $ config -> db [ " port " ];
}
// Your other methods or code here
}By doing this, you have a clean and organized way to retrieve configuration values within your application.
This approach keeps your configuration centralized and allows for easy changes based on the environment. It also promotes a clean and maintainable codebase.
Elemental introduces a Facade system inspired by Laravel, providing a convenient and expressive static interface to classes within the application's Dependency Injection (DI) container. Facades act as static proxies to classes in the service container, offering a balance between a concise syntax and the testability and flexibility of traditional static methods.
In Elemental, the CoreFacadeRoute serves as a Facade, offering a static interface to the application's Router instance enabling you to use it like this in the routes.php file:
// routes.php
<?php
use Core Facade Route ;
Route:: get ( " /register " , [AuthController::class, " showRegister " ]);
Route:: get ( " /login " , [AuthController::class, " showLogin " ]);
Route:: get ( " /logout " , [AuthController::class, " logout " ]);
Route:: post ( " /register " , [AuthController::class, " register " ]);To create a custom Facade for any class, follow these steps:
FacadeClass that extends the CoreFacadeFacade class.getFacadeAccessor , returning the class string for the associated instance in the DI container. Here's an example of creating a PaymentGateway Facade:
<?php
use Core Facade Facade ;
use Core Services PaymentGateway ;
class PaymentGatewayFacade extends Facade
{
protected static function getFacadeAccessor ()
{
return PaymentGateway::class;
}
} Now, you can access the instance methods of your custom class by calling static methods on the corresponding FacadeClass .
LARAVEL is Magic . Like any unsuspecting Muggle, it's enchantments terrify you. Until one fine day, you dare to pick up the wand and start waving it. Then, you fall in love with it.
The Elemental framework is open-sourced software licensed under the MIT License.
All contributions are welcome. Please create an issue first for any feature request or bug. Then fork the repository, create a branch and make any changes to fix the bug or add the feature and create a pull request. Itu saja! Terima kasih!
For bug reports, feature requests, or general questions, please use the issue tracker.