Ele lê a rota da URL e analisa os valores do caminho, para que possa ser interpretado manual ou automaticamente da maneira mais rápida possível (por exemplo, para implementar um sistema MVC).
Ao contrário de outras bibliotecas, esta biblioteca não possui dependências e está contida em uma única classe, portanto é compatível com qualquer projeto PHP, por exemplo WordPress, Laravel, Drupal, um projeto PHP personalizado, etc.
Esta biblioteca é baseada na Convenção CoC sobre Configuração . Reduz o clichê, mas possui funcionalidades fixas. Esta biblioteca não permite a utilização de "rotas" personalizadas mas cobre praticamente todos os casos, aumentando o desempenho e a usabilidade ao mesmo tempo que sacrifica a flexibilidade.
Digamos que temos a próxima URL http://somedomain.dom/Customer/Update/2 Esta biblioteca converte esta URL em variáveis que podem ser de processo ou chamando diretamente um método.
rota.php
$ route = new RouteOne ( ' http://www.somedomain.dom ' );
$ route -> addPath ( ' api/{controller}/{action}/{id} ' );
$ route -> addPath ( ' {controller}/{action}/{id}/{idparent} ' );
$ route -> fetchPath ();
$ this -> callObjectEx ( ' cocacolacontroller{controller}Controller ' );
classe controllerCustomerController.php
namespace cocacola controller ;
class CustomerController {
public function updateAction ( $ id = null , $ idparent = null , $ event = null ) {
echo " We want to update the customer $ id " ;
}
}
Digamos que façamos a próxima operação:
Um usuário chama o próximo site http://somedomain.com/Customer/Insert, ele deseja mostrar um formulário para inserir um cliente
use eftec RouteOne RouteOne ;
$ route = new RouteOne ( ' . ' , null , null ); // Create the RouteOne Class
$ route -> fetch (); // fetch all the input values (from the route, get, post and such).
$ route -> callObject ( ' somenamespace \ controller \ %sController ' ); // where it will call the class CustomerController*
ou
use eftec RouteOne RouteOne ;
$ route = new RouteOne ( ' . ' , null , null ); // Create the RouteOne Class
$ route -> fetch (); // fetch all the input values (from the route, get, post and such).
$ route -> callObjectEx ( ' somenamespace \ controller \ {controller}Controller ' ); // where it will call the class CustomerController*
Este código chama o método InsertActionGet (GET), InsertActionPost (POST) ou InsertAction (GET/POST) dentro da classe Customer
O método chamado é escrito da seguinte forma:
class Customer {
public function insertAction ( $ id = "" , $ idparent = "" , $ event = "" ) {
// here we do our operation.
}
}
Vamos querer atualizar um número de cliente 20 , então poderíamos ligar para a próxima página
http://somedomain.com/Customer/Update/20
onde 20 é o "$id" do cliente a ser editado (pode ser um número de uma string)
E se quisermos atualizar um cliente número 20 do APPL empresarial
http://somedomain.com/Customer/Update/20/APPL
Onde APPL é o idparent
Agora, digamos que clicamos em algum botão ou realizamos alguma ação. Pode ser capturado pelo campo _event e lido pelo argumento $event . Esta variável pode ser enviada via GET ou POST.
http://somedomain.com/Customer/Update/20/APPL?_event=click
Nota: Os módulos são obtidos automaticamente se você usar addPath() e fetchPath(), portanto não é necessário especificá-los. Agora, digamos que nosso sistema seja modular e tenhamos vários clientes (clientes internos, externos, etc.)
$ route = new RouteOne ( ' . ' , null , true ); // true indicates it is modular.
ou
$ route = new RouteOne ( ' . ' , null ,[ ' Internal ' ]); // or we determine the module automatically. In this case, every url that starts with Internal
então
$ route -> fetch ();
$ route -> callObject ( ' somenamespace \ %2s% \ controller \ %1sController ' );
http://somedomain.com/Internal/Customer/Update/20/APPL?_event=click
Então, a primeira ramificação é o nome do módulo ( Internal ) e chama a classe somenamespaceInternalcontrollerCustomerController
compositor requer eftec/ RouteOne
Linux:
vendor/bin/ RouteOne cli -init (if the binary does not work, then chage the permission to execution)
Windows:
. v endor b in r outeonecli.bat -init
Ele criará o arquivo .htaccess e os arquivos route.php e route.php terão uma configuração padrão.
const BASEURL = " http://localhost " ; // Base url edit this value.
const BASEWEBNS = " eftec \ controller " ; // Base namespace (web) edit this value
const BASEAPINS = " eftec \ api " ; // Base namespace (api) edit this value
Posteriormente, você poderá adicionar ou editar o código neste arquivo.
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews -Indexes
</IfModule>
RewriteEngine On
DirectoryIndex route.php
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]
# Send Requests To Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ route.php?req=$1 [L,QSA]
</IfModule>
Se o seu host não permitir a opção FollowSymlinks, tente substituí-la por Options +SymLinksIfOwnerMatch.
A linha importante é:
RewriteRule ^(.*)$ route.php?req=$1 [L,QSA] # O roteador a ser chamado.
server {
listen 80;
server_name localhost;
root /example.com/public;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
index index.html index.htm index.php;
charset utf-8;
location / {
try_files $uri $uri/ /router.php?req=$document_uri&$query_string;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
error_page 404 /index.php;
location ~ .php$ {
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /.(?!well-known).* {
deny all;
}
}
A linha importante é:
try_files $uri $uri/ /router.php?req=$document_uri&$query_string;
server {
listen 80;
server_name localhost;
root c:/www;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
index index.html index.htm index.php;
charset utf-8;
location / {
try_files $uri $uri/ /router.php?req=$document_uri&$query_string;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
error_page 404 /index.php;
location ~ .php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /.(?!well-known).* {
deny all;
}
}
A linha importante é:
try_files $uri $uri/ /router.php?req=$document_uri&$query_string;
onde router.php é o arquivo que funcionará como roteador. ?req=$1 é importante porque o sistema irá ler a rota de "req"
// router.php
$ route = new RouteOne (); // Create the RouteOne Class
$ route -> fetch (); // fetch all the input values (from the route, get, post and such).
$ route -> callObject ( ' somenamespace \ controller \ %sController ' ); // where it will call the class somenamespacecontrollerCustomerController
Observação:
Se você quiser usar um argumento diferente de "req", poderá alterá-lo usando o próximo código:
$route->argumentName='newargument';
Desde a versão 1.21, é possível usar um caminho personalizado em vez de um caminho predefinido. É a forma recomendada. O outro método ainda está presente.
Sintaxe:
limparPath()
Limpa todos os caminhos definidos
Sintaxe:
addPath($caminho, $nome = null,chamável $middleWare=null)
Ele adiciona caminhos que podem ser avaliados usando fetchPath()
Exemplo:
$ this -> addPath ( ' api/{controller}/{action}/{id:0} ' , ' apipath ' );
$ this -> addPath ( ' /api/{controller}/{action}/{id:0}/ ' , ' apipath ' ); // "/" at the beginner and end are trimmed.
$ this -> addPath ( ' {controller}/{action}/{id:0} ' , ' webpath ' );
$ this -> addPath ( ' {controller:root}/{action}/{id:0} ' , ' webpath ' ); // root path using default
$ this -> addPath ( ' somepath ' , ' namepath ' ,
function ( callable $ next , $ id = null , $ idparent = null , $ event = null ) {
echo " middleware n" ;
$ result = $ next ( $ id , $ idparent , $ event ); // calling the controller
echo " endmiddleware n" ;
return $ result ;
});
Observação:
A primeira parte do caminho, antes de "{" é usada para determinar qual caminho será usado.
Exemplo "path/{controller}" e "path/{controller}/{id}", o sistema considerará que são o mesmo caminho
string de parâmetro $path O caminho, exemplo "aaa/{controller}/{action:default}/{id}"
Onde default é o valor padrão opcional.
parâmetro string|null $name (opcional), o nome do caminho
parâmetro callable|null $middleWare Uma função que pode ser chamada usada para middleware.
O primeiro argumento da função deve ser um método que pode ser chamado
Os próximos argumentos devem ser os argumentos definidos por callObjectEx
(id, idparent, evento)
O caminho pode começar com um local estático, mas o restante do caminho deve ser definido por variáveis (entre {}) e separadas por "/".
Você também pode definir um valor padrão para um caminho escrevendo ":" após o nome da variável: {name:defaultvalue}
O nome pode ser obtido usando $this->currentPath. Se você adicionar um nome com o mesmo nome, ele será substituído.
Se você não definir um nome, ele usará um número automático.
O nome também é retornado quando você chama $this->fetchPath()
Exemplo:
$ this -> addPath ( ' {controller}/{id}/{idparent} ' );
$ this -> addPath ( ' myapi/otherfolder/{controller}/{id}/{idparent} ' );
$ this -> addPath ( ' {controller:defcontroller}/{action:defaction}/{id:1}/{idparent:2} ' );
// url: /dummy/10/20 =>(controller: dummy, id=10, idparent=20)
// url: /myapi/otherfolder/dummy/10/20 =>(controller: dummy, id=10, idparent=20)
Você pode definir caminhos diferentes, porém usa apenas a primeira parte do caminho que corresponde a alguma URL. 'path/somepath/{id}' funcionará 'path/{id}/other' não funcionará
Sintaxe:
buscarPath()
Ele busca o caminho previamente definido por addPath e retorna o nome (ou número) do caminho. Se não for encontrado, retorna falso
Exemplo:
$ route = new RouteOne ( ' http://www.example.dom ' );
$ route -> addPath ( ' {controller}/{id}/{idparent} ' , ' optionalname ' );
// if the url is : http://www.example.dom/customer/1/200 then it will return
echo $ route -> fetchPath (); // optionalname
echo $ route -> controller ; // customer
echo $ route -> id ; // 1
echo $ route -> idparent ; // 200
Obtém um valor de consulta (URL).
Nota: Esta consulta não inclui os valores "req","_event" e "_extra"
Exemplo:
// http://localhost/..../?id=hi
$ id = $ router -> getQuery ( " id " ); // hi
$ nf = $ router -> getQuery ( " something " , " not found " ); // not found
Ele define um valor de consulta
Exemplo:
$ route -> setQuery ( " id " , " hi " );
$ id = $ router -> getQuery ( " id " ); // hi
Sintaxe:
buscarPath()
Busque os valores da rota e os valores serão processados.
Sintaxe
callObjectEx($classStructure, $throwOnError, $method, $methodGet, $methodPost,$arguments,$injectArguments)
Ele cria uma nova instância de um objeto (por exemplo, um objeto Controller) e chama o método.
Nota: É uma versão avançada deste::callObject()
Este método usa {} para substituir valores com base nas próximas variáveis:
Marcação | Descrição |
---|---|
{controlador} | O nome do controlador |
{Ação} | A ação atual |
{evento} | O evento atual |
{tipo} | O tipo atual de caminho (ws,controller,front,api) |
{módulo} | O módulo atual (se o módulo estiver ativo) |
{eu ia} | O ID atual |
{idparent} | O idparent atual |
{categoria} | A categoria atual |
{subcategoria} | A subcategoria atual |
{subsubcategoria} | A subsubcategoria atual |
Exemplo:
// controller example http://somedomain/Customer/Insert/23
$ this -> callObjectEx ( ' cocacolacontroller{controller}Controller ' );
// it calls the method cocacolacontrollerCustomer::InsertAction(23,'','');
// front example: http://somedomain/product/coffee/nescafe/1
$ this -> callObjectEx ( ' cocacolacontroller{category}Controller ' // the class to call
, false // if error then it throw an error
, ' {subcategory} ' // the method to call (get, post or any other method)
, null // the method to call (method get)
, null // the method to call (method post)
,[ ' subsubcategory ' , ' id ' ] // the arguments to call the method
,[ ' arg1 ' , ' arg2 ' ]); // arguments that will be passed to the constructor of the instance
// it calls the method cocacolacontrollerproduct::coffee('nescafe','1');
Chame um método dentro de um objeto usando a rota atual.
Exemplo:
Roteador:
$ databaseService = new SomeDatabaseService ();
$ route = new RouteOne ();
$ route -> callObjectEx ( ' cocacolacontroller{controller}Controller ' // the class to call
, false // if error then it throw an error
, ' {action}Action ' // the method to call (get, post or any other method)
, ' {action}Action{verb} ' // the method to call (method get)
, ' {action}Action{verb} ' // the method to call (method post)
,[ ' id ' , ' idparent ' , ' event ' ] // the arguments to call the method
,[ $ databaseService , $ route ]); // (optional)arguments that will be passed to the constructor of the instance
Controlador:
namespace cocacola controller ;
class CustomerController {
protected $ databaseService ;
protected $ route ;
public function __construct ( $ databaseService , $ route ) {
// optional: injecting services
$ this -> databaseService = $ databaseService ;
$ this -> route = $ route ;
}
// any action GET or POST
public function GreenAction ( $ id = "" , $ idparent = "" , $ event = "" ) {
}
// GET only action (optional)
public function BlueActionGET ( $ id = "" , $ idparent = "" , $ event = "" ) {
// **my code goes here.**
}
// POST only action (optional)
public function YellowActionPOST ( $ id = "" , $ idparent = "" , $ event = "" ) {
// **my code goes here.**
}
// GET only action (optional)
public function RedActionGET ( $ id = "" , $ idparent = "" , $ event = "" ) {
// **my code goes here.**
}
// any action GET or POST
public function RedAction ( $ id = "" , $ idparent = "" , $ event = "" ) {
// **my code goes here.**
}
}
Resultados:
url | método chamado |
---|---|
http://localhost/Cliente/Verde (GET) | Ação Verde |
http://localhost/Customer/Green/20/30?_event=click (OBTER) | GreenAction($id=20, $idparent=30, $event='clique') |
http://localhost/Cliente/Verde (POST) | Ação Verde |
http://localhost/Cliente/Azul (GET) | BlueActionGET |
http://localhost/Cliente/Azul (POST) | ERRO |
http://localhost/Cliente/Amarelo (GET) | ERRO |
http://localhost/Cliente/Amarelo (POST) | AmareloAçãoPOST |
http://localhost/Customer/Red (GET) | RedActionGET (tem prioridade sobre RedAction) |
http://localhost/Customer/Red (POST) | Redação |
http://localhost/Cliente/Laranja | ERRO |
Ele chama (inclui) um arquivo php usando o nome atual do controlador
Sintaxe:
getHeader($chave, $valorIfNotFound = null)
Obtém o cabeçalho atual (se houver). Se o valor não for encontrado, ele retornará $valueIfNotFound. Observe que a chave $ é sempre convertida em maiúsculas.
Exemplo:
$ token = $ this -> getHeader ( ' token ' , ' TOKEN NOT FOUND ' );
Sintaxe:
getBody($jsonDeserialize = falso, $asAssociative = verdadeiro)
Obtém o corpo de uma solicitação.
Exemplo:
$ body = $ this -> getBody (); // '{"id"=>1,"name"=>john}' (as string)
$ body = $ this -> getBody ( true ); // stdClass {id=>1,name=>john}
$ body = $ this -> getBody ( true , true ); // ["id"=>1,"name"=>john]
Retorna o URL base atual sem espaço de busca, parâmetros ou consultas
Nota : esta função depende de $_SERVER['SERVER_NAME'], e pode ser modificada pelo usuário final
Ele retorna o servidor atual sem barra final.
$ route -> getCurrentServer (); // http://somedomain
Ele define o nome do servidor atual. É usado por getCurrentUrl() e getCurrentServer().
Nota: Se $this->setCurrentServer() não estiver definido, então ele usa $_SERVER['SERVER_NAME'] e pode ser modificado pelo usuário.
$ route -> setCurrentServer ( ' localhost ' );
$ route -> setCurrentServer ( ' 127.0.0.1 ' );
$ route -> setCurrentServer ( ' domain.dom ' );
Ele obtém o URL (completo) com base nas informações da classe.
$ route -> getUrl (); // http://somedomain/controller/action/id
$ route -> getUrl ( ' id=20 ' ); // http://somedomain/controller/action/id?id=20
$ route -> getUrl ( ' id=20 ' , true ); // http://somedomain/controller/action/id?id=20&field=20&field2=40
Ele cria um URL baseado em valores personalizados
$ route -> url ( null , " Customer " , " Update " , 20 ); // Customer/Update/20
Ele cria uma URL (frontal) baseada em valores personalizados
$ route -> url ( null , " Daily " , " Milk " , 20 ); // Daily/Milk/20
Se o subdomínio estiver vazio ou for diferente de www, ele redirecionará para www.domain.com.
Nota: Não funciona com localhost, domínio sem TLD (netbios) ou domínios ip. É de propósito.
Nota: Se este código precisar ser redirecionado, ele interromperá a execução do código. Geralmente deve ser chamado no topo do código
$ route -> alwaysWWW (); // if the domain is somedomain.dom/url, then it redirects to www.somedomain.dom/url
$ route -> alwaysWWW ( true ); // if the domain is http: somedomain.dom/url, then it redirects to https: www.somedomain.dom/url
Se a página for carregada como http, ela redirecionará para https.
Nota: Não funciona com localhost, domínio sem TLD (netbios) ou domínios ip. É de propósito.
Nota: Se este código precisar ser redirecionado, ele interromperá a execução do código. Geralmente deve ser chamado no topo do código
$ route -> alwaysHTTPS (); // http://somedomain.com ---> https://somedomain.com
$ route -> alwaysHTTPS (); // http://localhost ---> // http://localhost
$ route -> alwaysHTTPS (); // http://127.0.0.1 ---> // http://127.0.0.1
$ route -> alwaysHTTPS (); // http://mypc ---> // http://mypc
Se o subdomínio for www (exemplo www.domain.dom), ele redirecionará para um domínio simples domain.dom
Nota: Não funciona com localhost, domínio sem TLD (netbios) ou domínios ip. É de propósito.
Nota: Se este código precisar ser redirecionado, ele interromperá a execução do código. Normalmente, deve ser chamado no topo do código
$ route -> alwaysNakedDomain (); // if the domain is www.somedomain.dom/url, then it redirects to somedomain.dom/url
$ route -> alwaysNakedDomain ( true ); // if the domain is http: www.somedomain.dom/url, then it redirects to https: somedomain.dom/url
Campo | caminho | Descrição | Exemplo |
---|---|---|---|
$argumentoNome | O nome do argumento usado pelo Apache .Htaccess e nginx | $this-argumentName='req'; | |
$ base | É o URL base. | $this->base=0; | |
$tipo | É o tipo de URL (api,ws,controller ou front) | echo $este->tipo; //API | |
$ módulo | {módulo} | É o módulo atual | echo $este->módulo; |
$controlador | {controlador} | É o controlador. | echo $este->controlador; |
$ação | {Ação} | É a ação. | echo $this->ação; |
$id | {eu ia} | É o identificador | echo $este->id; |
$evento | {evento} | É o evento (como “clique no botão”). | echo$este->evento; |
$idparente | {idparent} | É o ID do pai atual (se houver) | echo $this->idparent; |
$ extra | {extra} | É o evento (como "clique no botão) | echo $isto->extra; |
$categoria | {categoria} | A categoria atual. É útil para o tipo 'front' | echo $this->categoria; |
$subcategoria | {subcategoria} | A subcategoria atual. É útil para o tipo 'front' | echo $this->subcategoria; |
$subsubcategoria | {subsubcategoria} | A subcategoria atual. É útil para o tipo 'front' | echo $this->subsubcategoria; |
$ identificar | É um array associativo que ajuda a identificar a rota api e ws. | $this->identify=['api'=>'apiurl','ws'=>'webservices','controller'=>'']; | |
$isPostBack | é verdade se a página for POST, caso contrário, é falso. | if ($this->isPostBack) { ... }; | |
$verbo | {verbo} | O verbo atual pode ser GET, POST, PUT e DELETE. | if ($este->verbo) { ... }; |
Exemplo:
$ this -> addPath ( ' portal/web/{controller}/{action:list} ' );
$ this -> fetchPath ();
var_dump ( $ this -action); // it shows the current action or the default value "list" if none.
Campo | Descrição | Exemplo |
---|---|---|
$allowedVerbos | Uma lista com verbos permitidos | $this->allowedVerbs=['GET', 'POST', 'PUT', 'DELETE']; |
$campos permitidos | Uma lista com campos permitidos usados por callObjectEx() | $this->allowedFields=['controlador', 'ação', 'verbo', 'evento', 'tipo', 'módulo', 'id' , 'idparent','categoria', 'subcategoria', 'subsubcategoria']; |
setWhitelist() | Ele define uma matriz associativa com a lista de permissões para controller , action , category , subcategory , subsubcategory e module . Se não for definido (valor padrão nulo), permitirá qualquer entrada. Atualmente só funciona com controlador e categoria | $this->setWhitelist('controlador','Compra','Fatura','Cliente'); $this->setWhitelist('controller',null) // permite qualquer controlador; |
Colocar um método na lista de permissões permite duas operações:
Por exemplo:
// Example, value not in the whitelist: someweb.dom/customer/list
$ this -> setWhiteList ( ' controller ' ,[ ' Product ' , ' Client ' ]);
$ this -> fetch ();
var_dump ( $ this -> controller ); // null or the default value
var_dump ( $ this -> notAllowed ); // true (whitelist error)
// Example, value in the whitelist but with the wrong case: someweb.dom/customer/list
$ this -> setWhiteList ( ' controller ' ,[ ' Customer ' ]);
$ this -> fetch ();
var_dump ( $ this -> controller ); // it shows "Customer" instead of "customer"
var_dump ( $ this -> notAllowed ); // false (not error with the validation of the whitelist)
// reset whitelist for controllers
$ this -> setWhiteList ( ' controller ' , null );
RouteOne contém uma CLI básica para criar e inicializar a configuração. O CLI binário RouteOne está localizado na pasta vendor/bin
./vendor/bin/ RouteOne cli
entre no roteador e pressione enter.
No menu do roteador, será exibida a próxima tela:
Pendente significa que a operação está pendente ou requer algo para configurar.
Uma vez feito isso, configure será marcado como "ok"
Agora vamos configurar os caminhos