Lee la ruta URL y analiza los valores de la ruta, por lo que podría interpretarse manual o automáticamente de la forma más rápida posible (por ejemplo, para implementar un sistema MVC).
A diferencia de otras bibliotecas, esta biblioteca no tiene dependencias y está contenida en una sola clase, por lo que es compatible con cualquier proyecto PHP, por ejemplo WordPress, Laravel, Drupal, un proyecto PHP personalizado, etc.
Esta biblioteca se basa en la Convención CoC sobre Configuración . Reduce el texto estándar pero tiene funcionalidades fijas. Esta biblioteca no permite utilizar "rutas" personalizadas pero cubre prácticamente todos los casos, por lo que aumenta el rendimiento y la usabilidad sacrificando flexibilidad.
Digamos que tenemos la siguiente URL http://somedomain.dom/Customer/Update/2. Esta biblioteca convierte esta URL en variables que podrían procesarse o llamar directamente a un método.
ruta.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 ' );
clase controladorCustomerController.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 hacemos la siguiente operación:
Un usuario llama al siguiente sitio web http://algundominio.com/Cliente/Insert, quiere mostrar un formulario para insertar un 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*
o
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 llama al método InsertActionGet (GET), InsertActionPost (POST) o InsertAction (GET/POST) dentro de la clase Customer
El método llamado se escribe de la siguiente manera:
class Customer {
public function insertAction ( $ id = "" , $ idparent = "" , $ event = "" ) {
// here we do our operation.
}
}
Si queremos actualizar un número de cliente 20 , entonces podríamos llamar a la página siguiente
http://algundominio.com/Cliente/Update/20
donde 20 es el "$id" del cliente a editar (podría ser un número de una cadena)
¿Y si queremos Actualizar un Cliente número 20 de la APPL empresarial?
http://algundominio.com/Cliente/Update/20/APPL
Donde APPL es el idparent
Ahora, digamos que hacemos clic en algún botón o realizamos alguna acción. Podría ser capturado por el campo _event y leído por el argumento $event . Esta variable podría enviarse mediante GET o POST.
http://algúndominio.com/Cliente/Update/20/APPL?_event=click
Nota: Los módulos se obtienen automáticamente si usa addPath() y fetchPath(), por lo que no es necesario especificarlos. Ahora, digamos que nuestro sistema es modular y tenemos varios clientes (clientes internos, externos, etc.)
$ route = new RouteOne ( ' . ' , null , true ); // true indicates it is modular.
o
$ route = new RouteOne ( ' . ' , null ,[ ' Internal ' ]); // or we determine the module automatically. In this case, every url that starts with Internal
entonces
$ route -> fetch ();
$ route -> callObject ( ' somenamespace \ %2s% \ controller \ %1sController ' );
http://algundominio.com/Internal/Customer/Update/20/APPL?_event=click
Luego, la primera ramificación es el nombre del módulo ( Internal ) y llama a la clase somenamespaceInternalcontrollerCustomerController
El compositor requiere eftec/ RouteOne
Linux:
vendor/bin/ RouteOne cli -init (if the binary does not work, then chage the permission to execution)
Ventanas:
. v endor b in r outeonecli.bat -init
Creará el archivo .htaccess y los archivos route.php y route.php tendrán una configuración predeterminada.
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
Más adelante, podrá agregar o editar el código en este archivo.
<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>
Si su servidor web no permite la opción FollowSymlinks, intente reemplazarla con Options +SymLinksIfOwnerMatch.
La línea importante es:
RewriteRule ^(.*)$ route.php?req=$1 [L,QSA] # El enrutador al que llamar.
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;
}
}
La línea importante es:
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;
}
}
La línea importante es:
try_files $uri $uri/ /router.php?req=$document_uri&$query_string;
donde router.php es el archivo que funcionará como enrutador. ?req=$1 es importante porque el sistema leerá la ruta 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
Nota:
Si desea utilizar un argumento diferente a "req", puede cambiarlo usando el siguiente código:
$ruta->argumentName='newargument';
Desde la versión 1.21, es posible utilizar una ruta personalizada en lugar de una ruta predefinida. Es la forma recomendada. El otro método todavía está presente.
Sintaxis:
borrar ruta()
Borra todos los caminos definidos.
Sintaxis:
addPath($ruta, $nombre = nulo,invocable $middleWare=null)
Agrega rutas que podrían evaluarse usando fetchPath()
Ejemplo:
$ 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 ;
});
Nota:
La primera parte de la ruta, antes de "{", se utiliza para determinar qué ruta se utilizará.
Ejemplo "ruta/{controlador}" y "ruta/{controlador}/{id}", el sistema considerará que son la misma ruta
cadena de parámetro $path La ruta, ejemplo "aaa/{controller}/{action:default}/{id}"
Donde predeterminado es el valor predeterminado opcional.
cadena de parámetro |nulo $nombre (opcional), el nombre de la ruta
parámetro invocable|null $middleWare Una función invocable utilizada para middleware.
El primer argumento de la función debe ser un método invocable.
Los siguientes argumentos deben ser los argumentos definidos por callObjectEx
(id,idpadre,evento)
La ruta podría comenzar con una ubicación estática, pero el resto de la ruta debe estar definida por variables (entre {}) y separadas por "/".
También puede establecer un valor predeterminado para una ruta escribiendo ":" después del nombre de la variable: {nombre:valor predeterminado}
El nombre se puede obtener usando $this->currentPath. Si agrega un nombre con el mismo nombre, se reemplaza.
Si no establece un nombre, utiliza un autonumérico.
El nombre también se devuelve cuando llamas a $this->fetchPath()
Ejemplo:
$ 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)
Puede definir diferentes rutas, sin embargo, solo utiliza la primera parte de la ruta que coincide con alguna URL. 'ruta/alguna ruta/{id}' funcionará 'ruta/{id}/otra' no funcionará
Sintaxis:
buscar ruta()
Obtiene la ruta previamente definida por addPath y devuelve el nombre (o número) de la ruta. Si no se encuentra, devuelve falso.
Ejemplo:
$ 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
Obtiene un valor de consulta (URL).
Nota: Esta consulta no incluye los valores "req","_event" y "_extra"
Ejemplo:
// http://localhost/..../?id=hi
$ id = $ router -> getQuery ( " id " ); // hi
$ nf = $ router -> getQuery ( " something " , " not found " ); // not found
Establece un valor de consulta.
Ejemplo:
$ route -> setQuery ( " id " , " hi " );
$ id = $ router -> getQuery ( " id " ); // hi
Sintaxis:
buscar ruta()
Obtenga los valores de la ruta y los valores se procesarán.
Sintaxis
callObjectEx($classStructure, $throwOnError, $método, $methodGet, $methodPost,$argumentos,$injectArguments)
Crea una nueva instancia de un objeto (por ejemplo, un objeto Controlador) y llama al método.
Nota: Es una versión avanzada de esto::callObject()
Este método usa {} para reemplazar valores basados en las siguientes variables:
Etiqueta | Descripción |
---|---|
{controlador} | El nombre del controlador |
{acción} | La acción actual |
{evento} | El evento actual |
{tipo} | El tipo de ruta actual (ws,controller,front,api) |
{módulo} | El módulo actual (si el módulo está activo) |
{identificación} | La identificación actual |
{identificador} | El padre de familia actual |
{categoría} | La categoría actual |
{subcategoría} | La subcategoría actual |
{subsubcategoría} | La subsubcategoría actual |
Ejemplo:
// 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');
Llame a un método dentro de un objeto usando la ruta actual.
Ejemplo:
Enrutador:
$ 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 llamado |
---|---|
http://localhost/Cliente/Verde (OBTENER) | Acción Verde |
http://localhost/Cliente/Green/20/30?_event=click (OBTENER) | Acciónverde($id=20, $idparent=30, $evento='clic') |
http://localhost/Cliente/Verde (POST) | Acción Verde |
http://localhost/Cliente/Azul (OBTENER) | AcciónAzulOBTENER |
http://localhost/Cliente/Azul (POST) | ERROR |
http://localhost/Cliente/Amarillo (OBTENER) | ERROR |
http://localhost/Cliente/Amarillo (POST) | AmarilloAcciónPOST |
http://localhost/Cliente/Rojo (OBTENER) | RedActionGET (Tiene prioridad sobre RedAction) |
http://localhost/Cliente/Rojo (POST) | Redacción |
http://localhost/Cliente/Orange | ERROR |
Llama (incluye) un archivo php usando el nombre actual del controlador
Sintaxis:
getHeader($clave, $valorIfNotFound = nulo)
Obtiene el encabezado actual (si lo hay). Si no se encuentra el valor, devuelve $valueIfNotFound. Tenga en cuenta que la clave $ siempre se convierte a mayúsculas.
Ejemplo:
$ token = $ this -> getHeader ( ' token ' , ' TOKEN NOT FOUND ' );
Sintaxis:
getBody($jsonDeserialize = false, $asAssociative = true)
Obtiene el cuerpo de una solicitud.
Ejemplo:
$ 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]
Devuelve la URL base actual sin espacio de seguimiento, parámetros ni consultas.
Nota : esta función se basa en $_SERVER['SERVER_NAME'] y el usuario final podría modificarla
Devuelve el servidor actual sin barra diagonal.
$ route -> getCurrentServer (); // http://somedomain
Establece el nombre del servidor actual. Lo utilizan getCurrentUrl() y getCurrentServer().
Nota: Si $this->setCurrentServer() no está configurado, entonces usa $_SERVER['SERVER_NAME'] y el usuario podría modificarlo.
$ route -> setCurrentServer ( ' localhost ' );
$ route -> setCurrentServer ( ' 127.0.0.1 ' );
$ route -> setCurrentServer ( ' domain.dom ' );
Obtiene la URL (completa) basada en la información de la clase.
$ 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
Construye una URL basada en valores personalizados.
$ route -> url ( null , " Customer " , " Update " , 20 ); // Customer/Update/20
Construye una URL (frontal) basada en valores personalizados.
$ route -> url ( null , " Daily " , " Milk " , 20 ); // Daily/Milk/20
Si el subdominio está vacío o es diferente a www, redirige a www.dominio.com.
Nota: No funciona con localhost, dominio sin TLD (netbios) ni dominios ip. Es a propósito.
Nota: Si este código necesita redirigirse, detiene la ejecución del código. Por lo general, debe llamarse en la parte superior del 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
Si la página se carga como http, redirige a https.
Nota: No funciona con localhost, dominio sin TLD (netbios) ni dominios ip. Es a propósito.
Nota: Si este código necesita redirigirse, detiene la ejecución del código. Por lo general, debe llamarse en la parte superior del 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
Si el subdominio es www (ejemplo www.dominio.dom), entonces redirige a un dominio simple dominio.dom
Nota: No funciona con localhost, dominio sin TLD (netbios) o dominios ip. Es a propósito.
Nota: Si este código necesita redirigirse, detiene la ejecución del código. Por lo general, debe llamarse en la parte superior del 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 | camino | Descripción | Ejemplo |
---|---|---|---|
$nombreargumento | El nombre del argumento utilizado por Apache .Htaccess y nginx. | $this-argumentName='req'; | |
$ base | Es la URL base. | $this->base=0; | |
$tipo | Es el tipo de url (api,ws,controller o front) | echo $este->tipo; // API | |
$módulo | {módulo} | es el modulo actual | echo $este->módulo; |
$controlador | {controlador} | Es el controlador. | echo $este->controlador; |
$acción | {acción} | Es la acción. | echo $this->acción; |
$identificación | {identificación} | es el identificador | echo $this->id; |
$evento | {evento} | Es el evento (como "hacer clic en el botón"). | echo$este->evento; |
$idpadre | {identificador} | Es la identificación actual del padre (si corresponde) | echo $this->idparent; |
$extra | {extra} | Es el evento (como "hacer clic en el botón") | echo $esto->extra; |
$categoría | {categoría} | La categoría actual. Es útil para el tipo 'frontal' | echo $esta->categoría; |
$subcategoría | {subcategoría} | La subcategoría actual. Es útil para el tipo 'frontal' | echo $this->subcategoría; |
$subsubcategoría | {subsubcategoría} | La subsubcategoría actual. Es útil para el tipo 'frontal' | echo $this->subsubcategoría; |
$identificar | Es una matriz asociativa que ayuda a identificar la ruta api y ws. | $this->identify=['api'=>'apiurl','ws'=>'webservices','controller'=>'']; | |
$isPostBack | es verdadero si la página es POST; de lo contrario, es falso. | si ($this->isPostBack) {...}; | |
$ verbo | {verbo} | El verbo actual podría ser GET,POST,PUT y DELETE. | si ($este->verbo) { ... }; |
Ejemplo:
$ 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 | Descripción | Ejemplo |
---|---|---|
$verbos permitidos | Una lista con verbos permitidos | $this->allowedVerbs=['GET', 'POST', 'PUT', 'DELETE']; |
$ campos permitidos | Una lista con los campos permitidos utilizados por callObjectEx() | $this->allowedFields=['controlador', 'acción', 'verbo', 'evento', 'tipo', 'módulo', 'id' , 'idparent','categoría', 'subcategoría', 'subsubcategoría']; |
establecer lista blanca() | Establece una matriz asociativa con la lista blanca para controlador , acción , categoría , subcategoría , subsubcategoría y módulo . Si no se establece (valor predeterminado nulo), permite cualquier entrada. Actualmente solo funciona con controlador y categoría. | $this->setWhitelist('controlador','Compra','Factura','Cliente'); $this->setWhitelist('controller',null) // permite cualquier controlador; |
Incluir un método en la lista blanca permite dos operaciones:
Por ejemplo:
// 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 contiene una CLI básica para crear e inicializar la configuración. El cli binario RouteOne se encuentra en la carpeta proveedor/bin
./vendor/bin/ RouteOne cli
ingrese al enrutador y presione enter.
En el menú del enrutador, se mostrará la siguiente pantalla:
Pendiente significa que la operación está pendiente de realizarse o requiere algo para configurar.
Una vez hecho esto, la configuración se marcará como "ok"
Ahora, configuremos las rutas.