Elemental ist ein PHP-Framework, das für dynamische, benutzerfreundliche Codierungserlebnisse von Grund auf neu entwickelt wurde. Es enthält Funktionen wie Abhängigkeitsinjektion und folgt der MVC -Architektur, um die Webentwicklung zu optimieren und die Codeorganisation zu verbessern. Entwickelt mit Leidenschaft für Einfachheit und Flexibilität lädt es Entwickler in einen Bereich ein, in dem sie eine beispiellose Kontrolle führen und ein tiefgreifendes Verständnis der ihnen zur Verfügung stehenden Werkzeuge erlangen können.
Um die Funktionen von Elementar zu präsentieren, wurde eine vollständig funktionierende Plattform namens Inkwell mit Elemental entwickelt. Inkwell ist ein einzigartiger Raum, der der reinen Essenz des Geschichtenerzählens gewidmet ist. In Übereinstimmung mit dem Ziel von Elemental, keine externen Abhängigkeiten zu haben, wurde Inkwell nur mit einfachem HTML, CSS, JS und PHP hergestellt.
Fühlen Sie sich frei, sich sowohl in die Live -Plattform als auch in die entsprechende Codebasis eintauchen. Entdecken Sie die Funktionen von Inkwell, um zu verstehen, wie Elementar für Ihre eigenen Projekte genutzt werden kann.
Sehen Sie die Inspiration hinter der Erschaffung von Elementar .
Elementar wurde mit dem Ziel entwickelt, keine Saiten angebracht zu haben. Es gibt keine Abhängigkeiten von externen Bibliotheken oder Frameworks. Ziel ist es, den Entwicklern ein echtes Gefühl der Kontrolle zu geben - eine offene Tür, um die magischen Dinge, die den Rahmen versorgen, unabhängig zu erforschen und zu verstehen.
Das übergeordnete Ziel? Lassen Sie Entwickler die Eleganz starker Abstraktionen wie DI -Container, Orms, Middlewares und vieles mehr voll und ganz nutzen und nutzen. Aber hier ist der Kicker - Elemental zeigt nicht nur den Weg. Es gibt Ihnen die Schlüssel, um die Geheimnisse zu enträtseln, und befähigen Sie zu untersuchen, wie diese Abstraktionen im Code festgelegt werden.
Tatsächlich werden Sie ermutigt, nicht nur dem Weg zu folgen, sondern sich von der ausgetretenen Strecke zu wagen. Tauchen Sie in die Codebasis ein, zerlegen Sie die Abstraktionen und verstehen Sie ihre inneren Arbeiten. Fühlen Sie sich frei zu optimieren und zu experimentieren, denn Elementar ist nicht nur ein Rahmen - es ist eine offene Einladung, die Ihnen zur Verfügung stehenden Werkzeuge zu formen und zu formen. Weil das Codieren kein Labyrinth sein sollte; Es sollte eine Reise sein. Lassen Sie uns diese Reise gemeinsam machen.
Im Gegensatz zu anderen Frameworks verlässt sich Elemental nicht auf Komponist oder externe Bibliotheken. Es ist so einfach wie das Klonieren des Repositorys und mit dem auf Ihrem System installierten guten alten PHP.
Öffnen Sie Ihr Terminal und führen Sie den folgenden Befehl aus:
git clone https://github.com/aneesmuzzafer/elemental.gitKeine Sorge über Paketmanager oder Abhängigkeiten - Elementar wird von Grund auf neu erstellt, um Sie von solchen Bedenken zu befreien.
Für diejenigen, die die Komponistroute bevorzugen, ist das Erstellen einer neuen Elementar -App nur ein Befehl entfernt:
composer create-project fragment/elemental sample-app Dadurch wird ein Projekt mit einer composer.json -Datei generiert.
Sobald Ihr Projekt fertig ist, starten Sie den elementaren lokalen Entwicklungsserver mit dem Befehl ignite mithilfe unserer Befehlszeilenmotor, Kerze :
cd sample-app
php candle igniteVoila! Ihre Bewerbung ist jetzt unter http://127.0.0.1:8000 zugänglich.
Wir haben uns um das grundlegende Setup gekümmert, damit Sie sich auf die Magie konzentrieren können.
Lassen Sie die Verzauberung beginnen!
Das wichtigste Merkmal des Elementars ist der Abhängigkeitsinjektionsbehälter, den es zur Verwaltung von Klassenabhängigkeiten und zur Durchführung von Abhängigkeitsinjektionen verwendet.
Die Abhängigkeitsinjektion ist ein Entwurfsmuster in der Softwareentwicklung, das sich darum befasst, wie Komponenten ihre Abhängigkeiten erfassen. In einem traditionellen System ist eine Klasse für die Erstellung ihrer eigenen Abhängigkeiten verantwortlich. Bei DI liegt die Verantwortung für die Erstellung und Bereitstellung von Abhängigkeiten außerhalb der Klasse. Anstelle einer Klasse, die ihre Abhängigkeiten erstellt, werden sie von einer externen Quelle in die Klasse "injiziert".
DI hilft bei der locker gekoppelten und wartbaren Code. Es fördert die Trennung von Bedenken, indem es jeder Klasse ermöglicht, sich auf ihre spezifischen Funktionen zu konzentrieren, ohne sich Sorgen darüber zu machen, wie sie ihre Abhängigkeiten erstellen oder erhalten können.
Die Abhängigkeitsinjektion ist eine spezifische Umsetzung des breiteren Konzepts, das als Inversion der Kontrolle (IOC) bekannt ist. IOC repräsentiert ein Design -Paradigma, bei dem der Kontrollfluss eines Programms invertiert oder an eine externe Entität, einen Container oder ein Framework übergeben wird.
In Elementar müssen Sie, wenn Sie die Abhängigkeitsinjektion (DI) verwenden (DI), wenn sich eine Klasse nicht auf andere Klassen stützt oder nur auf konkrete Klassen (nicht auf abstrakte Schnittstellen) beruht, dem DI -Container nicht explizit mitteilen, wie eine Instanz dieser Klasse erstellt wird. Der DI -Container ermittelt es automatisch.
Der Container versucht, eine Instanz der Klasse zu erstellen, und wenn diese Klasse Abhängigkeiten von anderen Klassen hat, versucht der Container rekursiv, diese Abhängigkeiten zu lösen. Dieser Prozess wird fortgesetzt, bis alle erforderlichen Klassen erfolgreich gelöst werden. Sie müssen also nicht manuell angeben, wie Sie jede Klasse erstellen - der DI -Container kümmert sich um Sie.
<?php
class MailService {
public function __construct ( private MailerAgent $ mailer ) {
}
}
// Inside some other class
class UserController {
public function sendMail ( MailService $ mailService )
{
$ mailService -> sendMail ();
}
} Durch das Typ-Sinne des MailService in das Argument der Methode konnte Elemental die Klasse beheben und eine Instanz dieser Klasse erstellen und an die sendMail weitergeben, damit Sie sie verwenden können, ohne sich Sorgen darüber zu machen, welche Abhängigkeiten von der MailService Klasse erforderlich sind. Wie Sie sehen können, hängt der MailService selbst von einem anderen MailerAgent der Klasse ab. Elemental kümmerte sich jedoch um die Lösung der MailerAgent -Klasse hinter den Kulissen, übergab dies an den MailService , während er seine Instanz erstellt und diese Instanz für Ihre Verwendung bereitgestellt hat.
"Also, wo wird diese Art von injizierenden Abhängigkeiten nur durch Typ-Sinne des Klassennamens in Elementar funktionieren?" Alle constructor , alle controller methods und die handle der Befehlserstellungskurs.
Hinter den Kulissen löst Elemental eine Klasse oder Schnittstelle in eine konkrete Instanz auf, indem sie alle registrierten Bindungen betrachtet. Mit anderen Worten, um das Framework ausdrücklich zu sagen, wie die Instanz einer bestimmten Klasse oder Schnittstelle behoben werden soll, müssten Sie eine Bindung dieser Klasse oder Schnittstelle mithilfe der bind -Methode auf der Application registrieren und den Namen oder die Schnittstellenname übergeben, die wir zusammen mit einem Verschluss registrieren möchten, der eine Instanz der Klasse zurückgibt:
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));
});Beachten Sie, dass Sie normalerweise nur eine Klasse binden müssen, wenn Sie eine zusätzliche Logik für die Lösung einer Klasse ausführen müssen, oder eine Schnittstelle an eine konkrete Implementierung binden müssen. Andernfalls wird Elementar die Klasse beheben, ohne dass Sie sie explizit gebeten haben, sie zu binden.
Die singleton -Methode bindet eine Klasse oder Schnittstelle mit dem Container, um sicherzustellen, dass sie nur einmal aufgelöst wird. Nach der anfänglichen Auflösung gibt alle nachfolgenden Aufrufe des Containers zur gleichen Bindung dieselbe Objektinstanz zurück.
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 Es ist zwar vollkommen in Ordnung, eine Bindung in der App überall zu registrieren, aber es ist häufig erforderlich, sie zu binden, während die Anwendung Bootstrapping ist, damit andere Komponenten der App sie verwenden können. Elemental bietet einen besonderen Ort, um alle Bindungen der App zu registrieren und andere Bootstrapping -Logik auszuführen, die von Ihrer Anwendung erforderlich sind. Dies ist AppBootstrapAppServiceProvider . Der App -Dienstanbieter enthält ein register und eine boot -Methode.
In der register sollten Sie Dinge in den Abhängigkeitsinjektionsbehälter einbinden. Sie sollten jedoch nicht versuchen, eine Bindung zu beheben. Routen oder andere Funktionen in der register ausführen. Andernfalls können Sie versehentlich einen Dienst in einem Container verwenden, der noch nicht geladen wurde.
Diese Methode wird aufgerufen, nachdem alle anderen Dienstleister registriert wurden, was den Zugriff auf alle vom Framework registrierten Dienste gewährt. Jede Initialisierungslogik, die Sie ausführen möchten, sollte hier platziert werden.
<?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
}
} Sie können die Methode make , um eine Klasseninstanz aus dem DI -Container zu beheben. Die make für die Anwendung akzeptiert den Namen der Klasse oder Schnittstelle, die Sie beheben möchten:
use App Services MailService ;
$ mailService = app ()-> make (MailService::class); Sie können die Anwendungsinstanz auch mit der statischen instance direkt in der Application erhalten.
use Core Main Application ;
use App Services MailService ;
$ mailService = Application:: instance ()-> make (MailService::class); Die Methode make ist besonders nützlich, wenn Sie versuchen, eine Klasse innerhalb einer Codekomponente aus zu beheben, in der es unpraktisch ist, eine Abhängigkeit mit dem Typ-Sendung zu injizieren. In solchen Szenarien können Sie den Abhängigkeitsinjektionscontainer der Anwendung explizit anfordern, um eine Instanz für Sie zu beheben.
Routen werden in der Datei approutes.php definiert, sodass Entwickler verschiedene Routen einfach registrieren können, um verschiedene HTTP -Anforderungen zu verarbeiten.
Die Routen werden registriert, indem die entsprechende Methode auf der Routenfassade wie Route::get() aufgerufen wird und ein URI -Muster als erstes Argument angeben. Das zweite Argument kann entweder ein Verschluss oder ein Array sein, das den Controller und die Methode definiert, die für die Behandlung der Anforderung verantwortlich ist.
Zum Beispiel:
<?php
use App Controllers AuthController ;
use Core Facade Route ;
Route:: get ( " /settings " , function () {
// handling logic goes here
});
Route:: post ( " /register " , [AuthController::class, " register " ]);Immer wenn eine Anforderungs -URI übereinstimmt, wird die entsprechende Verschluss- oder Controller -Methode ausgeführt und eine Antwort erzeugt und an den Browser zurückgesandt.
Sie können Routen registrieren, die auf jedes HTTP -Verb mit den folgenden Methoden reagieren:
Route::get($uri, $callback);Route::post($uri, $callback);Route::put($uri, $callback);Route::patch($uri, $callback);Route::delete($uri, $callback);Route::options($uri, $callback); Manchmal müssen Sie Segmente der URI in Ihrer Route erfassen. Zum Beispiel müssen Sie möglicherweise die ID eines Benutzers aus der URL erfassen. Sie können dies tun, indem Sie Routenparameter definieren:
Route:: get ( ' /user/{id} ' , function ( string $ id ) {
return ' User ' . $ id ;
});
Route:: get ( " /story/{id} " , function ( $ id ) { /*...*/ });Sie können so viele Routenparameter definieren, wie dies von Ihrer Route erforderlich ist:
Route:: post ( " story/edit/{id} " , [StoryController::class, " edit " ]);
Route:: get ( " story/{story_id}/comment/{comment_id} " , [StoryController::class, " comment " ]);Diese werden auch in die Controller -Methode übergeben.
Elementar wird nahtlos die Injektion der erforderlichen Abhängigkeiten für Ihre Controller -Methoden behandelt. Auf diese Weise können Sie alle Abhängigkeiten angeben, die Ihre Route in der Rückrufsignatur unter Verwendung des Typs angegeben haben. Elemental kümmert sich um automatisch auf die Auflösung und Injektion der deklarierten Abhängigkeiten in den Rückruf.
Wenn Sie beispielsweise innerhalb des Rückrufs CoreRequestRequest eingeben, stellt Elemental sicher, dass die aktuelle HTTP-Anforderung automatisch in Ihren Route Callback eingeleitet wird:
<?php
use Core Request Request ;
Route:: get ( ' /users ' , function ( Request $ request ) {
// ...
});Sie können die typisierten Abhängigkeiten und Routenparameter in beliebiger Reihenfolge einfügen.
Wenn Sie eine Modell -ID als Parameter an eine Route oder eine Controller -Aktion übergeben, beinhaltet der typische Ansatz die Abfrage der Datenbank, um das entsprechende Modell basierend auf dieser ID abzurufen. Elemental vereinfacht diesen Prozess durch Routenmodellbindung und bietet eine bequeme Möglichkeit, Modellinstanzen automatisch direkt in Ihre Routen zu injizieren.
Anstatt nur die ID eines Benutzers in Ihre Route zu injizieren, haben Sie beispielsweise die Möglichkeit, die gesamte Benutzermodellinstanz zu injizieren, die der angegebenen ID entspricht.
Im Kontext von Routen oder Controller-Aktionen werden Modelle mithilfe von Typ-gekleideten Variablennamen definiert, die mit einem bestimmten Segment in der Route übereinstimmen. Zum Beispiel:
use App Models User ;
Route:: get ( ' /users/{user} ' , function ( User $ user ) {
return $ user -> email ;
}); Manchmal möchten Sie Modelle mithilfe einer anderen Spalte als id auflösen. Dazu können Sie die Spalte in der Routenparameterdefinition angeben:
use App Models User ;
Route:: get ( ' /users/{user:email} ' , function ( User $ user ) {
return $ user ;
});In diesem Szenario injiziert Elemental die Modellinstanz, die eine E -Mail besitzt, die dem entsprechenden Wert aus dem URI -Anforderungs -URI entspricht.
Natürlich funktioniert die Routenmodellbindung auch mit Controller-Methoden.
Wenn in der Datenbank keine Matching -Modellinstanz gefunden wird, wird von der App eine ModelNotFoundException geworfen. Sie können solche Ausnahmen bewältigen und das Verhalten einer solchen und anderen Ausnahmen steuern, die von der App in der ExceptionsHandler geworfen werden. Mehr dazu später.
Mit der Route::fallback -Methode können Sie eine Route definieren, die ausgeführt wird, wenn keine andere Route mit der eingehenden Anfrage übereinstimmt.
Route:: fallback ( function () {
// ...
}); Die route:list Candle -Befehl enthält die Liste aller in der Anwendung definierten Routen:
php candle route:list Anstatt alle Anforderungen zur Handhabung der Logik in Schließungen in Ihren Routendateien zu konsolidieren, sollten Sie dieses Verhalten über "Controller" -Kassen strukturieren. Mit Controllern können Sie die verwandte Anforderungsbehandlungslogik in eine zusammenhängende Klasse organisieren. Beispielsweise könnte eine UserController -Klasse verschiedene eingehende Anfragen verwalten, die sich auf Benutzer beziehen, z. B. das Anzeigen, Erstellen, Aktualisieren und Löschen von Benutzern. Diese Controller -Klassen werden konventionell im app/Controllers -Verzeichnis gespeichert.
Um einen neuen Controller zu generieren, können Sie den Befehl build:controller Candle" ausführen.
php candle build:controller UserController Dadurch werden im app/Controllers -Verzeichnis eine neue Datei namens "UserController.php" generiert.
Ein Controller kann eine beliebige Anzahl von öffentlichen Methoden haben, die auf eingehende HTTP -Anfragen reagieren:
<?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 ( " / " );
}
}Nachdem Sie eine Controller -Klasse und ihre Methoden erstellt haben, können Sie wie folgt einen Weg zur Controller -Methode definieren:
use App Controllers UserController ;
Route:: get ( " /register " , [AuthController::class, " showRegister " ]); Wenn eine empfangene Anforderung mit der benannten Route URI übereinstimmt, wird die showRegister -Methode in der AppControllersUserController -Klasse aufgerufen, und die Methode empfängt die entsprechenden Routenparameter.
Der Elementar -Service -Container ist für die Auflösung von Instanzen aller Controller verantwortlich. Infolgedessen können Sie im Konstruktor Ihres Controllers Typenstyp verwenden, um die von ihm möglicherweise erforderlichen Abhängigkeiten anzugeben. Die angegebenen Abhängigkeiten werden automatisch aufgelöst und in die Controller -Instanz injiziert
<?php
namespace App Controllers ;
use Core Database Database ;
class UserController
{
/**
* Create a new controller instance.
*/
public function __construct (
public Database $ db ,
) {}
} Abgesehen von der Injektion von Abhängigkeiten durch den Konstruktor können Sie auch Typen für Abhängigkeiten in den Methoden Ihres Controller verwenden. Eine häufige Anwendungsfälle für die Methodeninjektion injiziert die CoreRequestRequest oder eine Serviceinstanz in Ihre Controller-Methoden:
Erstellen und verwalten Sie Controller, um Anforderungen effektiv zu bearbeiten.
<?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 " );
}
}Wenn Ihre Controller -Methode die Eingabe von einem Routenparameter vorwegnimmt. Sie haben die Flexibilität, Ihre Argumente in beliebiger Reihenfolge aufzulisten. Betrachten Sie beispielsweise die folgende Routendefinition:
Route:: post ( " story/update/{id} " , [StoryController::class, " update " ]); Sie können weiterhin den CoreRequestRequest ucing auf Ihren id -Parameter eingeben, indem Sie Ihre Controller-Methode wie folgt definieren:
<?php
namespace App Controllers ;
use Core Request Request ;
class StoryController
{
public function update ( string $ id , Request $ request )
{
// Update $story
return redirect ( " /story/ $ story -> id " );
}
} Die CoreRequestRequest Klasse in Elemental bietet einen objektorientierten Ansatz für die Inaktion mit der vorliegenden HTTP-Anforderung, die von Ihrer Anwendung verwaltet wird. Es erleichtert das Abrufen von Eingaben, Cookies und Dateien, die zusammen mit der Anfrage eingereicht wurden.
Um die aktuelle HTTP-Anforderungsinstanz durch Abhängigkeitsinjektion zu erwerben, können Sie die Typ-Sendung für die CoreRequestRequest -Klasse in Ihrer Routenverschlusses oder Controller-Methode verwenden. Der Service -Container injiziert automatisch die Anforderungsinstanz.
<?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 " );
}
}Der Service -Container injiziert automatisch auch die eingehende Anfrage in die Routenverschlusses.
Wenn Ihre Controller -Methode Eingaben von einem Routenparameter vorwegnimmt, haben Sie die Flexibilität, Ihre Argumente in jeder Reihenfolge aufzulisten. Betrachten Sie beispielsweise die folgende Routendefinition:
Route:: post ( " story/update/{id} " , [StoryController::class, " update " ]); Sie können weiterhin den CoreRequestRequest ucing auf Ihren id -Parameter eingeben, indem Sie Ihre Controller-Methode wie folgt definieren:
<?php
namespace App Controllers ;
use Core Request Request ;
class StoryController
{
public function update ( string $ id , Request $ request )
{
// Update $story
return redirect ( " /story/ $ story -> id " );
}
} Sie können alle Eingabedaten der Eingangsanforderung als array mit der Methode data() erhalten. Diese Methode kann verwendet werden, unabhängig davon, ob die eingehende Anforderung aus einem HTML -Formular stammt oder eine XHR -Anfrage ist:
$ data = $ request -> data (); Sie können über Ihre Request auf alle Benutzereingaben zugreifen, ohne sich Sorgen darüber zu machen, welches HTTP -Verb für die Anfrage verwendet wurde. Unabhängig vom HTTP -Verb kann die data verwendet werden, um die Benutzereingabe abzurufen:
$ name = $ request -> data ()[ " name " ]; Die CoreRequestRequest -Instanz bietet eine Vielzahl von Methoden zur Untersuchung der eingehenden HTTP -Anforderung. Lassen Sie uns einige der wichtigsten Methoden unten diskutieren.
Sie können die Anforderungsheader mithilfe der headers -Methode aus der CoreRequestRequest -Instanz abrufen.
$ headers = $ request -> headers (); Sie können die Anforderungsmethode abrufen, indem Sie method unter CoreRequestRequest -Instanz aufrufen.
$ method = $ request -> method (); Sie können die Anforderungs -URI mit der uri -Methode aus der CoreRequestRequest -Instanz abrufen.
$ uri = $ request -> uri (); Sie können die Anforderungs -Cookies mithilfe der cookies -Methode von der CoreRequestRequest -Instanz abrufen.
$ cookies = $ request -> cookies (); Sie können den Rohinhalt mithilfe der rawContent -Methode aus der CoreRequestRequest -Instanz abrufen.
$ content = $ request -> rawContent ();Seien Sie vorsichtig, wenn Sie sich mit dem Rohinhalt einer Anfrage befassen.
Sie können die Dateien mithilfe der files -Methode aus der CoreRequestRequest -Instanz abrufen.
$ files = $ request -> files (); Die ip -Methode kann verwendet werden, um die IP -Adresse des Clients abzurufen, die die Anfrage an Ihre Anwendung gestellt haben:
$ ipAddress = $ request -> ip (); Die port kann verwendet werden, um die Portadresse des Clients abzurufen, der die Anfrage an Ihre Anwendung gestellt hat:
$ port = $ request -> port (); Sie können den Inhaltstyp mit der contentType -Methode aus der CoreRequestRequest Instanz abrufen.
$ contentType = $ request -> contentType (); Sie können die Abfragezeichenfolge der Anforderung mit der queryString -Methode abrufen.
$ query = $ request -> queryString (); Sie können den Textinhalt der Anforderung mit der text text/plain
$ text = $ request -> text (); Sie können den JS-Inhalt der Anforderung mit der js application/javascript abrufen
$ js = $ request -> js (); Sie können den HTML-Inhalt der Anforderung mit der html text/html abrufen
$ js = $ request -> html (); Sie können den JSON-Inhalt der Anforderung mit der json -Methode abrufen, die der Inhaltstyp auf application/json der $request->data() gesetzt ist, gibt alle an die Anforderung übergebenen JSON-Daten zurück. Jedoch,
$ jsonData = $ request -> json (); Die $request->data() enthält alle JSON-Daten zusammen mit den Eingängen, die die Abfrageparameter in der Anforderung übergeben haben. $request->json() kann jedoch verwendet werden, um nur den JSON-Inhalt abzurufen.
Sie können den XML-Inhalt der Anforderung mit der xml application/json abrufen
$ xmlData = $ request -> xml ();Jede Route und jeder Controller wird voraussichtlich eine Antwort für die Lieferung an den Browser des Benutzers ergeben. Elemental bietet verschiedene Methoden zur Generierung von Antworten. Die einfachste Form der Antwort besteht darin, eine Zeichenfolge direkt von einer Route oder einem Controller zurückzugeben. Das Framework wandelt diese Zeichenfolge nahtlos in eine vollständige HTTP -Antwort um.
Route:: get ( ' / ' , function () {
return ' Hello World ' ;
});Zusätzlich zur Rückgabe von Zeichenfolgen von Ihren Routen und Controllern können Sie auch Arrays oder Objekte zurückgeben. Das Framework verwandelt sie automatisch in eine JSON -Antwort:
Route:: get ( ' / ' , function () {
return [ 1 , 2 , 3 ];
}); Normalerweise werden Sie nicht nur einfache Zeichenfolgen oder Arrays aus Ihren Routenaktionen zurückkehren. Stattdessen geben Sie häufig vollständige Instanzen von CoreResponseResponse oder Ansichten zurück.
Durch die Rückgabe einer vollständigen Response können Sie den HTTP -Statuscode und die Header der Antwort anpassen. Sie können die Antwortinstanz durch Typ-Sinne der Antwortinstanz in Ihrem Controller oder in Ihrem Controller oder Routenverschluss injizieren.
use Core Response Response ;
Route:: get ( ' /home ' , function ( Response $ response ) {
$ response -> setHeader ( " content-type " , " text/plain " )
-> setStatusCode ( 200 )
-> setContent ( " Hello World " );
return $ response ;
}); Sie können natürlich eine view von einem Controller zurückgeben. Wenn Sie jedoch die Kontrolle über den Status und die Header der Antwort benötigen, aber auch eine view als Inhalt der Antwort zurückgeben müssen, können Sie dies als folgende tun:
use Core Response Response ;
class UserController {
public function register ( Response $ response ){
$ response -> setHeader ( " x-is_register " , " true " );
return view ( " Register " );
}
}Dadurch wird der Header automatisch für die Ansichtsantwort festgelegt, die an den Browser gesendet wird.
Beachten Sie, dass die meisten Reaktionsmethoden kettig sind und die fließende Konstruktion von Reaktionsinstanzen ermöglichen.
Sie können den Inhalt der Antwort mithilfe setContent -Methode für die Antwortinstanz festlegen.
$ response -> setContent ( " ... " ); Wenn Sie sich jedoch an den Inhalt der Antwort anhängen möchten, können Sie dies mithilfe appendContent -Methode für die Antwortinstanz tun.
$ response -> appendContent ( " ... " ); Sie können einen Header für die Antwortinstanz mithilfe der setHeader -Methode festlegen
$ response -> setHeader ( " content-type " , " text/plain " ); Wenn Sie jedoch mehrere Header gleichzeitig festlegen möchten, können Sie dies mit der setHeaders -Methode tun und eine Reihe von Kopfzeilen übergeben.
$ response -> setHeaders ([ " content-type " => " text/html " , ...]); Sie können den Statuscode der Antwort direkt mithilfe setHeader -Methode für die Antwortinstanz festlegen.
$ response -> setStatusCode ( 301 );Ein Statustext wird standardmäßig für die gemeinsamen Statuscodes festgelegt.
Sie können eine Umleitungsantwort erstellen, die die richtigen Header enthält, die erforderlich sind, um den Benutzer in eine andere URL umzuleiten, indem Sie die statische Methode auf der CoreResponseResponse Antwortklasse redirect .
use Core Response Response ;
Route:: get ( ' /dashboard ' , function () {
return Response:: redirect ( ' home/dashboard ' );
}); Der Einfachheit halber ist jedoch auch eine Helfer -Methode redirect() weltweit verfügbar, um die gleiche Funktionalität zu erreichen.
use Core Response Response ;
Route:: post ( ' /story/create ' , function () {
if (! $ someCondition )
return redirect ( ' /story ' , 204 );
}); Sie können auch eine JSON -Antwort generieren, indem Sie die statische Methode JSON in der CoreResponseResponse Antwortklasse aufrufen. Die an die Methode übergebenen Daten werden in den richtigen JSON konvertiert. Sie können optional auch den Statuscode und das Header -Array als das zweite und dritte Argument an die Funktion übergeben.
use Core Response Response ;
Route:: post ( ' /post ' , function () {
$ post = ( . . . );
return Response:: JSON ( $ post , 201 , [ " header " => " value " ]);
});Middleware bietet einen bequemen Mechanismus, um eingehende HTTP -Anforderungen an Ihre Anwendung zu untersuchen und zu filtern. Beispielsweise können Sie Middleware entwickeln, um den Authentifizierungsstatus des Benutzers Ihrer Anwendung zu validieren. Wenn der Benutzer nicht authentifiziert ist, leitet die Middleware sie in den Anmeldebildschirm um. Wenn der Benutzer authentifiziert ist, erlaubt die Middleware die Anfrage, tiefer in die Anwendung einzusteigen.
Sie haben die Flexibilität, zusätzliche Middleware zu erstellen, um verschiedene Aufgaben über die Authentifizierung hinaus auszuführen. Als Illustration könnte eine Protokollierungsmiddleware alle eingehenden Anfragen an Ihre Anwendung aufzeichnen. Diese Middleware -Komponenten sind im app/middlewares -Verzeichnis untergebracht.
Verwenden Sie zum Erstellen einer neuen Middleware den Befehl build:middleware Candle:
php candle build:middleware IsAuthenticated Durch die Ausführung dieses Befehls wird eine frische Middleware -Klasse mit dem Namen "Isauthenticated" im app/middlewares -Verzeichnis generiert. Innerhalb dieser Klasse wird eine Methode namens handle erstellt, bei der Sie die Logik für die Middleware artikulieren können.
Hier ermöglichen wir nur den Zugriff auf die Route, wenn der Benutzer authentifiziert ist. Andernfalls werden wir die Benutzer wieder zum login -URI umleiten:
<?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 );
}
} Um die Anfrage eingehender an die Bewerbung zu übergeben, sollten Sie den $next Rückruf mit der $request anrufen.
Betrachten Sie Middleware als eine Abfolge von "Ebenen", die HTTP vor dem Erreichen Ihrer Anwendung anfordert. Jede Schicht hat die Fähigkeit, die Anforderung zu überprüfen und möglicherweise abzulehnen.
Natürlich kann eine Middleware die Aufgaben vor oder nach der Eingabe der Anfrage in die Anwendung ausführen. Beispielsweise würde diese Middleware ihre Aufgabe ausführen, nachdem die Anfrage von der Anwendung bearbeitet wurde:
<?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 ;
}
} Wenn Sie bestimmte Routen Middleware zuweisen möchten, können Sie beim Definieren der Route die middleware -Methode aufrufen:
Route:: get ( ' /profile ' , function () {
// ...
})-> middleware (IsAuthenticated::class); Sie können der Route mehrere Middleware zuweisen, indem Sie ein Array von Middleware -Namen an die middleware -Methode übergeben:
Route:: get ( ' / ' , function () {
// ...
})-> middleware ([First::class, Second::class]); Sie können Middlewares einer Routengruppe zuweisen, indem Sie ein Array von Middleware -Namen an die Attribut middlewares übergeben, wenn Sie die Gruppe definieren:
Route:: group ([ " middleware " => [HasSession::class]], function () {
Route:: get ( " / " , [StoryController::class, " index " ]);
Route:: get ( " /story/{story} " , [StoryController::class, " show " ]);
}); Sie können verschachtelte Routengruppen verwenden, um Middlewares mit ihrer Elterngruppe zu kombinieren. Im nachfolgenden Beispiel wird die Middleware "Hasession" auf die Routen "/" und "/story/{story}" angewendet, während "Hasession", "Isauth" und "Log" Middlewares auf die Rest der Routes angewendet werden:
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 " ]);
});
});Im elementaren PHP -Framework ist es nicht praktisch, ganze HTML -Dokumentzeichenfolgen direkt von Routen und Controllern zurückzugeben. Ansichten bieten eine bequeme Möglichkeit, alle HTML in separaten Dateien zu platzieren.
Ansichten spielen eine entscheidende Rolle bei der Trennung von Controller/Anwendungslogik von Präsentationsbedenken und werden im app/views -Verzeichnis gespeichert. Diese in PHP geschriebenen Ansichtsdateien verkapulieren das Markup. Betrachten Sie ein grundlegendes Beispiel für eine Ansicht:
<html>
<body>
<h1>Hello, <?= $ name ?> </h1>
</body>
</html> Wenn diese Ansicht bei app/views/Welcome.php gespeichert ist, kann sie mit dem Global view -Helfer in einer Route zurückgegeben werden:
Route:: get ( ' / ' , function () {
return view ( ' Welcome ' , [ ' name ' => ' Ahmed ' ]);
}); Das erste Argument, das an die view übergeben wurde, entspricht dem Namen der Ansichtsdatei im Verzeichnis resources/views . Das zweite Argument kann eine Reihe von Schlüsselwertpaaren sein, die an die Ansicht übergeben werden. Beispielsweise ist im obigen Code $name direkt zugegriffen und enthält den Wert "Ahmed".
Ansichten können auch mit der statischen Methode make der CoreViewView -Klasse zurückgegeben werden:
Route:: get ( ' / ' , function () {
return View:: make ( " Post " , $ params );
}); Ansichten können in Unterverzeichnissen des app/views -Verzeichnisses verschachtelt werden. "DOT" -Boting kann verwendet werden, um verschachtelte Ansichten zu verweisen. Wenn Ihre Ansicht beispielsweise bei app/views/layouts/MainLayout.php gespeichert ist, können Sie sie wie SO von einer Route/Controller zurückgeben:
return view ( ' layouts.MainLayout ' , $ data ); Elemental bietet eine bequeme Möglichkeit, das gleiche Layout über mehrere Ansichten hinweg aufrechtzuerhalten und die Code -Duplikation zu verringern. Ein Layout ist selbst eine Ansichtsdatei mit einem Platzhalter {{ content }} . Wenn eine Ansicht mit dem Layout zurückgegeben wird, wird die endgültige Ansicht zusammengestellt, indem die Ansicht in den Inhalt des Layouts gelegt wird.
Elemental bietet eine bequeme Möglichkeit, das gleiche Layout über mehrere Ansichten hinweg aufrechtzuerhalten und die Code -Duplikation zu verringern. Ein Layout ist eine Ansichtsdatei, die einen benannten Platzhalter enthält, der mit {{ content }} gekennzeichnet ist. Wenn eine Ansicht unter Verwendung eines bestimmten Layouts zurückgegeben wird, wird die Zusammensetzung erreicht, indem der Inhalt der Sicht innerhalb des benannten Platzhalters in das Layout eingebettet wird. Dieser Ansatz strömt die Organisation von Ansichten und verbessert die Wartbarkeit der Code, indem gemeinsame Layoutelemente zentralisiert werden.
Unten finden Sie ein grundlegendes Beispiel:
<!DOCTYPE html >
< html lang =" en " >
< head >
<!-- Head content -->
</ head >
< body >
< ?= component("components.Navbar") ? >
< div style =" min-height: calc(100vh - 140px); " >
{{ content }}
</ div >
</ body >
</ html >Eine Ansicht kann mit einem solchen Layout zurückgegeben werden:
public function compose ()
{
return view ( " Compose " )-> withLayout ( " layouts.DashboardLayout " );
}Elemental bietet einen leistungsfähigen Ansatz für das Erstellen von Ansichten. Jede Ansicht ist im Wesentlichen eine Komponente, und jede Ansicht kann aus anderen Komponenten zusammengestellt werden. Es ist eine Symphonie der Komposition, bei der jedes Stück zur Schaffung eines harmonischen und dynamischen Ganzen beiträgt.
Beispielkomponentendatei ( views/components/Logo.php ):
<a class="logo" href="/ " >
<span class= " logo-img">
<img src="logo.png" class ="logo-text">
LOGO
</span>
</a> Diese Komponente kann in jeder anderen Ansichtsdatei verwendet werden. Zum Beispiel in views/Login.php :
<div>
<?= component ( " components.Logo " ) ?>
<p>Welcome Back!</p>
<!-- Other login form elements -->
</div>Daher befähigt Elemente Sie sowohl Layout- als auch Komponentenkonstrukte, sodass Sie Ihre Ansichten mit der Finesse sowohl von oben nach unten als auch von Bottom-up-Ansätzen zusammenstellen können. Diese Flexibilität ermöglicht eine nahtlose Fusion, bei der Sie Elemente mühelos mischen und kombinieren können, um eine elegante und anspruchsvolle Benutzeroberfläche für Ihre Anwendung zu erstellen.
In den modernen Webanwendungen ist die Datenbankinteraktion ein grundlegender Aspekt. Elemental wurde entwickelt, um diese Interaktion nahtlos in einer Vielzahl unterstützter Datenbanken zu optimieren und die inhärenten Funktionen von PHP -PDO zu nutzen. Mit Elementar haben Sie die Flexibilität, eine komplexe Abfrage oder Transaktion mithilfe der CoreDatabaseDatabase -Klasse auszuführen.
Elemental bietet einen robusten Objekt-Relational Mapper (ORM), der viele Feinheiten effektiv abstrahiert und für die Mehrheit der Datenbankabfragen von unschätzbarem Wert ist. Die CoreDatabaseDatabase kann jedoch verwendet werden, um erweiterte SQL -Abfragen auszuführen.
Alle Konfigurationen für Ihre Elementar -App befinden sich in app/config/config.php -Konfigurationsdatei Ihrer Anwendung. Hier können Sie alle Ihre Datenbankverbindungen definieren und angeben, welche Verbindung standardmäßig verwendet werden soll. Die meisten Konfigurationsoptionen in dieser Datei werden von den Werten der Umgebungsvariablen Ihrer Anwendung gestellt.
Alle Konfigurationen für Ihre Elementar -App befinden sich in app/config/config.php -Konfigurationsdatei Ihrer Anwendung. Hier können Sie alle Ihre Datenbankverbindungen definieren und angeben, welche Verbindung standardmäßig verwendet werden soll. Die meisten Konfigurationsoptionen in dieser Datei werden von den Werten der Umgebungsvariablen Ihrer Anwendung gestellt.
<?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 verwendet PDO als zugrunde liegende Datenbankhandhabungsklasse. Alle PDO -Funktionen sind direkt in der CoreDatabaseDatabase -Klasse verfügbar. Sie können eine Instanz von CoreDatabaseDatabase in eine beliebige Konstruktor- oder Controller -Methode injizieren, um PDO -Methoden aufzurufen. Die Standardkonfiguration für Elemental ist für MySQL -Datenbanken eingerichtet, aber Sie können den Treiber in der Konfigurationsdatei ändern.
Hier ist ein Beispiel für das Ausführen einer Abfrage über die 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 ();
}Weitere Informationen zu PDO finden Sie in der PDO -Dokumentation von PHP
Elemental enthält einen maßgefertigten Objektrelations-Mapper (ORM), der es angenehm macht, mit der Datenbank zu interagieren. Bei Verwendung des ORM verfügt jede Datenbanktabelle über ein entsprechendes "Modell", mit dem mit dieser Tabelle interagiert wird. Zusätzlich zum Abrufen von Datensätzen aus der Datenbanktabelle ermöglichen es Ihnen Modellen auch, auch Datensätze aus der Tabelle einzufügen, zu aktualisieren und zu löschen.
Modelle sind im app/models -Verzeichnis vorhanden und erweitern die CoreModelModel -Klasse. Sie können ein neues Modell mit dem Befehl build:model Candle generieren.
php candle build:model Post Modelle, die durch den Befehl build:model erzeugt werden, werden im app/Models -Verzeichnis platziert. Ein sehr grundlegendes Modell hat die folgende Struktur:
<?php
namespace App Models ;
use Core Model Model ;
class Post extends Model
{
// ...
} Tabellenname: Nach Konvention wird der "Schlangenfall" der pluralische Name der Klasse als Tabellenname verwendet, es sei denn, ein anderer Name wird explizit angegeben. In diesem Fall wird Elementar also angenommen, dass das Post -Modell Datensätze in der posts -Tabelle speichert.
Sie können den Tabellennamen des Modells manuell angeben, indem Sie eine tableName -Eigenschaft auf dem Modell definieren:
<?php
namespace App Models ;
use Core Model Model ;
class Post extends Model
{
protected $ tableName = ' elemental_posts ' ;
}Grundschlüssel:
Elemental wird auch davon ausgehen, dass die entsprechende Datenbanktabelle jedes Modells eine primäre Schlüsselspalte mit dem Namen id enthält. Bei Bedarf können Sie eine geschützte $primaryKey -Eigenschaft in Ihrem Modell definieren, um eine andere Spalte anzugeben, die als Primärschlüssel Ihres Modells dient:
<?php
namespace App Models ;
use Core Model Model ;
class Post extends Model
{
protected $ primaryKey = ' elemental_id ' ;
}Sie können sich jedes Modell als einen leistungsstarken Abfragebauer vorstellen, mit dem Sie die mit dem Modell zugeordnete Datenbanktabelle fließend abfragen können.
all der Methode des Modells wird alle Datensätze aus der zugehörigen Datenbanktabelle des Modells abgerufen:
use App Models Story ;
foreach (Story:: all () as $ story ) {
echo $ story [ " content " ];
}Standardmäßig werden die abgerufenen Datensätze als Array dargestellt. Sie können jedoch ein Modus -Argument übergeben, das steuert, wie jeder Datensatz dargestellt wird. Das Modus -Argument nimmt einen der PDO -Fetchmodi an. Zum Beispiel,
use App Models Story ;
foreach (Story:: all () as $ story ) {
echo $ story -> content ;
} Die Methode allWhere ist eine leistungsstarke Abstraktion im Modell, die es ermöglicht, komplexe Abfragen auszuführen. Diese Methode nimmt drei Argumente an: conditions , options und fetchMode .
public static function allWhere( array $ conditions , array $ options = [], int $ fetchMode = PDO :: FETCH_ASSOC ) Bedingungen: Der Parameter conditions ist eine Reihe von Klauseln, die der Datensatz erfüllen muss, um abgerufen zu werden. Jede Bedingung kann entweder ein [key => value] pair oder ein [key => [operator, value]] pair sein.
key entspricht einer bestimmten Spalte in der Tabelle.[key => value] befindet, ist der Standardoperator = und der value sind die Daten in dieser Spalte für den Datensatz.[key => [operator, value]] befindet, können Sie den Bediener für jede Bedingung angeben. Die unterstützten Betreiber sind:['=', '!=', '<', '>', '<=', '>=', 'LIKE', 'IS NULL', 'IS NOT NULL'] Optionen: Der options ist ein Array, das zusätzliche Abfrageargumente festlegt, z. B. order by , limit usw. unterstützte Konstrukte im Optionsargument gehören:
"orderBy""limit""offset""sortDir" FetchMode: Der Parameter fetchMode steuert, wie jeder abgerufene Datensatz dargestellt wird. Das Modus -Argument nimmt einen der PDO -Fetchmodi an:
PDO::FETCH_ASSOCPDO::FETCH_NUMPDO::FETCH_BOTHPDO::FETCH_OBJPDO::FETCH_CLASSPDO::FETCH_INTOPDO::FETCH_LAZYPDO::FETCH_KEY_PAIREin Beispiel wird es deutlicher:
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
);
}
} Zusätzlich zum Abrufen aller Datensätze, die mit einer bestimmten Abfrage entsprechen, können Sie auch einzelne Datensätze mithilfe der find und where Methode abrufen. Anstatt eine Reihe von Datensätzen zurückzugeben, geben diese Methoden eine einzelne Modellinstanz zurück:
Finden Sie: Dadurch wird der erste Datensatz abgerufen, der mit der Primärschlüssel der Tabelle übereinstimmt.
$ flight = Story:: find ( 1 ); Wo: Die Where -Methode nimmt eine Reihe von Bedingungen, die der Datensatz erfüllen muss, um abgerufen zu werden. Jede Bedingung kann entweder ein [key => value] pair oder ein [key => [operator, value]] pair sein.
key entspricht einer bestimmten Spalte in der Tabelle.[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'] .Zum Beispiel
$ 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. Zum Beispiel:
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. Das war's! Danke!
For bug reports, feature requests, or general questions, please use the issue tracker.