Antes de tudo precisamos importar nosso loader do composer:
include 'vendor/autoload.php;
Agora podemos instânciar o Router.
$router = new \Albreis\Router;
// ou
use Albreis\Router;
$router = new Router;
O Router aceita qualquer método de requisição e possui 3 argumentos:
$router->[metodo]([path], [callback], [bypass], [return]);
metodo GET, POST, DELETE, CLI, etc
path é o caminho em que o callback deve ser executado. Usa REGEX para definir as rotas.
callback é um callable, seja uma função ou método e aceita os formatos:
- função anônima
function() { ... }
- métodos
[$instancia, metodo]
Ex. [$this, run] - métodos estáticos
'Classe::metodo'
(caso não seja estático será criada uma instância da classe automaticamente) - Arrow functions
fn() => return true
bypass indica se o script vai continuar sendo executado após o match com a rota.
return indica se será retornado o valor caso o callback retorne algum valor
Exemplo 1:
$router->get('^login$', function(){
/**
* Aqui tu podes criar toda sua lógica seja retornar
* um JSON ou um HTML
**/
});
Exemplo 2:
$router->get('^([^/]+)/([^/]+)$', function($category, $post){
/**
* Aqui tu podes criar toda sua lógica seja retornar
* um JSON ou um HTML
**/
});
O Router chamará a função exit()
após executar o callback, evitando assim a execução do restante do script.
Caso queira que o script continue sendo executado mesmo após dar match com a rota basta passar o parâmetro bypass como true.
Exemplo 3:
$router->get('^([^/]+)/([^/]+)$', function($category, $post){
/**
* Ao acessar a URL /frutas/melancia
* A saída do var_dump abaixo seria:
* string(6) "frutas" string(8) "melancia"
*/
var_dump($category, $post);
/**
* Essa rota vai ser executada e continuar para
* a próxima rota pois foi passado o parâmetro 3 como true
*/
}, true);
Ao acessar a rota http://seusite.com.br/minha-categoria/postagem-109 as variáveis $category
e $post
teriam os valores minha-categoria e postagem-109 respectivamente.
Para usar o Router como um middleware para setar a rota como bypass.
No exemplo abaixo temos um middleware que é executado em todas as requisições do método POST para a rota login.
Um exemplo de uso seria para criar um sistema de logs de requisição ou pré tratamento de dados.
Exemplo 4:
$router->get('^login$', function(){
/**
* Executa as instruções e segue para a próxima rota
*/
/**
* Este print_r() irá retornar Array ( )
*/
print_r($_GET);
$_GET['teste'] = 123;
}, true);
$router->get('^login$', function(){
/**
* Daqui em diante nada será executado
*/
/**
* Este print_r() irá retornar Array ( [teste] => 123 )
*/
print_r($_GET);
});
Existem 2 métodos que também podem ser utilizados com middlwares.
A diferença entre usar esses métodos ou utilizar uma rota com bypass é que com before e after você não precisa escrever o pattern da rota.
Before e After podem ser usados também em rotas com bypass.
$router->before(function(){
/**
* Callback executado antes da action da rota
*/
})->after(function(){
/**
* Callback executado após a action da rota
*/
})->get('^login$', function(){
/**
* Executa as instruções da rota e pára a excusão do script
*/
/**
* Este print_r() irá retornar Array ( )
*/
print_r($_GET);
$_GET['teste'] = 123;
});
Você pode usar o Router via terminal para chamar as rotas usando o padrão abaixo:
$ php index.php METODO PATH ARGUMENTOS
Exemplo:
$ php index.php POST /login username=usuario01 password=1234
Exemplo 5 (funções anônimas):
$router->get('^login$', function(){
});
Exemplo 6 (arrow functions):
$router->get('^([^/]+)/([^/]+)$', fn($a, $b) => var_dump($a, $b));
Exemplo 6 (métodos):
class Home {
public function index($a, $b) {
echo 'Homepage';
}
}
$home = new Home;
$router->get('^([^/]+)/([^/]+)$', [$home, 'index']);
// ou
$router->get('^([^/]+)/([^/]+)$', 'Home::index');
// ou
$router->get('^([^/]+)/([^/]+)$', function($a, $b) use ($home) {
$home->index($a, $b);
});
// ou
$router->get('^([^/]+)/([^/]+)$', fn($a, $b) => $home->index($a, $b));
Agora é possível agrupar rotas usando prefixos:
Exemplo:
$router->prefix('/api')->all(function(Router $router) {
$router->get('^([^/]+)/([^/]+)$', [$home, 'index']);
// ou
$router->get('^([^/]+)/([^/]+)$', 'Home::index');
// ou
$router->get('^([^/]+)/([^/]+)$', function($a, $b) use ($home) {
$home->index($a, $b);
});
// ou
$router->get('^([^/]+)/([^/]+)$', fn($a, $b) => $home->index($a, $b));
});
Agora os métodos podem usar injeção de parâmetro, exemplo:
$router = new Albreis\Router;
class Model { }
$router->get('/', function(Model $model){
// $model é uma instância da classe Model
});
Agora também é possivel acessar uma instância do Router a partir do método:
$router = new Albreis\Router;
$router->get('/', function($router){
// $router é uma instância do router atual e está sempre disponível
});
Router Registry é uma forma de carregar automaticamente rotas usando DocBlock @Route.
Exemplo:
class HomeController {
/**
* @Route::get('^/?$')
*/
public function index() {
var_dump(123);
}
}
<?php
use Albreis\Router;
use Albreis\RouterRegistry;
require '../vendor/autoload.php';
$router = new Router;
$registry = new RouterRegistry($router);
$registry->loadFrom(__DIR__ . '/../src/Http/Controllers', 'App/');
$registry->run();
Isso vai fazer com o todas as classes do namespace App/ do diretorio sejam mapeadas.
<?php
use Albreis\Router;
use Albreis\RouterRegistry;
use App\Http\Controllers\HomeController;
require '../vendor/autoload.php';
$router = new Router;
$registry = new RouterRegistry($router);
$registry->addClass(HomeController::class);
$registry->run();
Isso vai fazer com os metodos da classe sejam mapeados.
Você pode utilizar funções para trabalhar com rotas:
<?php
use Albreis\Router;
use Albreis\RouterRegistry;
use App\Http\Controllers\HomeController;
require '../vendor/autoload.php';
$router = new Router;
$registry = new RouterRegistry($router);
/**
* @Route::get('/hello')
*/
function hello()
{
echo('hello');
}
$registry->loadUserFunctions();
$registry->run();
Ao acessar /hello o Router vai executar essa função. Lembre-se que a função precisa existir.
Caso a função esteja em um arquivo externo que ainda não tenha sido feito include/require vocêpode usar o método loadUserFunctionsFrom(), ele vai fazer include do arquivo antes de buscar rotas.
<?php
use Albreis\Router;
use Albreis\RouterRegistry;
use App\Http\Controllers\HomeController;
require '../vendor/autoload.php';
$router = new Router;
$registry = new RouterRegistry($router);
$registry->loadUserFunctionsFrom('../functions.php');
$registry->run();
<?php
use Albreis\Router;
use Albreis\RouterRegistry;
use App\Http\Controllers\HomeController;
require '../vendor/autoload.php';
$router = new Router;
$registry = new RouterRegistry($router);
/**
* @Route::get('/hello')
*/
function hello()
{
echo('hello');
}
$registry->addFunction('hello');
$registry->run();
Em produção o ideal é que a aplicação não fique escaneando os arquivos por rotas a cada requisição.
Para isso você pode gerar um arquivo de rotas usando o método $registry->save([caminho do arquivo]).
O caminho padrão do arquivo é routes.php no direotrio atual.