Elemental-это PHP-структура, разработанная с нуля для динамического, удобного для пользователя опыта кодирования. Он включает в себя такие функции, как инъекция зависимости, и следует архитектуре MVC, чтобы упростить разработку веб -разработки и улучшения организации кода. Производившийся к страсти к простоте и гибкости, он приглашает разработчиков в сферу, где они могут иметь беспрецедентный контроль и получить глубокое понимание инструментов, находящихся в их распоряжении.
Чтобы продемонстрировать возможности Elemental, была разработана полностью работающая платформа под названием Inkwell с использованием Elemental. Inkwell - это уникальное пространство, посвященное чистой сущности рассказывания историй. В соответствии с целью Elemental не иметь внешних зависимостей, Inkwell был изготовлен с использованием только простых HTML, CSS, JS и PHP.
Не стесняйтесь углубиться как в живую платформу, так и соответствующую кодовую базу. Исследуйте особенности Inkwell, чтобы понять, как Elemental можно использовать для ваших собственных проектов.
Смотрите вдохновение в создании Elemental .
Elemental была разработана с целью отсутствия строк. Нет никаких зависимостей от внешних библиотек или фреймворков. Цель состоит в том, чтобы дать разработчикам подлинное чувство контроля - открытая дверь, чтобы самостоятельно исследовать и понять волшебные вещи, которые способствуют структуре.
Всеобъемлющая цель? Пусть разработчики полностью примут и используют элегантность мощных абстракций, таких как DI -контейнеры, ORM, средние войны и многое другое. Но вот кикер - Элементный - это не просто указывать путь. Он передает вам ключи, чтобы раскрыть тайны, позволяя вам исследовать, как эти абстракции изложены в коде.
На самом деле, вам рекомендуется не только следовать по пути, но и выходить из проторенной дорожки. Погрузитесь в кодовую базу, рассекайте абстракции и поймите их внутреннюю работу. Не стесняйтесь настраивать и экспериментировать, потому что Elemental - это не просто структура - это открытое приглашение формировать и формировать инструменты в вашем распоряжении. Потому что кодирование не должно быть лабиринтом; Это должно быть путешествие. Давайте вместе отправимся в путешествие.
В отличие от других структур, Elemental не полагается на композитор или внешние библиотеки. Это так же просто, как клонировать репозиторий и начать работу с хорошим PHP, установленным в вашей системе.
Откройте свой терминал и выполните следующую команду:
git clone https://github.com/aneesmuzzafer/elemental.gitНе беспокойтесь о менеджерах или зависимостях пакетов - Elemental строится с нуля, чтобы освободить вас от таких проблем.
Для тех, кто предпочитает маршрут композитора, создание нового элементарного приложения - это всего лишь команда:
composer create-project fragment/elemental sample-app Это генерирует проект с файлом composer.json .
Как только ваш проект будет готов, Kickstart Elemental Local Development Server с командой ignite с помощью нашего двигателя командной строки, Candle :
cd sample-app
php candle igniteВуаля! Ваше приложение теперь доступно по адресу http://127.0.0.1:8000.
Мы позаботились о базовой настройке, чтобы вы могли сосредоточиться на магии.
Пусть начало очарование!
Наиболее важной особенностью Elemental является контейнер для впрыскивания зависимости, который он использует для управления зависимостями класса и выполнения впрыска зависимостей.
Инъекция зависимостей - это дизайн разработки программного обеспечения, который касается того, как компоненты обладают их зависимостями. В традиционной системе класс отвечает за создание собственных зависимостей. С DI ответственность за создание и обеспечение зависимостей перемещается за пределы класса. Вместо класса, создающего свои зависимости, они «вводят» в класс из внешнего источника.
DI помогает в достижении свободно связанного и более поддерживаемого кода. Он способствует разделению проблем, позволяя каждому классу сосредоточиться на своей конкретной функциональности, не беспокоясь о том, как создавать или получить его зависимости.
Инъекция зависимости - это специфическая реализация более широкой концепции, известной как инверсия контроля (МОК). МОК представляет собой парадигму дизайна, где управляющий поток программы инвертируется или передается внешней сущности, контейнеру или структуре.
В Elemental, когда вы используете инъекцию зависимостей (DI), если класс не полагается на какие -либо другие классы или не опирается только на конкретные классы (не абстрактные интерфейсы), вам не нужно явно рассказывать DI Container, как создать экземпляр этого класса. Контейнер DI автоматически выяснит его.
Контейнер попытается создать экземпляр класса, и если этот класс имеет зависимости от других классов, контейнер повторно попытается разрешить эти зависимости. Этот процесс продолжается до тех пор, пока все необходимые классы не будут успешно не разрешены. Таким образом, вам не нужно вручную указывать, как создать каждый класс - контейнер DI позаботится об этом для вас.
<?php
class MailService {
public function __construct ( private MailerAgent $ mailer ) {
}
}
// Inside some other class
class UserController {
public function sendMail ( MailService $ mailService )
{
$ mailService -> sendMail ();
}
} Здесь, подтягивая типа MailService внутри аргумента метода, Elemental смог разрешить класс, создать экземпляр этого класса и передать его в sendMail , чтобы вы могли использовать его, не беспокоясь о том, какие зависимости требуются классом MailService . Как вы можете видеть, сама MailService зависит от какого -то другого класса MailerAgent , однако Elemental позаботился о разрешении класса MailerAgent за кулисами, передал его в MailService , создавая его экземпляр и предоставил этот экземпляр для вашего использования.
«Итак, где этот вид зависимостей будет просто подтягивание типа названия класса в Elemental?» Все функции constructor класса, все controller methods и метод handle класса создания команд.
За кулисами Elemental разрешает класс или интерфейс в конкретный экземпляр, рассматривая любые зарегистрированные привязки. Другими словами, для того, чтобы явно сообщить структуру о том, как разрешить экземпляр конкретного класса или интерфейса, вам необходимо зарегистрировать привязку этого класса или интерфейса, используя метод bind в экземпляре Application , передавая класс или имя интерфейса, которое мы хотим зарегистрировать вместе с закрытием, который возвращает экземпляр класса:
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));
});Обратите внимание, что вам, как правило, нужно связать класс только тогда, когда вам нужно запустить дополнительную логику для разрешения класса, или вам нужно связать интерфейс с конкретной реализацией. В противном случае Elemental разрешит класс без явного требования вас связывать его.
Метод singleton связывает класс или интерфейс с контейнером, гарантируя, что его разрешается только один раз. После первоначального разрешения любые последующие вызовы в контейнер для того же привязки возвращают тот же экземпляр объекта.
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 Несмотря на то, что в любом месте приложения в любом месте в любом месте приложения очень хорошо, он часто привязан, пока приложение загружается, чтобы другие компоненты приложения могли начать использовать его. Elemental предоставляет особое место для регистрации всех привязков приложения и выполнения любой другой логики начальной загрузки, требуемой вашим приложением. Это AppBootstrapAppServiceProvider . Поставщик услуг приложений содержат register и метод boot .
В рамках метода register вы должны связывать вещи в контейнер для инъекции зависимости. Тем не менее, вы не должны пытаться разрешить какое -либо привязку. маршруты или запустите любую другую функциональность в методе register . В противном случае вы можете случайно использовать службу внутри контейнера, который еще не загружен.
Этот метод вызывается после того, как все остальные поставщики услуг были зарегистрированы, предоставляя доступ ко всем услугам, зарегистрированным в рамках. Любая логика инициализации, которую вы хотите выполнить, должна быть размещена здесь.
<?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
}
} Вы можете использовать метод make для разрешения экземпляра класса из контейнера DI. Метод make в экземпляре приложения принимает имя класса или интерфейса, который вы хотите решить:
use App Services MailService ;
$ mailService = app ()-> make (MailService::class); Вы также можете получить экземпляр приложения, используя instance статического метода непосредственно в классе Application .
use Core Main Application ;
use App Services MailService ;
$ mailService = Application:: instance ()-> make (MailService::class); Метод make особенно полезен при попытке разрешить класс из кодового компонента, где нецелесообразно вводить зависимость, используя награждение типа. В таких сценариях вы можете явно запросить контейнер впрыскивания зависимости приложения для разрешения экземпляра для вас.
Маршруты определяются в файле approutes.php , что позволяет разработчикам легко регистрировать различные маршруты для обработки различных HTTP -запросов.
Маршруты зарегистрированы путем вызова соответствующего метода на фасаде маршрута, например, Route::get() , и включают в себя указание шаблона URI в качестве первого аргумента. Второй аргумент может быть либо закрытием, либо массивом, который определяет контроллер и метод, ответственный за обработку запроса.
Например:
<?php
use App Controllers AuthController ;
use Core Facade Route ;
Route:: get ( " /settings " , function () {
// handling logic goes here
});
Route:: post ( " /register " , [AuthController::class, " register " ]);Всякий раз, когда подходит URI запроса, выполняется соответствующий метод закрытия или контроллера, и ответ генерируется и отправляется обратно в браузер.
Вы можете зарегистрировать маршруты, которые отвечают на любой глагол HTTP, используя следующие методы:
Route::get($uri, $callback);Route::post($uri, $callback);Route::put($uri, $callback);Route::patch($uri, $callback);Route::delete($uri, $callback);Route::options($uri, $callback); Иногда вам нужно будет захватить сегменты URI на вашем маршруте. Например, вам может потребоваться захватить идентификатор пользователя из URL. Вы можете сделать это, определив параметры маршрута:
Route:: get ( ' /user/{id} ' , function ( string $ id ) {
return ' User ' . $ id ;
});
Route:: get ( " /story/{id} " , function ( $ id ) { /*...*/ });Вы можете определить столько параметров маршрута, сколько требуется вашим маршрутом:
Route:: post ( " story/edit/{id} " , [StoryController::class, " edit " ]);
Route:: get ( " story/{story_id}/comment/{comment_id} " , [StoryController::class, " comment " ]);Они также будут переданы в метод контроллера.
Elemental плавно обрабатывает инъекцию необходимых зависимостей для ваших методов контроллера. Это позволяет вам указать любые зависимости, требуемые вашим маршрутом в подписи обратного вызова, используя Heinting. Elemental заботится об автоматическом разрешении и введении заявленных зависимостей в обратный вызов.
Например, если вы введите CoreRequestRequest в обратном вызове, Elemental гарантирует, что текущий HTTP-запрос автоматически вводится в ваш обратный вызов вашего маршрута:
<?php
use Core Request Request ;
Route:: get ( ' /users ' , function ( Request $ request ) {
// ...
});Вы можете поместить напечатанные зависимости и параметры маршрута в любом порядке.
Когда вы передаете идентификатор модели в качестве параметра в действие маршрута или контроллера, типичный подход включает в себя запрос базы данных для получения соответствующей модели на основе этого идентификатора. Elemental упрощает этот процесс с помощью привязки модели маршрута, предлагая удобный способ автоматического введения экземпляров модели непосредственно в ваши маршруты.
Например, вместо того, чтобы вводить только идентификатор пользователя в ваш маршрут, у вас есть возможность внедрить весь экземпляр модели пользователя, который соответствует данному идентификатору.
В контексте маршрутов или действий контроллера модели определяются с использованием имен переменных, намеченных типом, которые соответствуют конкретному сегменту в маршруте. Например:
use App Models User ;
Route:: get ( ' /users/{user} ' , function ( User $ user ) {
return $ user -> email ;
}); Иногда вы можете разрешить модели, используя столбец, отличный от id . Для этого вы можете указать столбец в определении параметра маршрута:
use App Models User ;
Route:: get ( ' /users/{user:email} ' , function ( User $ user ) {
return $ user ;
});В этом сценарии Elemental будет плавно вводить экземпляр модели, который обладает электронной почтой, соответствующей соответствующему значению из URI запроса.
Конечно, маршрутная модель связывание также работает с методами контроллера.
Если соответствующий экземпляр модели не найден в базе данных, приложение будет брошено ModelNotFoundException . Вы можете справиться с такими исключениями и контролировать поведение любых таких и других исключений, брошенных приложением в классе ExceptionsHandler . Подробнее об этом позже.
Используя метод Route::fallback , вы можете определить маршрут, который будет выполнен, когда ни один другой маршрут не соответствует входящему запросу.
Route:: fallback ( function () {
// ...
}); route:list Candle Command предоставит список всех маршрутов, определенных в приложении:
php candle route:list Вместо того, чтобы консолидировать всю логику обработки запросов в закрытии в файлах вашего маршрута, рассмотрите возможность структурирования этого поведения с помощью классов «контроллера». Контроллеры позволяют организовать соответствующую логику обработки запросов в сплоченный класс. Например, класс UserController может управлять различными входящими запросами, связанными с пользователями, такими как отображение, создание, обновление и удаление пользователей. Эти классы контроллера обыкновенно хранятся в каталоге app/Controllers .
Чтобы сгенерировать новый контроллер, вы можете запустить команду build:controller Candle.
php candle build:controller UserController Это генерирует новый файл с именем "usercontroller.php" в каталоге app/Controllers .
У контроллера может быть любое количество публичных методов, которые будут отвечать на входящие HTTP -запросы:
<?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 ( " / " );
}
}После создания класса контроллера и его методов вы можете определить маршрут к методу контроллера следующим образом:
use App Controllers UserController ;
Route:: get ( " /register " , [AuthController::class, " showRegister " ]); Когда полученный запрос совпадает с назначенным URI Route, будет вызван метод showRegister в классе AppControllersUserController , и метод будет получать соответствующие параметры маршрута.
Контейнер Elemental Service несет ответственность за урегулированные экземпляры всех контроллеров. Следовательно, вы можете использовать навесность типа в конструкторе вашего контроллера для указания любых зависимостей, которые он может потребовать. Заявленные зависимости будут автоматически разрешены и введены в экземпляр контроллера
<?php
namespace App Controllers ;
use Core Database Database ;
class UserController
{
/**
* Create a new controller instance.
*/
public function __construct (
public Database $ db ,
) {}
} Помимо инъекции зависимостей через конструктор, вы также можете использовать Heinting для зависимостей в методах вашего контроллера. Распространенным вариантом использования для впрыска метода является инъекция CoreRequestRequest или любой экземпляр службы в методы контроллера:
Создайте и управляйте контроллерами для эффективного обработки запросов.
<?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 ваш метод контроллера предвидит ввод с параметра маршрута, у вас есть гибкость, чтобы перечислить ваши аргументы в любом порядке. Например, рассмотрим следующее определение маршрута:
Route:: post ( " story/update/{id} " , [StoryController::class, " update " ]); Вы по-прежнему можете набрать CoreRequestRequest и получить доступ к параметру id , определив метод контроллера следующим образом:
<?php
namespace App Controllers ;
use Core Request Request ;
class StoryController
{
public function update ( string $ id , Request $ request )
{
// Update $story
return redirect ( " /story/ $ story -> id " );
}
} Класс CoreRequestRequest в Elemental предлагает объектно-ориентированный подход для взаимодействия с настоящим HTTP-запросом, управляемым вашим приложением. Это облегчает поиск ввода, файлов cookie и файлов, представленных вместе с запросом.
Чтобы получить текущий экземпляр HTTP-запроса через инъекцию зависимостей, вы можете использовать Heinting для класса CoreRequestRequest в вашем методе закрытия маршрута или контроллера. Сервисный контейнер автоматически внедрит экземпляр входящего запроса.
<?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 " );
}
}Сервисный контейнер также автоматически вводит входящий запрос в закрытие маршрута.
Если ваш метод контроллера предвидит ввод с параметра маршрута, у вас есть гибкость, чтобы перечислить ваши аргументы в любом порядке. Например, рассмотрим следующее определение маршрута:
Route:: post ( " story/update/{id} " , [StoryController::class, " update " ]); Вы по-прежнему можете набрать CoreRequestRequest и получить доступ к параметру id , определив метод контроллера следующим образом:
<?php
namespace App Controllers ;
use Core Request Request ;
class StoryController
{
public function update ( string $ id , Request $ request )
{
// Update $story
return redirect ( " /story/ $ story -> id " );
}
} Вы можете получить все входные данные входящего запроса в качестве array , используя метод data() . Этот метод может использоваться независимо от того, является ли входящий запрос из формы HTML или является запросом XHR:
$ data = $ request -> data (); Вы можете получить доступ ко всем пользовательским вводу из вашего экземпляра Request , не беспокоясь о том, какой глагол HTTP использовался для запроса. Независимо от глагола HTTP, метод data может использоваться для извлечения пользовательского ввода:
$ name = $ request -> data ()[ " name " ]; Экземпляр CoreRequestRequest предоставляет различные методы для изучения входящего HTTP -запроса. Давайте обсудим несколько наиболее важных методов ниже.
Вы можете получить заголовки запроса из экземпляра CoreRequestRequest используя метод headers .
$ headers = $ request -> headers (); Вы можете получить метод запроса, позвонив по method в CoreRequestRequest Extance.
$ method = $ request -> method (); Вы можете получить URI запроса из экземпляра CoreRequestRequest используя метод uri .
$ uri = $ request -> uri (); Вы можете получить файлы cookie для запроса из экземпляра CoreRequestRequest используя метод cookies .
$ cookies = $ request -> cookies (); Вы можете получить необработанное содержание из экземпляра CoreRequestRequest используя метод rawContent .
$ content = $ request -> rawContent ();Будьте осторожны, имея дело с необработанным содержанием запроса.
Вы можете получить файлы из экземпляра CoreRequestRequest используя метод files .
$ files = $ request -> files (); Метод ip может использоваться для извлечения IP -адреса клиента, который сделал запрос на ваше приложение:
$ ipAddress = $ request -> ip (); Метод port может использоваться для извлечения адреса порта клиента, который сделал запрос на ваше приложение:
$ port = $ request -> port (); Вы можете получить тип контента из экземпляра CoreRequestRequest используя метод contentType .
$ contentType = $ request -> contentType (); Вы можете получить строку запроса запроса, используя метод queryString .
$ query = $ request -> queryString (); Вы можете получить текстовое содержимое запроса, используя метод text , при условии, что тип контента установлен на text/plain
$ text = $ request -> text (); Вы можете получить содержимое JS запроса с помощью метода js при условии, что тип контента установлен на application/javascript
$ js = $ request -> js (); Вы можете получить HTML-контент запроса, используя метод html , при условии, что тип контента установлен на text/html
$ js = $ request -> html (); Вы можете извлечь контент JSON запроса, используя метод json , при условии, что тип контента установлен для application/json , $request->data() возвращает все данные JSON, передаваемые в запрос. Однако,
$ jsonData = $ request -> json (); $request->data() содержит все данные JSON вместе с входами, передаваемыми через параметры запроса в запросе. Тем не менее, $request->json() может использоваться для получения только контента JSON.
Вы можете получить содержимое XML запроса, используя метод xml , при условии, что тип контента установлен на application/json
$ xmlData = $ request -> xml ();Ожидается, что каждый маршрут и контроллер дадут ответ на доставку в браузер пользователя. Elemental предлагает различные методы для создания ответов. Самая простая форма ответа включает в себя возврат строки непосредственно с маршрута или контроллера. Структура будет беспрепятственно преобразовать эту строку в полный HTTP -ответ.
Route:: get ( ' / ' , function () {
return ' Hello World ' ;
});В дополнение к возвращению строк из ваших маршрутов и контроллеров, вы также можете вернуть массивы или объекты. Структура автоматически преобразует их в ответ JSON:
Route:: get ( ' / ' , function () {
return [ 1 , 2 , 3 ];
}); Обычно вы не будете просто вернуть простые строки или массивы из вашего маршрута. Вместо этого вы часто возвращаете полные экземпляры CoreResponseResponse или представления.
Возвращение полного экземпляра Response позволяет настроить код состояния и заголовков HTTP ответа. Вы можете ввести экземпляр ответа, подняв экземпляр ответа внутри вашего контроллера или закрытия маршрута.
use Core Response Response ;
Route:: get ( ' /home ' , function ( Response $ response ) {
$ response -> setHeader ( " content-type " , " text/plain " )
-> setStatusCode ( 200 )
-> setContent ( " Hello World " );
return $ response ;
}); Вы, конечно, можете вернуть view от контроллера. Однако, если вам нужно контролировать статус и заголовки ответа, но также нужно вернуть view в качестве содержания ответа, вы можете сделать это следующим образом:
use Core Response Response ;
class UserController {
public function register ( Response $ response ){
$ response -> setHeader ( " x-is_register " , " true " );
return view ( " Register " );
}
}Это автоматически установит заголовок на ответ, который будет отправлен в браузер.
Имейте в виду, что большинство методов ответа цепны, что позволяет свободно построить экземпляры ответа.
Вы можете установить содержимое ответа, используя метод setContent на экземпляре ответа.
$ response -> setContent ( " ... " ); Однако, если вы хотите добавить в содержимое ответа, вы можете сделать это, используя метод appendContent в экземпляре ответа.
$ response -> appendContent ( " ... " ); Вы можете установить заголовок на экземпляре ответа, используя метод setHeader
$ response -> setHeader ( " content-type " , " text/plain " ); Однако, если вы хотите установить несколько заголовков одновременно, вы можете сделать это, используя метод setHeaders и пройдя массив заголовков.
$ response -> setHeaders ([ " content-type " => " text/html " , ...]); Вы можете напрямую установить код состояния ответа, используя метод setHeader на экземпляре ответа.
$ response -> setStatusCode ( 301 );Текст статуса будет установлен по умолчанию для общих кодов состояния.
Вы можете сгенерировать отклик перенаправления, который содержит соответствующие заголовки, необходимые для перенаправления пользователя на другой URL, вызывая статический метод redirect в классе CoreResponseResponse .
use Core Response Response ;
Route:: get ( ' /dashboard ' , function () {
return Response:: redirect ( ' home/dashboard ' );
}); Однако для простоты вспомогательный метод redirect() также доступен во всем мире для достижения той же функциональности.
use Core Response Response ;
Route:: post ( ' /story/create ' , function () {
if (! $ someCondition )
return redirect ( ' /story ' , 204 );
}); Вы также можете сгенерировать ответ JSON, вызывая статический метод JSON в классе CoreResponseResponse . Данные, передаваемые методу, будут преобразованы в надлежащий JSON. Вы также можете при условии при желании передать массив кода состояния и заголовков в качестве второго и третьего аргумента функции.
use Core Response Response ;
Route:: post ( ' /post ' , function () {
$ post = ( . . . );
return Response:: JSON ( $ post , 201 , [ " header " => " value " ]);
});Промежуточное программное обеспечение предлагает удобный механизм для изучения и фильтрации входящих HTTP -запросов в ваше заявление. Например, вы можете разработать промежуточное программное обеспечение для проверки состояния аутентификации пользователя вашего приложения. Если пользователь не будет аутентифицирован, промежуточное программное обеспечение будет перенаправить их на экран входа в систему. И наоборот, если пользователь аутентифицирован, промежуточное программное обеспечение позволит запросу углубляться в приложение.
У вас есть гибкость для создания дополнительного промежуточного программного обеспечения для выполнения разнообразных задач за пределами аутентификации. В качестве иллюстрации, промежуточное программное обеспечение для ведения журнала может записать все входящие запросы в ваше приложение. Эти компоненты промежуточного программного обеспечения размещены в каталоге app/middlewares .
Чтобы создать новое промежуточное программное обеспечение, используйте команду build:middleware Candle:
php candle build:middleware IsAuthenticated Выполнение этой команды генерирует свежий класс промежуточного программного обеспечения с именем «Isauthenticated» в каталоге app/middlewares . В этом классе создается метод именованной handle , где вы можете сформулировать логику для промежуточного программного обеспечения.
Здесь мы допустим доступ к маршруту только в том случае, если пользователь будет аутентифицирован, в противном случае мы перенаправим пользователей обратно в 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 );
}
} Чтобы передать запрос глубже в приложение, вам следует позвонить в $next обратный вызов с помощью $request .
Рассмотрим промежуточное программное обеспечение как последовательность «слоев», которые HTTP просит просьбы до достижения вашего приложения. Каждый слой имеет возможность тщательно изучить запрос и потенциально отклонить его.
Конечно, промежуточное программное обеспечение может выполнять задачи до или после прохождения запроса глубже в приложение. Например, это промежуточное программное обеспечение выполнит свою задачу после того, как запрос будет обработан приложением:
<?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 ;
}
} Если вы хотите назначить промежуточное программное обеспечение на определенные маршруты, вы можете вызвать метод middleware при определении маршрута:
Route:: get ( ' /profile ' , function () {
// ...
})-> middleware (IsAuthenticated::class); Вы можете назначить несколько промежуточного программного обеспечения на маршрут, передавая массив имен промежуточного программного обеспечения методу middleware :
Route:: get ( ' / ' , function () {
// ...
})-> middleware ([First::class, Second::class]); Вы можете назначить MiddleWares в группу маршрутов, передавая множество имен промежуточного программного обеспечения в атрибут middlewares при определении группы:
Route:: group ([ " middleware " => [HasSession::class]], function () {
Route:: get ( " / " , [StoryController::class, " index " ]);
Route:: get ( " /story/{story} " , [StoryController::class, " show " ]);
}); Вы можете использовать вложенные группы маршрутов, чтобы объединить средние войны с их родительской группой. В последующем примере промежуточное программное обеспечение «Hassession» применяется к маршрутам "/" и "/story/{story}" , тогда как «Hassession», «Isauth» и «Log» средние войны применяются к остальным маршрутам:
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 " ]);
});
});В Elemental PHP -структуре не практично возвращать целые строки документов HTML непосредственно с маршрутов и контроллеров. Просмотры предоставляют удобный способ разместить весь HTML в отдельные файлы.
Просмотры играют решающую роль в разделении контроллера/логики приложения от проблем с презентацией и хранятся в каталоге app/views . Эти файлы просмотра, написанные в PHP, инкапсулируют разметку. Рассмотрим основной пример представления:
<html>
<body>
<h1>Hello, <?= $ name ?> </h1>
</body>
</html> Если это представление хранится в app/views/Welcome.php view
Route:: get ( ' / ' , function () {
return view ( ' Welcome ' , [ ' name ' => ' Ahmed ' ]);
}); Первый аргумент, переданный view , соответствует имени файла представления в каталоге resources/views . Второй аргумент может быть массивом пар клавишных значений, переданных в представление. Например, в приведенном выше коде $name будет непосредственно доступно и содержать значение «Ахмед».
Просмотры также могут быть возвращены, используя статический метод make в классе CoreViewView :
Route:: get ( ' / ' , function () {
return View:: make ( " Post " , $ params );
}); Взгляды могут быть вложены в подкаталости каталога app/views . «Точка» нотация может использоваться для ссылки на вложенные представления. Например, если ваше представление хранится в app/views/layouts/MainLayout.php , вы можете вернуть его с маршрута/контроллера, как так:
return view ( ' layouts.MainLayout ' , $ data ); Elemental предоставляет удобный способ поддерживать одинаковую макету для нескольких представлений, уменьшая дублирование кода. Макет сам по себе является файлом представления, содержащим заполнителя {{ content }} . Когда представление возвращается с макетом, окончательное представление составлено путем размещения представления в контент макета.
Elemental предоставляет удобный способ поддерживать одинаковую макету для нескольких представлений, уменьшая дублирование кода. Макет - это файл представления, который включает назначенный заполнитель, обозначенный {{ content }} . Когда представление возвращается с использованием определенного макета, композиция достигается путем внедрения содержания представления в назначенный заполнитель в макет. Этот подход упростит организацию представлений и повышает обезжириваемость кода за счет централизации общих элементов макета.
Ниже приведен основной пример:
<!DOCTYPE html >
< html lang =" en " >
< head >
<!-- Head content -->
</ head >
< body >
< ?= component("components.Navbar") ? >
< div style =" min-height: calc(100vh - 140px); " >
{{ content }}
</ div >
</ body >
</ html >Представление можно вернуть с такими макетами, как это:
public function compose ()
{
return view ( " Compose " )-> withLayout ( " layouts.DashboardLayout " );
}Elemental предлагает мощный подход к созданию видов. Каждое представление по сути является компонентом, и любой вид может быть собран из других компонентов. Это симфония композиции, где каждая часть вносит вклад в создание гармоничного и динамичного целого.
Пример файла компонента ( views/components/Logo.php ):
<a class="logo" href="/ " >
<span class= " logo-img">
<img src="logo.png" class ="logo-text">
LOGO
</span>
</a> Этот компонент можно использовать в любом другом файле представления. Например, в views/Login.php :
<div>
<?= component ( " components.Logo " ) ?>
<p>Welcome Back!</p>
<!-- Other login form elements -->
</div>Таким образом, Elemental дает вам возможность как с макетами, так и компонентными конструкциями, позволяя вам составлять ваши представления с изяществом как сверху вниз, так и снизу вверх. Эта гибкость обеспечивает беспроблемное слияние, где вы можете легко смешивать и объединить элементы, чтобы создать элегантный и сложный пользовательский интерфейс для вашего приложения.
В современных веб -приложениях взаимодействие базы данных является фундаментальным аспектом. Elemental был разработан для беспрепятственной оптимизации этого взаимодействия в разнообразном диапазоне поддерживаемых баз данных, используя неотъемлемые возможности PHP PDO. С помощью Elemental у вас есть гибкость, чтобы выполнить любой сложный запрос или транзакцию, используя класс CoreDatabaseDatabase .
Elemental предлагает надежный объект-реламентальный карт (ORM), который эффективно абстрагирует многие тонкости, доказывая бесценную для большинства запросов базы данных. Тем не менее, CoreDatabaseDatabase может использоваться для запуска более продвинутых запросов SQL.
Все конфигурации для вашего приложения Elemental расположены в файле конфигурации вашего app/config/config.php . Здесь вы можете определить все подключения к базе данных, а также указать, какое соединение следует использовать по умолчанию. Большинство параметров конфигурации в этом файле обусловлены значениями переменных среды вашего приложения.
Все конфигурации для вашего приложения Elemental расположены в файле конфигурации вашего app/config/config.php . Здесь вы можете определить все подключения к базе данных, а также указать, какое соединение следует использовать по умолчанию. Большинство параметров конфигурации в этом файле обусловлены значениями переменных среды вашего приложения.
<?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 использует PDO в качестве базового класса обработки базы данных. Все функции PDO доступны непосредственно в классе CoreDatabaseDatabase . Вы можете ввести экземпляр CoreDatabaseDatabase в любой метод конструктора или контроллера для вызова методов PDO. Конфигурация по умолчанию для Elemental настроена для баз данных MySQL, но вы можете изменить драйвер в файле конфигурации.
Вот пример запуска запроса через экземпляр 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 ();
}Для получения дополнительной информации о PDO вы можете обратиться к документации PHP PDO
Elemental включает в себя специально созданную объектно-реламентальную карту (ORM), которая делает его приятным взаимодействием с базой данных. При использовании ORM каждая таблица базы данных имеет соответствующую «модель», которая используется для взаимодействия с этой таблицей. В дополнение к получению записей из таблицы баз данных, модели позволяют также вставлять, обновлять и удалять записи из таблицы.
Модели присутствуют в каталоге app/models и расширяют класс CoreModelModel . Вы можете генерировать новую модель, используя команду build:model Candle.
php candle build:model Post Модели, сгенерированные командой build:model , будут размещены в каталоге app/Models . Очень базовая модель имеет следующую структуру:
<?php
namespace App Models ;
use Core Model Model ;
class Post extends Model
{
// ...
} Имя таблицы: согласно соглашению, «Случайный корпус», имя множественного числа класса будет использоваться в качестве имени таблицы, если не указано другое имя. Таким образом, в этом случае Elemental предполагает, что Post Model сохраняет записи в таблице posts .
Вы можете вручную указать имя таблицы модели, определив свойство tableName на модели:
<?php
namespace App Models ;
use Core Model Model ;
class Post extends Model
{
protected $ tableName = ' elemental_posts ' ;
}Первичный ключ:
Elemental также предполагает, что соответствующая таблица базы данных каждой модели имеет столбец первичного ключа с id . При необходимости вы можете определить защищенное свойство $primaryKey на вашей модели, чтобы указать другой столбец, который служит первичным ключом вашей модели:
<?php
namespace App Models ;
use Core Model Model ;
class Post extends Model
{
protected $ primaryKey = ' elemental_id ' ;
}Вы можете думать о каждой модели как о мощном строителе запросов, позволяющей свободно запросить таблицу баз данных, связанную с моделью.
Метод all модели будет извлекать все записи из связанной модели таблицы баз данных:
use App Models Story ;
foreach (Story:: all () as $ story ) {
echo $ story [ " content " ];
}По умолчанию полученные записи представлены как массив. Тем не менее, вы можете передать аргумент режима, который контролирует, как представлена каждая запись. Аргумент режима принимает любой из режимов извлечения PDO. Например,
use App Models Story ;
foreach (Story:: all () as $ story ) {
echo $ story -> content ;
} Метод allWhere - это мощная абстракция в модели, которая позволяет выполнять сложные запросы. Этот метод принимает три аргумента: conditions , options и fetchMode .
public static function allWhere( array $ conditions , array $ options = [], int $ fetchMode = PDO :: FETCH_ASSOC ) Условия: Параметр conditions представляет собой массив предложений, которые запись должна удовлетворить, чтобы быть извлеченными. Каждое условие может быть либо парой [key => value] , либо парой [key => [operator, value]] .
key соответствует конкретному столбцу в таблице.[key => value] , оператор по умолчанию составляет = и value - это данные внутри этого столбца для записи.[key => [operator, value]] , вы можете указать оператор для каждого условия. Поддерживаемые операторы:['=', '!=', '<', '>', '<=', '>=', 'LIKE', 'IS NULL', 'IS NOT NULL'] . Параметры: Параметр options - это массив, который определяет дополнительные аргументы запроса, такие как order by , limit и т. Д. Поддерживаемые конструкции в аргументе параметров включают:
"orderBy""limit""offset""sortDir" FetchMode: параметр fetchMode контролирует, как представлена каждая извлеченная запись. Аргумент режима принимает любой из режимов извлечения PDO:
PDO::FETCH_ASSOCPDO::FETCH_NUMPDO::FETCH_BOTHPDO::FETCH_OBJPDO::FETCH_CLASSPDO::FETCH_INTOPDO::FETCH_LAZYPDO::FETCH_KEY_PAIRПример прояснит:
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
);
}
} В дополнение к получению всех записей, соответствующих данному запросу, вы также можете получить отдельные записи, используя find и where метод. Вместо того, чтобы вернуть массив записей, эти методы возвращают один экземпляр модели:
Найти: это принесет первую запись, которая соответствует основному ключу таблицы.
$ flight = Story:: find ( 1 ); Где: где метод, который принимает множество условий, которые должна быть удовлетворена записи. Каждое условие может быть либо парой [key => value] , либо парой [key => [operator, value]] .
key соответствует конкретному столбцу в таблице.[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'] .Например
$ 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. Например:
php candle ingite --host=192.168.1.10 Custom Port If you prefer binding to a specific port, use the --port argument:
php candle ingite --port=8080 To serve your application at a custom IP and port simultaneously, provide both the --host and --port arguments:
php candle ingite --host=192.168.1.10 --port=8080 The --host and --port arguments can be placed in any order.
To obtain a comprehensive view of all registered routes within your application, utilize the route:list command provided by Candle:
bash
php candle route:list You can use the Candle build command to generate files for your models, controllers, middleware and commands.
To create a model, execute the following command:
php candle build:model Story This command will generate a file named Story.php within the appmodels directory, containing the Story class.
For generating a controller, the build command is similarly employed:
php candle build:controller StoryController Executing this command will generate a file named StoryController.php in the appcontrollers directory, featuring the MyController class.
To generate a middleware, utilize the build command as follows:
php candle build:middleware HasSession This will create a file named HasSession.php within the appmiddleware directory, housing the handle method.
For command generation, execute the build command with the appropriate arguments:
php candle build:command Migration Executing this command will generate a file named Migration.php in the appcommands directory, containing the Migration class and the handle method.
Generating custom commands is where the Candle's power can be experienced. Commands are stored in the app/commands directory, and it's essential to load them inside the array returned in appcommandsCommands.php for proper registration within the app.
After generating a command, define values for the key and description properties of the class. The key is used as the argument for the command, while description will be displayed in the help screen. The handle method will be called when the command is executed, and you can place your command logic in this method.
You can type-hint any dependencies required for your command handling. Elemental's DI Container will automatically inject all dependencies type-hinted in the handle method's signature.
Let's take a look at an example command:
<?php
namespace App Commands ;
use App Models User ;
use App Service MailService ;
use Core Console Command ;
class SendEmails extends Command
{
protected $ key = ' mail:send ' ;
protected $ description = ' Send mails to all users ' ;
public function handle ( MailService $ mailService ): void
{
$ mailService -> send (User:: all ());
}
}To execute the command in the command line:
php candle mail:send You can use Elemental's CoreConsoleCommander to retrieve any inputs passed through the command line. The CoreConsoleCommander provides a method named getArgs that returns an array of inputs passed from the command line. The Commander instance can be type-hinted through the handler method and used as required.
A concrete example will make it clear:
<?php
namespace App Commands ;
use Core Console Command ;
use Core Console Commander ;
class Migration extends Command
{
protected $ key = " migrate " ;
protected $ description = " Custom migration handler. " ;
private $ commander ;
public function handle ( Commander $ commander , Database $ db )
{
$ args = $ commander -> getArgs ();
if (! isset ( $ args [ 1 ])) {
$ this -> up ();
return ;
}
switch ( $ args [ 1 ]) {
case " fresh " :
$ this -> downThenUp ();
break ;
case " delete " :
$ this -> down ();
break ;
default :
$ this -> up ();
}
}
public function up ()
{
$ sql = " CREATE TABLE IF NOT EXISTS users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
bio TEXT,
image VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) " ;
try {
$ db -> exec ( $ sql );
console_log ( " Table 'users' created successfully! " );
} catch ( PDOException $ e ) {
console_log ( " Table creation error: " . $ e -> getMessage ());
}
}
public function down ()
{
$ sql = " DROP TABLE IF EXISTS users " ;
try {
$ db -> exec ( $ sql );
console_log ( " Table 'users' deleted successfully! " );
} catch ( PDOException $ e ) {
console_log ( " Table deletion error: " . $ e -> getMessage ());
}
}
public function downThenUp ()
{
$ this -> down ();
$ this -> up ();
}
}It is recommended to type-hint dependencies inside the handle method as opposed to inside the constructor of the command class.
To execute these migration commands in the command line:
php candle migrate
php candle migrate fresh
php candle migrate deleteAs you can see, generating commands are very powerful and can be helpful to achieve a variety of functionalities. Here, a custom migration handler has been built. You can expand and organize the above structure or create a custom Migration Service that can handle your migration logic.
Commands can also be used for handling task scheduling. You may create a command that executes some logic, and then pass the command to your operating systems CRON handler.
Elemental includes a variety of global "helper" PHP functions. You can use these functions in any way that is convenient to you.
The app function returns the Application instance:
$ app = app ();This is pretty useful when you want to register your own services as well as resolve any framework or custom service.
app ()-> bind (CustomService::class, function () {
return new CustomService ( new anotherService ());
});
$ service = app ()- make (CustomService::class); The dump function dumps the variable passed as the first argument. You can also pass an additional second argument that can serve as the identifier on screen:
dump ( $ value );
dump ( $ user , " user " ); The dd function dumps the given variable and ends the execution of the script:
dd ( $ value );
dd ( $ user , " user " ); The console_log function serves as a unique tool for logging variables, distinct from the dump function. Notably, it doesn't return output to the browser; instead, it directs information to the console initiated by the script. You can pass any variable number of arguments to the console_log function.
console_log ( $ value );
console_log ( $ user , $ post , $ image , $ comment ); The router function returns the returns the Router instance.
The view function is used to return a view from the controller method:
return view ( ' Login ' ); The component function is used to return a view as a component to be used inside another view:
<body>
<?= component ( " Logo " ) ?>
//...
</body> The redirect function returns a redirect HTTP response and is used to redirect to any other route.
return redirect ( ' /home ' );Elemental provides a convenient way to handle all the exceptions thrown by the app.
The handle method of AppExceptionsHandler class is where all exceptions thrown by your application pass through before being rendered to the user. By default, exceptions thrown by the app will be formatted, and a structured response will be sent back to the browser. However, inside the handle method, you can intercept any exception and perform custom logic before the response is sent back.
You can even send back a custom view or a response.
<?php
namespace App Exceptions ;
use Core Exception ExceptionHandler ;
class Handler extends ExceptionHandler
{
public function handle ( $ e )
{
// Perform some processing here
// You can customize the handling of exceptions based on your requirements
}
}Elemental has defined some specific exception classes by default:
AppExceptionModelNotFoundExceptionRouteNotFoundExceptionRouterExceptionViewNotFoundException If you need to handle different types of exceptions in different ways, you can modify the handle method accordingly:
<?php
class Handler extends ExceptionHandler
{
public function handle ( $ e )
{
if ( $ e instanceof ModelNotFoundException || $ e instanceof RouteNotFoundException) {
return view ( " 404 " )-> withLayout ( " layouts.DashboardLayout " );
}
if ( $ e instanceof ViewNotFoundException) {
return view ( " Home " );
}
// Handle other specific exceptions as needed
}
} You are free to create your own exception classes by extending from the base Exception class, which can then be handled as required.
Feel free to customize the handle method based on your application's specific needs.
All configuration settings for the application are centralized in the appconfigconfig.php file. These configurations cover various aspects such as database connection information and other core settings essential for your app.
To cater to different environments where the application might run, a .env.example file is provided in the root directory. This file outlines common environment variables that can be configured. If you are working in a team, it's recommended to include the .env.example file with placeholder values. This makes it clear to other developers which environment variables are required to run the application.
When your application receives a request, all the variables listed in the .env file will be loaded into the $_ENV PHP super-global. You can then use the getenv function to retrieve values from these variables in your configuration files.
$ appName = getenv ( " APP_NAME " ); To access configuration values, you can use type-hinting and inject the CoreConfigConfig class into your constructors, controller methods, or route closures.
use Core Config Config ;
class YourClass {
public function __construct ( Config $ config ) {
$ driver = $ config -> db [ " driver " ];
$ host = $ config -> db [ " host " ];
$ port = $ config -> db [ " port " ];
}
// Your other methods or code here
}By doing this, you have a clean and organized way to retrieve configuration values within your application.
This approach keeps your configuration centralized and allows for easy changes based on the environment. It also promotes a clean and maintainable codebase.
Elemental introduces a Facade system inspired by Laravel, providing a convenient and expressive static interface to classes within the application's Dependency Injection (DI) container. Facades act as static proxies to classes in the service container, offering a balance between a concise syntax and the testability and flexibility of traditional static methods.
In Elemental, the CoreFacadeRoute serves as a Facade, offering a static interface to the application's Router instance enabling you to use it like this in the routes.php file:
// routes.php
<?php
use Core Facade Route ;
Route:: get ( " /register " , [AuthController::class, " showRegister " ]);
Route:: get ( " /login " , [AuthController::class, " showLogin " ]);
Route:: get ( " /logout " , [AuthController::class, " logout " ]);
Route:: post ( " /register " , [AuthController::class, " register " ]);To create a custom Facade for any class, follow these steps:
FacadeClass that extends the CoreFacadeFacade class.getFacadeAccessor , returning the class string for the associated instance in the DI container. Here's an example of creating a PaymentGateway Facade:
<?php
use Core Facade Facade ;
use Core Services PaymentGateway ;
class PaymentGatewayFacade extends Facade
{
protected static function getFacadeAccessor ()
{
return PaymentGateway::class;
}
} Now, you can access the instance methods of your custom class by calling static methods on the corresponding FacadeClass .
LARAVEL is Magic . Like any unsuspecting Muggle, it's enchantments terrify you. Until one fine day, you dare to pick up the wand and start waving it. Then, you fall in love with it.
The Elemental framework is open-sourced software licensed under the MIT License.
All contributions are welcome. Please create an issue first for any feature request or bug. Then fork the repository, create a branch and make any changes to fix the bug or add the feature and create a pull request. Вот и все! Спасибо!
For bug reports, feature requests, or general questions, please use the issue tracker.