Un marco Micro PHP adaptable que intenta mantenerse fuera de su camino.
Mucho trabajo en progreso, use bajo su propio riesgo ...
Certeza de muerte. Pequeñas posibilidades de éxito. ¿A qué estamos esperando?
composer require danc0/gimliduck-php
Crear un proyecto de esqueleto con: composer create-project danc0/gimli-skeleton
Agregue el DevTools con composer require --dev danc0/gimliduck-devtools
Cree un archivo .htaccess que se vea así para señalar solicitudes a su archivo index.php
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
Crear una aplicación Gimliduck es 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 ();Eso es realmente todo lo que necesitas para comenzar. Puede agregar más como un motor de plantilla, un archivo de configuración, etc., pero no tiene que hacerlo.
<?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 clase Application también registra el controlador de eventos básicos y la clase de sesión cuando se crea. Además, si su configuración incluye enable_latte , el motor de plantilla Latte se agregará a la instancia de la aplicación utilizando el valor de configuración para template_base_dir como directorio de plantilla.
Por defecto, GIMLI requerirá cualquier archivo en el directorio App/Routes . Puede deshabilitar esto configurando autoload_routes en false en su archivo de configuración. Puede cambiar el directorio configurando el valor de route_directory en su archivo de configuración. También puede cargar archivos de ruta adicionales con el siguiente método:
// Load routes from a file(s)
$ App -> loadRouteFiles ([
' App/routes/web.php ' ,
]);Hay algunas cosas que puede hacer con las devoluciones de llamada de su ruta ... pase una cadena, una llamada o una matriz.
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 ' ]);Cualquiera de esos trabajos, depende de ti cómo lo haces.
Puede agregar middleware si necesita una defensa adicional
Route:: get ( ' / ' , [Home_Controller::class, ' homePage ' ])-> addMiddleware (Logged_In_Middleware::class); Esa debería ser una clase que implementa GimliMiddlewareMiddleware_Interface que requiere un método process que devuelve GimliMiddlewareMiddleware_Response . El middleware tiene acceso a la instancia de la aplicación, incluido el inyector y cualquier otra cosa que decida establecer en él.
También puede agregar grupos, definir un archivo de ruta predeterminado que debe cargarse y cargar archivos de ruta adicionales para ayudar a organizar sus rutas.
Sus rutas también pueden contener argumentos variables que cumplen con los siguientes patrones:
protected array $ patterns = [
' :all ' => " ([^/]+) " ,
' :alpha ' => " ([A-Za-z_-]+) " ,
' :alphanumeric ' => " ([w-]+) " ,
' :integer ' => " ([0-9_-]+) " ,
' :numeric ' => " ([0-9_-.]+) " ,
' :id ' => " ([0-9_-]+) " ,
' :slug ' => " ([A-Za-z0-9_-]+) " ,
]; Deberá agregar su nombre variable utilizando el símbolo # en la definición de ruta.
Route:: get ( ' /user/:integer#id ' , [User_Controller::class, ' getUser ' ]); Este nombre de variable se pasa al enrutador y se establece como una dependencia para su método de controlador. Debe usar el nombre de la variable definido como argumento en su método de controlador. El valor se tipeará en función de los tipos disponibles para settype , tipos posibles:
integer or int
float or double
string
array
object
boolean or bool
Método del controlador de ejemplo:
public function getUser ( Response $ Response , int $ id ): Response {
// do something with $id
} Los controladores deben devolver un objeto GimliHttpResponse . Hay métodos auxiliares que devuelven objetos Response formateados para ayudar a limitar alguna lógica condicional:
response una respuesta básicaredirect la respuesta de redirecciónredirect_on_success Redirect si la respuesta es exitosaredirect_on_failure redirección si la respuesta no es exitosajson_response JSON Respuesta Los archivos de trabajo también reciben el siguiente subcommand , options y flags de los siguientes argumentos. El argumento options es una matriz de matrices que contienen el nombre y el valor. El argumento flags es una matriz con las banderas dadas. El argumento subcommand es solo una cadena si se dio un subcomando.
Puede usar el inyector incorporado para vincular o registrar dependencias. También puede resolver dependencias del inyector. Puede agregar todo lo que necesite al inyector y acceder a él a lo largo de su aplicación a través de la instancia Application .
El inyector incorporado se realizará a las clases y resolverá las dependencias según sea necesario. También puede unir una clase a un cierre si necesita hacer una configuración antes de devolver la clase o registrar un objeto ya creado. El siguiente ejemplo muestra un solo controlador de acción que se resolvería desde la clase de enrutador. Los parámetros del método __construct se resuelven desde el inyector.
<?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 ));
}
}El inyector también resuelve los parámetros del método cuando la ruta envía el método.
También hay métodos a ayuda de inyector que reducen algún código en línea. Por lo general, si desea inyectar una clase en línea, podría hacerlo con $this->Application->Injector->resolve(Some_Class::class) o Application::get()->Injector->resolve(Some_Class::class) . Los métodos resolve y resolve_fresh están disponibles para cortar ese código en línea.
Hay una Database básica de envoltura PDO, así como una clase Pdo_Manager que puede usar para administrar consultas de la base de datos. La clase Pdo_Manager devuelve e instancia de PDO y se puede usar para ejecutar consultas directamente. La clase Database es un envoltorio alrededor de la clase Pdo_Manager y proporciona algunos métodos básicos de consulta. También existe una clase base Model muy básica y métodos de ayuda de ayuda para Database , como en otros lugares, estos métodos manejan la inyección de dependencia y llaman a los métodos en la clase de Database inyectada. Los ayudantes son:
fetch_columnfetch_rowfetch_allrow_exists Hay una clase básica de sembradora que se puede usar para sembrar su base de datos. Esto se basa en los atributos colocados en las clases de modelo para instruir al Seeder cómo crear los datos.
<?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 ;
}Luego puede sembrar la base de datos con el siguiente código:
Seeder:: make (User_Model::class)
-> seed ( 123 )
-> count ( 1 )
-> create (); En lugar de crear, puede llamar a getSeededData para obtener los datos que se insertarían en la base de datos. Esto es útil para probar o cargar manualmente un modelo sin guardarlo. También puede aprobar un método de devolución de llamada que se les dará los datos del modelo inicial. Esto ayuda a los datos relacionados con las semillas. La devolución de llamada debe devolver una variedad de instancias 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 semilla pasada asegura que los datos sigan siendo los mismos cada vez que se ejecuta Sembrador, lo que resulta en conjuntos de datos reproducibles. La clase Seeder tiene un método getRandomSeed que devolverá un valor de semilla aleatorio. Esto es útil para crear datos aleatorios que no necesita ser reproducible o para generar una semilla aleatoria que puede copiar y usar.
También hay algunos ayudantes de configuración:
get_config para obtener toda la matriz de configuraciónget_config_value para obtener un valor específico de la matriz de configuraciónconfig_has para verificar si existe una clave en la matriz de configuración