Elemental é uma estrutura PHP desenvolvida a partir do zero para experiências de codificação dinâmica e amigável. Ele incorpora recursos como injeção de dependência e segue a arquitetura MVC para otimizar o desenvolvimento da Web e melhorar a organização de código. Projetado com uma paixão pela simplicidade e flexibilidade, convida os desenvolvedores a um reino, onde eles podem exercer controle incomparável e obter uma compreensão profunda das ferramentas à sua disposição.
Para mostrar os recursos do Elemental, uma plataforma totalmente funcional chamada Inkwell foi desenvolvida usando elementar. Inkwell é um espaço único dedicado à pura essência da narrativa. De acordo com o objetivo da Elemental de não ter dependências externas, o Inkwell foi criado usando apenas HTML, CSS, JS e PHP simples.
Sinta -se à vontade para mergulhar na plataforma ao vivo e na base de código correspondente. Explore os recursos de Inkwell para entender como ele elementar pode ser aproveitado para seus próprios projetos.
Veja a inspiração por trás da criação do Elemental .
Elemental foi projetado com o objetivo de não ter cordas. Não há dependências de bibliotecas ou estruturas externas. O objetivo é dar aos desenvolvedores uma genuína sensação de controle - uma porta aberta para explorar e entender independentemente as coisas mágicas que alimentam a estrutura.
O objetivo abrangente? Deixe os desenvolvedores adotarem e aproveitarem completamente a elegância de abstrações poderosas, como contêineres DI, ORMS, Middlewares e muito mais. Mas aqui está o kicker - a elementar não está apenas apontando o caminho. Está entregando as chaves para desvendar os mistérios, capacitando você a explorar como essas abstrações são dispostas no código.
De fato, você é incentivado não apenas a seguir o caminho, mas a se aventurar na trilha batida. Mergulhe na base de código, disseca as abstrações e entenda seu funcionamento interno. Sinta -se à vontade para ajustar e experimentar, pois o Elemental não é apenas uma estrutura - é um convite aberto para moldar e moldar as ferramentas à sua disposição. Porque a codificação não deve ser um labirinto; Deve ser uma jornada. Vamos fazer essa jornada juntos.
Ao contrário de outras estruturas, o Elemental não depende de compositor ou bibliotecas externas. É tão simples quanto clonar o repositório e começar com o bom php instalado no seu sistema.
Abra seu terminal e execute o seguinte comando:
git clone https://github.com/aneesmuzzafer/elemental.gitNão se preocupe com os gerentes ou dependências de pacotes - elementar é construído do zero para libertá -lo de tais preocupações.
Para quem prefere a rota do compositor, criar um novo aplicativo elementar é apenas um comando fora:
composer create-project fragment/elemental sample-app Isso gerará um projeto com um arquivo composer.json .
Depois que seu projeto estiver pronto, inicie o servidor de desenvolvimento local elementar com o comando ignite usando nosso mecanismo de linha de comando, vela :
cd sample-app
php candle ignitePronto! Seu aplicativo agora está acessível em http://127.0.0.1:8000.
Cuidamos da configuração básica para que você possa se concentrar na magia.
Deixe o encantamento começar!
A característica mais importante do elementar é o recipiente de injeção de dependência que ele usa para gerenciar dependências de classe e executar a injeção de dependência.
A injeção de dependência é um padrão de design no desenvolvimento de software que lida com a forma como os componentes se aposentam de suas dependências. Em um sistema tradicional, uma classe é responsável por criar suas próprias dependências. Com a DI, a responsabilidade de criar e fornecer dependências é movida para fora da classe. Em vez de uma classe criar suas dependências, elas são "injetadas" na classe a partir de uma fonte externa.
O DI ajuda a alcançar um código pouco acoplado e mais sustentável. Ele promove a separação de preocupações, permitindo que cada classe se concentre em sua funcionalidade específica sem se preocupar em como criar ou obter suas dependências.
A injeção de dependência é uma implementação específica do conceito mais amplo conhecido como inversão de controle (IOC). O COI representa um paradigma de design em que o fluxo de controle de um programa é invertido ou entregue a uma entidade, contêiner ou estrutura externa.
No Elemental, quando você está usando a injeção de dependência (DI), se uma classe não depende de outras classes ou apenas depende de classes de concreto (não interfaces abstratas), você não precisa dizer explicitamente ao contêiner DI como criar uma instância dessa classe. O contêiner DI irá descobrir automaticamente.
O contêiner tentará criar uma instância da classe e, se essa classe tiver dependências de outras classes, o contêiner também tentará resolver essas dependências. Esse processo continua até que todas as classes necessárias sejam resolvidas com sucesso. Portanto, você não precisa especificar manualmente como criar cada classe - o contêiner DI cuida dela para você.
<?php
class MailService {
public function __construct ( private MailerAgent $ mailer ) {
}
}
// Inside some other class
class UserController {
public function sendMail ( MailService $ mailService )
{
$ mailService -> sendMail ();
}
} Aqui, ao cair o tipo de MailService dentro do argumento do método, o Elemental conseguiu resolver a classe e criar uma instância dessa classe e passá-la para o sendMail , para que você possa usá-la sem se preocupar com as dependências exigidas pela classe MailService . Como você pode ver, o próprio MailService depende de outro MailerAgent , no entanto, o Elemental cuidou da resolução da classe MailerAgent nos bastidores, passou isso para o MailService ao criar sua instância e forneceu essa instância para seu uso.
"Então, onde esse tipo de injeção de dependências, apenas para que o nome da classe funcione no Elemental?" Todas as funções constructor de classe, todos os controller methods e o método handle da classe de criação de comando.
Nos bastidores, o Elemental resolve uma classe ou interface em uma instância concreta, observando qualquer ligação que tenha sido registrada. Em outras palavras, para informar explicitamente a estrutura sobre como resolver a instância de uma classe ou interface específica, você precisaria registrar uma ligação dessa classe ou interface usando o método bind na instância Application , passando a classe ou o nome da interface que desejamos registrar junto com um fechamento que retorna uma instância da 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));
});Observe que você normalmente precisa vincular uma classe somente quando precisar executar uma lógica adicional para resolver uma classe ou vincular uma interface a uma implementação concreta. Caso contrário, o Elemental resolverá a classe sem exigir explicitamente que você a vincule.
O método singleton liga uma classe ou interface ao contêiner, garantindo que ele seja resolvido apenas uma vez. Após a resolução inicial, quaisquer chamadas subsequentes para o contêiner para a mesma ligação retornarão a mesma instância do objeto.
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 Embora seja perfeitamente bom registrar uma ligação em qualquer lugar do aplicativo, geralmente é necessário vinculá -lo enquanto o aplicativo estiver no bootstrapping, para que outros componentes do aplicativo possam começar a usá -lo. O Elemental fornece um local especial para registrar todas as ligações do aplicativo e executar qualquer outra lógica de inicialização exigida pelo seu aplicativo. Este é AppBootstrapAppServiceProvider . O provedor de serviços de aplicativo contém um register e um método boot .
No método register , você deve vincular as coisas ao recipiente de injeção de dependência. No entanto, você não deve tentar resolver nenhuma ligação. rotas ou execute qualquer outra peça de funcionalidade dentro do método register . Caso contrário, você pode usar acidentalmente um serviço dentro de um contêiner que ainda não carregou.
Este método é chamado depois que todos os outros provedores de serviços foram registrados, concedendo acesso a todos os serviços registrados pela estrutura. Qualquer lógica de inicialização que você deseja executar deve ser colocada aqui.
<?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
}
} Você pode usar o método make para resolver uma instância de classe no contêiner DI. O método make na instância do aplicativo aceita o nome da classe ou interface que você deseja resolver:
use App Services MailService ;
$ mailService = app ()-> make (MailService::class); Você também pode obter a instância do aplicativo usando a instance do método estático diretamente na classe de Application .
use Core Main Application ;
use App Services MailService ;
$ mailService = Application:: instance ()-> make (MailService::class); O método make é particularmente útil ao tentar resolver uma classe dentro de um componente de código, onde é impraticável injetar uma dependência usando o tipo de tipo de tipo. Nesses cenários, você pode solicitar explicitamente o contêiner de injeção de dependência do aplicativo para resolver uma instância para você.
As rotas são definidas no arquivo approutes.php , permitindo que os desenvolvedores registrem facilmente várias rotas para lidar com diferentes solicitações HTTP.
As rotas são registradas chamando o método relevante na fachada da rota, como Route::get() e envolve a especificação de um padrão de URI como o primeiro argumento. O segundo argumento pode ser um fechamento ou uma matriz que define o controlador e o método responsável por lidar com a solicitação.
Por exemplo:
<?php
use App Controllers AuthController ;
use Core Facade Route ;
Route:: get ( " /settings " , function () {
// handling logic goes here
});
Route:: post ( " /register " , [AuthController::class, " register " ]);Sempre que um URI de solicitação é correspondido, o método de fechamento ou controlador correspondente é executado e uma resposta é gerada e enviada de volta ao navegador.
Você pode registrar rotas que respondem a qualquer verbo http usando os seguintes métodos:
Route::get($uri, $callback);Route::post($uri, $callback);Route::put($uri, $callback);Route::patch($uri, $callback);Route::delete($uri, $callback);Route::options($uri, $callback); Às vezes, você precisará capturar segmentos do URI em sua rota. Por exemplo, pode ser necessário capturar o ID de um usuário do URL. Você pode fazê -lo definindo parâmetros de rota:
Route:: get ( ' /user/{id} ' , function ( string $ id ) {
return ' User ' . $ id ;
});
Route:: get ( " /story/{id} " , function ( $ id ) { /*...*/ });Você pode definir tantos parâmetros de rota conforme exigido pela sua rota:
Route:: post ( " story/edit/{id} " , [StoryController::class, " edit " ]);
Route:: get ( " story/{story_id}/comment/{comment_id} " , [StoryController::class, " comment " ]);Eles também serão transmitidos para o método do controlador.
Elementar lida perfeitamente com a injeção de dependências necessárias para os métodos do seu controlador. Isso permite que você especifique qualquer dependência exigida pela sua rota na assinatura do retorno de chamada usando o tipo de tipo de tipo. O Elemental cuida de resolver e injetar automaticamente as dependências declaradas no retorno de chamada.
Por exemplo, se você digitar CoreRequestRequest dentro do retorno de chamada, o Elemental garante que a solicitação HTTP atual seja injetada automaticamente no seu retorno de chamada de rota:
<?php
use Core Request Request ;
Route:: get ( ' /users ' , function ( Request $ request ) {
// ...
});Você pode colocar as dependências digitadas e os parâmetros de rotear em qualquer ordem.
Quando você passa um ID do modelo como um parâmetro para uma ação de rota ou controlador, a abordagem típica envolve a consulta do banco de dados para buscar o modelo correspondente com base nesse ID. O Elemental Simplifica esse processo por meio da ligação do modelo de rota, oferecendo uma maneira conveniente de injetar automaticamente instâncias modelo diretamente em suas rotas.
Por exemplo, em vez de injetar apenas o ID de um usuário em sua rota, você tem a opção de injetar toda a instância do modelo de usuário que corresponde ao ID fornecido.
No contexto de rotas ou ações do controlador, os modelos são definidos usando nomes de variáveis de tipo que correspondem a um segmento específico na rota. Por exemplo:
use App Models User ;
Route:: get ( ' /users/{user} ' , function ( User $ user ) {
return $ user -> email ;
}); Às vezes, você pode querer resolver modelos usando uma coluna que não seja id . Para fazer isso, você pode especificar a coluna na definição de parâmetro de rota:
use App Models User ;
Route:: get ( ' /users/{user:email} ' , function ( User $ user ) {
return $ user ;
});Nesse cenário, o Elemental injetará perfeitamente a instância do modelo que possui um email correspondendo ao valor correspondente do URI da solicitação.
Obviamente, a ligação ao modelo de rotas também funciona com os métodos controladores.
Se uma instância do modelo correspondente não for encontrada no banco de dados, uma ModelNotFoundException será lançada pelo aplicativo. Você pode lidar com essas exceções e controlar o comportamento de essas e outras exceções lançadas pelo aplicativo na classe ExceptionsHandler . Mais sobre isso mais tarde.
Usando o método Route::fallback , você pode definir uma rota que será executada quando nenhuma outra rota corresponder à solicitação recebida.
Route:: fallback ( function () {
// ...
}); O comando route:list Candle fornecerá a lista de todas as rotas definidas no aplicativo:
php candle route:list Em vez de consolidar toda a lógica de manuseio de solicitação dentro de fechamentos em seus arquivos de rota, considere estruturar esse comportamento por meio de classes "controlador". Os controladores permitem que você organize a lógica de manuseio de solicitações relacionadas em uma classe coesa. Por exemplo, uma classe UserController pode gerenciar várias solicitações recebidas relacionadas aos usuários, como exibir, criar, atualizar e excluir usuários. Essas classes de controlador são convencionalmente armazenadas no diretório app/Controllers .
Para gerar um novo controlador, você pode executar o comando build:controller Candle.
php candle build:controller UserController Isso gerará um novo arquivo chamado "userController.php" dentro do diretório app/Controllers .
Um controlador pode ter qualquer número de métodos públicos que responderão às solicitações HTTP recebidas:
<?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 ( " / " );
}
}Depois de criar uma classe de controlador e seus métodos, você pode definir uma rota para o método do controlador da seguinte forma:
use App Controllers UserController ;
Route:: get ( " /register " , [AuthController::class, " showRegister " ]); Quando uma solicitação recebida corresponde ao URI da rota designada, o método showRegister dentro da classe AppControllersUserController será chamado e o método receberá os parâmetros de rota correspondentes.
O contêiner de serviço elementar é responsável pela resolução de instâncias de todos os controladores. Consequentemente, você pode usar o tipo de tipo de tipo no construtor do seu controlador para especificar quaisquer dependências necessárias. As dependências declaradas serão resolvidas e injetadas automaticamente na instância do controlador
<?php
namespace App Controllers ;
use Core Database Database ;
class UserController
{
/**
* Create a new controller instance.
*/
public function __construct (
public Database $ db ,
) {}
} Além de injetar dependências através do construtor, você também pode usar o tipo de tipo de dependências nos métodos do seu controlador. Um caso de uso comum para injeção de método está injetando o CoreRequestRequest ou qualquer instância de serviço nos métodos do controlador:
Crie e gerencie controladores para lidar com solicitações de maneira eficaz.
<?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 O método do seu controlador antecipa a entrada de um parâmetro de rota, você tem a flexibilidade de listar seus argumentos em qualquer ordem. Por exemplo, considere a seguinte definição de rota:
Route:: post ( " story/update/{id} " , [StoryController::class, " update " ]); Você ainda pode digitar o CoreRequestRequest e acessar seu parâmetro id definindo o método do controlador da seguinte forma:
<?php
namespace App Controllers ;
use Core Request Request ;
class StoryController
{
public function update ( string $ id , Request $ request )
{
// Update $story
return redirect ( " /story/ $ story -> id " );
}
} A classe CoreRequestRequest em Elemental oferece uma abordagem orientada a objetos para se envolver com a atual solicitação HTTP gerenciada pelo seu aplicativo. Ele facilita a recuperação de entrada, cookies e arquivos enviados junto com a solicitação.
Para adquirir a instância atual da solicitação HTTP por meio de injeção de dependência, você pode utilizar a classe de tipo de CoreRequestRequest em seu método de fechamento ou controlador de rota. O contêiner de serviço injetará automaticamente a instância de solicitação recebida.
<?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 " );
}
}O contêiner de serviço também injetará automaticamente a solicitação de entrada no fechamento da rota.
Se o seu método do controlador antecipar a entrada de um parâmetro de rota, você terá a flexibilidade de listar seus argumentos em qualquer ordem. Por exemplo, considere a seguinte definição de rota:
Route:: post ( " story/update/{id} " , [StoryController::class, " update " ]); Você ainda pode digitar o CoreRequestRequest e acessar seu parâmetro id definindo o método do controlador da seguinte forma:
<?php
namespace App Controllers ;
use Core Request Request ;
class StoryController
{
public function update ( string $ id , Request $ request )
{
// Update $story
return redirect ( " /story/ $ story -> id " );
}
} Você pode obter todos os dados de entrada da solicitação de entrada como uma array usando o método data() . Este método pode ser usado independentemente de a solicitação de entrada ser de um formulário HTML ou ser uma solicitação XHR:
$ data = $ request -> data (); Você pode acessar toda a entrada do usuário da sua instância Request sem se preocupar com qual verbo http foi usado para a solicitação. Independentemente do verbo http, o método data pode ser usado para recuperar a entrada do usuário:
$ name = $ request -> data ()[ " name " ]; A instância CoreRequestRequest fornece uma variedade de métodos para examinar a solicitação HTTP recebida. Vamos discutir alguns dos métodos mais importantes abaixo.
Você pode recuperar os cabeçalhos da solicitação da instância do CoreRequestRequest usando o método headers .
$ headers = $ request -> headers (); Você pode recuperar o método de solicitação, chamando method da instância CoreRequestRequest .
$ method = $ request -> method (); Você pode recuperar a solicitação URI da instância CoreRequestRequest usando o método uri .
$ uri = $ request -> uri (); Você pode recuperar os cookies de solicitação da instância CoreRequestRequest usando o método cookies .
$ cookies = $ request -> cookies (); Você pode recuperar o conteúdo bruto da instância CoreRequestRequest usando o método rawContent .
$ content = $ request -> rawContent ();Tenha cuidado ao lidar com o conteúdo bruto de uma solicitação.
Você pode recuperar os arquivos da instância CoreRequestRequest usando o método files .
$ files = $ request -> files (); O método ip pode ser usado para recuperar o endereço IP do cliente que fez a solicitação para o seu aplicativo:
$ ipAddress = $ request -> ip (); O método port pode ser usado para recuperar o endereço da porta do cliente que fez a solicitação ao seu aplicativo:
$ port = $ request -> port (); Você pode recuperar o tipo de conteúdo da instância CoreRequestRequest usando o método contentType .
$ contentType = $ request -> contentType (); Você pode recuperar a sequência de consultas da solicitação usando o método queryString .
$ query = $ request -> queryString (); Você pode recuperar o conteúdo de texto da solicitação usando o método text , desde que o tipo de conteúdo seja definido como text/plain
$ text = $ request -> text (); Você pode recuperar o conteúdo JS da solicitação usando o método js , desde que o tipo de conteúdo seja definido como application/javascript
$ js = $ request -> js (); Você pode recuperar o conteúdo HTML da solicitação usando o método html , desde que o conteúdo seja definido como text/html
$ js = $ request -> html (); Você pode recuperar o conteúdo JSON da solicitação usando o método json , desde que o tipo conteúdo seja definido como application/json o $request->data() retorna todos os dados JSON passados para a solicitação. No entanto,
$ jsonData = $ request -> json (); O $request->data() contém todos os dados JSON, juntamente com as entradas passadas pelos parâmetros de consulta na solicitação. No entanto, $request->json() pode ser usado para recuperar apenas o conteúdo JSON.
Você pode recuperar o conteúdo XML da solicitação usando o método xml , desde que o tipo de conteúdo esteja definido como application/json
$ xmlData = $ request -> xml ();Espera -se que todas as rota e controlador produzam uma resposta para entrega ao navegador do usuário. O Elemental oferece vários métodos para gerar respostas. A forma mais simples de resposta envolve o retorno de uma string diretamente de uma rota ou controlador. A estrutura converterá perfeitamente essa string em uma resposta HTTP completa.
Route:: get ( ' / ' , function () {
return ' Hello World ' ;
});Além de devolver strings de suas rotas e controladores, você também pode retornar matrizes ou objetos. A estrutura será convertida automaticamente em uma resposta JSON:
Route:: get ( ' / ' , function () {
return [ 1 , 2 , 3 ];
}); Normalmente, você não apenas retorna seqüências ou matrizes diretas de suas ações de rota. Em vez disso, você geralmente retorna instâncias completas de CoreResponseResponse ou Views.
O retorno de uma instância Response completa permite que você personalize o código de status HTTP da resposta e os cabeçalhos. Você pode injetar a instância de resposta, que entra na instância de resposta dentro do seu controlador ou fechamento de rota.
use Core Response Response ;
Route:: get ( ' /home ' , function ( Response $ response ) {
$ response -> setHeader ( " content-type " , " text/plain " )
-> setStatusCode ( 200 )
-> setContent ( " Hello World " );
return $ response ;
}); É claro que você pode retornar uma view de um controlador. No entanto, se você precisar de controle sobre o status e os cabeçalhos da resposta, mas também precisará retornar uma view como o conteúdo da resposta, poderá fazer isso como seguinte:
use Core Response Response ;
class UserController {
public function register ( Response $ response ){
$ response -> setHeader ( " x-is_register " , " true " );
return view ( " Register " );
}
}Isso definirá automaticamente o cabeçalho na resposta de visualização que será enviada ao navegador.
Lembre -se de que a maioria dos métodos de resposta é em cadeia, permitindo a construção fluente de instâncias de resposta.
Você pode definir o conteúdo da resposta usando o método setContent na instância de resposta.
$ response -> setContent ( " ... " ); No entanto, se você deseja anexar o conteúdo da resposta, poderá fazê -lo usando o método appendContent na instância de resposta.
$ response -> appendContent ( " ... " ); Você pode definir um cabeçalho na instância de resposta usando o método setHeader
$ response -> setHeader ( " content-type " , " text/plain " ); No entanto, se você deseja definir vários cabeçalhos simultaneamente, poderá fazê -lo usando o método setHeaders e passando uma variedade de cabeçalhos.
$ response -> setHeaders ([ " content-type " => " text/html " , ...]); Você pode definir diretamente o código de status da resposta usando o método setHeader na instância de resposta.
$ response -> setStatusCode ( 301 );Um texto de status será definido por padrão para os códigos de status comuns.
Você pode gerar uma resposta de redirecionamento que contém os cabeçalhos adequados necessários para redirecionar o usuário para outra URL, invocando redirect do método estático na classe CoreResponseResponse .
use Core Response Response ;
Route:: get ( ' /dashboard ' , function () {
return Response:: redirect ( ' home/dashboard ' );
}); No entanto, por simplicidade, um método auxiliar redirect() também está disponível globalmente para alcançar a mesma funcionalidade.
use Core Response Response ;
Route:: post ( ' /story/create ' , function () {
if (! $ someCondition )
return redirect ( ' /story ' , 204 );
}); Você também pode gerar uma resposta JSON chamando o método estático JSON na classe CoreResponseResponse . Os dados passados para o método serão convertidos para JSON adequado. Opcionalmente, você também pode passar o código de status e os cabeçalhos como o segundo e o terceiro argumento para a função.
use Core Response Response ;
Route:: post ( ' /post ' , function () {
$ post = ( . . . );
return Response:: JSON ( $ post , 201 , [ " header " => " value " ]);
});O Middleware oferece um mecanismo conveniente para examinar e filtrar solicitações HTTP recebidas para o seu aplicativo. Por exemplo, você pode desenvolver middleware para validar o status de autenticação do usuário do seu aplicativo. Se o usuário não for autenticado, o middleware os redirecionará para a tela de login. Por outro lado, se o usuário for autenticado, o middleware permitirá que a solicitação avançasse mais no aplicativo.
Você tem a flexibilidade de criar middleware adicional para executar diversas tarefas além da autenticação. Como ilustração, um middleware de madeira pode registrar todas as solicitações recebidas no seu aplicativo. Esses componentes do middleware estão alojados no diretório app/middlewares .
Para criar um novo middleware, use o comando build:middleware Candle:
php candle build:middleware IsAuthenticated A execução deste comando gerará uma nova classe de middleware chamada "isauthenticated" no diretório app/middlewares . Nesta classe, um método chamado handle é criado onde você pode articular a lógica para o middleware.
Aqui, permitiremos apenas o acesso à rota se o usuário for autenticado; caso contrário, redirecionaremos os usuários de volta ao 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 );
}
} Para aprovar a solicitação no aplicativo, você deve ligar para o $next Retorno com a $request .
Considere o middleware como uma sequência de "camadas" que o HTTP solicita que o Traverse antes de atingir seu aplicativo. Cada camada tem a capacidade de examinar a solicitação e potencialmente rejeitá -la.
Obviamente, um middleware pode executar tarefas antes ou depois de passar a solicitação mais profundamente para o aplicativo. Por exemplo, esse middleware executaria sua tarefa após a solicitação ser tratada pelo aplicativo:
<?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 ;
}
} Se você deseja atribuir middleware a rotas específicas, pode invocar o método middleware ao definir a rota:
Route:: get ( ' /profile ' , function () {
// ...
})-> middleware (IsAuthenticated::class); Você pode atribuir vários middleware à rota passando uma variedade de nomes de middleware para o método middleware :
Route:: get ( ' / ' , function () {
// ...
})-> middleware ([First::class, Second::class]); Você pode atribuir middlewares a um grupo de rota, passando uma variedade de nomes de middleware para o atributo middlewares ao definir o grupo:
Route:: group ([ " middleware " => [HasSession::class]], function () {
Route:: get ( " / " , [StoryController::class, " index " ]);
Route:: get ( " /story/{story} " , [StoryController::class, " show " ]);
}); Você pode usar grupos de rota aninhados para combinar utensílios médios com o grupo dos pais. No exemplo subsequente, o middleware "hassession" é aplicado às rotas "/" e "/story/{story}" , enquanto "Hassession", "Isauth" e "Log" Middlewares são aplicadas ao restante das rotas:
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 " ]);
});
});Na estrutura elementar do PHP, não é prático devolver strings de documentos HTML inteiros diretamente de rotas e controladores. As visualizações fornecem uma maneira conveniente de colocar todo o HTML em arquivos separados.
As visualizações desempenham um papel crucial na separação da lógica do controlador/aplicativo das preocupações de apresentação e são armazenadas no diretório app/views . Esses arquivos de exibição, gravados em PHP, encapsulam a marcação. Considere um exemplo básico de uma visão:
<html>
<body>
<h1>Hello, <?= $ name ?> </h1>
</body>
</html> Se essa visualização for armazenada no app/views/Welcome.php , ela poderá ser devolvida usando o Helper Global view em uma rota:
Route:: get ( ' / ' , function () {
return view ( ' Welcome ' , [ ' name ' => ' Ahmed ' ]);
}); O primeiro argumento passou para o auxiliar view corresponde ao nome do arquivo de exibição no diretório resources/views . O segundo argumento pode ser uma matriz de pares de valores-chave passados para a vista. Por exemplo, no código acima, $name será diretamente acessível e conterá o valor 'ahmed'.
As visualizações também podem ser retornadas usando o método estático make na classe CoreViewView :
Route:: get ( ' / ' , function () {
return View:: make ( " Post " , $ params );
}); As visualizações podem ser aninhadas nos subdiretos do diretório de app/views . A notação "DOT" pode ser usada para fazer referência a visões aninhadas. Por exemplo, se sua visualização for armazenada em app/views/layouts/MainLayout.php , você poderá devolvê -la de uma rota/controlador assim:
return view ( ' layouts.MainLayout ' , $ data ); O Elemental fornece uma maneira conveniente de manter o mesmo layout em várias visualizações, reduzindo a duplicação de código. Um layout é um arquivo de visualização que contém um espaço reservado {{ content }} . Quando uma visualização é retornada com o layout, a visualização final é compilada colocando a exibição dentro do conteúdo do layout.
O Elemental fornece uma maneira conveniente de manter o mesmo layout em várias visualizações, reduzindo a duplicação de código. Um layout é um arquivo de exibição que incorpora um espaço reservado designado, indicado por {{ content }} . Quando uma visualização é retornada usando um layout específico, a composição é alcançada incorporando o conteúdo da visualização dentro do espaço reservado designado no layout. Essa abordagem simplifica a organização de visualizações e aprimora a manutenção de código, centralizando elementos de layout comuns.
Abaixo está um exemplo básico:
<!DOCTYPE html >
< html lang =" en " >
< head >
<!-- Head content -->
</ head >
< body >
< ?= component("components.Navbar") ? >
< div style =" min-height: calc(100vh - 140px); " >
{{ content }}
</ div >
</ body >
</ html >Uma visão pode ser devolvida com um layout como este:
public function compose ()
{
return view ( " Compose " )-> withLayout ( " layouts.DashboardLayout " );
}O Elemental oferece uma abordagem poderosa para criar vistas. Toda visão é essencialmente um componente, e qualquer visualização pode ser montada de outros componentes. É uma sinfonia de composição, onde cada peça contribui para a criação de um todo harmonioso e dinâmico.
Exemplo de arquivo de componente ( views/components/Logo.php ):
<a class="logo" href="/ " >
<span class= " logo-img">
<img src="logo.png" class ="logo-text">
LOGO
</span>
</a> Este componente pode ser usado dentro de qualquer outro arquivo de exibição. Por exemplo, no views/Login.php :
<div>
<?= component ( " components.Logo " ) ?>
<p>Welcome Back!</p>
<!-- Other login form elements -->
</div>Assim, o elementar o capacita com construções de layout e componentes, permitindo que você componha suas visões com a requinte das abordagens de cima para baixo e de baixo para cima. Essa flexibilidade permite uma fusão perfeita, onde você pode misturar e combinar elementos sem esforço para criar uma interface de usuário elegante e sofisticada para o seu aplicativo.
Nos aplicativos modernos da Web, a interação do banco de dados é um aspecto fundamental. O Elemental foi projetado para otimizar perfeitamente essa interação em uma gama diversificada de bancos de dados suportados, aproveitando os recursos inerentes ao PDO PHP. Com o Elemental, você tem a flexibilidade de executar qualquer consulta ou transação complexa usando a classe CoreDatabaseDatabase .
O Elemental oferece um mapeador robusto de objetos relacionados a objetos (ORM) que abstraça efetivamente muitos meandros, provando inestimável para a maioria das consultas de banco de dados. No entanto, o CoreDatabaseDatabase pode ser usado para executar consultas SQL mais avançadas.
Todas as configurações para o seu aplicativo elementar estão localizadas no arquivo de configuração do app/config/config.php do seu aplicativo. Aqui você pode definir todas as suas conexões de banco de dados, bem como especificar qual conexão deve ser usada por padrão. A maioria das opções de configuração dentro deste arquivo é acionada pelos valores das variáveis de ambiente do seu aplicativo.
Todas as configurações para o seu aplicativo elementar estão localizadas no arquivo de configuração do app/config/config.php do seu aplicativo. Aqui você pode definir todas as suas conexões de banco de dados, bem como especificar qual conexão deve ser usada por padrão. A maioria das opções de configuração dentro deste arquivo é acionada pelos valores das variáveis de ambiente do seu aplicativo.
<?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 " ) ?? "" ,
],
]; O Elemental usa o PDO como a classe de manuseio de banco de dados subjacente. Todas as funções PDO estão diretamente disponíveis na classe CoreDatabaseDatabase . Você pode injetar uma instância do CoreDatabaseDatabase em qualquer método de construtor ou controlador para chamar os métodos PDO. A configuração padrão para Elemental é configurada para bancos de dados MySQL, mas você pode alterar o driver dentro do arquivo de configuração.
Aqui está um exemplo de execução de uma consulta através da instância 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 ();
}Para obter mais informações sobre PDO, você pode consultar a documentação de PDO do PHP
O Elemental Inclui um mapeador de objetos feitos personalizados (ORM) que torna agradável interagir com o banco de dados. Ao usar o ORM, cada tabela de banco de dados possui um "modelo" correspondente usado para interagir com essa tabela. Além de recuperar registros da tabela de banco de dados, os modelos permitem inserir, atualizar e excluir registros da tabela também.
Os modelos estão presentes no diretório de app/models e estendem a classe CoreModelModel . Você pode gerar um novo modelo usando o comando build:model Candle.
php candle build:model Post Os modelos gerados pelo comando build:model serão colocados no diretório app/Models . Um modelo muito básico tem a seguinte estrutura:
<?php
namespace App Models ;
use Core Model Model ;
class Post extends Model
{
// ...
} Nome da tabela: Por convenção, o "Caso Snake", o nome do plural da classe será usado como nome da tabela, a menos que outro nome seja explicitamente especificado. Portanto, nesse caso, o Elemental assumirá que o Post Model armazena registros na tabela posts .
Você pode especificar manualmente o nome da tabela do modelo definindo uma propriedade de tableName no modelo:
<?php
namespace App Models ;
use Core Model Model ;
class Post extends Model
{
protected $ tableName = ' elemental_posts ' ;
}Chave primária:
Elemental também assumirá que a tabela de banco de dados correspondente de cada modelo possui uma coluna de chave primária chamada id . Se necessário, você pode definir uma propriedade $primaryKey protegido em seu modelo para especificar uma coluna diferente que serve como chave primária do seu modelo:
<?php
namespace App Models ;
use Core Model Model ;
class Post extends Model
{
protected $ primaryKey = ' elemental_id ' ;
}Você pode pensar em cada modelo como um poderoso construtor de consultas, permitindo que você consulte fluentemente a tabela de banco de dados associada ao modelo.
O método all do modelo recuperará todos os registros da tabela de banco de dados associada do modelo:
use App Models Story ;
foreach (Story:: all () as $ story ) {
echo $ story [ " content " ];
}Por padrão, os registros buscados são representados como uma matriz. No entanto, você pode passar em um argumento de modo que controla como cada registro é representado. O argumento do modo leva qualquer um dos modos de busca de PDO. Por exemplo,
use App Models Story ;
foreach (Story:: all () as $ story ) {
echo $ story -> content ;
} O método allWhere é uma abstração poderosa no modelo que permite executar consultas complexas. Este método leva três argumentos: conditions , options e fetchMode .
public static function allWhere( array $ conditions , array $ options = [], int $ fetchMode = PDO :: FETCH_ASSOC ) Condições: O parâmetro conditions é uma matriz de cláusulas que o registro deve satisfazer a ser buscado. Cada condição pode ser um par [key => value] ou um par [key => [operator, value]] .
key corresponde a uma coluna específica na tabela.[key => value] , o operador padrão é = e o value é os dados dentro dessa coluna para o registro.[key => [operator, value]] , você poderá especificar o operador para cada condição. Os operadores suportados são:['=', '!=', '<', '>', '<=', '>=', 'LIKE', 'IS NULL', 'IS NOT NULL'] . Opções: O parâmetro options é uma matriz que determina argumentos de consulta adicionais, como order by , limit , etc. As construções suportadas no argumento de opções incluem:
"orderBy""limit""offset""sortDir" FetchMode: O parâmetro fetchMode controla como cada registro buscado é representado. O argumento do modo leva qualquer um dos modos de busca de PDO:
PDO::FETCH_ASSOCPDO::FETCH_NUMPDO::FETCH_BOTHPDO::FETCH_OBJPDO::FETCH_CLASSPDO::FETCH_INTOPDO::FETCH_LAZYPDO::FETCH_KEY_PAIRUm exemplo deixará mais claro:
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
);
}
} Além de recuperar todos os registros que correspondem a uma determinada consulta, você também pode recuperar registros únicos usando o find e where o método. Em vez de retornar uma variedade de registros, esses métodos retornam uma única instância de modelo:
Encontre: isso buscará o primeiro registro que corresponde à chave primária da tabela.
$ flight = Story:: find ( 1 ); Onde: o método Where pega uma variedade de condições que o registro deve satisfazer para ser buscado. Cada condição pode ser um par [key => value] ou um par [key => [operator, value]] .
key corresponde a uma coluna específica na tabela.[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'] .Por exemplo
$ 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. Por exemplo:
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. É isso! Obrigado!
For bug reports, feature requests, or general questions, please use the issue tracker.