Configure el enrutamiento en aplicaciones PHP utilizando el componente de enrutamiento de Symfony
() translation by (you can also view the original English article)
Hoy veremos el componente de enrutamiento de Symfony, que le permite configurar el enrutamiento en sus aplicaciones de PHP
¿Qué es el componente de enrutamiento de Symfony?
El componente de enrutamiento de Symfony es un componente de enrutamiento muy popular que está adaptado por varios sistemas y proporciona mucha flexibilidad en caso de que desee configurar rutas en su aplicación PHP.
Si ha creado una aplicación PHP personalizada y está buscando una biblioteca de enrutamiento rica en funciones, el Componente de enrutamiento de Symfony merece más que un vistazo. También le permite definir rutas para su aplicación en el formato YAML.
Comenzando con la instalación y la configuración, veremos ejemplos del mundo real para demostrar una variedad de opciones que tiene el componente para la configuración de rutas. En este artículo, aprenderá:
- instalacion y configuracion
- cómo configurar rutas básicas
- cómo cargar rutas desde el archivo YAML
- cómo usar el enrutador todo en uno
Instalacion y configuracion
En esta sección, vamos a instalar las bibliotecas que se requieren para configurar el enrutamiento en sus aplicaciones PHP. Supongo que ha instalado Composer en su sistema, ya que lo necesitaremos para instalar las bibliotecas necesarias que están disponibles en Packagist.
Una vez que haya instalado Composer, continúe e instale el componente Core Routing con el siguiente comando.
1 |
$composer require symfony/routing |
Aunque el componente de enrutamiento en sí es suficiente para proporcionar funciones completas de enrutamiento en su aplicación, vamos a seguir adelante e instalar algunos otros componentes para facilitar nuestra vida y enriquecer la funcionalidad de enrutamiento básico existente.
Para empezar, procederemos e instalaremos el componente HttpFoundation, que proporciona un contenedor orientado a objetos para variables globales de PHP y funciones relacionadas con la respuesta. Se asegura de que no necesite acceder a variables globales como $ _GET
, $ _POST
y similares directamente.
1 |
$composer require symfony/http-foundation |
A continuación, si quiere definir las rutas de su aplicación en el archivo YAML en lugar del código PHP, es el componente YAML el que lo rescata, ya que le ayuda a convertir cadenas YAML en matrices PHP y viceversa.
1 |
$composer require symfony/yaml |
Finalmente, instalaremos el componente Config, que proporciona varias clases de utilidad para inicializar y tratar los valores de configuración definidos en los diferentes tipos de archivos como YAML, INI, XML, etc. En nuestro caso, lo usaremos para cargar rutas del archivo YAML.
1 |
$composer require symfony/config |
Esa es la parte de la instalación, pero ¿cómo se supone que debes usarla? De hecho, solo se trata de incluir el archivo autoload.php creado por Composer en su aplicación, como se muestra en el siguiente fragmento.
1 |
<?php
|
2 |
require_once './vendor/autoload.php'; |
3 |
|
4 |
// application code
|
5 |
?>
|
Configurar rutas básicas
En la sección anterior, realizamos la instalación de los componentes de enrutamiento necesarios. Ahora, ya está listo para configurar el enrutamiento en su aplicación PHP de inmediato.
Avancemos y creemos el archivo basic_routes.php con los siguientes contenidos.
1 |
<?php
|
2 |
require_once './vendor/autoload.php'; |
3 |
|
4 |
use Symfony\Component\Routing\Matcher\UrlMatcher; |
5 |
use Symfony\Component\Routing\RequestContext; |
6 |
use Symfony\Component\Routing\RouteCollection; |
7 |
use Symfony\Component\Routing\Route; |
8 |
use Symfony\Component\HttpFoundation\Request; |
9 |
use Symfony\Component\Routing\Generator\UrlGenerator; |
10 |
use Symfony\Component\Routing\Exception\ResourceNotFoundException; |
11 |
|
12 |
try
|
13 |
{
|
14 |
// Init basic route
|
15 |
$foo_route = new Route( |
16 |
'/foo', |
17 |
array('controller' => 'FooController') |
18 |
);
|
19 |
|
20 |
// Init route with dynamic placeholders
|
21 |
$foo_placeholder_route = new Route( |
22 |
'/foo/{id}', |
23 |
array('controller' => 'FooController', 'method'=>'load'), |
24 |
array('id' => '[0-9]+') |
25 |
);
|
26 |
|
27 |
// Add Route object(s) to RouteCollection object
|
28 |
$routes = new RouteCollection(); |
29 |
$routes->add('foo_route', $foo_route); |
30 |
$routes->add('foo_placeholder_route', $foo_placeholder_route); |
31 |
|
32 |
// Init RequestContext object
|
33 |
$context = new RequestContext(); |
34 |
$context->fromRequest(Request::createFromGlobals()); |
35 |
|
36 |
// Init UrlMatcher object
|
37 |
$matcher = new UrlMatcher($routes, $context); |
38 |
|
39 |
// Find the current route
|
40 |
$parameters = $matcher->match($context->getPathInfo()); |
41 |
|
42 |
// How to generate a SEO URL
|
43 |
$generator = new UrlGenerator($routes, $context); |
44 |
$url = $generator->generate('foo_placeholder_route', array( |
45 |
'id' => 123, |
46 |
));
|
47 |
|
48 |
echo '<pre>'; |
49 |
print_r($parameters); |
50 |
|
51 |
echo 'Generated URL: ' . $url; |
52 |
exit; |
53 |
}
|
54 |
catch (ResourceNotFoundException $e) |
55 |
{
|
56 |
echo $e->getMessage(); |
57 |
}
|
La configuración del enrutamiento utilizando el componente de enrutamiento de Symfony generalmente pasa por una serie de pasos como se detalla a continuación.
- Inicialice el objeto de
Route
para cada una de sus rutas de aplicación. - Agregue todos los objetos de
Route
al objetoRouteCollection
. - Inicialice el objeto
RequestContext
que contiene la información de contexto de solicitud actual. - Inicialice el objeto
UrlMatcher
pasando el objetoRouteCollection
y el objetoRequestContext
.
Inicializar el objeto de ruta para diferentes rutas
Avancemos y definamos una ruta de Foo
bastante básica.
1 |
$foo_route = new Route( |
2 |
'/foo', |
3 |
array('controller' => 'FooController') |
4 |
);
|
El primer argumento del constructor Route
es la ruta URI, y el segundo argumento es la matriz de atributos personalizados que desea devolver cuando se hace coincidir esta ruta en particular. Normalmente, sería una combinación del controlador y el método al que desea llamar cuando se solicite esta ruta.
A continuación, echemos un vistazo a la ruta parametrizada.
1 |
$foo_placeholder_route = new Route( |
2 |
'/foo/{id}', |
3 |
array('controller' => 'FooController', 'method'=>'load'), |
4 |
array('id' => '[0-9]+') |
5 |
);
|
La ruta anterior puede coincidir con URI como foo / 1
, foo / 123
y similares. Tenga
en cuenta que hemos restringido el parámetro {id}
a valores numéricos
solamente, y por lo tanto no coincidirá con los URI como foo / bar
, ya
que el parámetro {id}
se proporciona como una cadena.
Agregar todos los objetos de ruta al objeto RouteCollection
El siguiente paso es agregar objetos de ruta que hemos inicializado en la sección anterior al objeto RouteCollection
.
1 |
$routes = new RouteCollection(); |
2 |
$routes->add('foo_route', $foo_route); |
3 |
$routes->add('foo_placeholder_route', $foo_placeholder_route); |
Como
puede ver, es bastante sencillo ya que solo necesita usar el método add
del objeto RouteCollection
para agregar objetos de ruta. El primer argumento del método add
es el nombre de la ruta, y el segundo argumento es el objeto route.
Inicializar el objeto RequestContext
A continuación, necesitamos inicializar el objeto RequestContext
, que contiene la información de contexto de solicitud actual. Necesitaremos este objeto cuando inicialicemos el objeto UrlMatcher
, ya que lo revisaremos en un momento.
1 |
$context = new RequestContext(); |
2 |
$context->fromRequest(Request::createFromGlobals()); |
Inicializa el objeto UrlMatcher
Finalmente, necesitamos inicializar el objeto UrlMatcher
junto con las rutas y la información de contexto.
1 |
// Init UrlMatcher object
|
2 |
$matcher = new UrlMatcher($routes, $context); |
Ahora, tenemos todo lo que podemos combinar con nuestras rutas.
Cómo hacer coincidir las rutas
Es el método de Match
del objeto UrlMatcher
que le permite hacer coincidir
cualquier ruta con un conjunto de rutas predefinidas.
El método de Match
toma el URI como su primer argumento e intenta hacer coincidirlo con las rutas predefinidas. Si se encuentra la ruta, devuelve atributos personalizados asociados con esa ruta. Por otro lado, arroja la excepción ResourceNotFoundException
si no hay ninguna ruta asociada con el URI actual.
1 |
$parameters = $matcher->match($context->getPathInfo()); |
En nuestro caso, proporcionamos el URI actual obteniéndolo del objeto $ context
. Entonces,
si está accediendo a la URL http: //your-domain/basic_routes.php/foo, $
context-> getPathInfo ()
devuelve foo
, y ya hemos definido una ruta
para el URI foo
, por lo que debería devolvernos lo siguiente.
1 |
Array |
2 |
( |
3 |
[controller] => FooController |
4 |
[_route] => foo_route |
5 |
) |
Ahora, vamos a probar la ruta parametrizada accediendo a la URL http: //your-domain/basic_routes.php/foo/123.
1 |
Array |
2 |
( |
3 |
[controller] => FooController |
4 |
[method] => load |
5 |
[id] => 123 |
6 |
[_route] => foo_placeholder_route |
7 |
) |
Funcionó si puede ver que el parámetro id
está vinculado con el valor apropiado 123
.
A continuación, intentemos acceder a una ruta inexistente como http: //your-domain/basic_routes.php/unknown-route, y debería ver el siguiente mensaje.
1 |
No routes found for "/unknown-route". |
Así es como puedes encontrar rutas usando el método de Match
.
Además de esto, también puede usar el componente de Routing
para generar enlaces en su aplicación. Proporcionados objetos RouteCollection
y RequestContext
, el UrlGenerator
le permite construir enlaces para rutas específicas.
1 |
$generator = new UrlGenerator($routes, $context); |
2 |
$url = $generator->generate('foo_placeholder_route', array( |
3 |
'id' => 123, |
4 |
));
|
El
primer argumento del método generate
es el nombre de la ruta, y el
segundo argumento es la matriz que puede contener parámetros si se trata
de la ruta parametrizada. El código anterior debe generar la URL /basic_routes.php/foo/123.
Cargar rutas desde el archivo YAML
En la sección anterior, construimos nuestras rutas personalizadas utilizando los objetos Route
y RouteCollection
. De hecho, el componente Routing
ofrece diferentes formas de elegir entre crear instancias de rutas. Puede elegir entre varios cargadores como YamlFileLoader
, XmlFileLoader
y PhpFileLoader
.
En esta sección, revisaremos el cargador YamlFileLoader
para ver cómo cargar rutas desde el archivo YAML.
El archivo YAML de Rutas
Continúa y crea el archivo routes.yaml con los siguientes contenidos.
1 |
foo_route: |
2 |
path: /foo |
3 |
defaults: { controller: 'FooController::indexAction' } |
4 |
|
5 |
foo_placeholder_route: |
6 |
path: /foo/{id} |
7 |
defaults: { controller: 'FooController::loadAction' } |
8 |
requirements: |
9 |
id: '[0-9]+' |
Un archivo de ejemplo
A continuación, siga adelante y cree el archivo load_routes_from_yaml.php con los siguientes contenidos.
1 |
<?php
|
2 |
require_once './vendor/autoload.php'; |
3 |
|
4 |
use Symfony\Component\Routing\Matcher\UrlMatcher; |
5 |
use Symfony\Component\Routing\RequestContext; |
6 |
use Symfony\Component\HttpFoundation\Request; |
7 |
use Symfony\Component\Routing\Generator\UrlGenerator; |
8 |
use Symfony\Component\Config\FileLocator; |
9 |
use Symfony\Component\Routing\Loader\YamlFileLoader; |
10 |
use Symfony\Component\Routing\Exception\ResourceNotFoundException; |
11 |
|
12 |
try
|
13 |
{
|
14 |
// Load routes from the yaml file
|
15 |
$fileLocator = new FileLocator(array(__DIR__)); |
16 |
$loader = new YamlFileLoader($fileLocator); |
17 |
$routes = $loader->load('routes.yaml'); |
18 |
|
19 |
// Init RequestContext object
|
20 |
$context = new RequestContext(); |
21 |
$context->fromRequest(Request::createFromGlobals()); |
22 |
|
23 |
// Init UrlMatcher object
|
24 |
$matcher = new UrlMatcher($routes, $context); |
25 |
|
26 |
// Find the current route
|
27 |
$parameters = $matcher->match($context->getPathInfo()); |
28 |
|
29 |
// How to generate a SEO URL
|
30 |
$generator = new UrlGenerator($routes, $context); |
31 |
$url = $generator->generate('foo_placeholder_route', array( |
32 |
'id' => 123, |
33 |
));
|
34 |
|
35 |
echo '<pre>'; |
36 |
print_r($parameters); |
37 |
|
38 |
echo 'Generated URL: ' . $url; |
39 |
exit; |
40 |
}
|
41 |
catch (ResourceNotFoundException $e) |
42 |
{
|
43 |
echo $e->getMessage(); |
44 |
}
|
¡Lo único que es diferente en este caso es la forma en que iniciamos las rutas!
1 |
$fileLocator = new FileLocator(array(__DIR__)); |
2 |
$loader = new YamlFileLoader($fileLocator); |
3 |
$routes = $loader->load('routes.yaml'); |
Hemos
utilizado el cargador YamlFileLoader
para cargar rutas desde el archivo
routes.yaml en lugar de inicializarlo directamente en el PHP. Aparte de eso, todo es igual y debería producir los mismos resultados que el del archivo basic_routes.php.
El enrutador todo en uno
Por último, en
esta sección, examinaremos la clase Router
, que le permite configurar el
enrutamiento rápidamente con menos líneas de código.
Continúa y crea el archivo all_in_one_router.php con los siguientes contenidos.
1 |
<?php
|
2 |
require_once './vendor/autoload.php'; |
3 |
|
4 |
use Symfony\Component\Routing\RequestContext; |
5 |
use Symfony\Component\Routing\Router; |
6 |
use Symfony\Component\HttpFoundation\Request; |
7 |
use Symfony\Component\Routing\Generator\UrlGenerator; |
8 |
use Symfony\Component\Config\FileLocator; |
9 |
use Symfony\Component\Routing\Loader\YamlFileLoader; |
10 |
use Symfony\Component\Routing\Exception\ResourceNotFoundException; |
11 |
|
12 |
try
|
13 |
{
|
14 |
$fileLocator = new FileLocator(array(__DIR__)); |
15 |
|
16 |
$requestContext = new RequestContext(); |
17 |
$requestContext->fromRequest(Request::createFromGlobals()); |
18 |
|
19 |
$router = new Router( |
20 |
new YamlFileLoader($fileLocator), |
21 |
'routes.yaml', |
22 |
array('cache_dir' => __DIR__.'/cache'), |
23 |
$requestContext
|
24 |
);
|
25 |
|
26 |
// Find the current route
|
27 |
$parameters = $router->match($requestContext->getPathInfo()); |
28 |
|
29 |
// How to generate a SEO URL
|
30 |
$routes = $router->getRouteCollection(); |
31 |
$generator = new UrlGenerator($routes, $requestContext); |
32 |
$url = $generator->generate('foo_placeholder_route', array( |
33 |
'id' => 123, |
34 |
));
|
35 |
|
36 |
echo '<pre>'; |
37 |
print_r($parameters); |
38 |
|
39 |
echo 'Generated URL: ' . $url; |
40 |
exit; |
41 |
}
|
42 |
catch (ResourceNotFoundException $e) |
43 |
{
|
44 |
echo $e->getMessage(); |
45 |
}
|
Todo es prácticamente igual, excepto que hemos creado una instancia del objeto Router
junto con las dependencias necesarias.
1 |
$router = new Router( |
2 |
new YamlFileLoader($fileLocator), |
3 |
'routes.yaml', |
4 |
array('cache_dir' => __DIR__.'/cache'), |
5 |
$requestContext
|
6 |
);
|
Con eso en su lugar, puede usar directamente el método de match
del objeto Router para el mapeo de ruta.
1 |
$parameters = $router->match($requestContext->getPathInfo()); |
Además, deberá usar el método getRouteCollection
del objeto Router para buscar rutas.
1 |
$routes = $router->getRouteCollection(); |
Conclusión
Continúe y explore las otras opciones disponibles en el componente Enrutamiento: ¡me encantaría escuchar sus pensamientos!
Hoy,
exploramos el componente de enrutamiento de Symfony, que hace que la
implementación del enrutamiento en aplicaciones PHP sea muy sencilla. En el camino, creamos un puñado de ejemplos para demostrar diversos aspectos del componente Enrutamiento.
Espero que hayas disfrutado este artículo, y no dudes en publicar tus comentarios utilizando el feed a continuación.