Configurar aplicaciones CakePHP es pan comido. Despues de instalar
CakePHP, crear una aplicación web básica solo requiere aplicar la
configuración de una base de datos. Existen, otras configuraciones
opcionales, que puedes realizar con el objetivo de aprovechar las
ventajas de la arquitectura flexible de CakePHP. Tu puedes agregar
facilmente elementos al núcleo de CakePHP, configurar URL personalizadas
y definir inflexiones.
Configuración de Base de Datos
CakePHP espera que los detalles de configuración de la base de datos
estén en app/config/database.php. Un ejemplo de configuración puede
encontrarse en el archivo app/config/database.php.default. Esta
configuración debería verse como sigue:
var $default = array('driver' => 'mysql',
'persistent' => false,
'host' => 'localhost',
'login' => 'cakephpuser',
'password' => 'c4k3roxx!',
'database' => 'mi_proyecto',
'prefix' => '');
El arreglo de configuración $default es el utilizado a menos que se
especifique algún otro en la propiedad $usDbConfig de los modelos. Por
ejemplo, si mi aplicación tiene aplicaciones legadas adicionales a la
que se va a utilizar por defecto, podría utilizarla en mis modelos
creando un nuevo arreglo de configuración $legada que sea similar a
$default, y asignado var $useDbConfig = “legada”; en los modelos
correspondientes.
Rellena cada para clave/valor en el arreglo de configuración, como mejor
se ajuste a tus necesidades
Clave |
Valor |
driver |
El nombre del controlador de base de datos que se desea utilizar. Ejemplo: mysql, postgres, sqlite, pear-nombrededriver, adodb-nombrededriver, mssql, oracle, odbc. |
persistent |
Si se debe usar o no una conexión persistente a la base de datos. |
host |
El nombre de servidor de la base de datos (o dirección IP). |
login |
El nombre de usuario para la cuenta. |
password |
La contraseña para la cuenta. |
database |
Nombre de la base de datos a usar para la conexión |
prefix (opcional) |
El texto que prefija cada nombre de tabla en la base de datos. Útil si se comparte la base de datos con varias aplicaciones. Dejar vacío si no se desea ninguno. |
port (opcional) |
El puerto TCP o socket Unix a usarse para la conexión con el servidor de base de datos. |
encoding |
Indica la codificación de caracteres a usar para enviar las sentencias SQL al servidor. |
schema |
Usado en la configuración de PostgreSQL para especificar el esquema a utilizar. |
Nota que los prefijos son para las tablas, no para los modelos. Por
ejemplo, si creaste una tabla join para tus modelos Torta y Sabor, esta
debe llamarse prefijo_sabor_torta (no
prefijo_sabor_prefijo_torta), y asignar la clave prefix con
‘prefijo_’.
A este punto, pudieras querer echar un vistazo a las Convenciones de
CakePHP, enunciadas en el apéndice
de este manual. Nombrar correctamente tus tablas (y algunas columnas)
según las convenciones puede librarte de mucho trabajo de configuración.
Por ejemplo, si nombras una tabla como tortas, el modelo Torta y el
controller TortasController, todo funcionará automáticamente si
necesidad de tu intervención. Por convención, utiliza guiones bajos,
minúsculas, y nombres en plural para los nombres de tus tablas - por
ejemplo: reposteros, reposterias, sabores.
Definir Rutas
Definir tus propias rutas te permite definir cómo va a responder tu
aplicación cuando se solicite un URL determinado. Tus rutas deben ser
definidas en el archivo /app/config/routes.php usando el método
Router::connect().
El método connect() toma hasta tres parámetros: el patron de URL que
deseas hacer coindicir, los valores por defecto para los elementos de
enrutamient propios, y expresiones regulares que ayuden al enrutador a
hacer coincidir elementos en el URL.
El formáto básico para una definición de ruta es:
Router::connect(
'URL',
array('nombreParam' => 'valorPorDefecto'),
array('nombreParam' => 'expresionRegular')
)
El primer parámetro es usado para decirle al enrutador qué tipo de URL
estás tratando de controlar. El URL es una cadena de caracteres
separadas por barras inclinadas (slash), pero también pueden contener el
un comodín comodín (*) o elementos de enrutamiento propios (Elementos
de URL prefijados con el caracter dos puntos «:»). Usar un comodín le
indica al enrutador qué tipos de URL quieres hacer coincidir, y
especificar elementos de enrutamiento te permite recolectar parámetros
para las acciones de tus controladores
Una vez que hayas especificado un URL, debes utilizar los últimos dos
parámetros del método connect() para decirle a CakePHP que hacer con esa
petición una vez que ha sido seleccionada la regla adecuada. El segundo
parámetro es una arreglo asociativo. Las claves de este arreglo deben
ser nombradas como los elementos de enrutamiento en el URL, o los
elementos por defecto, que son, :controller, :action y :plugin. Los
valores en este arreglo son los valores por omisión para cada una de las
claves. Veamos algunos ehjemplos básicos antes de empezar a usar el
tercer parámetro de connect()
Router::connect(
'/pages/*',
array('controller' => 'pages', 'action' => 'display')
);
Esta ruta se encuentra en el archivo routes.php distribuido con CakePHP
(linea 40). Esta ruta coincide con los URL que comienzan con /pages/ y
delega a la acción display() de PagesController el manejo de la
petición. La petición /pages/productos puede sería dirigida a
PagesController->display(“productos”), por ejemplo.
Router::connect(
'/mujeres',
array('controller' => 'productos', 'action' => 'mostrar', 5)
);
Este segundo ejemplo muestra como usar el segundo parámetro de connect()
para definir parámetros por omisión. Si construiste un sitio que muestra
productos para diferentes categorías de clientes, puedes considerar el
hacer una ruta. Esto te ayuda a crear el enlace /mujeres en lugar de
/productos/mostrar/5
Para tener flexibilidad adicional, puedes especificar elementos de
enrutamiento propios. Hacer esto te da el poder de definir lugares en el
URL donde los parámentros para las acciones deben residir. Cuando se
hace una petición, los valores para estos elementos propios se
encuentran en $this-gt;params del controlador. Estos son diferentres de
los parametros con nombre, y esta es la diferencia: los parmámetros con
nombre (/controlador/accion/nombre:valor) se encuentran en
$this->passedArgs, mientras que los elementos propios de enrutamiento se
encuentran en $this->params. Cuando defines un elemento propio de
enrutamiento, también necesitas especificar una expresión regular. Esto
le indica a CakePHP cómo reconocer si el URL está bien formado o no.
Router::connect(
'/:controller/:id',
array('action' => 'ver'),
array('id' => '[0-9]+')
);
Este ejemplo sencillo muestra cómo crear una manera sencilla de ver
registros desde cualquier controlador accediendo a un URL que luce como
/mincontrolador/id. El URL suministrado a connect() especifica dos
elementos de enrutamiento, :controller e :id, El primer elemento es uno
que viene por defecto con CakePHP, así que el enrutador sabe cómo
reconocer nombres de controladores en el URL. El elemento :id es propio,
y debe ser clarificado especificando una expresión regular en el tercer
parámetro de conenct(). Esto le dice a CakePHP cómo reconocer el ID en
el URL en contraposición a cualquier otra cosa que esté allí, como el
nombre de una acción.
Una vez que hayas definido esta ruta, solicitar /manzanas/5, sería lo
mismo que solicitar /manzanas/ver/5. Ambos harán una llamada al método
ver() de ManzanasController. Dentro del método ver(), podrías acceder al
id en $this->params[“id”].
unejemplo más y serás un profesional del enrutador.
Router::connect(
'/:controller/:year/:month/:day',
array('action' => 'listar', 'day' => null),
array(
'year' => '[12][0-9]{3}',
'month' => '(0[1-9]|1[012])',
'day' => '(0[1-9]|[12][0-9]|3[01])'
)
);
Puede parecer un poco enredado, pero muestra lo poderosas que pueden ser
las rutas. El URL suministrado tiene cuatro elemento. El primero ya debe
resultarte familiar: el elemento que le dice a CakePHP que se trata de
un nombre de controlador.
A continuación, vamos a especificar algunos valores por defecto. Sin
importar el controlador, queremos que la acción listar() sea llamada.
Asignamos el parámetro day (día, que es el cuarto elemento en el URL) a
null, para marcarlo como opcional.
Finalmente especificamos algunas expresiones regulares que coindidiran
con años, meses y días en su forma numérica.
Una vez definda, esta ruta coindcidirá con /articulos/2007/02/01,
/escritos/2004/11/16 y /productos/2001/05 (¿recuerdas que el parametro
day era opcional?), enviando la petición a listar() de sus respectivos
controladores, con los parámetros de fecha definidos en $this->params.
Rutas con prefijos
Muchas cplicaciones requieren una zona administrativa donde los usuarios
privilegiados puedan hacer cambios. Estos es comunment hecho a través de
un URL especial como /admin/usuarios/editar/5
. En CakePHP, las rutas
admin pueden ser habilitadas en el archivo core.php asignando la ruta
para Routing.admin.
Configure::write('Routing.admin', 'admin');
En tu controlador, cualquier acción que empiece por admin_
será
llamada. Usando nuestro ejemplo de usuarios, el nombre de la acción de
nuestro UsuariosController
debe ser admin_editar
Puedes usar el enrutador para usar prefijos propios para usos más allá
de la administraión
Router::connect('/perfiles/:controller/:action', array('prefix' => 'perfiles'));
Cualquier llamada a la sección de perfiles buscará el prefijo
perfiles_
en las llamadas a métodos. Nuestro ejemplo de usuarios
tendría una estructura de URL que luciría como
/perfiles/usuarios/editar/5
, lo cual invocaría el método
perfiles_editar
del UsuariosController
. también es importante
reordar que usar el Ayudante HTML para construir tus enlaces te ayudará
a mantener los prefijos. Este es un ejemplo de un enlace usando el
ayudante HTML
echo $html->link('Editat tu perfil', array('controller' => 'usuarios', 'action' => 'perfiles_editar'));
Puedes utilizar múltiples prefijos de ruta para crar una muy flexible
estructura de URL para tu aplicación
Enrutamiento por defecto
Antes de que leas como configurar tus rutas, deberías saber que CakePHP
incluye algunas por defecto. El enrutamiento en CakePHP te ofrece mucho
más que cualquier otra aplicación. Puedes acceder directamente a
cualquier acción poniéndola solo en la URL. Puedes enviar también
variables a la acción a través de la URL.
Patrones de enrutamiento por defecto:
http://example.com/controller/action/param1/param2/param3
La URL /posts/view enruta hacia la accion view() del controlador
PostsController y /products/viewClearance enruta hacia la accion
view_clearance() del controlador ProductsController. Si la acción no
esta definida en la URL, el método index() es asumido por defecto.
El enrutamiento por defecto te permite enviar parámetros a la acción a
través de la URL. Una petición hacia /posts/view/25 sería equivalente a
llamar a la acción view(25) en el controlador PostsController.
Passed arguments
Los argumentos pasados son argumentos adicionales o segmentos de rutas
que se usan al hacer una solicitud. Generalmente se usan para pasar
parámetros a los métodos de los controladores.
http://localhost/calendars/view/recent/mark
En el ejemplo anterior, recent
y mark
son argumentos que se
pasan a CalendarsController::view()
. Los argumentos pasados se dan a
los controladores de tres formas. Primero, como argumentos al método de
acción llamado, segundo estan disponibles en $this->params['pass']
como una matriz indexada numericamente. Por último, existe
$this->passedArgs
disponible de la misma manera que la segunda
forma. Al utilizar rutas personalizadas pueden pasarse ciertos
parámetros junto con los argumentos pasados. Ver “Pasando Argumentos a
una
acción”
para más información.
Argumentos del método de acción llamado
CalendarsController extends AppController{
function view($arg1, $arg2){
debug($arg1);
debug($arg2);
debug(func_get_args());
}
}
Aqui tendremos:
Array
(
[0] => recent
[1] => mark
)
$this->params[“pass”] como matriz indexada numericamente
debug($this->params['pass'])
Aqui tendremos:
Array
(
[0] => recent
[1] => mark
)
$this->passedArgs como matriz indexada numericamente
Array
(
[0] => recent
[1] => mark
)
$this->passedArgs también puede contener parámentros Nombrados como una
matriz mixta con los argumentos pasados.
Parámetros con nombre
Una nueva característica en CakePHP 1.2 es la posibilidad de setear
nombres de parámetros y su valor por la URL. Una petición a
/posts/view/title:first+post/category:general resultaría en una llamada
a la acción view() del controlador PostsController. En esta acción,
podrás encontrar los valores para title y category dentro de
$this->passedArgs[“title”] y $this->passedArgs[“category”]
respectivamente.
Algunos ejemplos que pueden ser de utilidad.
Acceder a la acción jump() del controlador MonkeysController desde la URL:
URL: /monkeys/jump
Enrutado: MonkeysController->jump();
URL: /products
Enrutado: ProductsController->index();
URL: /tasks/view/45
Enrutado: TasksController->view(45);
URL: /donations/view/recent/2001
Enrutado: DonationsController->view('recent', '2001');
URL: /contents/view/chapter:models/section:associations
Enrutado: ContentsController->view();
$this->passedArgs['chapter'] = 'models';
$this->passedArgs['section'] = 'associations';
Defining Routes
Defining your own routes allows you to define how your application will
respond to a given URL. Define your own routes in the
/app/config/routes.php file using the Router::connect()
method.
The connect()
method takes up to three parameters: the URL you wish
to match, the default values for your route elements, and regular
expression rules to help the router match elements in the URL.
The basic format for a route definition is:
Router::connect(
'URL',
array('paramName' => 'defaultValue'),
array('paramName' => 'matchingRegex')
)
The first parameter is used to tell the router what sort of URL you’re
trying to control. The URL is a normal slash delimited string, but can
also contain a wildcard (*) or route elements (variable names prefixed
with a colon). Using a wildcard tells the router what sorts of URLs you
want to match, and specifying route elements allows you to gather
parameters for your controller actions.
Once you’ve specified a URL, you use the last two parameters of
connect()
to tell CakePHP what to do with a request once it has been
matched. The second parameter is an associative array. The keys of the
array should be named after the route elements in the URL, or the
default elements: :controller, :action, and :plugin. The values in the
array are the default values for those keys. Let’s look at some basic
examples before we start using the third parameter of connect().
Router::connect(
'/pages/*',
array('controller' => 'pages', 'action' => 'display')
);
This route is found in the routes.php file distributed with CakePHP
(line 40). This route matches any URL starting with /pages/ and hands it
to the display()
method of the PagesController();
The request
/pages/products would be mapped to
PagesController->display('products')
, for example.
Router::connect(
'/government',
array('controller' => 'products', 'action' => 'display', 5)
);
This second example shows how you can use the second parameter of
connect()
to define default parameters. If you built a site that
features products for different categories of customers, you might
consider creating a route. This allows you link to /government rather
than /products/display/5.
Another common use for the Router is to define an «alias» for a
controller. Let’s say that instead of accessing our regular URL at
/users/someAction/5, we’d like to be able to access it by
/cooks/someAction/5. The following route easily takes care of that:
Router::connect(
'/cooks/:action/*', array('controller' => 'users', 'action' => 'index')
);
This is telling the Router that any url beginning with /cooks/ should be
sent to the users controller.
When generating urls, routes are used too. Using
array('controller' => 'users', 'action' => 'someAction', 5)
as a url
will output /cooks/someAction/5 if the above route is the first match
found
If you are planning to use custom named arguments with your route, you
have to make the router aware of it using the Router::connectNamed
function. So if you want the above route to match urls like
/cooks/someAction/type:chef
we do:
Router::connectNamed(array('type'));
Router::connect(
'/cooks/:action/*', array('controller' => 'users', 'action' => 'index')
);
You can specify your own route elements, doing so gives you the power to
define places in the URL where parameters for controller actions should
lie. When a request is made, the values for these route elements are
found in $this->params of the controller. This is different than named
parameters are handled, so note the difference: named parameters
(/controller/action/name:value) are found in $this->passedArgs, whereas
custom route element data is found in $this->params. When you define a
custom route element, you also need to specify a regular expression -
this tells CakePHP how to know if the URL is correctly formed or not.
Router::connect(
'/:controller/:id',
array('action' => 'view'),
array('id' => '[0-9]+')
);
This simple example illustrates how to create a quick way to view models
from any controller by crafting a URL that looks like
/controllername/id. The URL provided to connect() specifies two route
elements: :controller and :id. The :controller element is a CakePHP
default route element, so the router knows how to match and identify
controller names in URLs. The :id element is a custom route element, and
must be further clarified by specifying a matching regular expression in
the third parameter of connect(). This tells CakePHP how to recognize
the ID in the URL as opposed to something else, such as an action name.
Once this route has been defined, requesting /apples/5 is the same as
requesting /apples/view/5. Both would call the view() method of the
ApplesController. Inside the view() method, you would need to access the
passed ID at $this->params['id']
.
If you have a single controller in your application and you want that
controller name does not appear in url, e.g have urls like /demo instead
of /home/demo:
Router::connect('/:action', array('controller' => 'home'));
One more example, and you’ll be a routing pro.
Router::connect(
'/:controller/:year/:month/:day',
array('action' => 'index', 'day' => null),
array(
'year' => '[12][0-9]{3}',
'month' => '0[1-9]|1[012]',
'day' => '0[1-9]|[12][0-9]|3[01]'
)
);
This is rather involved, but shows how powerful routes can really
become. The URL supplied has four route elements. The first is familiar
to us: it’s a default route element that tells CakePHP to expect a
controller name.
Next, we specify some default values. Regardless of the controller, we
want the index() action to be called. We set the day parameter (the
fourth element in the URL) to null to flag it as being optional.
Finally, we specify some regular expressions that will match years,
months and days in numerical form. Note that parenthesis (grouping) are
not supported in the regular expressions. You can still specify
alternates, as above, but not grouped with parenthesis.
Once defined, this route will match /articles/2007/02/01,
/posts/2004/11/16, and /products/2001/05 (as defined, the day parameter
is optional as it has a default), handing the requests to the index()
actions of their respective controllers, with the date parameters in
$this->params.
Pasando parámetros a las acciones
Asumiendo que tu action fue definida así y quieres acceder los
argumentos usando $articleID
en vez de $this->params['id']
, tan
solo agrega un array extra en el 3er parámetro de Router::connect()
.
// some_controller.php
function view($articleID = null, $slug = null) {
// some code here...
}
// routes.php
Router::connect(
// E.g. /blog/3-CakePHP_Rocks
'/blog/:id-:slug',
array('controller' => 'blog', 'action' => 'view'),
array(
// el orden es importante ya que esto va a mapear ":id" con $articleID en tu action
'pass' => array('id', 'slug'),
'id' => '[0-9]+'
)
);
Y ahora, gracias a la capacidad de enrutamiento inverso podrás pasar la
url como se muestra abajo y Cake sabrá como formar la URL como se
definió en los routers.
// view.ctp
// esto devolverá un link a /blog/3-CakePHP_Rocks
<?php echo $html->link('CakePHP Rocks', array(
'controller' => 'blog',
'action' => 'view',
'id' => 3,
'slug' => Inflector::slug('CakePHP Rocks')
)); ?>
Prefix Routing
Muchas aplicaciones necesitan una sección administrativa donde los
usuarios con privilegios puedan hacer cambios. Con frecuencia, esto se
hace con una URL especial como /admin/users/edit/5. En CakePHP, el admin
routing puede activarse dentro del archivo de configuración del core
ajustando la ruta de administración para Routing.admin.
Configure::write('Routing.admin', 'admin');
En tu controlador, será llamada cualquier acción con un prefijo
admin_
. Recurriendo a nuestro ejemplo de usuarios, acceder a la URL
/admin/users/edit/5 debería llamar al método admin_edit
de nuestro
UsersController
pasando 5 como primer parámetro.
Puedes mapear la URL /admin a tu acción admin_index
del pages
controller usando la ruta
Router::connect('/admin', array('controller' => 'pages', 'action' => 'index', 'admin' => true));
Puedes configurar el Router usado múltiples prefijos:
Router::connect('/profiles/:controller/:action/*', array('prefix' => 'profiles', 'profiles' => true));
Cualquier llamada a la sección Profiles buscaría el prefijo
profiles_
en las llamadas a los métodos. Nuestro ejemplo tendría una
URL como /profiles/users/edit/5 que llamaría al método profiles_edit
en el UsersController
. Es también importante recordar que usar el
HTML helper para construir tus enlaces, te ayudará a mantener las
llamadas a los prefijos. He aquí cómo construir este enlace usando el
HTML helper:
echo $html->link('Edit your profile', array('profiles' => true, 'controller' => 'users', 'action' => 'edit', 'id' => 5));
Puedes ajustar múltiples rutas con prefijos usando esta metodología para
crear una estructura de URL flexible para tu aplicación.
Rutas y plugins
Las rutas a Plugins utilizan la clave plugin. Puedes crear enlaces
que apunten a un plugin siempre que añadas la clave plugin al array de
la url.
echo $html->link('New todo', array('plugin' => 'todo', 'controller' => 'todo_items', 'action' => 'create'));
Por el contrario, si la petición activa es un plugin y quieres crear un
enlace que no tiene plugin, puedes hacerlo como sigue.
echo $html->link('New todo', array('plugin' => null, 'controller' => 'users', 'action' => 'profile'));
Al poner plugin => null
le estás diciendo al Router que quieres
crear un enlace que no forma parte de un plugin.
Extensiones de archivo
Para manejar diferentes extensiones de archivo con tus rutas, necesitas
una línea extra en el archivo de configuración de rutas:
Router::parseExtensions('html', 'rss');
Esto le dirá al router que retire las extensiones de archivo
coincidentes y que procese entonces el resto..
Si quieres crear una url como /page/title-of-page.html podrías crear tu
ruta como se explica a continuación:
Router::connect(
'/page/:title',
array('controller' => 'pages', 'action' => 'view'),
array(
'pass' => array('title')
)
);
Para crear enlaces que se mapeen a esas rutas simplemente usamos:
$html->link('Link title', array('controller' => 'pages', 'action' => 'view', 'title' => Inflector::slug('text to slug', '-'), 'ext' => 'html'))
Custom Route classes
Custom route classes allow you to extend and change how individual
routes parse requests and handle reverse routing. A route class should
extend CakeRoute
and implement one or both of match()
and
parse()
. Parse is used to parse requests and match is used to handle
reverse routing.
You can use a custom route class when making a route by using the
routeClass
option, and loading the file containing your route before
trying to use it.
Router::connect(
'/:slug',
array('controller' => 'posts', 'action' => 'view'),
array('routeClass' => 'SlugRoute')
);
This route would create an instance of SlugRoute
and allow you to
implement custom parameter handling