Core
Routing and URL rewriting
From URL to controller
Route::parseURI() splits the URL without any route declarations:
- It lower-cases everything and replaces
-with_(/reset-password→reset_password). - If the first segment is
adminand there are more segments, it removes it and marks the route as an admin one (looked up inControllers/Admin/). - If the next segment is the name of an active plugin, it removes it and looks for controllers in
plugins/<plugin>/src/Controllers/. - While the segments match sub-folders of
Controllers/, they are consumed as folders. - What is left is
controller/action/arguments….
| URL | Controller | Action | Arguments |
|---|---|---|---|
/ |
IndexController |
index |
|
/cuentas |
CuentasController |
index |
|
/cuentas/reset-password |
CuentasController |
resetPassword |
|
/productos/ver/15/rojo |
ProductosController |
ver |
15, rojo |
/ajax/cuentas/login |
Ajax/CuentasController |
login |
|
/admin/sistema/usuarios/editar/7 |
Admin/Sistema/UsuariosController |
editar |
7 |
/noticias/listado (noticias plugin) |
plugins/noticias/…/ListadoController |
index |
Arguments are passed to the action as parameters, in order:
public function ver($id = null, $color = null) {
$producto = TMProductos::find(intval($id));
if (!$producto) {
$this->Response->setCode(404);
return;
}
$this->set(['producto' => $producto]);
}
Action names
The action is converted to camelCase (reset_password → resetPassword). The template, however, uses the original lower-case name: cuentas/reset_password.tpl.
Special parameters
?action=namein the query string (or the POST data) replaces the URL's action.?subaction=nameis available inRoute::get()['subaction'].
Reading the current route
$route = Route::get();
// ['uri'=>'productos/ver/15', 'qs'=>'', 'plugin'=>'', 'controller'=>'Productos',
// 'action'=>'ver', 'raw_action'=>'ver', 'arguments'=>['15']]
Route::getDomain(); // 'https://mysite.com'
Route::setAction('other');
Plugin static files
If the URL starts with a plugin name and ends in .js, .css, .map or an image extension, Koshkil serves the file straight from plugins/<plugin>/webroot/. A .js URL that is not a real file is treated as the controller's javascript action, which is handy for generating JavaScript from PHP.
Rewrite rules
For URLs that don't follow the convention, define rules in config/rewrite.php (or the domain's) under System.Web.Rewrite. They are evaluated before routing, in order, against the URL without its leading slash.
<?php
$CONFIG = [
'System' => [
'Web' => [
'Rewrite' => [
// /negocios/lopez-bakery -> /negocios?nombre=lopez-bakery
['rule' => '^negocios/([a-z\-0-9]*)$', 'target' => '/negocios?nombre=$1', 'flags' => 'L,NC'],
// alias for an admin section
['rule' => '^admin/usuarios/(editar|listado)$', 'target' => '/admin/sistema/usuarios/$1?subusuarios=1', 'flags' => 'L,NC'],
],
],
],
];
| Part | Meaning |
|---|---|
rule |
Regular expression (~ delimiter). |
target |
New URL. $1, $2… are replaced by the captured groups. The target's query string is added to $_GET. |
flags |
L: last rule, stop evaluating. NC: case-insensitive. RW: keep evaluating the following rules against the rewritten URL. |
Rules can also be added from code, before routing:
RewriteManager::addRule('^ofertas$', '/productos/listado?oferta=1', 'L,NC');
RewriteManager::addRule('^promo$', '/productos/promo', 'L', true); // true: at the top
Plugins declare their rules in plugins/<plugin>/config/rewrite.php (a $RULES array), added after the global ones. With Debug.Rewrite at 5 or more, every evaluation is logged to tmp/logs/rewrite.log.
Building links
Never hard-code absolute paths: the project may live in a sub-folder.
| Method | Returns |
|---|---|
Koshkil::getLink('/productos/ver/15') |
A page URL (prepends Web.Path). |
Koshkil::getPath('/css/app.css') |
A file's web path. With true as the second argument, its physical path on disk. |
Koshkil::getThemePath('css/theme.css') |
A file inside the active theme. |
Koshkil::redirect('/cuentas') |
Redirects and stops execution. |
<a href="{Koshkil::getLink('/productos/ver/'|cat:$producto->prd_codigo)}">View</a>
<link rel="stylesheet" href="{Koshkil::getThemePath('css/theme.css')}">