Un cadre micro PHP adaptable qui essaie de rester à l'écart.
Très un travail en cours, utilisez à vos propres risques ...
Certitude de mort. Petite chance de succès. Qu'attendons-nous?
composer require danc0/gimliduck-php
Créez un projet squelette avec: composer create-project danc0/gimli-skeleton
Ajouter les devtools avec composer require --dev danc0/gimliduck-devtools
Créez un fichier .htaccess qui ressemble à ceci pour pointer des demandes à votre fichier index.php
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
La création d'une application Gimliduck est simple:
declare (strict_types= 1 );
require_once __DIR__ . ' /vendor/autoload.php ' ;
use Gimli Application ;
use Gimli Router Route ;
Application:: create ( __DIR__ , $ _SERVER );
Route:: get ( ' / ' , function (){
echo " Hello World " ;
});
Application:: start ();C'est vraiment tout ce dont vous avez besoin pour commencer. Vous pouvez ajouter plus comme un moteur de modèle, un fichier de configuration, etc., mais vous n'êtes pas obligé .
<?php
declare (strict_types= 1 );
require_once __DIR__ . ' /vendor/autoload.php ' ;
use Gimli Application ;
use App Core Config ;
use App Core Cache ;
define ( ' APP_ROOT ' , __DIR__ );
$ App = Application:: create ( APP_ROOT , $ _SERVER );
// set up your config and add it to the Application
$ config_file = parse_ini_file ( APP_ROOT . ' /App/Core/config.ini ' , true );
$ App -> Config = $ App -> Injector -> resolveFresh (Config::class, [ ' config ' => $ config_file ]);
// Register a cache class with the Injector
$ App -> Injector -> register (Cache::class, Cache:: getCache ( $ App -> Config -> admin_cache ));
// Run Application
$ App -> run (); La classe Application enregistre également le gestionnaire d'événements de base et la classe de session lors de sa création. De plus, si votre configuration inclut enable_latte le moteur de modèle Latte sera ajouté à l'instance d'application à l'aide de la valeur de configuration pour template_base_dir comme répertoire de modèle.
Par défaut, Gimli nécessitera tous les fichiers dans le répertoire App/Routes . Vous pouvez désactiver cela en définissant autoload_routes sur false dans votre fichier de configuration. Vous pouvez modifier le répertoire en définissant la valeur de route_directory dans votre fichier de configuration. Vous pouvez également charger des fichiers d'itinéraire supplémentaires avec la méthode suivante:
// Load routes from a file(s)
$ App -> loadRouteFiles ([
' App/routes/web.php ' ,
]);Il y a quelques choses que vous pouvez faire avec vos rappels d'itinéraire ... passez une chaîne, un appel ou un tableau.
Route::get( ' / ' , function (){
echo " Hello World "
});
// Single action controller, must use __invoke method
Route:: get ( ' / ' , Home_Controller::class);
// cli routes are single action Job classes
Route:: cli ( ' build-cache ' , Cache_Job::class);
Route:: get ( ' / ' , Home_Controller::class . ' @homePage ' );
Route:: get ( ' / ' , [Home_Controller::class, ' homePage ' ]);Tout ce qui travaille, c'est à vous de décider comment vous le faites.
Vous pouvez ajouter du middleware si vous avez besoin d'une défense supplémentaire
Route:: get ( ' / ' , [Home_Controller::class, ' homePage ' ])-> addMiddleware (Logged_In_Middleware::class); Cela devrait être une classe qui implémente GimliMiddlewareMiddleware_Interface qui nécessite une méthode process qui renvoie GimliMiddlewareMiddleware_Response . Le middleware a accès à l'instance d'application, y compris l'injecteur et tout ce que vous décidez de le définir.
Vous pouvez également ajouter des groupes, définir un fichier d'itinéraire par défaut qui devrait se charger et charger des fichiers d'itinéraire supplémentaires pour aider à organiser vos itinéraires.
Vos itinéraires peuvent également contenir des arguments variables qui répondent aux modèles suivants:
protected array $ patterns = [
' :all ' => " ([^/]+) " ,
' :alpha ' => " ([A-Za-z_-]+) " ,
' :alphanumeric ' => " ([w-]+) " ,
' :integer ' => " ([0-9_-]+) " ,
' :numeric ' => " ([0-9_-.]+) " ,
' :id ' => " ([0-9_-]+) " ,
' :slug ' => " ([A-Za-z0-9_-]+) " ,
]; Vous devrez ajouter leur nom de variable en utilisant le symbole # dans la définition de l'itinéraire.
Route:: get ( ' /user/:integer#id ' , [User_Controller::class, ' getUser ' ]); Ce nom de variable est transmis au routeur et défini comme une dépendance pour votre méthode de contrôleur. Vous devez utiliser le nom de variable défini comme argument dans votre méthode de contrôleur. La valeur sera dactylographiée en fonction des types disponibles pour settype , types possibles:
integer or int
float or double
string
array
object
boolean or bool
Exemple de méthode du contrôleur:
public function getUser ( Response $ Response , int $ id ): Response {
// do something with $id
} Les contrôleurs doivent renvoyer un objet GimliHttpResponse . Il existe des méthodes d'assistance qui renvoient des objets Response formatés pour aider à limiter une logique conditionnelle:
response une réponse de baseredirect la réponse à redirectionredirect_on_success rediriger si la réponse est réussieredirect_on_failure rediriger si la réponse n'est pas réussiejson_response JSON RÉPONSE Les fichiers de travail sont également donnés par les arguments suivants subcommand , options et flags . L'argument options est un tableau de tableaux contenant le nom et la valeur. L'argument flags est un tableau avec les drapeaux donnés. L'argument subcommand n'est qu'une chaîne si une sous-commande a été donnée.
Vous pouvez utiliser l'injecteur intégré pour lier ou enregistrer les dépendances. Vous pouvez également résoudre les dépendances de l'injecteur. Vous pouvez ajouter tout ce dont vous avez besoin à l'injecteur et y accéder à travers votre application via l'instance Application .
L'injecteur intégré sera automatiquement automatiquement des classes et résoudra les dépendances au besoin. Vous pouvez également lier une classe à une fermeture si vous devez effectuer une configuration avant de retourner la classe ou d'enregistrer un objet déjà créé. L'exemple ci-dessous montre un contrôleur d'action unique qui serait résolu à partir de la classe du routeur. Les paramètres de la méthode __construct sont résolus à partir de l'injecteur.
<?php
declare (strict_types= 1 );
namespace App Controllers ;
use App Logic Dashboard_Logic ;
use Gimli Http Response ;
use Gimli Application ;
use Gimli View Latte_Engine ;
class Dashboard_Landing_Controller {
/**
* Constructor
*
* @param Application $Application
*/
public function __construct (
public Application $ Application ,
protected Dashboard_Logic $ Dashboard_Logic ,
protected Latte_Engine $ View
){
//
}
/**
* Single action controller call
*
* @return Response
*/
public function __invoke ( Response $ Response ): Response {
$ template_data = $ this -> Dashboard_Logic -> getTemplateData ();
return $ Response -> setResponse ( $ this -> View -> render ( ' dashboard/dashboard.latte ' , $ template_data ));
}
}Les paramètres de la méthode sont également résolus par l'injecteur lorsque l'itinéraire envoie la méthode.
Il existe également des méthodes d'assistance injecteur qui réduisent un code en ligne. En règle générale, si vous vouliez injecter une classe en ligne, vous pouvez le faire avec $this->Application->Injector->resolve(Some_Class::class) ou Application::get()->Injector->resolve(Some_Class::class) . Les méthodes resolve et resolve_fresh sont disponibles pour couper ce code en ligne.
Il existe une Database de base PDO de base ainsi qu'une classe Pdo_Manager que vous pouvez utiliser pour gérer les requêtes de base de données. La classe Pdo_Manager renvoie et l'instance de PDO et peut être utilisée pour exécuter directement les requêtes. La classe Database est un wrapper autour de la classe Pdo_Manager et fournit quelques méthodes de requête de base. Il existe également une classe de base Model très basique et des méthodes d'assistance supplémentaires pour Database , comme ailleurs, ces méthodes gèrent l'injection de dépendance et appellent les méthodes sur la classe Database injectée. Les aides sont:
fetch_columnfetch_rowfetch_allrow_exists Il existe une classe de semence de base qui peut être utilisée pour semer votre base de données. Cela repose sur les attributs placés dans les classes de modèle pour instruire le Seeder comment créer les données.
<?php
declare (strict_types= 1 );
namespace Gimli Database ;
use Gimli Database Model ;
use Gimli Database Seed ;
class User_Model extends Model {
/**
* @var string $table_name
*/
protected string $ table_name = ' users ' ;
/**
* ID
*
* @var int $id
*/
public $ id ;
/**
* Unique_Id
*
* @var string $unique_id
*/
#[Seed(type: ' unique_id ' , args: [ ' length ' => 12 ])]
public $ unique_id ;
/**
* Username
*
* @var string $username
*/
#[Seed(type: ' username ' )]
public $ username ;
/**
* Email
*
* @var string $email
*/
#[Seed(type: ' email ' )]
public $ email ;
/**
* Password
*
* @var string $password
*/
#[Seed(type: ' password ' )]
public $ password ;
/**
* Is_Active
*
* @var int $is_active
*/
#[Seed(type: ' tiny_int ' )]
public $ is_active ;
/**
* First Name
*
* @var string $first_name
*/
#[Seed(type: ' first_name ' )]
public $ first_name ;
/**
* Last Name
*
* @var string $last_name
*/
#[Seed(type: ' last_name ' )]
public $ last_name ;
/**
* Status
*
* @var int $status
*/
#[Seed(type: ' one_of ' , args: [ 0 , 1 ])]
public $ status ;
/**
* Created_At
*
* @var string $created_at
*/
#[Seed(type: ' date ' , args: [ ' format ' => ' Y-m-d H:i:s ' , ' min ' => ' 2021-01-01 ' , ' max ' => ' 2021-04-01 00:00:00 ' ])]
public $ created_at ;
/**
* Updated_At
*
* @var string $updated_at
*/
#[Seed(type: ' date ' , args: [ ' format ' => ' Y-m-d H:i:s ' , ' min ' => ' 2021-04-01 00:02:00 ' ])]
public $ updated_at ;
/**
* bio
*
* @var string $about
*/
#[Seed(type: ' paragraph ' , args: [ ' count ' => 1 ])]
public $ about ;
}Vous pouvez ensuite semer la base de données avec le code suivant:
Seeder:: make (User_Model::class)
-> seed ( 123 )
-> count ( 1 )
-> create (); Au lieu de créer, vous pouvez appeler getSeededData pour obtenir les données qui seraient insérées dans la base de données. Ceci est utile pour tester ou charger manuellement un modèle sans l'enregistrer. Vous pouvez également transmettre une méthode de rappel qui recevra les données du modèle initial. Cela aide à semer les données liées. Le rappel doit retourner une gamme d'instances Seeder .
Seeder:: make (User_Model::class)
-> seed ( 123 )
-> count ( 1 )
-> callback ( function ( $ data ) {
return [
Seeder:: make (User_Hobby_Model::class)-> with ([ ' user_id ' => $ data [ ' id ' ]]),
Seeder:: make (User_Group_Model::class)-> with ([ ' user_id ' => $ data [ ' id ' ]]),
]
})
-> create (); La graine passée garantit que les données restent les mêmes à chaque fois que Seeder est exécutée, ce qui entraîne des ensembles de données reproductibles. La classe Seeder a une méthode getRandomSeed qui renvoie une valeur de graines aléatoires. Ceci est utile pour créer des données aléatoires que vous n'avez pas besoin d'être reproductibles ou pour générer une graine aléatoire que vous pouvez copier et utiliser.
Il existe également quelques aides à la configuration:
get_config pour obtenir l'intégralité du tableau de configurationget_config_value pour obtenir une valeur spécifique à partir du tableau de configurationconfig_has pour vérifier si une clé existe dans le tableau de configuration