Elementalは、ダイナミックでユーザーフレンドリーなコーディングエクスペリエンスのためにゼロから開発されたPHPフレームワークです。依存関係注射などの機能が組み込まれ、MVCアーキテクチャに従ってWeb開発を合理化し、コード組織を改善します。シンプルさと柔軟性に情熱を注いで設計された開発者は、比類のないコントロールを行使し、自由に使えるツールを深く理解できる領域に招待します。
Elementalの機能を紹介するために、 Inkwellと呼ばれる完全に機能するプラットフォームがElementalを使用して開発されました。 Inkwellは、ストーリーテリングの純粋な本質に特化したユニークな空間です。外部依存関係を持たないというElementalの目標に沿って、InkwellはPlain HTML、CSS、JS、およびPHPのみを使用して作成されています。
ライブプラットフォームと対応するコードベースの両方を自由に掘り下げてください。 Inkwellの機能を調べて、あなた自身のプロジェクトのためにElementalをどのように活用できるかを理解してください。
Elementalの作成の背後にあるインスピレーションをご覧ください。
Elementalは、文字列が付いていないことを目的として設計されています。外部ライブラリやフレームワークに依存関係はありません。目的は、開発者に真のコントロール感を与えることです。これは、フレームワークを動かす魔法のようなものを独立して探求し理解するための開かれた扉です。
包括的な目標?開発者は、DIコンテナ、ORM、ミドルウェアなどの強力な抽象化の優雅さを完全に受け入れ、活用できます。しかし、ここにキッカーがいます。要素はただ道を指しているわけではありません。それはあなたに謎を解き明かすための鍵を渡し、これらの抽象化がコードにどのようにレイアウトされているかを探ることができるようにします。
実際、あなたは道をたどるだけでなく、beatられたトラックから冒険するように勧められています。コードベースに飛び込み、抽象化を分析し、それらの内部の仕組みを理解します。 Elementalは単なるフレームワークではなく、ツールを自由に使用できるツールを形作り、成形するためのオープンな招待状であるため、お気軽に調整して実験してください。コーディングは迷路であってはならないからです。それは旅でなければなりません。その旅を一緒にしましょう。
他のフレームワークとは異なり、Elementalは作曲家や外部ライブラリに依存していません。リポジトリをクローン化し、システムにインストールされている古き良きPHPを開始するのと同じくらい簡単です。
端末を開き、次のコマンドを実行します。
git clone https://github.com/aneesmuzzafer/elemental.gitパッケージマネージャーや依存関係についての心配はありません。そのような懸念から解放するために、Elementalはゼロから構築されています。
作曲家ルートを好む人にとっては、新しいElementalアプリを作成することは単なるコマンドです。
composer create-project fragment/elemental sample-appこれにより、 composer.jsonファイルを使用してプロジェクトが生成されます。
プロジェクトの準備ができたら、コマンドラインエンジン、キャンドルを使用してigniteコマンドを使用してElemental Local Development Serverをキックスタートします。
cd sample-app
php candle ignite出来上がり!アプリケーションはhttp://127.0.0.1:8000でアクセス可能になりました。
魔法に集中できるように、基本的なセットアップの世話をしました。
エンチャントを始めましょう!
Elementalの最も重要な特徴は、クラスの依存関係を管理し、依存関係噴射を実行するために使用する依存関係噴射コンテナです。
依存関係注射は、コンポーネントが依存関係を保持する方法を扱うソフトウェア開発の設計パターンです。従来のシステムでは、クラスは独自の依存関係を作成する責任があります。 DIを使用すると、依存関係を作成および提供する責任がクラスの外に移動されます。依存関係を作成するクラスの代わりに、それらは外部ソースからクラスに「注入」されます。
DIは、ゆるく結合されたより保守可能なコードを達成するのに役立ちます。各クラスが依存関係を作成または取得する方法を心配することなく、各クラスが特定の機能に集中できるようにすることにより、懸念の分離を促進します。
依存噴射は、制御の反転(IOC)として知られるより広範な概念の特定の実装です。 IOCは、プログラムの制御フローが反転または外部エンティティ、コンテナ、またはフレームワークに引き渡される設計パラダイムを表します。
Elementalでは、依存噴射(DI)を使用している場合、クラスが他のクラスに依存せず、コンクリートクラス(抽象インターフェイスではない)にのみ依存している場合、DIコンテナにそのクラスのインスタンスを作成する方法を明示的に伝える必要はありません。 DIコンテナは自動的にそれを把握します。
コンテナはクラスのインスタンスを作成しようとし、そのクラスが他のクラスに依存関係がある場合、コンテナはこれらの依存関係を再帰的に解決しようとします。このプロセスは、必要なすべてのクラスが正常に解決されるまで続きます。したがって、各クラスを作成する方法を手動で指定する必要はありません。Iコンテナがあなたのためにそれを処理します。
<?php
class MailService {
public function __construct ( private MailerAgent $ mailer ) {
}
}
// Inside some other class
class UserController {
public function sendMail ( MailService $ mailService )
{
$ mailService -> sendMail ();
}
}ここで、メソッド引数内のMailServiceをタイプヒントすることにより、Elementalはクラスを解決してこのクラスのインスタンスを作成し、 MailServiceクラスで必要な依存関係を心配することなく使用できるように、 sendMailに渡すことができました。ご覧のとおり、 MailService自体は他のクラスMailerAgentに依存していますが、Elementalは舞台裏のMailerAgentクラスの解決に依存し、それをMailServiceに渡し、インスタンスを作成し、そのインスタンスを使用するためのインスタンスを提供しました。
「では、クラス名がElementalで機能するだけのタイプヒントだけで、この種の注入依存関係はどこにありますか?」すべてのクラスconstructorが機能し、すべてのcontroller methods 、およびコマンド作成クラスのhandleメソッド。
舞台裏では、Elementalは、登録されているバインディングを調べることにより、クラスまたはインターフェイスを具体的なインスタンスに解決します。言い換えれば、特定のクラスまたはインターフェイスのインスタンスを解決する方法についてフレームワークを明示的に伝えるには、 Applicationインスタンスのbindメソッドを使用してそのクラスまたはインターフェイスのバインディングを登録する必要があります。
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));
});通常、クラスを解決するために追加のロジックを実行する必要がある場合にのみ、クラスにバインドする必要があるか、インターフェイスをコンクリートの実装にバインドする必要があることに注意してください。それ以外の場合、Elementalはクラスを明示的にバインドすることを要求することなく解決します。
singletonメソッドは、クラスまたはインターフェイスをコンテナと結合し、1回だけ解決されるようにします。最初の解像度の後、同じバインディングのコンテナへの後続の呼び出しが同じオブジェクトインスタンスを返します。
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アプリのどこにでもバインディングを登録することはまったく問題ありませんが、アプリケーションがブートストラップしている間にバインドする必要があることがよくあります。そのため、アプリの他のコンポーネントが使用を開始できます。 Elementalは、アプリのすべてのバインディングを登録し、アプリケーションに必要な他のブートストラップロジックを実行する特別な場所を提供します。これはAppBootstrapAppServiceProviderです。アプリサービスプロバイダーには、 registerとbootメソッドが含まれています。
registerメソッド内で、依存関係噴射コンテナに物事をバインドする必要があります。ただし、バインディングを解決しようとしないでください。ルート、またはregisterメソッド内で他の機能を実行します。それ以外の場合は、まだロードされていないコンテナ内のサービスを誤って使用できます。
この方法は、他のすべてのサービスプロバイダーが登録された後に呼び出され、フレームワークによって登録されたすべてのサービスへのアクセスを許可します。実行したい初期化ロジックは、ここに配置する必要があります。
<?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
}
}makeメソッドを使用して、DIコンテナからクラスインスタンスを解決できます。アプリケーションインスタンスのmakeメソッドは、解決したいクラスまたはインターフェイスの名前を受け入れます。
use App Services MailService ;
$ mailService = app ()-> make (MailService::class);また、 ApplicationクラスでStatic Method instanceを直接使用してアプリケーションインスタンスを取得することもできます。
use Core Main Application ;
use App Services MailService ;
$ mailService = Application:: instance ()-> make (MailService::class); makeメソッドは、タイプヒントを使用して依存関係を注入することは非現実的であるコードコンポーネント内からクラスを解決しようとする場合に特に役立ちます。このようなシナリオでは、アプリケーションの依存関係噴射コンテナを明示的に要求して、インスタンスを解決できます。
ルートはapproutes.phpファイルで定義されているため、開発者はさまざまなルートを簡単に登録して、さまざまなHTTP要求を処理できます。
ルートは、 Route::get()などのルートファサードに関連するメソッドを呼び出し、最初の引数としてURIパターンを指定することにより登録されます。 2番目の引数は、リクエストの処理を担当するコントローラーとメソッドを定義する閉鎖または配列のいずれかです。
例えば:
<?php
use App Controllers AuthController ;
use Core Facade Route ;
Route:: get ( " /settings " , function () {
// handling logic goes here
});
Route:: post ( " /register " , [AuthController::class, " register " ]);リクエストURIが一致するときはいつでも、対応する閉鎖またはコントローラーメソッドが実行され、応答が生成され、ブラウザに送信されます。
次の方法を使用して、任意のHTTP動詞に応答するルートを登録できます。
Route::get($uri, $callback);Route::post($uri, $callback);Route::put($uri, $callback);Route::patch($uri, $callback);Route::delete($uri, $callback);Route::options($uri, $callback); ルート内のURIのセグメントをキャプチャする必要がある場合があります。たとえば、URLからユーザーのIDをキャプチャする必要がある場合があります。ルートパラメーターを定義することで、次のことを行うことができます。
Route:: get ( ' /user/{id} ' , function ( string $ id ) {
return ' User ' . $ id ;
});
Route:: get ( " /story/{id} " , function ( $ id ) { /*...*/ });ルートで要求される限り多くのルートパラメーターを定義できます。
Route:: post ( " story/edit/{id} " , [StoryController::class, " edit " ]);
Route:: get ( " story/{story_id}/comment/{comment_id} " , [StoryController::class, " comment " ]);これらはコントローラーメソッドにも渡されます。
Elementalは、コントローラー方法に必要な依存関係の注入をシームレスに処理します。これにより、タイプヒントを使用してコールバック署名でルートに必要な依存関係を指定できます。 Elementalは、宣言された依存関係をコールバックに自動的に解決して注入します。
たとえば、コールバック内でCoreRequestRequestを入力すると、Elementalは現在のHTTP要求がルートコールバックに自動的に注入されることを保証します。
<?php
use Core Request Request ;
Route:: get ( ' /users ' , function ( Request $ request ) {
// ...
});タイプ付き依存関係とルートパラメーターを任意の順序で配置できます。
モデルIDをパラメーターとしてルートまたはコントローラーアクションに渡す場合、典型的なアプローチでは、データベースを照会して、そのIDに基づいて対応するモデルを取得します。 Elementalは、ルートモデルバインディングを介してこのプロセスを簡素化し、モデルインスタンスをルートに直接自動的に挿入する便利な方法を提供します。
たとえば、ユーザーのIDのみをルートに注入する代わりに、指定されたIDに対応するユーザーモデルインスタンス全体を挿入するオプションがあります。
ルートまたはコントローラーアクションのコンテキストでは、モデルは、ルートの特定のセグメントに一致するタイプヒント変数名を使用して定義されます。例えば:
use App Models User ;
Route:: get ( ' /users/{user} ' , function ( User $ user ) {
return $ user -> email ;
});id以外の列を使用してモデルを解決したい場合があります。これを行うには、ルートパラメーター定義で列を指定できます。
use App Models User ;
Route:: get ( ' /users/{user:email} ' , function ( User $ user ) {
return $ user ;
});このシナリオでは、Elementalは、リクエストURIの対応する値に一致する電子メールを所有するモデルインスタンスをシームレスに挿入します。
もちろん、ルートモデルバインディングはコントローラーメソッドでも動作します。
一致するモデルインスタンスがデータベースにない場合、 ModelNotFoundExceptionがアプリによってスローされます。このような例外を処理し、 ExceptionsHandlerクラスでアプリによってスローされたそのような例外の動作を制御できます。それについては後で詳しく説明します。
Route::fallbackメソッドを使用すると、他のルートが着信要求と一致しない場合に実行されるルートを定義できます。
Route:: fallback ( function () {
// ...
});route:listキャンドルコマンドは、アプリケーションで定義されているすべてのルートのリストを提供します。
php candle route:listルートファイルのクロージャー内ですべての要求処理ロジックを統合するのではなく、「コントローラー」クラスを通じてこの動作を構築することを検討してください。コントローラーを使用すると、関連するリクエスト処理ロジックをまとまりのあるクラスに整理できます。たとえば、 UserControllerクラスは、ユーザーの表示、作成、更新、削除など、ユーザーに関連するさまざまな着信リクエストを管理できます。これらのコントローラークラスは、従来app/Controllersディレクトリに保存されています。
新しいコントローラーを生成するには、 build:controller Candleコマンドを実行できます。
php candle build:controller UserControllerこれにより、 app/Controllersディレクトリ内で「usercontroller.php」という名前の新しいファイルが生成されます。
コントローラーには、着信HTTPリクエストに応答する任意の数のパブリックメソッドがあります。
<?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 ( " / " );
}
}コントローラークラスとそのメソッドを作成した後、次のようにコントローラーメソッドへのルートを定義できます。
use App Controllers UserController ;
Route:: get ( " /register " , [AuthController::class, " showRegister " ]);受信した要求が指定されたルートURIと一致すると、 AppControllersUserControllerクラス内のshowRegisterメソッドが呼び出され、メソッドは対応するルートパラメーターを受信します。
Elemental Serviceコンテナは、すべてのコントローラーのインスタンスを解決する責任があります。その結果、コントローラーのコンストラクターでタイプヒントを使用して、必要な依存関係を指定できます。指定された依存関係は自動的に解決され、コントローラーインスタンスに注入されます
<?php
namespace App Controllers ;
use Core Database Database ;
class UserController
{
/**
* Create a new controller instance.
*/
public function __construct (
public Database $ db ,
) {}
}コンストラクターを介して依存関係を注入することとは別に、コントローラーの方法で依存関係にタイプヒントを使用することもできます。メソッドインジェクションの一般的なユースケースはCoreRequestRequestまたは任意のサービスインスタンスをコントローラーメソッドに注入することです。
コントローラーを作成および管理して、リクエストを効果的に処理します。
<?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 " );
}
}コントローラーの方法では、ルートパラメーターからの入力を予測する場合、引数を任意の順序でリストする柔軟性があります。たとえば、次のルート定義を検討してください。
Route:: post ( " story/update/{id} " , [StoryController::class, " update " ]);コントローラーメソッドを次のように定義して、 CoreRequestRequestを入力し、 idパラメーターにアクセスすることができます。
<?php
namespace App Controllers ;
use Core Request Request ;
class StoryController
{
public function update ( string $ id , Request $ request )
{
// Update $story
return redirect ( " /story/ $ story -> id " );
}
}ElementalのCoreRequestRequestクラスは、アプリケーションによって管理されている現在のHTTP要求に関与するためのオブジェクト指向のアプローチを提供します。リクエストとともに提出された入力、Cookie、およびファイルの取得を容易にします。
依存関係インジェクションを介して現在のHTTP要求インスタンスを取得するには、ルートクロージャーまたはコントローラーメソッドのCoreRequestRequestクラスのタイプヒントを利用できます。サービスコンテナは、着信リクエストインスタンスを自動的に注入します。
<?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 " );
}
}サービスコンテナは、着信要求をルートの閉鎖に自動的に注入します。
コントローラーメソッドがルートパラメーターからの入力を予測する場合、任意の順序で引数をリストする柔軟性があります。たとえば、次のルート定義を検討してください。
Route:: post ( " story/update/{id} " , [StoryController::class, " update " ]);コントローラーメソッドを次のように定義して、 CoreRequestRequestを入力し、 idパラメーターにアクセスすることができます。
<?php
namespace App Controllers ;
use Core Request Request ;
class StoryController
{
public function update ( string $ id , Request $ request )
{
// Update $story
return redirect ( " /story/ $ story -> id " );
}
}data()メソッドを使用して、すべての着信要求の入力データをarrayとして取得できます。この方法は、着信要求がHTMLフォームからのものであるか、XHRリクエストであるかに関係なく使用できます。
$ data = $ request -> data ();リクエストに使用されたHTTP動詞を心配することなく、 Requestインスタンスからすべてのユーザー入力にアクセスできます。 HTTP動詞に関係なく、 data方法を使用してユーザー入力を取得できます。
$ name = $ request -> data ()[ " name " ];CoreRequestRequestインスタンスは、着信HTTP要求を調べるためのさまざまな方法を提供します。以下の最も重要な方法のいくつかについて説明しましょう。
headersメソッドを使用して、 CoreRequestRequestインスタンスからリクエストヘッダーを取得できます。
$ headers = $ request -> headers ();CoreRequestRequestインスタンスでmethodを呼び出すことにより、リクエストメソッドを取得できます。
$ method = $ request -> method ();uriメソッドを使用して、 CoreRequestRequestインスタンスからリクエストURIを取得できます。
$ uri = $ request -> uri ();cookiesメソッドを使用して、 CoreRequestRequestインスタンスからリクエストCookieを取得できます。
$ cookies = $ request -> cookies ();rawContentメソッドを使用して、 CoreRequestRequestインスタンスから生のコンテンツを取得できます。
$ content = $ request -> rawContent ();リクエストの生の内容を扱うときは注意してください。
filesメソッドを使用して、 CoreRequestRequestインスタンスからファイルを取得できます。
$ files = $ request -> files ();ipメソッドは、アプリケーションにリクエストを行ったクライアントのIPアドレスを取得するために使用できます。
$ ipAddress = $ request -> ip ();portメソッドは、アプリケーションにリクエストを行ったクライアントのポートアドレスを取得するために使用できます。
$ port = $ request -> port ();contentTypeメソッドを使用してCoreRequestRequestインスタンスからコンテンツタイプを取得できます。
$ contentType = $ request -> contentType ();queryStringメソッドを使用して、リクエストのクエリ文字列を取得できます。
$ query = $ request -> queryString ();コンテンツタイプがtext/plainに設定されている場合、 textメソッドを使用してリクエストのテキストコンテンツを取得できます
$ text = $ request -> text ();コンテンツタイプがapplication/javascriptに設定されている場合、 jsメソッドを使用してリクエストのJSコンテンツを取得できます
$ js = $ request -> js ();コンテンツタイプがtext/htmlに設定されている場合、 htmlメソッドを使用してリクエストのHTMLコンテンツを取得できます
$ js = $ request -> html ();コンテンツタイプがapplication/jsonに設定されている場合$request->data() jsonメソッドを使用してリクエストのJSONコンテンツを取得できます。しかし、
$ jsonData = $ request -> json (); $request->data()は、すべてのJSONデータと、リクエストのクエリパラメーションを通過した入力とともに含まれます。ただし、 $request->json()使用して、JSONコンテンツのみを取得できます。
コンテンツタイプがapplication/jsonに設定されている場合、 xmlメソッドを使用してリクエストのXMLコンテンツを取得できます
$ xmlData = $ request -> xml ();すべてのルートとコントローラーは、ユーザーのブラウザへの配信のための応答を生成することが期待されています。 Elementalは、応答を生成するためのさまざまな方法を提供します。最も単純な形式の応答には、ルートまたはコントローラーから直接文字列を返すことが含まれます。フレームワークは、この文字列を完全なHTTP応答にシームレスに変換します。
Route:: get ( ' / ' , function () {
return ' Hello World ' ;
});ルートやコントローラーから文字列を返すことに加えて、配列またはオブジェクトを返すこともできます。フレームワークは、自動的にそれらをJSON応答に変換します。
Route:: get ( ' / ' , function () {
return [ 1 , 2 , 3 ];
});通常、ルートアクションから簡単な文字列や配列を返すだけではありません。代わりに、 CoreResponseResponseまたはビューの完全なインスタンスを返すことがよくあります。
完全なResponseインスタンスを返すと、応答のHTTPステータスコードとヘッダーをカスタマイズできます。コントローラー内の応答インスタンスをタイプヒントするか、ルートの閉鎖を型にすることにより、応答インスタンスを挿入できます。
use Core Response Response ;
Route:: get ( ' /home ' , function ( Response $ response ) {
$ response -> setHeader ( " content-type " , " text/plain " )
-> setStatusCode ( 200 )
-> setContent ( " Hello World " );
return $ response ;
});もちろん、コントローラーからviewを返すことができます。ただし、応答のステータスとヘッダーを制御する必要がある場合でも、応答のコンテンツとしてviewを返す必要がある場合は、次のようにすることができます。
use Core Response Response ;
class UserController {
public function register ( Response $ response ){
$ response -> setHeader ( " x-is_register " , " true " );
return view ( " Register " );
}
}これにより、ブラウザに送信されるビュー応答にヘッダーが自動的に設定されます。
ほとんどの応答方法は連鎖可能であり、応答インスタンスの流fluent構築を可能にすることに注意してください。
応答インスタンスでsetContentメソッドを使用して、応答の内容を設定できます。
$ response -> setContent ( " ... " );ただし、応答のコンテンツに追加する場合は、応答インスタンスでappendContentメソッドを使用して行うことができます。
$ response -> appendContent ( " ... " );setHeaderメソッドを使用して、応答インスタンスにヘッダーを設定できます
$ response -> setHeader ( " content-type " , " text/plain " );ただし、複数のヘッダーを同時に設定する場合は、 setHeadersメソッドを使用してヘッダーの配列を渡すことでそうすることができます。
$ response -> setHeaders ([ " content-type " => " text/html " , ...]);応答インスタンスでsetHeaderメソッドを使用して、応答のステータスコードを直接設定できます。
$ response -> setStatusCode ( 301 );共通ステータスコードのステータステキストはデフォルトで設定されます。
CoreResponseResponseクラスでStatic Method redirect呼び出すことにより、ユーザーを別のURLにリダイレクトするために必要な適切なヘッダーを含むリダイレクト応答を生成できます。
use Core Response Response ;
Route:: get ( ' /dashboard ' , function () {
return Response:: redirect ( ' home/dashboard ' );
});ただし、簡単にするために、ヘルパーメソッドredirect()も同じ機能を実現するためにグローバルに利用できます。
use Core Response Response ;
Route:: post ( ' /story/create ' , function () {
if (! $ someCondition )
return redirect ( ' /story ' , 204 );
});CoreResponseResponseクラスでStatic Method JSONを呼び出すことにより、JSON応答を生成することもできます。メソッドに渡されたデータは、適切なJSONに変換されます。また、オプションで、関数の2番目と3番目の引数としてステータスコードとヘッダー配列を渡すこともできます。
use Core Response Response ;
Route:: post ( ' /post ' , function () {
$ post = ( . . . );
return Response:: JSON ( $ post , 201 , [ " header " => " value " ]);
});Middlewareは、入ってくるHTTP要求をアプリケーションに調べてフィルタリングするための便利なメカニズムを提供します。たとえば、ミドルウェアを開発して、アプリケーションのユーザーの認証ステータスを検証できます。ユーザーが認証されていない場合、ミドルウェアはそれらをログイン画面にリダイレクトします。逆に、ユーザーが認証されている場合、ミドルウェアはリクエストがアプリケーションをより深く進めることを許可します。
認証を超えて多様なタスクを実行するために、追加のミドルウェアを作成する柔軟性があります。イラストとして、ロギングミドルウェアは、すべての着信リクエストをアプリケーションに記録できます。これらのミドルウェアコンポーネントはapp/middlewaresディレクトリ内に収容されています。
新しいミドルウェアを作成するには、 build:middlewareキャンドルコマンド:
php candle build:middleware IsAuthenticatedこのコマンドを実行すると、 app/middlewaresディレクトリに「Isauthenticated」という名前の新しいミドルウェアクラスが生成されます。このクラス内では、 handleという名前のメソッドが作成され、ミドルウェアのロジックを明確にすることができます。
ここでは、ユーザーが認証されている場合にのみルートへのアクセスを許可します。そうしないと、ユーザーを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 );
}
}リクエストをアプリケーションに深く渡すには、 $requestで$nextコールバックを呼び出す必要があります。
ミドルウェアは、アプリケーションに到達する前にHTTPがトラバースを要求する「レイヤー」のシーケンスと考えてください。各レイヤーには、リクエストを精査し、潜在的に拒否する機能があります。
もちろん、ミドルウェアは、リクエストをアプリケーションに深く渡す前または後にタスクを実行できます。たとえば、このミドルウェアは、リクエストがアプリケーションによって処理された後、タスクを実行します。
<?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 ;
}
}特定のルートにミドルウェアを割り当てたい場合は、ルートを定義するときにmiddlewareメソッドを呼び出すことができます。
Route:: get ( ' /profile ' , function () {
// ...
})-> middleware (IsAuthenticated::class);ミドルウェア名の配列をmiddlewareメソッドに渡すことにより、複数のミドルウェアをルートに割り当てることができます。
Route:: get ( ' / ' , function () {
// ...
})-> middleware ([First::class, Second::class]);グループを定義するときに、ミドルウェア名の配列を属性middlewaresに渡すことにより、ミドルウェアをルートグループに割り当てることができます。
Route:: group ([ " middleware " => [HasSession::class]], function () {
Route:: get ( " / " , [StoryController::class, " index " ]);
Route:: get ( " /story/{story} " , [StoryController::class, " show " ]);
});ネストされたルートグループを使用して、ミドルウェアと親グループを組み合わせることができます。その後の例では、「hassession」ミドルウェアは"/"と"/story/{story}"ルートに適用されますが、「hassession」、「isauth」、および "log" middlewaresは残りのルートに適用されます。
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 " ]);
});
});Elemental PHPフレームワークでは、HTMLドキュメント文字列全体をルートとコントローラーから直接返すことは実用的ではありません。ビューは、すべてのHTMLを別々のファイルに配置する便利な方法を提供します。
ビューは、コントローラー/アプリケーションのロジックをプレゼンテーションの懸念から分離する上で重要な役割を果たし、 app/viewsディレクトリに保存されます。 PHPで記述されたこれらのビューファイルは、マークアップをカプセル化します。ビューの基本的な例を考えてみましょう。
<html>
<body>
<h1>Hello, <?= $ name ?> </h1>
</body>
</html>このビューがapp/views/Welcome.phpに保存されている場合、ルート内のグローバルviewヘルパーを使用して返すことができます。
Route:: get ( ' / ' , function () {
return view ( ' Welcome ' , [ ' name ' => ' Ahmed ' ]);
}); viewヘルパーに渡された最初の引数はresources/viewsディレクトリのビューファイルの名前に対応しています。 2番目の引数は、ビューに渡されたキー価値のペアの配列です。たとえば、上記のコードでは、 $name直接アクセス可能になり、値「Ahmed」が含まれます。
CoreViewViewクラスでmake静的方法を使用して、ビューを返すこともできます。
Route:: get ( ' / ' , function () {
return View:: make ( " Post " , $ params );
});ビューはapp/viewsディレクトリのサブディレクトリ内にネストされる場合があります。 「ドット」表記は、ネストされたビューを参照するために使用できます。たとえば、ビューがapp/views/layouts/MainLayout.phpに保存されている場合、次のようなルート/コントローラーから返すことができます。
return view ( ' layouts.MainLayout ' , $ data );Elementalは、複数のビューで同じレイアウトを維持するための便利な方法を提供し、コードの複製を削減します。レイアウト自体は、プレースホルダー{{ content }}を含むビューファイルです。レイアウトでビューが返されると、レイアウトのコンテンツ内にビューを配置することにより、最終ビューがコンパイルされます。
Elementalは、複数のビューで同じレイアウトを維持するための便利な方法を提供し、コードの複製を削減します。レイアウトは、 {{ content }}で示される指定されたプレースホルダーを組み込んだビューファイルです。特定のレイアウトを使用してビューが返されると、レイアウト内の指定されたプレースホルダー内にビューのコンテンツを埋め込むことで構成が達成されます。このアプローチは、一般的なレイアウト要素を集中化することにより、ビューの構成を合理化し、コードの保守性を高めます。
以下は基本的な例です。
<!DOCTYPE html >
< html lang =" en " >
< head >
<!-- Head content -->
</ head >
< body >
< ?= component("components.Navbar") ? >
< div style =" min-height: calc(100vh - 140px); " >
{{ content }}
</ div >
</ body >
</ html >このようなレイアウトでビューを返すことができます:
public function compose ()
{
return view ( " Compose " )-> withLayout ( " layouts.DashboardLayout " );
}Elementalは、ビューを作成するための強力なアプローチを提供します。すべてのビューは基本的にコンポーネントであり、任意のビューは他のコンポーネントから組み立てることができます。それは作曲の交響曲であり、各作品は調和のとれたダイナミックな全体の創造に貢献します。
コンポーネントファイルの例( views/components/Logo.php ):
<a class="logo" href="/ " >
<span class= " logo-img">
<img src="logo.png" class ="logo-text">
LOGO
</span>
</a>このコンポーネントは、他のビューファイル内で使用できます。たとえば、 views/Login.php :
<div>
<?= component ( " components.Logo " ) ?>
<p>Welcome Back!</p>
<!-- Other login form elements -->
</div>したがって、Elementalはレイアウトとコンポーネントの両方のコンストラクトを使用して、トップダウンアプローチとボトムアップアプローチの両方のフィネスで自分のビューを構成することができます。この柔軟性により、シームレスなフュージョンを可能にします。ここでは、要素を楽に組み合わせて組み合わせて、アプリケーション用のエレガントで洗練されたユーザーインターフェイスを作成できます。
最新のWebアプリケーションでは、データベースの相互作用は基本的な側面です。 Elementalは、PHP PDOの固有の機能を活用して、サポートされている多様なデータベースでこの相互作用をシームレスに合理化するように設計されています。 Elementalを使用すると、 CoreDatabaseDatabaseクラスを使用して複雑なクエリまたはトランザクションを実行する柔軟性があります。
Elementalは、多くの複雑さを効果的に抽象化する堅牢なオブジェクトリレーショナルマッパー(ORM)を提供します。ただし、 CoreDatabaseDatabase使用して、より高度なSQLクエリを実行できます。
Elementalアプリのすべての構成は、アプリケーションのapp/config/config.php構成ファイルにあります。ここでは、すべてのデータベース接続を定義し、デフォルトで使用する接続を指定することができます。このファイル内の構成オプションのほとんどは、アプリケーションの環境変数の値によって駆動されます。
Elementalアプリのすべての構成は、アプリケーションのapp/config/config.php構成ファイルにあります。ここでは、すべてのデータベース接続を定義し、デフォルトで使用する接続を指定することができます。このファイル内の構成オプションのほとんどは、アプリケーションの環境変数の値によって駆動されます。
<?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は、基礎となるデータベース処理クラスとしてPDOを使用します。すべてのPDO関数はCoreDatabaseDatabaseクラスで直接使用できます。 CoreDatabaseDatabaseのインスタンスを任意のコンストラクターまたはコントローラーメソッドに挿入して、PDOメソッドを呼び出すことができます。 Elementalのデフォルトの構成はMySQLデータベース用に設定されていますが、構成ファイル内のドライバーを変更できます。
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 ();
}PDOの詳細については、PHPのPDOドキュメントを参照できます
Elementalには、データベースと対話するのが楽しくなるカスタムメイドのオブジェクト関連マッパー(ORM)が含まれています。 ORMを使用する場合、各データベーステーブルには、そのテーブルとの対話に使用される対応する「モデル」があります。データベーステーブルからレコードを取得することに加えて、モデルでは、テーブルからレコードを挿入、更新、削除することもできます。
モデルはapp/models Directoryに存在し、 CoreModelModel Classを拡張します。 build:model Candleコマンドを使用して、新しいモデルを生成できます。
php candle build:model Post build:modelコマンドによって生成されたモデルは、 app/Modelsディレクトリに配置されます。非常に基本的なモデルには次の構造があります。
<?php
namespace App Models ;
use Core Model Model ;
class Post extends Model
{
// ...
}テーブル名:慣習により、「ヘビのケース」であるクラスの複数名は、別の名前が明示的に指定されていない限り、テーブル名として使用されます。したがって、この場合、ElementalはPostモデルがpostsテーブルにレコードを保存すると想定します。
モデル上のtableNameプロパティを定義することにより、モデルのテーブル名を手動で指定できます。
<?php
namespace App Models ;
use Core Model Model ;
class Post extends Model
{
protected $ tableName = ' elemental_posts ' ;
}主キー:
Elementalは、各モデルの対応するデータベーステーブルには、 idという名前の主要な列があると仮定します。必要に応じて、モデルの保護された$primaryKeyプロパティを定義して、モデルのプライマリキーとして機能する別の列を指定できます。
<?php
namespace App Models ;
use Core Model Model ;
class Post extends Model
{
protected $ primaryKey = ' elemental_id ' ;
}各モデルを強力なクエリビルダーと考えることができ、モデルに関連付けられているデータベーステーブルを流croyすることができます。
モデルのall方法は、モデルに関連するデータベーステーブルからすべてのレコードを取得します。
use App Models Story ;
foreach (Story:: all () as $ story ) {
echo $ story [ " content " ];
}デフォルトでは、フェッチされたレコードは配列として表されます。ただし、各レコードの表現方法を制御するモード引数を渡すことができます。モード引数は、PDOフェッチモードのいずれかを取ります。例えば、
use App Models Story ;
foreach (Story:: all () as $ story ) {
echo $ story -> content ;
}allWhere Methodは、複雑なクエリを実行できるモデルの強力な抽象化です。この方法では、 conditions 、 options 、およびfetchMode 3つの引数が必要です。
public static function allWhere( array $ conditions , array $ options = [], int $ fetchMode = PDO :: FETCH_ASSOC )条件: conditionsパラメーターは、レコードを取得するために満たさなければならない条項の配列です。各条件は[key => value]ペアまたは[key => [operator, value]]ペアのいずれかです。
key 、テーブルの特定の列に対応します。[key => value]の形式である場合、デフォルトの演算子は=であり、 valueはレコードの列内のデータです。[key => [operator, value]]の形である場合、各条件の演算子を指定できます。サポートされているオペレーターは次のとおりです。['=', '!=', '<', '>', '<=', '>=', 'LIKE', 'IS NULL', 'IS NOT NULL'] 。オプション: optionsパラメーターはorder by 、 limitなどの追加のクエリ引数を決定する配列です。
"orderBy""limit""offset""sortDir" FetchMode: fetchModeパラメーターは、各Fetched Recordの表現方法を制御します。モード引数は、PDOフェッチモードのいずれかを取得します。
PDO::FETCH_ASSOCPDO::FETCH_NUMPDO::FETCH_BOTHPDO::FETCH_OBJPDO::FETCH_CLASSPDO::FETCH_INTOPDO::FETCH_LAZYPDO::FETCH_KEY_PAIR例として、それをより明確にします:
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
);
}
}特定のクエリに一致するすべてのレコードを取得することに加えて、 findとwhereを使用して単一のレコードを取得することもできます。レコードの配列を返す代わりに、これらのメソッドは単一のモデルインスタンスを返します。
検索:これは、テーブルの主キーに一致する最初のレコードを取得します。
$ flight = Story:: find ( 1 );場所:メソッドは、記録を取得するために満たさなければならない一連の条件を取る場所。各条件は[key => value]ペアまたは[key => [operator, value]]ペアのいずれかです。
key 、テーブルの特定の列に対応します。[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'] .例えば
$ 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.例えば:
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:
bash
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.それでおしまい!ありがとう!
For bug reports, feature requests, or general questions, please use the issue tracker.