Elemental est un framework PHP développé à partir de zéro pour les expériences de codage dynamiques et conviviales. Il intègre des fonctionnalités telles que l'injection de dépendance et suit l'architecture MVC pour rationaliser le développement Web et améliorer l'organisation du code. Issue avec une passion pour la simplicité et la flexibilité, il invite les développeurs dans un domaine où ils peuvent exercer un contrôle inégalé et acquérir une compréhension profonde des outils à leur disposition.
Pour présenter les capacités de Elemental, une plate-forme entièrement fonctionnelle appelée Inkwell a été développée à l'aide de Elemental. Inkwell est un espace unique dédié à la pure essence de la narration. Conformément à l'objectif d'Elemental de ne pas avoir de dépendances externes, Inkwell a été conçu en utilisant uniquement HTML, CSS, JS et PHP.
N'hésitez pas à plonger à la fois sur la plate-forme en direct et la base de code correspondante. Explorez les fonctionnalités d'Inkwell pour comprendre comment élémental peut être exploité pour vos propres projets.
Voir l'inspiration derrière la création de Elemental .
Elemental a été conçu dans le but de ne pas attacher de chaînes. Il n'y a pas de dépendances sur les bibliothèques ou les cadres externes. L'objectif est de donner aux développeurs un véritable sentiment de contrôle - une porte ouverte pour explorer et comprendre indépendamment les choses magiques qui alimentent le cadre.
Le but global? Laissez les développeurs embrasser et tirer parti de l'élégance des abstractions puissantes comme les conteneurs DI, les orms, les moyennes intermédiaires, etc. Mais voici le botteur - l'élémentaire ne pointe pas seulement la voie. Cela vous donne les clés pour démêler les mystères, vous permettant d'explorer comment ces abstractions sont présentées dans le code.
En fait, vous êtes encouragé non seulement à suivre le chemin mais à vous aventurer hors des sentiers battus. Plongez dans la base de code, disséquez les abstractions et comprenez leur fonctionnement interne. N'hésitez pas à modifier et à expérimenter, car Elemental n'est pas seulement un cadre - c'est une invitation ouverte à façonner et à façonner les outils à votre disposition. Parce que le codage ne devrait pas être un labyrinthe; Ce devrait être un voyage. Faisons ce voyage ensemble.
Contrairement à d'autres frameworks, Elemental ne reposait pas sur des bibliothèques compositeurs ou externes. C'est aussi simple que de cloner le référentiel et de commencer avec un bon ol 'php installé sur votre système.
Ouvrez votre terminal et exécutez la commande suivante:
git clone https://github.com/aneesmuzzafer/elemental.gitPas de soucis concernant les gestionnaires de packages ou les dépendances - Elemental est construit à partir de zéro pour vous libérer de ces préoccupations.
Pour ceux qui préfèrent l'itinéraire du compositeur, la création d'une nouvelle application élémentaire n'est qu'à une commande:
composer create-project fragment/elemental sample-app Cela générera un projet avec un fichier composer.json .
Une fois votre projet prêt, lancez le serveur de développement local élémentaire avec la commande ignite en utilisant notre moteur de ligne de commande, bougie :
cd sample-app
php candle igniteLe tour est joué! Votre application est désormais accessible à http://127.0.0.1:8000.
Nous avons pris soin de la configuration de base afin que vous puissiez vous concentrer sur la magie.
Laissez l'enchantement commencer!
La caractéristique la plus importante de l'élémentaire est son conteneur d'injection de dépendance qu'il utilise pour gérer les dépendances des cours et effectuer une injection de dépendance.
L'injection de dépendance est un modèle de conception dans le développement de logiciels qui traite de la façon dont les composants se réunissent de leurs dépendances. Dans un système traditionnel, une classe est responsable de la création de ses propres dépendances. Avec DI, la responsabilité de créer et de fournir des dépendances est déplacée en dehors de la classe. Au lieu d'une classe créant ses dépendances, elles sont "injectées" dans la classe à partir d'une source externe.
DI aide à réaliser un code à couplage lâche et plus maintenable. Il favorise la séparation des préoccupations en permettant à chaque classe de se concentrer sur sa fonctionnalité spécifique sans se soucier de la façon de créer ou d'obtenir ses dépendances.
L'injection de dépendance est une implémentation spécifique du concept plus large connu sous le nom d'inversion du contrôle (CIO). L'IOC représente un paradigme de conception où le flux de contrôle d'un programme est inversé ou remis à une entité, un conteneur ou un cadre externe.
Dans Elemental, lorsque vous utilisez l'injection de dépendance (DI), si une classe ne s'appuie pas sur d'autres classes ou si l'on compte uniquement des classes concrètes (pas des interfaces abstraites), vous n'avez pas besoin de dire explicitement au conteneur DI comment créer une instance de cette classe. Le conteneur DI le comprendra automatiquement.
Le conteneur tentera de créer une instance de la classe, et si cette classe a des dépendances sur d'autres classes, le conteneur essaiera également de résoudre ces dépendances. Ce processus se poursuit jusqu'à ce que toutes les classes nécessaires soient résolues avec succès. Ainsi, vous n'avez pas à spécifier manuellement comment créer chaque classe - le conteneur DI s'en occupe pour vous.
<?php
class MailService {
public function __construct ( private MailerAgent $ mailer ) {
}
}
// Inside some other class
class UserController {
public function sendMail ( MailService $ mailService )
{
$ mailService -> sendMail ();
}
} Ici, en hentant le MailService à l'intérieur de l'argument de la méthode, Elemental a pu résoudre la classe et créer une instance de cette classe et la transmettre au sendMail afin que vous puissiez l'utiliser sans vous soucier des dépendances requises par la classe MailService . Comme vous pouvez le voir, le MailService lui-même dépend d'une autre classe MailerAgent , cependant, Elemental s'est occupée de résoudre la classe MailerAgent dans les coulisses, l'a transmise au MailService tout en créant son instance et a fourni cet exemple pour votre usage.
"Alors, où ce type de dépendances injectant-t-il simplement en honnant le nom de classe fonctionnera-t-il en élémentaire?" Toutes les fonctions constructor de classe, toutes les controller methods et la méthode handle de la classe de création de commandes.
Dans les coulisses, élémentaire résout une classe ou une interface dans une instance concrète en examinant les liaisons enregistrées. En d'autres termes, afin de dire explicitement au framework quant à la façon de résoudre l'instance d'une classe ou d'une interface particulière, vous devrez enregistrer une liaison de cette classe ou interface à l'aide de la méthode bind sur l'instance Application , en passant le nom de classe ou d'interface que nous souhaitons enregistrer avec une fermeture qui renvoie une instance de la classe:
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));
});Notez que vous n'aurez généralement pas besoin de lier une classe uniquement lorsque vous devez exécuter une logique supplémentaire pour résoudre une classe, ou vous devez lier une interface à une implémentation concrète. Sinon, Elemental résoudra la classe sans vous obliger explicitement à le lier.
La méthode singleton lie une classe ou une interface avec le conteneur, garantissant qu'il n'est résolu qu'une seule fois. Après la résolution initiale, tous les appels ultérieurs au conteneur pour la même liaison renverront la même instance d'objet.
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 Bien qu'il soit parfaitement bien d'enregistrer une liaison n'importe où dans l'application, il est souvent nécessaire de le lier pendant que l'application est en constante évolution, afin que d'autres composants de l'application puissent commencer à l'utiliser. Elemental fournit un endroit spécial pour enregistrer toutes les liaisons de l'application et effectuer toute autre logique d'amorçage requise par votre application. Il s'agit d'approvider AppBootstrapAppServiceProvider . Le fournisseur de services d'application contienne un register et une méthode boot .
Dans la méthode register , vous devez lier les choses dans le conteneur d'injection de dépendance. Cependant, vous ne devez pas essayer de résoudre une liaison. itinéraires ou exécuter toute autre fonctionnalité dans la méthode register . Sinon, vous pouvez accidentellement utiliser un service à l'intérieur d'un conteneur qui n'a pas encore chargé.
Cette méthode est appelée une fois que tous les autres fournisseurs de services ont été enregistrés, accordant l'accès à tous les services enregistrés par le cadre. Toute logique d'initialisation que vous souhaitez exécuter doit être placée ici.
<?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
}
} Vous pouvez utiliser la méthode make pour résoudre une instance de classe dans le conteneur DI. La méthode make sur l'instance d'application accepte le nom de la classe ou de l'interface que vous souhaitez résoudre:
use App Services MailService ;
$ mailService = app ()-> make (MailService::class); Vous pouvez également obtenir l'instance d'application à l'aide de l' instance de méthode statique directement sur la classe Application .
use Core Main Application ;
use App Services MailService ;
$ mailService = Application:: instance ()-> make (MailService::class); La méthode make est particulièrement utile lors de la tentative de résolution d'une classe à partir d'un composant de code où il n'est pas pratique d'injecter une dépendance à l'aide de type hentoureuse. Dans de tels scénarios, vous pouvez demander explicitement le conteneur d'injection de dépendance de l'application pour résoudre une instance pour vous.
Les routes sont définies dans le fichier approutes.php , permettant aux développeurs d'enregistrer facilement divers itinéraires pour gérer différentes demandes HTTP.
Les itinéraires sont enregistrés en invoquant la méthode pertinente sur la façade de la route, comme Route::get() , et impliquent de spécifier un modèle URI comme premier argument. Le deuxième argument peut être une fermeture ou un tableau qui définit le contrôleur et la méthode responsable de la gestion de la demande.
Par exemple:
<?php
use App Controllers AuthController ;
use Core Facade Route ;
Route:: get ( " /settings " , function () {
// handling logic goes here
});
Route:: post ( " /register " , [AuthController::class, " register " ]);Chaque fois qu'une demande URI est appariée, la méthode de fermeture ou de contrôleur correspondante est exécutée, et une réponse est générée et renvoyée au navigateur.
Vous pouvez enregistrer des itinéraires qui répondent à tout verbe HTTP en utilisant les méthodes suivantes:
Route::get($uri, $callback);Route::post($uri, $callback);Route::put($uri, $callback);Route::patch($uri, $callback);Route::delete($uri, $callback);Route::options($uri, $callback); Parfois, vous devrez capturer des segments de l'URI dans votre itinéraire. Par exemple, vous devrez peut-être capturer l'ID d'un utilisateur à partir de l'URL. Vous pouvez le faire en définissant les paramètres de route:
Route:: get ( ' /user/{id} ' , function ( string $ id ) {
return ' User ' . $ id ;
});
Route:: get ( " /story/{id} " , function ( $ id ) { /*...*/ });Vous pouvez définir autant de paramètres d'itinéraire que requis par votre itinéraire:
Route:: post ( " story/edit/{id} " , [StoryController::class, " edit " ]);
Route:: get ( " story/{story_id}/comment/{comment_id} " , [StoryController::class, " comment " ]);Ceux-ci seront également transmis dans la méthode du contrôleur.
Élémental gère sans couture l'injection de dépendances nécessaires pour vos méthodes de contrôleur. Cela vous permet de spécifier toutes les dépendances requises par votre itinéraire dans la signature de rappel à l'aide de type hint. Elemental s'occupe de résoudre et d'injecter automatiquement les dépendances déclarées dans le rappel.
Par exemple, si vous tapez CoreRequestRequest taper dans le rappel, Elemental garantit que la demande HTTP actuelle est automatiquement injectée dans votre rappel d'itinéraire:
<?php
use Core Request Request ;
Route:: get ( ' /users ' , function ( Request $ request ) {
// ...
});Vous pouvez mettre les dépendances et les paramètres de route typés dans n'importe quel ordre.
Lorsque vous transmettez un ID de modèle en tant que paramètre à une action d'itinéraire ou de contrôleur, l'approche typique implique d'interroger la base de données pour récupérer le modèle correspondant en fonction de cet ID. Elemental simplifie ce processus via la liaison du modèle de route, offrant un moyen pratique d'injecter automatiquement des instances de modèle directement dans vos itinéraires.
Par exemple, au lieu d'injecter uniquement l'ID d'un utilisateur dans votre itinéraire, vous avez la possibilité d'injecter toute l'instance du modèle utilisateur qui correspond à l'ID donné.
Dans le contexte des itinéraires ou des actions de contrôleur, les modèles sont définis à l'aide de noms de variables introduits de type qui correspondent à un segment spécifique de l'itinéraire. Par exemple:
use App Models User ;
Route:: get ( ' /users/{user} ' , function ( User $ user ) {
return $ user -> email ;
}); Parfois, vous pouvez résoudre des modèles à l'aide d'une colonne autre que id . Pour ce faire, vous pouvez spécifier la colonne dans la définition du paramètre de route:
use App Models User ;
Route:: get ( ' /users/{user:email} ' , function ( User $ user ) {
return $ user ;
});Dans ce scénario, Elemental injectera de manière transparente l'instance de modèle qui possède un e-mail correspondant à la valeur correspondante de l'URI de la demande.
Bien sûr, la liaison au model d'itinéraire fonctionne également avec les méthodes de contrôleur.
Si une instance de modèle correspondante n'est pas trouvée dans la base de données, un ModelNotFoundException sera lancé par l'application. Vous pouvez gérer de telles exceptions et contrôler le comportement de telles exceptions ou autres exprimées par l'application dans la classe ExceptionsHandler . Plus à ce sujet plus tard.
En utilisant la méthode Route::fallback , vous pouvez définir un itinéraire qui sera exécuté lorsqu'aucune autre route ne correspond à la demande entrante.
Route:: fallback ( function () {
// ...
}); La commande route:list Candle fournira la liste de tous les itinéraires définis dans l'application:
php candle route:list Plutôt que de consolider toutes les logiques de traitement des demandes dans les fermetures dans vos fichiers d'itinéraire, envisagez de structurer ce comportement via des classes "Controller". Les contrôleurs vous permettent d'organiser la logique de traitement des demandes connexes dans une classe cohésive. Par exemple, une classe UserController pourrait gérer diverses demandes entrantes liées aux utilisateurs, telles que l'affichage, la création, la mise à jour et la suppression des utilisateurs. Ces classes de contrôleur sont conventionnellement stockées dans le répertoire app/Controllers .
Pour générer un nouveau contrôleur, vous pouvez exécuter la commande build:controller Candle.
php candle build:controller UserController Cela générera un nouveau fichier nommé "userController.php" dans le répertoire app/Controllers .
Un contrôleur peut avoir un certain nombre de méthodes publiques qui répondront aux demandes HTTP entrantes:
<?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 ( " / " );
}
}Après avoir créé une classe de contrôleur et ses méthodes, vous pouvez définir un itinéraire vers la méthode du contrôleur comme suit:
use App Controllers UserController ;
Route:: get ( " /register " , [AuthController::class, " showRegister " ]); Lorsqu'une demande reçue correspond à l'URI de route désignée, la méthode showRegister dans la classe AppControllersUserController sera appelée et la méthode recevra les paramètres de route correspondants.
Le conteneur de service élémentaire est responsable de la résolution des instances de tous les contrôleurs. Par conséquent, vous pouvez utiliser de type hint dans le constructeur de votre contrôleur pour spécifier toutes les dépendances dont il peut nécessiter. Les dépendances déclarées seront automatiquement résolues et injectées dans l'instance du contrôleur
<?php
namespace App Controllers ;
use Core Database Database ;
class UserController
{
/**
* Create a new controller instance.
*/
public function __construct (
public Database $ db ,
) {}
} Outre l'injection des dépendances via le constructeur, vous pouvez également utiliser la hontesse de type pour les dépendances dans les méthodes de votre contrôleur. Un cas d'utilisation courant pour l'injection de méthode consiste à injecter le CoreRequestRequest ou toute instance de service dans vos méthodes de contrôleur:
Créer et gérer les contrôleurs pour gérer efficacement les demandes.
<?php
namespace App Controllers ;
use Core Request Request ;
use App Services Auth ;
class StoryController
{
public function create ( Request $ request )
{
$ data = $ request -> data ();
$ user = Auth:: user ();
$ story = Story:: create ([...]);
return redirect ( " /story/ $ story -> id " );
}
}f Votre méthode de contrôleur prévoit la saisie d'un paramètre d'itinéraire, vous avez la flexibilité de répertorier vos arguments dans n'importe quel ordre. Par exemple, considérez la définition de l'itinéraire suivante:
Route:: post ( " story/update/{id} " , [StoryController::class, " update " ]); Vous pouvez toujours saisir la base du paramètre CoreRequestRequest et accéder à votre paramètre id en définissant votre méthode de contrôleur comme suit:
<?php
namespace App Controllers ;
use Core Request Request ;
class StoryController
{
public function update ( string $ id , Request $ request )
{
// Update $story
return redirect ( " /story/ $ story -> id " );
}
} La classe CoreRequestRequest dans Elemental propose une approche orientée objet pour s'engager avec la demande HTTP actuelle gérée par votre application. Il facilite la récupération des entrées, des cookies et des fichiers soumis avec la demande.
Pour acquérir l'instance de demande HTTP actuelle via l'injection de dépendance, vous pouvez utiliser la clôture de type de type pour la classe CoreRequestRequest dans votre méthode de fermeture ou de contrôleur d'itinéraire. Le conteneur de service injectera automatiquement l'instance de demande entrante.
<?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 " );
}
}Le conteneur de service injectera automatiquement la demande entrante dans la fermeture de l'itinéraire.
Si votre méthode de contrôleur anticipe les entrées d'un paramètre d'itinéraire, vous avez la flexibilité de répertorier vos arguments dans n'importe quel ordre. Par exemple, considérez la définition de l'itinéraire suivante:
Route:: post ( " story/update/{id} " , [StoryController::class, " update " ]); Vous pouvez toujours saisir la base du paramètre CoreRequestRequest et accéder à votre paramètre id en définissant votre méthode de contrôleur comme suit:
<?php
namespace App Controllers ;
use Core Request Request ;
class StoryController
{
public function update ( string $ id , Request $ request )
{
// Update $story
return redirect ( " /story/ $ story -> id " );
}
} Vous pouvez obtenir toutes les données d'entrée de la demande entrante en tant que array à l'aide de la méthode data() . Cette méthode peut être utilisée, que la demande entrante provienne d'un formulaire HTML ou soit une demande XHR:
$ data = $ request -> data (); Vous pouvez accéder à toutes les entrées de l'utilisateur de votre instance Request sans vous soucier du verbe HTTP utilisé pour la demande. Quel que soit le verbe HTTP, la méthode data peut être utilisée pour récupérer l'entrée utilisateur:
$ name = $ request -> data ()[ " name " ]; L'instance CoreRequestRequest fournit une variété de méthodes d'examen de la demande HTTP entrante. Discutons de quelques-unes des méthodes les plus importantes ci-dessous.
Vous pouvez récupérer les en-têtes de demande à partir de l'instance CoreRequestRequest à l'aide de la méthode headers .
$ headers = $ request -> headers (); Vous pouvez récupérer la méthode de la demande en appelant method sur l'instance CoreRequestRequest .
$ method = $ request -> method (); Vous pouvez récupérer l'uri de demande à l'instance CoreRequestRequest à l'aide de la méthode uri .
$ uri = $ request -> uri (); Vous pouvez récupérer les cookies de demande à partir de l'instance CoreRequestRequest à l'aide de la méthode cookies .
$ cookies = $ request -> cookies (); Vous pouvez récupérer le contenu brut à partir de l'instance CoreRequestRequest à l'aide de la méthode rawContent .
$ content = $ request -> rawContent ();Soyez prudent lorsque vous traitez avec le contenu brut d'une demande.
Vous pouvez récupérer les fichiers à partir de l'instance CoreRequestRequest à l'aide de la méthode files .
$ files = $ request -> files (); La méthode ip peut être utilisée pour récupérer l'adresse IP du client qui a fait la demande à votre application:
$ ipAddress = $ request -> ip (); La méthode port peut être utilisée pour récupérer l'adresse du port du client qui a fait la demande à votre application:
$ port = $ request -> port (); Vous pouvez récupérer le type de contenu à partir de l'instance CoreRequestRequest à l'aide de la méthode contentType .
$ contentType = $ request -> contentType (); Vous pouvez récupérer la chaîne de requête de la demande à l'aide de la méthode queryString .
$ query = $ request -> queryString (); Vous pouvez récupérer le contenu texte de la demande en utilisant la méthode text à condition que le type de contenu soit défini sur text/plain
$ text = $ request -> text (); Vous pouvez récupérer le contenu JS de la demande en utilisant la méthode js à condition que le type de contenu soit défini sur application/javascript
$ js = $ request -> js (); Vous pouvez récupérer le contenu HTML de la demande en utilisant la méthode html à condition que le type de contenu soit défini sur text/html
$ js = $ request -> html (); Vous pouvez récupérer le contenu JSON de la demande à l'aide de la méthode json à condition que le type de contenu soit défini sur application/json le $request->data() renvoie toutes les données JSON transmises à la demande. Cependant,
$ jsonData = $ request -> json (); Le $request->data() contient toutes les données JSON ainsi que les entrées transmises par les paramètres de requête dans la demande. Cependant, $request->json() peut être utilisé pour récupérer uniquement le contenu JSON.
Vous pouvez récupérer le contenu XML de la demande en utilisant la méthode xml à condition que le type de contenu soit défini sur application/json
$ xmlData = $ request -> xml ();Chaque itinéraire et contrôleur devrait produire une réponse pour la livraison au navigateur de l'utilisateur. Elemental propose diverses méthodes pour générer des réponses. La forme de réponse la plus simple consiste à renvoyer une chaîne directement à partir d'un itinéraire ou d'un contrôleur. Le cadre convertira de manière transparente cette chaîne en une réponse HTTP complète.
Route:: get ( ' / ' , function () {
return ' Hello World ' ;
});En plus de retourner les chaînes de vos itinéraires et contrôleurs, vous pouvez également retourner des tableaux ou des objets. Le cadre les convertira automatiquement en une réponse JSON:
Route:: get ( ' / ' , function () {
return [ 1 , 2 , 3 ];
}); Habituellement, vous ne retournerez pas simplement des chaînes ou des tableaux simples de vos actions d'itinéraire. Au lieu de cela, vous retournerez souvent des instances complètes de CoreResponseResponse ou Views.
Le retour d'une instance Response complète vous permet de personnaliser le code d'état HTTP de la réponse et les en-têtes. Vous pouvez injecter l'instance de réponse en hentant l'instance de réponse à l'intérieur de votre contrôleur ou fermeture de l'itinéraire.
use Core Response Response ;
Route:: get ( ' /home ' , function ( Response $ response ) {
$ response -> setHeader ( " content-type " , " text/plain " )
-> setStatusCode ( 200 )
-> setContent ( " Hello World " );
return $ response ;
}); Vous pouvez bien sûr renvoyer une view d'un contrôleur. Cependant, si vous avez besoin de contrôler l'état et les en-têtes de la réponse, mais que vous devez également renvoyer une view comme le contenu de la réponse, vous pouvez le faire comme suit:
use Core Response Response ;
class UserController {
public function register ( Response $ response ){
$ response -> setHeader ( " x-is_register " , " true " );
return view ( " Register " );
}
}Cela définira automatiquement l'en-tête de la réponse de la vue qui sera envoyée au navigateur.
Gardez à l'esprit que la plupart des méthodes de réponse sont chaînables, permettant la construction courante des instances de réponse.
Vous pouvez définir le contenu de la réponse en utilisant la méthode setContent sur l'instance de réponse.
$ response -> setContent ( " ... " ); Cependant, si vous souhaitez ajouter le contenu de la réponse, vous pouvez le faire en utilisant la méthode appendContent sur l'instance de réponse.
$ response -> appendContent ( " ... " ); Vous pouvez définir un en-tête sur l'instance de réponse en utilisant la méthode setHeader
$ response -> setHeader ( " content-type " , " text/plain " ); Cependant, si vous souhaitez définir plusieurs en-têtes simultanément, vous pouvez le faire en utilisant la méthode setHeaders et en passant un tableau d'en-têtes.
$ response -> setHeaders ([ " content-type " => " text/html " , ...]); Vous pouvez définir directement le code d'état de la réponse en utilisant la méthode setHeader sur l'instance de réponse.
$ response -> setStatusCode ( 301 );Un texte d'état sera défini par défaut pour les codes d'état communs.
Vous pouvez générer une réponse de redirection qui contient les en-têtes appropriés nécessaires pour rediriger l'utilisateur vers une autre URL en invoquant redirect de méthode statique sur la classe CoreResponseResponse .
use Core Response Response ;
Route:: get ( ' /dashboard ' , function () {
return Response:: redirect ( ' home/dashboard ' );
}); Cependant, pour la simplicité, une méthode d'assistance redirect() est également disponible à l'échelle mondiale pour obtenir les mêmes fonctionnalités.
use Core Response Response ;
Route:: post ( ' /story/create ' , function () {
if (! $ someCondition )
return redirect ( ' /story ' , 204 );
}); Vous pouvez également générer une réponse JSON en appelant la méthode statique JSON sur la classe CoreResponseResponse . Les données transmises à la méthode seront converties en JSON approprié. Vous pouvez également passer éventuellement le code d'état et le tableau des en-têtes comme deuxième et troisième argument à la fonction.
use Core Response Response ;
Route:: post ( ' /post ' , function () {
$ post = ( . . . );
return Response:: JSON ( $ post , 201 , [ " header " => " value " ]);
});Middleware offre un mécanisme pratique pour examiner et filtrer les demandes HTTP entrantes à votre demande. Par exemple, vous pouvez développer middleware pour valider l'état d'authentification de l'utilisateur de votre application. Si l'utilisateur n'est pas authentifié, le middleware les redirigera vers l'écran de connexion. Inversement, si l'utilisateur est authentifié, le middleware permettra à la demande de progresser plus profondément dans l'application.
Vous avez la flexibilité de créer un middleware supplémentaire pour exécuter diverses tâches au-delà de l'authentification. Comme illustration, un middleware de journalisation pourrait enregistrer toutes les demandes entrantes à votre application. Ces composants middleware sont logés dans le répertoire app/middlewares .
Pour créer un nouveau middleware, utilisez la commande build:middleware Candle:
php candle build:middleware IsAuthenticated L'exécution de cette commande générera une nouvelle classe de middleware nommée "IsAuthenticated" dans le répertoire app/middlewares . Dans cette classe, une méthode nommée handle est créée où vous pouvez articuler la logique du middleware.
Ici, nous autoriserons l'accès à l'itinéraire que si l'utilisateur est authentifié, sinon, nous redirigerons les utilisateurs vers l'URI login :
<?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 );
}
} Pour transmettre la demande plus profondément dans la demande, vous devez appeler le $next avec la $request .
Considérez le middleware comme une séquence de "couches" que HTTP demande parcourir avant d'atteindre votre application. Chaque couche a la capacité d'examiner la demande et de la rejeter potentiellement.
Bien sûr, un middleware peut effectuer des tâches avant ou après avoir passé la demande plus profondément dans l'application. Par exemple, ce middleware effectuerait sa tâche une fois la demande traitée par l'application:
<?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 ;
}
} Si vous souhaitez attribuer un middleware à des itinéraires spécifiques, vous pouvez invoquer la méthode middleware lors de la définition de l'itinéraire:
Route:: get ( ' /profile ' , function () {
// ...
})-> middleware (IsAuthenticated::class); Vous pouvez attribuer plusieurs middleware à l'itinéraire en passant un tableau de noms de middleware à la méthode middleware :
Route:: get ( ' / ' , function () {
// ...
})-> middleware ([First::class, Second::class]); Vous pouvez affecter Middlewares à un groupe de routes en passant un tableau de noms de middleware à l'attribut middlewares lors de la définition du groupe:
Route:: group ([ " middleware " => [HasSession::class]], function () {
Route:: get ( " / " , [StoryController::class, " index " ]);
Route:: get ( " /story/{story} " , [StoryController::class, " show " ]);
}); Vous pouvez utiliser des groupes d'itinéraires imbriqués pour combiner MiddleWares avec leur groupe parent. Dans l'exemple suivant, le middleware "Hassession" est appliqué aux routes "/" et "/story/{story}" , tandis que "Hassession", "Isauth" et "Log" Middlewares s'appliquent au reste des routes:
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 " ]);
});
});Dans le cadre PHP élémentaire, il n'est pas pratique de renvoyer des chaînes de documents HTML entières directement à partir des routes et des contrôleurs. Les vues offrent un moyen pratique de placer tous les HTML dans des fichiers séparés.
Les vues jouent un rôle crucial dans la séparation de la logique du contrôleur / application des problèmes de présentation et sont stockés dans le répertoire app/views . Ceux-ci affichent les fichiers, écrits en PHP, encapsulent le balisage. Considérez un exemple de base d'une vue:
<html>
<body>
<h1>Hello, <?= $ name ?> </h1>
</body>
</html> Si cette vue est stockée sur app/views/Welcome.php , elle peut être renvoyée à l'aide de l'assistance Global view dans un itinéraire:
Route:: get ( ' / ' , function () {
return view ( ' Welcome ' , [ ' name ' => ' Ahmed ' ]);
}); Le premier argument transmis à l'assistant view correspond au nom du fichier de vue dans le répertoire resources/views . Le deuxième argument peut être un tableau de paires de valeurs clés passées à la vue. Par exemple, dans le code ci-dessus, $name sera directement accessible et contiendra la valeur «Ahmed».
Les vues peuvent également être renvoyées à l'aide de la méthode statique make sur la classe CoreViewView :
Route:: get ( ' / ' , function () {
return View:: make ( " Post " , $ params );
}); Les vues peuvent être imbriquées dans les sous-répertoires du répertoire app/views . La notation "point" peut être utilisée pour référencer les vues imbriquées. Par exemple, si votre vue est stockée sur app/views/layouts/MainLayout.php , vous pouvez le retourner à partir d'un itinéraire / contrôleur comme tel:
return view ( ' layouts.MainLayout ' , $ data ); Elemental fournit un moyen pratique de maintenir la même mise en page sur plusieurs vues, réduisant la duplication de code. Une mise en page est elle-même un fichier d'affichage contenant un espace réservé {{ content }} . Lorsqu'une vue est retournée avec la mise en page, la vue finale est compilée en mettant la vue à l'intérieur du contenu de la disposition.
Elemental fournit un moyen pratique de maintenir la même mise en page sur plusieurs vues, réduisant la duplication de code. Une mise en page est un fichier de vue qui intègre un espace réservé désigné, indiqué par {{ content }} . Lorsqu'une vue est renvoyée à l'aide d'une disposition spécifique, la composition est obtenue en intégrant le contenu de la vue dans le lieu de placement désigné dans la disposition. Cette approche rationalise l'organisation des vues et améliore la maintenabilité du code en centralisant les éléments de disposition communs.
Vous trouverez ci-dessous un exemple de base:
<!DOCTYPE html >
< html lang =" en " >
< head >
<!-- Head content -->
</ head >
< body >
< ?= component("components.Navbar") ? >
< div style =" min-height: calc(100vh - 140px); " >
{{ content }}
</ div >
</ body >
</ html >Une vue peut être retournée avec une mise en page comme celle-ci:
public function compose ()
{
return view ( " Compose " )-> withLayout ( " layouts.DashboardLayout " );
}Elemental offre une approche puissante pour l'élaboration de vues. Chaque vue est essentiellement un composant, et toute vue peut être assemblée à partir d'autres composants. C'est une symphonie de composition, où chaque pièce contribue à la création d'un ensemble harmonieux et dynamique.
Exemple de fichier de composant ( views/components/Logo.php ):
<a class="logo" href="/ " >
<span class= " logo-img">
<img src="logo.png" class ="logo-text">
LOGO
</span>
</a> Ce composant peut être utilisé dans n'importe quel autre fichier d'affichage. Par exemple, dans views/Login.php :
<div>
<?= component ( " components.Logo " ) ?>
<p>Welcome Back!</p>
<!-- Other login form elements -->
</div>Ainsi, élémentaire vous permet à la fois des constructions de mise en page et de composants, vous permettant de composer vos vues avec la finesse des approches de haut en bas et de bas en haut. Cette flexibilité permet une fusion transparente, où vous pouvez mélanger et combiner sans effort des éléments pour élaborer une interface utilisateur élégante et sophistiquée pour votre application.
Dans les applications Web modernes, l'interaction de la base de données est un aspect fondamental. Elemental a été conçu pour rationaliser cette interaction de manière transparente à travers une gamme diversifiée de bases de données prises en charge, en tirant parti des capacités inhérentes de PHP PDO. Avec Elemental, vous avez la flexibilité d'exécuter n'importe quelle requête ou transaction complexe à l'aide de la classe CoreDatabaseDatabase .
Elemental propose un mappeur commercial robuste (ORM) qui résume efficacement de nombreuses subtilités, se révélant inestimable pour la majorité des requêtes de base de données. Cependant, la CoreDatabaseDatabase peut être utilisée pour exécuter des requêtes SQL plus avancées.
Toutes les configurations de votre application élémentaire sont situées dans le fichier de configuration app/config/config.php de votre application. Ici, vous pouvez définir toutes vos connexions de base de données, ainsi que spécifier quelle connexion doit être utilisée par défaut. La plupart des options de configuration de ce fichier sont motivées par les valeurs des variables d'environnement de votre application.
Toutes les configurations de votre application élémentaire sont situées dans le fichier de configuration app/config/config.php de votre application. Ici, vous pouvez définir toutes vos connexions de base de données, ainsi que spécifier quelle connexion doit être utilisée par défaut. La plupart des options de configuration de ce fichier sont motivées par les valeurs des variables d'environnement de votre application.
<?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 utilise PDO comme classe de gestion de la base de données sous-jacente. Toutes les fonctions PDO sont directement disponibles sur la classe de base CoreDatabaseDatabase . Vous pouvez injecter une instance de CoreDatabaseDatabase dans n'importe quelle méthode de constructeur ou de contrôleur pour appeler les méthodes PDO. La configuration par défaut de l'élémental est configurée pour les bases de données MySQL, mais vous pouvez modifier le pilote dans le fichier de configuration.
Voici un exemple d'exécution d'une requête via l'instance Database :
public function tokens ( Database $ db ) {
$ user_id = 1 ;
$ sql = " SELECT * FROM access_tokens WHERE user_id = :user_id " ;
$ stmt = $ db -> prepare ( $ sql );
$ stmt -> bindValue ( " :user_id " , $ user_id );
$ stmt -> execute ();
$ tokens = $ stmt -> fetchAll ();
}Pour plus d'informations sur l'OPD, vous pouvez vous référer à la documentation PDO de PHP
Elemental comprend un mappeur d'objet (ORM) sur mesure qui rend agréable d'interagir avec la base de données. Lorsque vous utilisez l'ORM, chaque table de base de données a un "modèle" correspondant qui est utilisé pour interagir avec ce tableau. En plus de récupérer les enregistrements de la table de la base de données, les modèles vous permettent également d'insérer, de mettre à jour et de supprimer les enregistrements du tableau.
Les modèles sont présents dans le répertoire app/models et étendent la classe CoreModelModel . Vous pouvez générer un nouveau modèle en utilisant la commande build:model de bougie.
php candle build:model Post Les modèles générés par la build:model seront placés dans le répertoire app/Models . Un modèle très basique a la structure suivante:
<?php
namespace App Models ;
use Core Model Model ;
class Post extends Model
{
// ...
} Nom de la table: Par convention, le «cas de serpent», le nom pluriel de la classe sera utilisé comme nom de table à moins qu'un autre nom ne soit explicitement spécifié. Ainsi, dans ce cas, Elemental supposera que les enregistrements des magasins Post modèle dans le tableau posts .
Vous pouvez spécifier manuellement le nom de la table du modèle en définissant une propriété tableName sur le modèle:
<?php
namespace App Models ;
use Core Model Model ;
class Post extends Model
{
protected $ tableName = ' elemental_posts ' ;
}Clé primaire:
Elemental supposera également que la table de base de données correspondante de chaque modèle a une colonne de clé principale nommée id . Si nécessaire, vous pouvez définir une propriété $primaryKey protégée sur votre modèle pour spécifier une autre colonne qui sert de clé principale de votre modèle:
<?php
namespace App Models ;
use Core Model Model ;
class Post extends Model
{
protected $ primaryKey = ' elemental_id ' ;
}Vous pouvez considérer chaque modèle comme un puissant constructeur de requêtes vous permettant de demander couramment la table de base de données associée au modèle.
La méthode all du modèle récupérera tous les enregistrements de la table de base de données associée du modèle:
use App Models Story ;
foreach (Story:: all () as $ story ) {
echo $ story [ " content " ];
}Par défaut, les enregistrements récupérés sont représentés comme un tableau. Cependant, vous pouvez transmettre un argument de mode qui contrôle la façon dont chaque enregistrement est représenté. L'argument de mode prend l'un des modes de récupération APD. Par exemple,
use App Models Story ;
foreach (Story:: all () as $ story ) {
echo $ story -> content ;
} La méthode allWhere est une abstraction puissante dans le modèle qui permet d'exécuter des requêtes complexes. Cette méthode prend trois arguments: conditions , options et fetchMode .
public static function allWhere( array $ conditions , array $ options = [], int $ fetchMode = PDO :: FETCH_ASSOC ) Conditions: Le paramètre conditions est un tableau de clauses que l'enregistrement doit satisfaire pour être récupéré. Chaque condition peut être une paire [key => value] ou une paire [key => [operator, value]] .
key correspond à une colonne spécifique du tableau.[key => value] , l'opérateur par défaut est = et la value est les données à l'intérieur de cette colonne pour l'enregistrement.[key => [operator, value]] , vous pouvez spécifier l'opérateur pour chaque condition. Les opérateurs pris en charge sont:['=', '!=', '<', '>', '<=', '>=', 'LIKE', 'IS NULL', 'IS NOT NULL'] . Options: Le paramètre options est un tableau qui détermine les arguments de requête supplémentaires, tels que order by , limit , etc. Les constructions prises en charge dans l'argument des options incluent:
"orderBy""limit""offset""sortDir" FetchMode: Le paramètre fetchMode contrôle la façon dont chaque enregistrement récupéré est représenté. L'argument de mode prend l'un des modes de récupération de PDO:
PDO::FETCH_ASSOCPDO::FETCH_NUMPDO::FETCH_BOTHPDO::FETCH_OBJPDO::FETCH_CLASSPDO::FETCH_INTOPDO::FETCH_LAZYPDO::FETCH_KEY_PAIRUn exemple le rendra plus clair:
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
);
}
} En plus de récupérer tous les enregistrements correspondant à une requête donnée, vous pouvez également récupérer des enregistrements uniques à l'aide de la méthode find and where . Au lieu de retourner un tableau d'enregistrements, ces méthodes renvoient une seule instance de modèle:
Find: Cela va récupérer le premier enregistrement qui correspond à la clé principale du tableau.
$ flight = Story:: find ( 1 ); Où: La méthode où prend un tableau de conditions que l'enregistrement doit satisfaire pour être récupéré. Chaque condition peut être une paire [key => value] ou une paire [key => [operator, value]] .
key correspond à une colonne spécifique du tableau.[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'] .Par exemple
$ 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. Par exemple:
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:
frapper
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. C'est ça! Merci!
For bug reports, feature requests, or general questions, please use the issue tracker.