Адаптируемая структура Micro PHP, которая пытается избежать вашего пути.
Очень много в процессе, используйте свой собственный риск ...
Уверенность смерти. Небольшой шанс на успех. Чего мы ждем?
composer require danc0/gimliduck-php
Создать скелетный проект с: composer create-project danc0/gimli-skeleton
Добавить Devtools с помощью composer require --dev danc0/gimliduck-devtools
Создайте файл .htaccess , который выглядит примерно так, чтобы указать запросы на ваш файл index.php
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
Создать приложение Gimliduck простое:
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 ();Это действительно все, что вам нужно, чтобы начать. Вы можете добавить больше похоже на шаблон, файл конфигурации и т. Д., Но вам не нужно .
<?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 (); Класс Application также регистрирует базовый обработчик событий и класс сеансов, когда он создается. Кроме того, если ваша конфигурация включает в себя enable_latte , в экземпляр приложения будет добавлено inable_latte, используя значение конфигурации для template_base_dir в качестве каталога шаблона.
По умолчанию Gimli потребует любых файлов в каталоге App/Routes . Вы можете отключить это, установив autoload_routes для false в вашем файле конфигурации. Вы можете изменить каталог, установив значение route_directory в вашем файле конфигурации. Вы также можете загрузить дополнительные файлы маршрута с помощью следующего метода:
// Load routes from a file(s)
$ App -> loadRouteFiles ([
' App/routes/web.php ' ,
]);Есть несколько вещей, которые вы можете сделать с обратными вызовами маршрута ... пройдите строку, вызов или массив.
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 ' ]);Любая из них работает, решать вам, как вы это делаете.
Вы можете добавить промежуточное программное обеспечение, если вам нужна дополнительная защита
Route:: get ( ' / ' , [Home_Controller::class, ' homePage ' ])-> addMiddleware (Logged_In_Middleware::class); Это должен быть класс, который реализует GimliMiddlewareMiddleware_Interface , который требует метода process , который возвращает GimliMiddlewareMiddleware_Response . Промежуточное программное обеспечение имеет доступ к экземпляру приложения, включая инжектор и все, что вы решите установить на нем.
Вы также можете добавить группы, определить файл маршрута по умолчанию, который должен загружать, и загружать дополнительные файлы маршрута, чтобы помочь организовать ваши маршруты.
Ваши маршруты также могут содержать переменные аргументы, которые соответствуют следующим шаблонам:
protected array $ patterns = [
' :all ' => " ([^/]+) " ,
' :alpha ' => " ([A-Za-z_-]+) " ,
' :alphanumeric ' => " ([w-]+) " ,
' :integer ' => " ([0-9_-]+) " ,
' :numeric ' => " ([0-9_-.]+) " ,
' :id ' => " ([0-9_-]+) " ,
' :slug ' => " ([A-Za-z0-9_-]+) " ,
]; Вам нужно будет добавить их имя переменной, используя символ # в определении маршрута.
Route:: get ( ' /user/:integer#id ' , [User_Controller::class, ' getUser ' ]); Это имя переменной передается в маршрутизатор и устанавливается в качестве зависимости вашего метода контроллера. Вы должны использовать определенное имя переменной в качестве аргумента в вашем методе контроллера. Значение будет тип на основе доступных типов для settype , возможные типы:
integer or int
float or double
string
array
object
boolean or bool
Пример метода контроллера:
public function getUser ( Response $ Response , int $ id ): Response {
// do something with $id
} Контроллеры должны вернуть объект GimliHttpResponse . Существуют вспомогательные методы, которые возвращают форматированные объекты Response , чтобы помочь ограничить некоторую условную логику:
response Основной ответredirect перенаправление ответаredirect_on_success redirect, если ответ успешноredirect_on_failure перенаправить, если ответ не успешенjson_response json ответ Файлы задания также получают следующие аргументы subcommand , options и flags . Аргумент options - это массив массивов, содержащих имя и значение. Аргумент flags - это массив с данными флагами. Аргумент subcommand - это просто строка, если была дана подкоманда.
Вы можете использовать встроенный инжектор для привязки или регистрации зависимостей. Вы также можете разрешить зависимости от инжектора. Вы можете добавить все, что вам нужно в инжектор, и получить доступ к нему на протяжении всего приложения через экземпляр Application .
Встроенный инжектор будет аутоизольно -классами и разрешает зависимости по мере необходимости. Вы также можете привязать класс с закрытием, если вам нужно сделать некоторую настройку, прежде чем вернуть класс или зарегистрировать уже созданный объект. В приведенном ниже примере показан единый контроллер действия, который будет разрешен из класса маршрутизатора. Параметры метода __construct разрешаются из инжектора.
<?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 ));
}
}Параметры метода также разрешаются инжектором, когда маршрут отправляет метод.
Есть также методы вспомогательных инжекторов, которые сокращают какой -то встроенный код. Как правило, если вы хотите ввести классную встроенную линию, вы можете сделать это с $this->Application->Injector->resolve(Some_Class::class) или Application::get()->Injector->resolve(Some_Class::class) . Методы resolve и resolve_fresh доступны для сокращения этого встроенного кода.
Существует базовая Database обертки PDO, а также класс Pdo_Manager , который вы можете использовать для управления запросами базы данных. Класс Pdo_Manager возвращает и экземпляр PDO и может использоваться для непосредственного запуска запросов. Класс Database - это обертка вокруг класса Pdo_Manager и предоставляет некоторые основные методы запроса. Существует также очень базовый базовый класс Model и дополнительные вспомогательные методы для Database , как и в других местах, эти методы обрабатывают инъекцию зависимостей и вызывают методы в классе инъекционной Database . Помощники:
fetch_columnfetch_rowfetch_allrow_exists Существует базовый класс сеялки, который можно использовать для заселения вашей базы данных. Это опирается на атрибуты, размещенные в классах моделей, чтобы дать инструкциям Seeder , как создать данные.
<?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 ;
}Затем вы можете заселить базу данных следующим кодом:
Seeder:: make (User_Model::class)
-> seed ( 123 )
-> count ( 1 )
-> create (); Вместо создания вы можете вызвать getSeededData , чтобы получить данные, которые будут вставлены в базу данных. Это полезно для тестирования или вручную загрузку модели без ее сохранения. Вы также можете передать метод обратного вызова, который будет предоставлен данные начальной модели. Это помогает заселить связанные данные. Обратный вызов должен вернуть массив экземпляров 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 (); Продолжительное семя гарантирует, что данные остаются одинаковыми каждый раз, когда сеялок запускается, что приводит к воспроизводимым наборам данных. У класса Seeder есть метод getRandomSeed , который вернет случайное значение семян. Это полезно для создания случайных данных, которые вам не нужно воспроизводить, или для создания случайного семян, которое вы можете копировать и использовать.
Есть также несколько помощников конфигурации:
get_config , чтобы получить весь конфигурационный массивget_config_value , чтобы получить определенное значение из конфигурацииconfig_has , чтобы проверить, существует ли ключ в массиве конфигурации