Rutas
La creación de rutas es una tarea fundamental durante el desarrollo de cualquier aplicación web. Luthier CI mejora el enrutamiento de CodeIgniter para que construir aplicaciones grandes no sea excesivamente complicado.
Índice
Diferencias entre el enrutamiento de CodeIgniter y Luthier CI
La forma en que las rutas son manejadas por CodeIgniter es modificada por Luthier CI durante su ejecución:
- En CodeIgniter, por defecto, las rutas son accesibles a través de cualquier verbo HTTP. Con Luthier CI es obligatorio definir en cada ruta los verbos HTTP aceptados.
- En CodeIgniter es posible acceder a los controladores sin necesidad de definir rutas, mientras que con Luthier CI únicamente las rutas definidas son detectadas.
- Con Luthier CI cada ruta es una entidad independiente y única, con parámetros bien definidos y con la capacidad de construir URLs a partir de ellas.
- Con Luthier CI es posible utilizar funciones anónimas como controladores e incluso construir una aplicación web completa sin usar ni un solo controlador.
Tipos de rutas
Tres tipos de rutas están disponibles en Luthier CI:
- Rutas HTTP: se acceden bajo peticiones HTTP y se definen en el archivo
application/routes/web.php
- Rutas AJAX: se acceden únicamente bajo peticiones AJAX y se definen en el archivo
application/routes/api.php
- Rutas CLI: se acceden únicamente bajo un entorno CLI (Command Line Interface) y se definen en el archivo
application/routes/cli.php
web.php
, lo ideal es hacerlo en api.php
Sintaxis
Si has usado Laravel entonces sabrás cómo escribir rutas en Luthier CI, pues su sintaxis muy parecida. Este es un ejemplo de una ruta de Luthier CI:
Route::get('foo', 'bar@baz');
Donde:
- foo es la URL de la ruta, y
- bar@baz es el nombre del controlador y método al que hace referencia, separados por @.
El método Route::get()
establece que la ruta acepta únicamente peticiones GET
.
Se pueden definir rutas para los verbos GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS y TRACE usando los siguientes métodos de la clase Route
:
Route::post('foo', 'bar@baz');
Route::put('foo', 'bar@baz');
Route::patch('foo', 'bar@baz');
Route::delete('foo', 'bar@baz');
Route::head('foo', 'bar@baz');
Route::options('foo', 'bar@baz');
Route::trace('foo', 'bar@baz');
Puedes pasar un arreglo con las propiedades de la ruta como tercer argumento:
Route::get('test', 'controller@method', ['prefix' => '...', 'namespace' => '...', (...)] );
También es posible aceptar múltiples verbos HTTP en una ruta, usando el método Route::match()
:
Route::match(['GET', 'POST'], 'path', 'controller@method', [ (...) ]);
Espacios de nombre
La propiedad namespace le indica a CodeIgniter el sub-directorio donde se encuentra el controlador.
// El controlador apuntará a application/controllers/foo/Bar.php
Route::get('hello/world', 'bar@index', ['namespace' => 'admin']);
Prefijos
Usa la propiedad prefix para agregar prefijos a las rutas:
// La URL será 'admin/hello/world'
Route::get('hello/world', 'testcontroller@index', ['prefix' => 'admin']);
Rutas con nombre
Es recomendable asignar un nombre a tus rutas, esto te permitirá construir URLs en tus vistas y en otros controladores:
Route::get('company/about_us', 'testcontroller@index')->name('about_us');
Para obtener una ruta por su nombre usa la función route($name)
, donde $name
es el nombre de la ruta:
route('about_us');
Grupos
Usa el método Route::group($prefix, $routes)
para definir un grupo de rutas, donde $prefix
es el prefijo en común y $routes
una función anónima con que contiene las sub-rutas:
Route::group('my_prefix', function(){
Route::get('bar','test@bar');
Route::get('baz','test@baz');
});
Es posible asignar propiedades para todas las rutas del grupo usando la sintaxis Route::group($prefix, $properties, $routes)
:
Route::group('prefix', ['namespace' => 'foo', 'middleware' => ['Admin','IPFilter']], function(){
Route::get('bar','test@bar');
Route::get('baz','test@baz');
});
Rutas de recurso
Las rutas de recurso son un atajo para crear el enrutamiento de operaciones CRUD (Create, Read, Update, Delete) para un controlador.
Para crer una ruta de recurso usa el método Route::resource($name, $controller)
, donde $name
es el nombre/prefijo de las rutas y $controller
el nombre del controlador:
Route::resource('photos','PhotosController');
Resultado:
[Name] [Path] [Verb] [Controller action]
photos.index photos GET PhotosController@index
photos.create photos/create GET PhotosController@create
photos.store photos POST PhotosController@store
photos.show photos/{id} GET PhotosController@show
photos.edit photos/{id}/edit GET PhotosController@edit
photos.update photos/{id} PUT, PATCH PhotosController@update
photos.destroy photos/{id} DELETE PhotosController@destroy
Es posible crear rutas de recurso parciales usando la sintaxis Route::resource($name, $controller, $include)
, donde $include
es un arreglo (incluyente) de las rutas a crear:
Route::resource('photos','PhotosController', ['index','edit','update']);
Resultado:
[Name] [Path] [Verb] [Controller action]
photos.index photos GET PhotosController@index
photos.edit photos/{id}/edit GET PhotosController@edit
photos.update photos/{id} PUT, PATCH PhotosController@update
Controlador por defecto
Luthier CI establece automáticamente cualquier ruta definida con la URL /
y el verbo HTTP GET como el controlador por defecto.
Puedes definir de forma explícita el controlador por defecto usando el método Route::set('default_controller', $name)
, donde $name
es el controlador por defecto:
Route::set('default_controller', 'welcome/index');
Funciones anónimas como rutas
No es necesario suministrar un nombre de un controlador y un método para definir una ruta en Luthier CI. También puedes usar funciones anónimas (o closures) como controladores:
Route::get('foo', function(){
ci()->load->view('some_view');
});
ci()
.
Parámetros de rutas
Los parámetros son secciones dinámicas de la URL de una ruta, haciendo posible que múltiples URLs resuelvan a la misma ruta. Para definir parámetros, enciérralos entre {llaves}
, por ejemplo:
Route::post('blog/{slug}', 'blog@post');
Parámetros opcionales
Para establecer un parámetro como opcional, agrega un ?
antes de cerrar las llaves:
Route::put('categories/{primary?}/{secondary?}/{filter?}', 'clients@list');
Ten en cuenta que, tal como sucede con los argumentos de funciones en PHP, luego del primer parámetro definido como opcional TODOS los demás deberán ser opcionales también.
Expresiones regulares en parámetros
Puedes limitar el contenido de un parámetro de ruta para restringirlo a un set de caracteres en específico:
Route::get('cars/{num:id}/{any:registration}', 'CarCatalog@index');
Los placeholders num:
y any:
son equivalentes a (:num)
y (:any)
, respectivamente.
También es posible usar una expresión regular para definir parámetros de ruta:
Route::get('main/{((es|en)):_locale}/about', 'about@index');
Lo anterior es equivalente a /^(es|en)$/
.
Parámetros adhesivos
Cuando trabajas con grupos de rutas que definen parámetros éstos deben ser declarados como argumentos en los métodos de los controladores, recursivamente. Dependiendo de la complejidad de tu aplicación, los parámetros heredados se irán acumulando, lo que hará que los métodos de tus controldores tengan una cantidad muy grande de argumentos.
Los parámetros adhesivos sirven precisamente para ayudarte a lidiar con éste problema.
Un parámetro adhesivo es cualquier parámetro de ruta que comience con un guión bajo (_
). Tienen las siguientes propiedades:
- No es necesario definirlo en los argumentos de los métodos de los controladores en las sub-rutas.
- El valor del parámetro se tomará de la URL y será suministrado automáticamente en la función
route()
, por lo que puede ser omitido, o sobreescribirlo por cualquier otro valor.
Considera el siguiente grupo de rutas:
Route::group('shop/{_locale}', function()
{
Route::get('category/{id}', 'ShopCategory@categoryList')->name('shop.category');
Route::get('product/{id}/details', 'ShopProduct@details')->name('shop.product.details');
});
Las rutas shop.category
y shop.product.details
comparten el parámetro adhesivo _locale
y, mientras que sigue siendo requerido que dicho parámetro esté en la URL, puedes omitirlo cuando construyas rutas dentro de éste grupo:
// Si la URL es 'shop/en/category/1', {_locale} será 'en' aquí:
echo route('shop.category', ['id' => 1]);
# shop/en/category/1
echo route('shop.category', ['id' => 2]);
# shop/en/category/2
echo route('shop.category', ['id' => 3]);
# shop/en/category/3
Esto es útil cuando necesites enlazar a otras variantes de la ruta actual:
echo route('shop.category', ['_locale' => 'es', 'id' => 1]);
# shop/es/category/1
Dentro de los controladores ShopCategory
y ShopProduct
, sus métodos tendrán un único argumento: $id
:
# application/controllers/ShopCategory.php
class ShopCategory extends CI_Controller
{
public function categoryList($id)
{
// (...)
}
}
# application/controllers/ShopProduct.php
class ShopProduct extends CI_Controller
{
public function details($id)
{
// (...)
}
}
Para obtener el valor de un parámetro adhesivo dentro de un controlador usa al método param($name)
de la propiedad route
, donde $name
es el nombre del parámetro:
public function categoryList($id)
{
$locale = $this->route->param('_locale');
}