Sunteți pe pagina 1din 385

El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.

org/es/complete/876/The-Manual

El manual
Click aquí para la versión 1.1.x del manual de CakePHP (/es/view/3/the-manual)

Bienvenido al Cookbook, la documentación de CakePHP. El Cookbook es un sistema wiki que permite las
contribuciones del público. Con un sistema abierto, esperamos mantener un alto nivel de calidad, validez, y precisión
en la documentación de CakePHP. El Cookbook también facilita a cualquier persona contribuir.

Un gran agradecimiento para AD7six, quién abogó desde un inicio por la causa del Cookbook, trabajando numerosas
horas para el desarrollo, prueba y mejora de está aplicación.

# (#Como-funciona-877) ¿Como funciona?

Si reconoces un error, algo que está incompleto, algo que no ha sido cubierto en su totalidad, o algo que
simplemente no está escrito a tu gusto, aquí te explicamos cómo puedes ayudar:

1. Haz click en el link Editar de la sección que deseas cambiar.


2. Inicia sesión en el Cookbook utilizando tu cuenta de Bakery (http://bakery.cakephp.org) . ¡Cualquiera puede
conseguir una cuenta!
3. Por favor revisa las indicaciones para contribuir en el Cookbook (/es/view/482/contributing-to-the-cookbook)
para asegurar la consistencia.
4. Envía tus ediciones o adiciones para su revisión, utilizando semántica HTML válida.
5. Sigue el progreso de tus envíos usando los feeds rss o revisa al día siguiente para ver tus cambios aprobados.

# (#Traducciones-878) Traducciones

Envía un email a John David Anderson (docs arroba cakephp punto org) o contacta con él a través del IRC (#cakephp
en freenode como _psychic_) para plantearle cualquier proyecto de traducción en el que te gustaría participar.

Pautas para la traducción:

Busca y edita en el mismo idioma al que estás traduciendo el contenido - de lo contrario será registrado como
una modificación en inglés, con escasas posibilidades de que el revisor conozca el idioma en que estás
escribiendo.
No dudes en cooperar si tu lengua ya existe en el Cookbook.
Usa la lista Todo (arriba a la derecha) para ver dónde se requiere atención en tu lengua.
Utiliza el registro informal (http://es.wikipedia.org/wiki/Registro_ling%C3%BC%C3%ADstico) .
Traduce a la vez el título y el contenido.
Comprara el texto con el contenido en inglés antes de enviar una corrección (si corriges algo, pero no integras
los cambios de la rama principal en inglés, tu propuesta no será aceptada).
Si necesitas escribir un término en inglés, mételo entre etiquetas <em>. E.g. "asdf asdf Controller asdf" o "asdf
asdf Kontroller (Controller ) asfd" como es apropiado.
No envíes traducciones parciales.
No edites una sección con cambios pendientes (ver información "Historia").
No uses entidades html (http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references) para
caracteres acentuados, el cookbook utiliza UTF-8.
No cambies significativamente el etiquetado (HTML) o añadas nuevo contenido - Si al contenido original le falta
información, edítalo primero.
Modifica los vínculos para enlazarlos con el idioma traducido.

Estamos comprometidos a hacer la documentación de CakePHP mejor de lo que nunca ha sido. Esperamos que te unas
a nosotros usando el Cookbook y realimentando un proyecto del que tanto nos hemos beneficiado todos.

1 (#Comenzando-con-CakePHP-879) Comenzando con CakePHP

¡Bienvenido al Cookbook, el manual para el framework CakePHP que convierte el desarrollo de aplicaciones web en un
juego de niños!

Este manual supone que posees conocimientos generales de PHP y conocimientos básicos de programación orientada
a objetos (POO). Las diferentes funciones del framework utilizan varias tecnologías -por ejemplo, SQL, JavaScript o

1 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

XML—. El manual no pretende explicar dichas tecnologías, sino cómo se utilizan en este contexto.

1.1 (#Qué-es-CakePHP-y-por-qué-hay-que-utilizarlo-880) ¿Qué es CakePHP y por qué hay que utilizarlo?

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/880)


Comparar con el texto original (/es/compare/880/Qué-es-CakePHP-y-por-qué-hay-que-utilizarlo)

Mas info sobre traduciones (/es/view/818)

CakePHP es un marco de desarrollo [framework] rápido para PHP, libre, de código abierto. Se trata de una estructura
que sirve de base a los programadores para que éstos puedan crear aplicaciones Web. Nuestro principal objetivo es
que puedas trabajar de forma estructurada y rápida, sin pérdida de flexibilidad.

Con CakePHP el desarrollo web ya no es monótono porque ofrecemos las herramientas para que empieces a escribir el
código que realmente necesitas: la lógica específica de tu aplicación. Consigue una copia de CakePHP, empieza con lo
verdaderamente importante y no reinventes la rueda cada vez que te incorpores a un nuevo proyecto.

CakePHP tiene un equipo de desarrolladores y una comunidad activos, lo que añade valor al proyecto. Con CakePHP,
además de no tener que reinventar la rueda, el núcleo de tu aplicación se mejora constantemente y está bien probado.

Esta es una lista breve con las características de las que disfrutarás al utilizar CakePHP:

Comunidad activa y amistosa


Licencia flexible
Compatible con PHP4 y PHP5
CRUD integrado para la interacción con la base de datos
Soporte de aplicación [scaffolding]
Generación de código
Arquitectura Modelo Vista Controlador (MVC)
Despachador de peticiones [dispatcher], con URLs y rutas personalizadas y limpias
Validación integrada
Plantillas rápidas y flexibles (sintaxis de PHP, con ayudantes[helpers])
Ayudantes para AJAX, Javascript, formularios HTML y más
Componentes de Email, Cookie, Seguridad, Sesión y Manejo de solicitudes
Listas de control de acceso flexibles
Limpieza de datos
Caché flexible
Localización
Funciona en cualquier subdirectorio del sitio web, con poca o ninguna configuración de Apache

1.2 (#Dónde-obtener-ayuda-881) Dónde obtener ayuda

# (#El-sitio-oficial-CakePHP-882) El sitio oficial CakePHP

http://www.cakephp.org (http://www.cakephp.org)

El sitio web oficial de CakePHP es siempre un gran lugar para visitar. Cuenta con enlaces a herramientas de desarrollo
frecuentemente utilizadas, videos, oportunidades de donar, y descargas.

# (#El-Cookbook-883) El Cookbook

http://book.cakephp.org (/es/)

Has comenzado en el lugar correcto. Este manual (y la API) es probablemente el primer lugar al que tienes que
dirigirte para obtener ayuda. Como ocurre con muchos otros proyectos de código abierto, tenemos gente nueva con
regularidad, por lo que, para reducir nuestra carga de trabajo, intenta primero buscar respuestas por tí mismo.

Las respuestas pueden demorarse, pero una vez obtenidas las recordarás durante mucho tiempo. Tanto el manual
como la API tienen una versión en línea.

# (#El-Bakery-884) El Bakery

http://bakery.cakephp.org (http://bakery.cakephp.org)

La Panadería de CakePHP (CakePHP Bakery) es un almacén de cosas relacionadas con CakePHP. Consúltalo si estás

2 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

buscando tutoriales, casos de estudio o ejemplos de código. Cuando estés familiarizado con CakePHP, accede a él y
comparte tus conocimientos con la comunidad.

# (#El-API-885) El API

http://api.cakephp.org/ (http://api.cakephp.org/)

Directo al grano y directamente de los desarrolladores de CakePHP, la API (Interfaz de Programación de Aplicaciones)
CakePHP es la documentación más completa y directa que explica los detalles internos del funcionamiento del
framework. Se trata de una guía de referencia de código concisa.

# (#CakeForge-886) CakeForge

http://www.cakeforge.org (http://www.cakeforge.org)

CakeForge es otro recurso para desarrolladores que puedes utilizar para hospedar tus proyectos CakePHP para
compartir con los demás. Si estás buscando (o quieres compartir) un componente interesante o un plugin
recomendable, echa un vistazo a CakeForge.

# (#Los-Casos-de-Prueba-887) Los Casos de Prueba

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/887)


Comparar con el texto original (/es/compare/887/Los-Casos-de-Prueba)

Mas info sobre traduciones (/es/view/818)

http://api.cakephp.org/tests (http://api.cakephp.org/tests)

Si crees que la información que proporciona la API no es suficiente, consulta el código de los casos de prueba que
proporciona CakePHP 1.2. Estos te pueden servir de ejemplos prácticos para el uso de funciones y datos miembros de
una clase. Para obtener casos de prueba necesitas bajar un paquete nightly o hacer un checkout de un branch de svn.
Los casos de prueba se encuentran en:

Plain Text View (#)


1. cake/tests/cases

# (#El-canal-IRC-888) El canal IRC

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/888)


Comparar con el texto original (/es/compare/888/El-canal-IRC)

Mas info sobre traduciones (/es/view/818)

#cakephp (irc://irc.freenode.net/cakephp) -- Discusión General


#cakephp-docs (irc://irc.freenode.net/cakephp-docs) -- Documentación
#cakephp-bakery (irc://irc.freenode.net/cakephp-bakery) -- Bakery

Si te quedas estancado en algún punto, consúltanos en el canal IRC de CakePHP. Generalmente, algún miembro del
equipo de desarrollo suele estar conectado, sobre todo durante las horas de luz solar de América del Norte y América
del Sur.

Nos gustaría mucho saber de tí: si necesitas ayuda, si deseas encontrar usuarios en tu área o si quieres donar tu
flamante coche deportivo.

#cakephp-es (irc://irc.freenode.net/cakephp-es) -- Canal de la comunidad hispano-parlante

# (#El-Google-Group-889) El Google Group

Además, CakePHP tiene un grupo Google muy activo; un recurso excelente en que se encuentran respuestas
archivadas, preguntas frecuentes, y donde también puedes obtener respuestas inmediatas a tus problemas.

http://groups.google.com/group/cake-php/ (http://groups.google.com/group/cake-php/)

3 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Si estás buscando un grupo Google en español, suscríbete al grupo de la comunidad hispanohablante.

http://groups.google.com/group/cakephp-esp/ (http://groups.google.com/group/cakephp-esp/)

1.3 (#Entendiendo-Modelo-Vista-Controlador-890) Entendiendo Modelo-Vista-Controlador

Las aplicaciones CakePHP bien escritas siguen el patrón de diseño de software MVC (Modelo-Vista-Controlador).
Programar utilizando MVC consiste en separar la aplicación en tres partes principales. El modelo representa los datos
de la aplicación, la vista hace una presentación del modelo de datos, y el controlador maneja y enruta las peticiones
[requests] hechas por los usuarios.

Figura 1: Una petición MVC básica

La figura 1 muestra un ejemplo sencillo de una petición [request] MVC en CakePHP. A efectos ilustrativos,
supongamos que un usuario llamado Ricardo acaba de hacer clic en el enlace "¡Comprar un pastel personalizado
ahora!" de la página de inicial de la aplicación.

1. Ricardo hace clic en el enlace apuntando a http://www.ejemplo.com/pasteles/comprar, y su navegador hace


una petición al servidor web.
2. El despachador comprueba la URL de la petición (/pasteles/comprar), y le pasa la petición al controlador
adecuado.
3. El controlador realiza lógica de aplicación específica. Por ejemplo, puede comprobar si Ricardo ha iniciado
sesión.
4. El controlador también utiliza modelos para acceder a los datos de la aplicación. La mayoría de las veces los
modelos representan tablas de una base de datos, aunque también pueden representar entradas LDAP, canales
RSS, o ficheros en el sistema. En este ejemplo, el controlador utiliza un modelo para buscar la última compra de
Ricardo en la base de datos.
5. Una vez que el controlador ha hecho su magia en los datos, se los pasa a la vista. La vista toma los datos y los
deja listos para su presentación al usuario. La mayoría de las veces las vistas en CakePHP vienen en formato
HTML, pero una vista puede ser fácilmente un PDF, un documento XML, o un objeto JSON, dependiendo de tus
necesidades.
6. Una vez que el objeto encargado de procesar vistas en CakePHP ha utilizado los datos del controlador para
construir una vista completa, el contenido se devuelve al navegador de Ricardo.

Casi todas las peticiones a tu aplicación seguirán este patrón básico. Más adelante, vamos a completar algunos
detalles específicos de Cake, así que, por favor, ten esto en cuenta a medida que avanzamos.

# (#Beneficios-891) Beneficios

¿Por qué utilizar MVC? Porque es un patrón de diseño de software probado y se sabe que funciona. Con MVC la
aplicación se puede desarrollar rápidamente, de forma modular y mantenible. Separar las funciones de la aplicación
en modelos, vistas y controladores hace que la aplicación sea muy ligera. Estas características nuevas se añaden
fácilmente y las antiguas toman automáticamente una forma nueva.

El diseño modular permite a los diseñadores y a los desarrolladores trabajar conjuntamente, así como realizar
rápidamente el prototipado. Esta separación también permite hacer cambios en una parte de la aplicación sin que las
demás se vean afectadas.

Aunque lleva algún tiempo acostumbrarse a construir aplicaciones así, estamos seguros de que, una vez construyas
tu primera aplicación con CakePHP, no querrás volver a hacerlo de otra forma.

2 (#Principios-básicos-de-CakePHP-892) Principios básicos de CakePHP

4 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

El framework CakePHP proporciona una base robusta para tu aplicación. Puede manejar cualquier aspecto, desde la
solicitud inicial del usuario hasta el renderizado final de la página web. Además, como el framework sigue los
principios MVC, puedes fácilmente personalizar y extender muchos aspectos de tu aplicación.

El framework también proporciona una estructura de organización básica, desde los nombres de los archivos hasta
los de las tablas de la base de datos, manteniendo toda tu aplicación consistente y lógica. Este aspecto es simple pero
poderoso. Sigue las convenciones y siempre sabrás exactamente dónde están las cosas y cómo están organizadas.

2.1 (#Estructura-de-CakePHP-893) Estructura de CakePHP

CakePHP incluye las clases Controlador [Controller], Modelo [Model] y Vista [View], pero también incluye otras clases y
objetos que hacen que el desarrollo en MVC sea un poco más rápido y agradable. Los Componentes [Components],
Comportamientos [Behaviors], y Ayudantes [Helpers] son clases que proporcionan extensibilidad y reusabilidad;
agregan rápidamente funcionalidad a las clases base MVC de las aplicaciones. Como de momento nos vamos a
mantener en este nivel de dificultad, ve preparando los detalles acerca de cómo usar estas herramientas.

2.1.1 (#Extensiones-de-los-Controladores-Componentes-894) Extensiones de los Controladores ("Componentes")

Un componente es una clase que ayuda a la lógica de un controlador. Si tienes alguna lógica y la quieres compartir
entre varios controladores (o aplicaciones), un componente suele ser una buena elección. A modo de ejemplo, la
clase del núcleo EmailComponent hace que la creación y el envío de mensajes de correo electrónico sea tan sencillo
como coser y cantar. En lugar de escribir lógica en el método de un controlador, puedes empaquetarla en un
componente para poder compartirla.

Los Controladores también están equipados con callbacks. Puedes utilizar estos callbacks si necesitas insertar alguna
lógica en las operaciones del núcleo de CakePHP. Los Callbacks disponibles incluyen:

beforeFilter(), se ejecuta antes que cualquier otra acción del controlador


beforeRender(), se ejecuta después de la lógica del controlador, pero antes de que la vista se renderice
afterFilter(), se ejecuta después de toda la lógica del controlador, incluido el renderizado de la vista. Puede que
no haya ninguna diferencia entre afterRender() y afterFilter(), a menos que hayas llamado manualmente a
render() en el controlador y hayas incluido alguna lógica después de esa llamada.

2.1.2 (#Extensiones-de-las-Vistas-895) Extensiones de las Vistas

Un ayudante [Helper] es una clase que ayuda a la lógica de una vista. Del mismo modo que varios controladores
utilizan un componente, los ayudantes [helpers] hacen que varias vistas accedan y compartan lógica presentacional.
Con uno de los ayudantes del núcleo, el AjaxHelper, el manejo de las peticiones Ajax en las vistas es mucho más
fácil.

La mayoría de las aplicaciones repiten piezas de código en sus vistas. CakePHP facilita la reutilización de este código
con diseños [layouts] y elementos [elements]. Por defecto, toda vista renderizada por un controlador se coloca en un
diseño [layout]; los elementos entran en juego cuando hay que reutilizar estos fragmentos pequeños de contenido.

2.1.3 (#Extensiones-de-los-Modelos-896) Extensiones de los Modelos

Del mismo modo, los Comportamientos [Behaviors] son formas de añadir funcionalidad común entre los modelos. Por
ejemplo, si almacena datos de los usuarios en una estructura de árbol, puede especificar que su modelo de usuario
se comporte como un árbol, y obtener libre funcionalidad para eliminar, añadir, y mover nodos en la estructura de
árbol subyacente.

Los modelos también cuentan con el apoyo de otra clase llamada DataSource (Origen de datos). Los DataSources son
una abstracción que permite a los modelos manipular diferentes tipos de datos en forma consistente. Si bien la
principal fuente de datos en una aplicación CakePHP es a menudo una base de datos, puede escribir DataSources
adicionales que le permitan a sus modelos representar canales RSS, archivos CSV, entradas LDAP, o eventos iCal. Los
DataSources le permiten asociar registros de diferentes fuentes: en lugar de limitarse sólo a uniones [joins] SQL, los
DataSources le permiten decirle a su modelo LDAP que está asociado a muchos eventos iCal.

Así como los controladores, los modelos también incluyen callbacks:

beforeFind()
afterFind()
beforeValidate()
beforeSave()
afterSave()
beforeDelete()

5 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

afterDelete()

Los nombres de estos métodos deben ser lo suficientemente descriptivos para que sepa lo que hacen. Asegúrese de
obtener los detalles en el capítulo acerca de los modelos.

2.1.4 (#Extensiones-de-la-Aplicación-897) Extensiones de la Aplicación

Tanto los controladores como los ayudantes [helpers] y modelos tienen una clase padre que puede usarse para
definir cambios a nivel global de la aplicación. AppController (localizado en /app/app_controller.php), AppHelper
(localizado en /app/app_helper.php) y AppModel (localizado en /app/app_model.php) son magníficos lugares donde
colocar métodos que desee compartir entre todos los controladores, ayudantes [helpers] o modelos.

Las rutas juegan un rol en las peticiones hechas a CakePHP. Las definiciones de rutas le dicen a CakePHP cómo
mapear URLs a acciones de controladores. El comportamiento por defecto asume que la URL "/controller/action
/var1/var2/" mapea a Controller::action($var1, $var2), pero puede usar rutas para personalizar URLs y la forma en
que éstas son interpretadas por su aplicación.

Algunas características en una aplicación merecen ser empaquetadas como un todo. Un plugin es un paquete de
modelos, controladores y vistas que cumplen un propósito específico que puede abarcar múltiples aplicaciones. Un
sistema de administración de usuarios o un blog simplificado pueden ser buenos ejemplos para plugins de CakePHP.

2.2 (#Una-petición-típica-de-CakePHP-898) Una petición típica de CakePHP

Hemos cubierto los ingredientes básicos de CakePHP, así que echemos un vistazo a cómo los objetos trabajan juntos
para completar una petición básica. Continuando con nuestro ejemplo de petición original, imaginemos que nuestro
amigo Ricardo acaba de hacer clic en el enlace "¡Comprar un pastel personalizado ahora!" en una página de
bienvenida de una aplicación CakePHP.

Figura 2. Petición típica de Cake.

Negro = elemento requerido, Gris = elemento opcional, Azul = callback

Ricardo hace clic en el enlace apuntando a http://www.ejemplo.com/tortas/comprar, y su navegador hace una


petición a su servidor Web.
El enrutador analiza la URL para extraer los parámetros para esta petición: el controlador, la acción, y cualquier
otro argumento(s) que pueda afectar a la lógica de negocio durante esta petición.
Usando las rutas, una petición URL es mapeada a una acción de controlador (un método en una clase de
controlador específica). En este caso, es el método comprar() del controlador PastelesController. El callback
beforeFilter() del controlador es llamado antes de que cualquier acción lógica del controlador sea ejecutada.

6 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

El controlador puede usar modelos para ganar acceso a los datos de la aplicación. En este ejemplo, el
controlador usa un modelo para obtener información de la base de datos de las últimas compras de Ricardo.
Cualquier callback de modelo, comportamiento [behavior], y orígenes de datos [DataSources] aplicables pueden
activarse durante esta operación. Mientras que el uso del modelo no es requerido, todos los controladores de
CakePHP inicialmente requieren al menos un modelo, salvo que el desarrollador indique lo contrario.
Después que el modelo ha obtenido toda la información, ésta es devuelta al controlador. Pueden activarse
callbacks del modelo.
El controlador puede usar componentes para refinar aun más los datos o realizar otras operaciones
(manipulación de sesiones, autenticación, o envíos de email, por ejemplo).
Una vez que el controlador ha usado modelos y componentes para preparar suficientemente la información,
ésta es entregada a la vista usando el método set() del controlador. Los callbacks de controlador pueden ser
aplicados antes de que la información sea enviada. La lógica de vista es ejecutada, la cual puede incluir el uso
de elementos y/o ayudantes [helpers]. Por defecto, la vista es creada dentro del diseño [layout].
Callbacks del controlador adicionales (como afterFilter) pueden ser aplicados. El código completo creado por la
vista es enviado al navegador de Ricardo.

2.3 (#Estructura-de-archivos-de-CakePHP-899) Estructura de archivos de CakePHP

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/899)


Comparar con el texto original (/es/compare/899/Estructura-de-archivos-de-CakePHP)

Mas info sobre traduciones (/es/view/818)

Tras descargar y extraer CakePHP, estos serán los ficheros y carpetas que deberías ver:

app
cake
vendors
.htaccess
index.php
README

Observarás 3 carpetas principales:

La carpeta app será donde haremos nuestra magia: es donde se ubicarán los ficheros de tu aplicación.
La carpeta cake es donde nosotros hemos hecho nuestra magia. Comprométete a no modificar los ficheros de
esta carpeta. No podremos ayudarte si has modificado el núcleo.
Finalmente, la carpeta vendors es donde ubicarás las librerías PHP de terceros que necesites usar con tus
aplicaciones en CakePHP.

# (#La-Carpeta-App-900) La Carpeta App

La carpeta app de CakePHP es donde realizarás la mayor parte del desarrollo de tu aplicación. Veámos un poco más de
cerca las carpetas dentro de app.

Contiene los (pocos) archivos de configuración que usa CakePHP. Detalles de conexión a bases de datos,
config
arranque (bootstrapping ), archivos de configuración del núcleo y demás deberían ser almacenados aquí.
controllers Contiene los controladores de tu aplicación y sus componentes.
locale Almacena archivos de cadenas de texto para la internacionalización.
models Contiene los modelos de tu aplicación, comportamientos (behaviors ) y orígenes de datos (datasources ).
plugins Contiene los paquetes de plugins.

Aquí es donde CakePHP almacena datos temporales. La información que realmente se almacena depende
de cómo hayas configurado CakePHP, pero normalmente esta carpeta es usada para almacenar
descripciones de modelos, registros (logs ) y algunas veces información de sesiones.
tmp
Asegúrate de que esta carpeta existe y tiene permisos de escritura, ya que de lo contrario el rendimiento
de tu aplicación se verá muy afectado. En modo debug CakePHP te avisará si este no es el caso.

Cualesquiera clases o librerías de terceros deberían ser ubicadas aquí. Hacerlo así hace que sea más fácil
de acceder a ellas usando la función App::Import('vendor','nombre'). Los observadores meticulosos
vendors notarán que esto parece redundante, ya que también existe una carpeta vendors en el nivel superior de
nuestra estructura de directorios. Veremos las diferencias entre las dos cuando discutamos acerca de la

7 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

administración de múltiples aplicaciones y configuraciones de sistemas más complejos.


Los archivos de presentación son ubicados aquí: elementos (elements ), páginas de error, ayudantes
views
(helpers ), layouts y archivos de vistas.
En una configuración de producción, esta carpeta debería servir como la raíz del sitio (document root)
webroot para tu aplicación. Las carpetas aquí también sirven como lugares de almacenamiento para hojas de
estilo en cascada (CSS stylesheets ), imágenes y archivos JavaScript.

2.4 (#Convenciones-de-CakePHP-901) Convenciones de CakePHP

Somos grandes fanáticos de convención sobre configuración. Aun cuando toma un poco de tiempo aprender las
convenciones de CakePHP, usted ahorrará tiempo en la marcha: siguiendo las convenciones, usted obtiene libre
funcionalidad, y también se libera de la pesadilla del mantenimiento del seguimiento de los archivos de
configuración. Las convenciones también hacen un sistema de desarrollo muy uniforme, permitiendo a otros
desarrolladores ayudar más fácilmente.

Las convenciones de CakePHP han sido destiladas de años de experiencia de desarrollo web y mejores prácticas.
Mientras que le sugerimos el uso de estas convenciones durante el desarrollo con CakePHP, deberíamos mencionar
que muchos de estos postulados pueden ser anulados, esto es especialmente útil cuando se trabaja con sistemas
heredados.

2.4.1 (#Convenciones-de-los-nombres-de-archivos-y-clases-902) Convenciones de los nombres de archivos y clases

En general, los nombres de archivo llevan el símbolo underscore "_", mientras que los nombres de las clases usan
CamelCase. La clase MyNiftyClass puede ser encontrada en el archivo my_nifty_class.php, por ejemplo.

Sin embargo, el nombre de la clase que contiene un archivo puede no necesariamente ser encontrada en el nombre de
archivo. La clase EmailComponent es encontrada en un archivo llamado email.php, y la clase HtmlHelper es
encontrada en un archivo llamado html.php.

2.4.2 (#Convenciones-de-Modelo-y-de-la-Base-de-datos-903) Convenciones de Modelo y de la Base de datos

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/903)


Comparar con el texto original (/es/compare/903/Convenciones-de-Modelo-y-de-la-Base-de-datos)

Mas info sobre traduciones (/es/view/818)

Los nombres de las clases de modelos están en singular y en formato CamelCase. Persona, PersonaGrande, y
PersonaMuyGrande son todos ejemplos de nombres de modelos convencionales.

Los nombres de las tablas correspondientes a modelos de CakePHP están en plural y usando guión bajo. Las tablas
subyacentes para los modelos arriba mencionados serían: personas, personas_grandes, y personas_muy_grandes
respectivamente.

Puedes utilizar la librería de utilidades "Inflector" para verificar las palabras singulares/plurales. Consulta la
documentación de Inflector (/es/view/491/Inflector) para más información.

Los nombres de los campos con dos o más palabras se definen con guiones bajos: nombre_y_apellidos.

El nombre por defecto de las claves foráneas en relaciones hasMany, belongsTo o hasOne, es el nombre de la tabla
relacionada (en singular) seguido de _id. Así, si Panadero hasMany Tarta, la tabla tartas referenciará la tabla
panaderos mediante la clave foránea panadero_id. Para una tabla compuesta por varias palabras como
tipos_categorias, la clave foránea sería tipo_categoria_id.

El nombre de las tablas de unión entre modelos, usadas en relaciones hasAndBelongToMany (HABTM), debería estar
formado por el nombre de las tablas que une puestos en orden alfabético (cebras_manzanas en vez de
manzanas_cebras).

Todas las tablas con las que interaccionan los modelos de CakePHP (con excepción de las de unión de tablas)
necesitan una clave primaria simple que identifique inequívocamente cada fila. Si deseas modelar una tabla que no
tiene una clave primaria de un sólo campo, como por ejemplo las filas de una tabla de unión posts_tags, la
convención de CakePHP dicta que se añada una clave primaria de un solo campo a la tabla.

CakePHP no soporta claves primarias compuestas. Si deseas manipular directamente los datos de tu tabla de unión,
usa llamadas directas a query (http://book.cakephp.org/es/view/456/query) o añade una clave primaria para que actue

8 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

como un modelo normal. Por ejemplo:

CREATE TABLE posts_tags (


id INT(10) NOT NULL AUTO_INCREMENT,
post_id INT(10) NOT NULL,
tag_id INT(10) NOT NULL,
PRIMARY KEY(id)
);

En vez de utilizar una clave autoincremental como clave primaria, puedes utilizar char(36). De este modo CakePHP
utilizará un uuid(String::uuid) único de 36 caracteres siempre que grabes un nuevo registro utilizando el método
Model::save.

2.4.3 (#Convenciones-de-Controladores-904) Convenciones de Controladores

Los nombres de las clases de los controladores son en plural, con formato CamelCased, y Terminan en Controller.
PersonasController y UltimosArticulosController son ejemplos de nombres convencionales de controladores.

El primer método que escribas para un controlador debe de ser el método index(). Cuando la petición especifica un
controlador pero no una acción, el comportamiento por defecto de CakePHP es ejecutar el método index() de dicho
controlador. Por ejemplo, una petición de http://www.example.com/apples/ se corresponde con la llama al método
index() del controlador ApplesController, mientras que http://www.example.com/apples/view se corresponde con
una llamada al método view() del controlador ApplesController.

También puedes cambiar la visibilidad de los métodos de los controladores en CakePHP anteponiendo al nombre del
método guiones bajos. Si un método de un controllador comienza por un guión bajo, el método no será accesible
diretamente desde la web, sino que estará disponible sólo para uso interno. Por ejemplo:

Plain Text View (#)


1. <?php
2. class NoticiasController extends AppController {
3. function ultimas() {
4. $this->_buscaNuevosArticulos();
5. }
6. function _buscaNuevosArticulos() {
7. //Lógica para encontrar los nuevos articulos.
8. }
9. }
10. ?>

Mientras que la página http://www.example.com/noticias/ultimas/ está accesible de manera normal, si alguien


intenta acceder a la página http://www.example.com/noticias/_buscaNuevosArticulos/ obtendrá un error porque el
nombre del método está precedido por un guión bajo.

2.4.3.1 (#Consideraciones-de-URL-para-nombres-de-controlador-905) Consideraciones de URL para nombres de controladores

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/905)


Comparar con el texto original (/es/compare/905/Consideraciones-de-URL-para-nombres-de-controlador)

Mas info sobre traduciones (/es/view/818)

Como se puede ver, los controladores con un nombre simple (de una sola palabra) pueden ser fácilmente mapeados a
una url en minúsculas. Por ejemplo, ApplesController (que se define en el archivo 'apples_controller.php') y accedido
desde http://example.com/apples.

Por otro lado múltiples combinaciones de palabras pueden ser transformadas automáticamente en un mismo nombre
de controlador:

/redApples
/RedApples
/Red_apples
/red_apples

9 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Todas resuelven la acción index de controlador RedApples. sin embargo, la convención es que las urls sean en
minúsculas y separadas con guión bajo, por lo tanto /red_apples/go_pick es la forma correcta de acceder a la acción.
RedApplesController::go_pick.

Para mas información sobre CakePHP URLs y sus parametros, ver Configuración de Rutas (/es/view/46/Routes-
Configuration) .

2.4.4 (#Convenciones-de-Vistas-906) Convenciones de Vistas

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/906)


Comparar con el texto original (/es/compare/906/Convenciones-de-Vistas)

Mas info sobre traduciones (/es/view/818)

Los archivos de plantillas de Vistas (Views) deben ser nombradas después de las funciones de los controladores con
guión bajo "_". La funcion getReady() del controlador PeopleController se visualizara con la plantilla de vista en
/app/views/people/get_ready.ctp por ejemplo.

El patrón básico es: /app/views/controller/underscored_function_name.ctp

Al nombrar las piezas de su aplicación utilizando las convenciones de CakePHP, usted adquiere funcionalidad sin
mucho mantenimiento de la configuración. Aquí encontramos un ejemplo final de las convenciones

Tabla de Base de Datos: ʻpeopleʼ


Clase de Modelo: ʻPersonʼ, encontrada en /app/models/person.php
Clase de Controlador: ʻPeopleControllerʼ, encontrada en /app/controllers/people_controller.php
Plantilla de Vista, encontrada en /app/views/people/index.ctp

Usando estas convenciones, CakePHP entiende que la peticion http://example.com/people/ apunta a la llamada de
funcion index() en el controlador , PeopleController, donde el modelo Person esta disponible automaticamente (y
apunta automaticamente a la tabla ʻpeopleʼ en la base de datos), y se renderiza en el archivo. Ninguna de estas
relaciones han sido configuradas por otra razon que crear clases y archivos que usted necesita crear.

Ahora que usted ya se ha involucrado con los fundamentos de CakePHP, puede revisar el tutorial para realizar un Blog
en CakePHP, que se encuentra al final de este manual.

3 (#Desarrollando-con-CakePHP-907) Desarrollando con CakePHP

Y ahora, a cocinar.

3.1 (#Requerimientos-908) Requerimientos

Servidor HTTP. Por ejemplo: Apache. Preferiblemente con mod_rewrite, pero no requerido.
PHP 4.3.2 o superior. Si, CakePHP funciona genial en PHP 4 y 5.

Técnicamente no se requiere un motor de base de datos, pero nos imaginamos que la mayoría de las aplicaciones
usarán uno. CakePHP soporta una gran variedad de motores de almacenamiento:

MySQL (4 o superior)
PostgreSQL
Firebird DB2
Microsoft SQL Server
Oracle
SQLite
ODBC
ADOdb

3.2 (#Preparándose-para-Instalar-909) Preparándose para Instalar

CakePHP es rápido y fácil de instalar.Los requisitos mínimos son un servidor web y una copia de Cake, ¡solo eso!
Aunque este manual se enfoca primariamente en la configuración sobre Apache (por que es el usado comúnmente),
Tu puedes configurar Cake para correr sobre la mayoría de servidores web, tales como, LightHTTPD o bien Microsoft
IIS. Preparar la instalación consta de los siguientes pasos:

Descargue CakePHP

10 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Configure su servidor para manejar php si es necesario


Chequee los permisos de los archivos

3.2.1 (#Obteniendo-CakePHP-910) Obteniendo CakePHP

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/910)


Comparar con el texto original (/es/compare/910/Obteniendo-CakePHP)

Mas info sobre traduciones (/es/view/818)

Hay dos principales maneras de obtener una copia limpia de CakePHP. Puedes descargar una copia comprimida
(zip/tar.gz/tar.bz2) de la página web principal, o puedes obtener el código desde el repositorio git.

Para descargar la última release principal de CakePHP, dirígete a la página web http://www.cakephp.org
(http://www.cakephp.org) y haz clic en el enlace “Download Now”.

Todas las releases actuales están alojadas en CakeForge. Este site también contiene enlaces a muchos otros proyectos
en CakePHP, incluyendo plugins y aplicaciones para CakePHP. Las releases de CakePHP estásn disponibles en
http://cakeforge.org/projects/cakephp (http://cakeforge.org/projects/cakephp) .

Se crean nightly builds alternativas que incluyen parches y mejoras al minuto (bueno, al día). Estas pueden ser
accedidas desde la página principal de descargas aquí: http://cakephp.org/downloads/index/nightly
(http://cakephp.org/downloads/index/nightly) . Para actualizaciones realmente al minuto, puedes obtener el código
directamente de la rama de desarrollo del repositorio git aquí: http://code.cakephp.org/source (http://code.cakephp.org
/source) .

3.2.2 (#Permisos-911) Permisos

CakePHP usa el directorio /app/tmp para diferentes operaciones, como almacenar descripciones de los modelos,
vistas en cache, información de sesiones, entre otros.

Por ello, asegúrate que el directorio /app/tmp de tu instalación de Cake tenga permisos de escritura por el usuario
del servidor web

3.3 (#Instalación-912) Instalación

Instalar CakePHP puede ser tan simple como colocar el directorio en el servidor, o tan complejo y flexible como
necesites. Esta sección cubrirá los tres tipos principales de instalación para CakePHP: desarrollo, producción y
avanzado

Desarrollo: fácil para iniciar, los URL de la aplicación incluyen el nombre del directorio, y es menos seguro.
Producción: Requiere la capacidad de configurar el servidor web para definir el "document root", muy seguro.
Avanzado: Con cierta configuración, permite ubicar los directorios clave de CakePHP en diferentes partes del
sistema de archivos, para compartir una misma instalación de CakePHP para varias aplicaciones.

3.3.1 (#Desarrollo-913) Desarrollo

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/913)


Comparar con el texto original (/es/compare/913/Desarrollo)

Mas info sobre traduciones (/es/view/818)

Usar una instalación de desarrollo es el método más rápido para montar Cake. Este ejemplo te ayudará a instalar una
aplicación de CakePHP y hacerla disponible en http://www.ejemplo.com/cake_1_2/. Asumimos para el fin de este
ejemplo que tu raíz de documentos está establecido a /var/www/html.

Descomprime los contenidos del archivo Cake en /var/www/html. Ahora tienes una carpeta en tu raíz de documentos
con un nombre dependiente de la versión que te has descargado (p.ej. cake_1.2.0.7962). Renombra esta carpeta a
cake_1_2. Tu configuración de desarrollo será como la siguiente en el sistema de archivos:

/var/www/html
cake_1_2
/app

11 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

/cake
/vendors
.htaccess
/index.php
README

Si tu servidor web está configurado correctamente, deberías encontrar tu aplicación de Cake accesible en
http://www.ejemplo.com/cake_1_2/.

3.3.2 (#Producción-914) Producción

Una instalación de producción es una manera más flexible de instalar Cake. Usar este método permite que un dominio
entero se comporte como una aplicación CakePHP única. Este ejemplo te ayudará a installar Cake en cualquier sitio de
tu sistema de ficheros y ponerlo disponible en http://www.ejemplo.com. Tener en cuenta que esta instalación puede
requerir los privilegios para cambiar el DocumentRoot (raíz de documentos) en servidores web Apache.

Descomprime los contenidos del archivo Cake en un directorio a tu elección. Por motivos de ejemplo, asumimos que
escoges instalar Cake en /cake_install. Tu configuración de producción se verá de la siguiente manera en el sistema
de ficheros:

/cake_install/
/app
/webroot (este directorio es el establecido con la directiva DocumentRoot)
/cake
/vendors
/.htaccess
/index.php
/README

Los desarrolladores que usan Apache deberán establecer la directiva DocumentRoot para el dominio a:

DocumentRoot /cake_install/app/webroot

Si tu servidor web está configurado correctamente, deberías encontrar tu aplicación Cake accesible en
http://www.ejemplo.com.

3.3.3 (#Instalación-Avanzada-915) Instalación Avanzada

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/915)


Comparar con el texto original (/es/compare/915/Instalación-Avanzada)

Mas info sobre traduciones (/es/view/818)

Existen situaciones en las que querrás colocar los directorios de CakePHP en lugares diferentes del sistema de
archivos. Esto puede ser debido a restricciones de un servidor compartido, o quizás simplemente deseas que algunas
de tus aplicaciones compartan las mismas librerías de Cake. Esta sección describe cómo esparcir los directorios de
CakePHP sobre un sistema de archivos.

En primer lugar, date cuenta que existen tres partes principales de una aplicación Cake:

1. Las librerías principales(core) de CakePHP, en /cake.


2. El código de tu aplicación, en /app.
3. El webroot de la aplicación, normalmente en /app/webroot.

Cada uno de estos directorios puede ser ubicado en cualquier lugar de tu sistema de archivos, a excepción del
webroot, que debe ser accesible por el servidor web. Incluso puedes mover el directorio webroot fuera de tu carpeta
app siempre que le indiques a Cake en donde lo has puesto.

Para configurar tu instalación de Cake, necesitarás hacer algunos cambios a /app/webroot/index.php. Hay tres
constantes que deberás editar: ROOT, APP_DIR, y CAKE_CORE_INCLUDE_PATH.

ROOT debe contener la ruta del directorio que contiene la carpeta app (es decir, el padre de APP_DIR).

12 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

APP_DIR debe ser establecida con el nombre(base) de tu carpeta app.


CAKE_CORE_INCLUDE_PATH debe contener la ruta al directorio que contiene las librerías de Cake.

Vamos a mostrar un ejemplo para ver cómo quedaría una instalación avanzada en la práctica. Imagina que quiero
configurar CakePHP para que funcione de esta manera:

Las Librerías de CakePHP serán ubicadas en /usr/lib/cake.


El webroot de mi aplicación será /var/www/misitio/.
El directorio app de mi aplicación estará en /home/yo/misitio.

Dada esta configuración, necesitaré editar mi webroot/index.php (el cual terminará ubicado en /var/www/misitio
/index.php, en este ejemplo) para que sea así:

Plain Text View (#)


1. // /app/webroot/index.php (codigo parcial, sin comentarios)
2. if (!defined('ROOT')) {
3. define('ROOT', DS.'home'.DS.'yo');
4. }
5. if (!defined('APP_DIR')) {
6. define ('APP_DIR', 'misitio');
7. }
8. if (!defined('CAKE_CORE_INCLUDE_PATH')) {
9. define('CAKE_CORE_INCLUDE_PATH', DS.'usr'.DS.'lib');
10. }

Es recomendable utilizar la constante DS en lugar de barras inclinadas para delimitar las rutas de los archivos. Esto
evita errores por falta de archivo como resultado de usar el delimitador equivocado, y además hace tu código más
portable.

3.3.3.1 (#Rutas-de-Clase-Adicionales-916) Rutas de Clase Adicionales

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/916)


Comparar con el texto original (/es/compare/916/Rutas-de-Clase-Adicionales)

Mas info sobre traduciones (/es/view/818)

Ocasionalmente es útil compartir clases MVC entre aplicaciones en el mismo sistema. Si quieres el mismo controler en
dos aplicaciones, puedes usar el archivo bootstrap.php de CakePHP para traer estas clases adicionales a la escena.

En el archivo bootstrap.php, define algunas variables especiales para que CakePHP sepa otros lugares en donde
buscar clases MVC:

Plain Text View (#)


1. $viewPaths = array();
2. $controllerPaths = array();
3. $modelPaths = array();
4. $helperPaths = array();
5. $componentPaths = array();
6. $behaviorPaths = array();
7. $pluginPaths = array();
8. $vendorPaths = array();
9. $localePaths = array();
10. $shellPaths = array();

Cada una de estas variables especiales pude ser establecida a un array de rutas absolutas en el sistema de archivos
donde las clases adicionales pueden ser encontradas cuando se solicite. Asegúrate que cada ruta contenga una barra
inclinada (o preferiblemente la constante DS) al final.

3.3.4 (#Apache-y-mod_rewrite-y-htaccess-917) Apache y mod_rewrite (y .htaccess)

A pesar de que CakePHP está hecho para funcionar con mod_rewrite sin tocar nada, y normalmente así es, hemos

13 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

notado que algunos usuarios tienen dificultades para lograr que todo funcione correctamente en sus sistemas.

Aquí hay unas cuantas cosas que puedes probar para conseguir que funcione correctamente. Primero mira en tu
httpd.conf (asegúrate de estar editando el httpd.conf del sistema y que no es httpd.conf específico de un usuario o
del site).

1. Asegúrate que la reescritura .htaccess esté permitida y que AllowOverride esté establecido a All para el
DocumentRoot adecuado. Deberías ver algo similar a:

Plain Text View (#)


1. #
2. # Cada directorio al que tiene acceso Apache puede ser configurado en
3. # función de qué servicios y características están permitidas y/o
4. # desactivadas en dicho directorio (y sus subdirectorios).
5. #
6. # Primero, configuramos "por defecto" para que sea un conjunto de
7. # características muy restrivo.
8. #
9. <Directory />
10. Options FollowSymLinks
11. AllowOverride All
12. # Order deny,allow
13. # Deny from all
14. </Directory>

2. Asegúrate de estar cargando el módulo mod_rewrite correctamente. Debes ver algo como:

Plain Text View (#)


1. LoadModule rewrite_module libexec/apache2/mod_rewrite.so

En muchos sistemas esto estará comentado (comenzando la línea con #) por defecto, así que sólo tendrás que
quitar los símbolos # del principio.

Tras realizar los cambios reinicia Apache para estar seguro de que las opciones de configuración están activas.

Asegúrate de que tus ficheros .htaccess están en los directorios correctos. Esto puede pasar durante la copia
porque algunos sistemas operativos consideran los archivos que comienzan por '.' como ocultos y por lo tanto
no los copian.

3. Asegúrate de que tu copia de CakePHP es de las sección de descargas de nuestro site o nuestro repositorio
GIT, y que ha sido desempaquetado correctamente verificando que existen los ficheros .htaccess:

En el directorio raíz de Cake (necesita ser copiado al directorio, esto redirige todo a tu aplicación de Cake):

Plain Text View (#)


1. <IfModule mod_rewrite.c>
2. RewriteEngine on
3. RewriteRule ^$ app/webroot/ [L]
4. RewriteRule (.*) app/webroot/$1 [L]
5. </IfModule>

En el directorio app de Cake (será copiado por bake):

Plain Text View (#)


1. <IfModule mod_rewrite.c>
2. RewriteEngine on
3. RewriteRule ^$ webroot/ [L]
4. RewriteRule (.*) webroot/$1 [L]
5. </IfModule>

En el directorio webroot de Cake (será copiado a tu webroot de la aplicación por bake):

Plain Text View (#)

14 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <IfModule mod_rewrite.c>
2. RewriteEngine On
3. RewriteCond %{REQUEST_FILENAME} !-d
4. RewriteCond %{REQUEST_FILENAME} !-f
5. RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
6. </IfModule>

En muchos servicios de hosting (GoDaddy, 1and1), tu servidor web está realmente siendo servido desde un
directorio de usuario que ya utiliza mod_rewrite. Si estás instalando CakePHP en un directorio de usuario
(http://ejemplo.com/~nombreusuario/cakephp), o en cualquier otra estructura que ya utilice mod_rewrite
necesitarás añadir sentencias RewriteBase a los archivos .htaccess que utiliza CakePHP (/.htaccess,
/app/.htaccess, /app/webroot/.htaccess)

Esto puede ser añadido a la misma sección con la directiva RewriteEngine, así, por ejmplo, tu archivo .htaccess
en el webroot devería ser así:

Plain Text View (#)


1. <IfModule mod_rewrite.c>
2. RewriteEngine On
3. RewriteBase /
4. RewriteCond %{REQUEST_FILENAME} !-d
5. RewriteCond %{REQUEST_FILENAME} !-f
6. RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
7. </IfModule>

Los detalles de esos cambios dependen de tu configuración, y pueden incluir cosas adicionales que no están
relacionadas con Cake. Consulta la documentación online de Apache para más información.

3.3.5 (#Lighttpd-y-mod_magnet-918) Lighttpd y mod_magnet

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/918)


Comparar con el texto original (/es/compare/918/Lighttpd-y-mod_magnet)

Mas info sobre traduciones (/es/view/818)

Aunque Lighttpd cuenta con un módulo de reescritura, no es equivalente al mod_rewrite de Apache. Las
funcinalidades completas de mod_rewrite se reparten entre el mod_rewrite de Lighttp, el mod_magnet y el mod_proxy.

Sin embargo, CakePHP, mayoritariamente necesita mod_magnet para redirigir las solicitudes a fin de trabajar con
bastantes URLs

Para utilizar bastantes URLs con CakePHP y Lighttp, sustituye este lua script en /etc/lighttpd/cake.

Plain Text View (#)

15 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. -- pequeña funcion helper


2. function file_exists(path)
3. local attr = lighty.stat(path)
4. if (attr) then
5. return true
6. else
7. return false
8. end
9. end
10. function removePrefix(str, prefix)
11. return str:sub(1,#prefix+1) == prefix.."/" and str:sub(#prefix+2)
12. end
13. -- prefijo sin la barra
14. local prefix = ''
15. -- la magia ;)
16. if (not file_exists(lighty.env["physical.path"])) then
17. -- fichero aún desaparecido, pasarlo al fastcgi Backend
18. request_uri = removePrefix(lighty.env["uri.path"], prefix)
19. if request_uri then
20. lighty.env["uri.path"] = prefix .. "/index.php"
21. local uriquery = lighty.env["uri.query"] or ""
22. lighty.env["uri.query"] = uriquery .. (uriquery ~= "" and "&" or "") .. "url=" .. request_uri
23. lighty.env["physical.rel-path"] = lighty.env["uri.path"]
24. lighty.env["request.orig-uri"] = lighty.env["request.uri"]
25. lighty.env["physical.path"] = lighty.env["physical.doc-root"] .. lighty.env["physical.rel-pat
26. end
27. end
28. -- fallthrough pondrá de nuevo la solucititud en el bucle lighty
29. -- eso significa que tenemos la manipulación 304 de forma gratuita. ;)

If you run your CakePHP installation from a subdirectory, you must set prefix = 'subdirectory_name' in the above
script.

Then tell Lighttpd about your vhost:

$HTTP["host"] =~ "example.com" {
server.error-handler-404 = "/index.php"

magnet.attract-physical-path-to = ( "/etc/lighttpd/cake.lua" )

server.document-root = "/var/www/cake-1.2/app/webroot/"

# además piensa como coger los ficheros vim tmp fuera


url.access-deny = (
"~", ".inc", ".sh", "sql", ".sql", ".tpl.php",
".xtmpl", "Entries", "Repository", "Root",
".ctp", "empty"
)
}

3.3.6 (#Pretty-URLs-en-nginx-919) Pretty URLs en nginx

nginx es un servidor popular que, del mismo modo que Lighttpd, consume menos recursos del sistema. Su
inconveniente es que no utiliza ficheros .htaccess como Apache y Lighttpd, por lo que es necesario crear esas
reescrituras de URLs en la configuración de site-available. Dependiendo de tu configuración, necesitarás modificar
esto, pero como mínimo necesitarás que PHP se ejecute como instancia de FastCGI.

Plain Text View (#)

16 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. server {
2. listen 80;
3. server_name www.ejemplo.com;
4. rewrite ^(.*) http://ejemplo.com$1 permanent;
5. }
6. server {
7. listen 80;
8. server_name ejemplo.com;
9. access_log /var/www/ejemplo.com/log/access.log;
10. error_log /var/www/ejemplo.com/log/error.log;
11. location / {
12. root /var/www/ejemplo.com/public/app/webroot/;
13. index index.php index.html index.htm;
14. if (-f $request_filename) {
15. break;
16. }
17. if (-d $request_filename) {
18. break;
19. }
20. rewrite ^(.+)$ /index.php?q=$1 last;
21. }
22. location ~ .*.php[345]?$ {
23. include /etc/nginx/fcgi.conf;
24. fastcgi_pass 127.0.0.1:10005;
25. fastcgi_index index.php;
26. fastcgi_param SCRIPT_FILENAME /var/www/ejemplo.com/public/app/webroot$fastcgi_script_name;
27. }
28. }

3.3.7 (#Enciéndelo-920) Enciéndelo

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/920)


Comparar con el texto original (/es/compare/920/Enciéndelo)

Mas info sobre traduciones (/es/view/818)

Muy bien, ahora veamos a CakePHP en acción. Dependiendo de la configuración que hayas usado, deberías apuntar tu
navegador a http://example.com/ o http://example.com/mi_aplicacion/. En este punto, se te presentará la vista de
bienvenida de CakePHP por omisión, y un mensaje que indica el estado de conexión con la base de datos.

¡Felicidades! Ya estás listo para crear tu primera aplicación CakePHP

3.4 (#Configuración-921) Configuración

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.

3.4.1 (#Configuración-de-Base-de-Datos-922) Configuración de Base de Datos

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/922)


Comparar con el texto original (/es/compare/922/Configuración-de-Base-de-Datos)

Mas info sobre traduciones (/es/view/818)

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:

17 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Plain Text View (#)


1. var $default = array('driver' => 'mysql',
2. 'persistent' => false,
3. 'host' => 'localhost',
4. 'login' => 'cakephpuser',
5. 'password' => 'c4k3roxx!',
6. 'database' => 'mi_proyecto',
7. '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
El nombre del controlador de base de datos que se desea utilizar. Ejemplo: mysql, postgres, sqlite,
driver
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 El texto que prefija cada nombre de tabla en la base de datos. Útil si se comparte la base de datos con
(opcional) varias aplicaciones. Dejar vacío si no se desea ninguno.
port
El puerto TCP o socket Unix a usarse para la conexión con el servidor de base de datos.
(opcional)
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 (/es/view/22/cakephp-conventions) ,
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.

3.4.2 (#Configuración-del-Core-923) Configuración del Core

La configuración de la aplicación en CakePHP se encuentra en /app/config/core.php. Este archivo es una colección


de definiciones de variables Configure y definiciones de constantes que determinan como ha de comportarse la
aplicación. Antes de sumergirse en cada una de estas directivas, necesitarás familiarizarte con Configure, la clase de
registro de configuraciones de CakePHP

3.4.3 (#La-Clase-de-Configuración-924) La Clase de Configuración

A pesar de que muy pocas cosas necesitan configuración en CakePHP, a veces es útil tener tus propias reglas de
configuración para tu aplicación. En el pasado seguramente habrías definido alguno de estos valores creando
constantes en varios archivos. Hacerlo de esa manera te obligaría a incluir estos archivos cada vez que desees
utilizarlos

La nueva clase Configure de CakePHP puede ser utilizada para guardar y recuperar valores específicos de la aplicación
o de tiempo de ejecución. Se cuidadoso, esta clase permite almacenar cualquier cosa en ella, para luego usarla en
cualquier lugar de tu código: una tentación segura para romper el patrón MVC con el cual fue diseñado CakePHP. El
objetivo principal de la clase Configure es mantener centralizadas las variables que pueden ser compartidas entre
varios objetos. Recuerda tratar de mantener la filosofía de "convención sobre configuración" y así no terminarás
rompiendo la estructura MVC que se ha diseñado

18 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Esta clase actúa como un singletón, y sus métodos pueden ser llamados desde cualquier lugar en tu aplicación, en un
contexto estático

Plain Text View (#)


1. <?php Configure::read('debug'); ?>

3.4.3.1 (#Métodos-de-la-Clase-Configure-925) Métodos de la Clase Configure

3.4.3.1.1 (#write-926) write

Plain Text View (#)


1. write(string $clave, mixed $valor)

Utiliza write() para almacenar datos en la configuración de la aplicación

Plain Text View (#)


1. Configure::write('Empresa.nombre','Pizza, Inc.');
2. Configure::write('Empresa.lema','Pizza para tu cuerpo y alma');

Nota el uso de la notación punto en el parámetro $clave. Puedes utilizar esta notación para organizar tus
configuraciones dentro de grupos lógicos

El ejemplo anterior pudo ser escrito en una sola llamada:

Plain Text View (#)


1. Configure::write(
2. 'Empresa',array('nombre'=>'Pizza, Inc.','lema'=>'Pizza para tu cuerpo y alma')
3. );

Puedes utilizar Configure::write(ʻdebugʼ, $int) para cambiar entre desarrollo y producción dentro de la ejecución de tu
programa. Esto es especialmente útil para interacciones AMF o SOAP donde la información de depuración puede
ocasionar problema de parseo.

3.4.3.1.2 (#read-927) read

read(string $clave = 'debug')

Se usa para leer datos de configuración de la aplicación. Por defecto devuelve el importante valor de "debug" (nivel de
depuración). Si se especifica una clave, los datos correspondientes son devueltos. Usando nuestros anteriores
ejemplos de write(), podemos leer esos datos de vuelta:

Plain Text View (#)


1. Configure::read('Empresa.nombre'); //devuelve: 'Pizza, Inc.'
2. Configure::read('Empresa.lema'); //devuelve: 'Pizza para tu cuerpo y alma'
3.
4. Configure::read('Empresa');
5.
6. //devuelve:
7. array('nombre' => 'Pizza, Inc.', 'lema' => 'Pizza para tu cuerpo y alma');

3.4.3.1.3 (#delete-928) delete

delete(string $clave)

Se usa para borrar información de configuración de la aplicación.

Plain Text View (#)


1. Configure::delete('Empresa.nombre');

3.4.3.1.4 (#load-929) load

19 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Plain Text View (#)


1. load(string $path)

Usa este método para cargar información de configuración desde una archivo específico.

Plain Text View (#)


1. // /app/config/mensajes.php:
2. <?php
3. $config['Empresa']['nombre'] = 'Pizza, Inc.';
4. $config['Empresa']['lema'] = 'Pizza para tu cuerpo y alma';
5. $config['Empresa']['telefono'] = '555-55-55';
6. ?>
7.
8. <?php
9. Configure::load('mensajes');
10. Configure::read('Empresa.nombre');
11. ?>

Cada clave-valor de la configuración está representado en el archivo con la variable $config. Cualquier otra variable
que aparezca en el archivo será ignorada por la función load().

3.4.3.1.5 (#version-930) version

version()

Devuelve la versión de CakePHP de la aplicación actual.

3.4.3.2 (#Variables-de-Configuración-Principales-de-CakePHP-931) Variables de Configuración Principales de CakePHP

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/931)


Comparar con el texto original (/es/compare/931/Variables-de-Configuración-Principales-de-CakePHP)

Mas info sobre traduciones (/es/view/818)

La clase Configure se usa para manejar un conjunto de variables de configuración de CakePHP. Estas variables pueden
ser encontradas en app/config/core.php. Abajo se encuentra una descripción de cada variable y cómo afecta tu
aplicación CakePHP

Variable de
Descripción
Configuración
Cambia el nivel de depuración de cake

0 = Modo produción. No produce ninguna salida.


debug
1 = Muestra los error y warnings.
2 = Muestra los error, warnings, y consultas SQL
3 = Muestra los error, warnings, consultas SQL, y volcado completo del Controller.
Descomenta esta definición si no deseas utilizar el mod_rewrite de Apache. No te olvides de
App.baseUrl
eliminar los archivos .htaccess también.
Descomenta esta definición si deseas utilizar las rutas admin de CakePHP. Asigna la variable
Routing.admin
al nombre de la ruta que te gustaría utilizar. Más adelante se explicará en detalle.
Cache.disable Cuando se asigna true, el cache se deshabilita para toda la aplicación.
Si se asigna true, habilita el cache de las vistas. También es necesario activar el cache en los
Cache.check
controllers, pero esta variable habilita la detección de dichas configuraciones.
Le indica a CakePHP qué mecanismo de almacenamiento de sesiones se debe utilizar

php = Utiliza el almacenamiento por defecto de php


Session.save
cake = Guarda los datos de sesión en /app/tmp
database = Guarda los datos en una tabla de la base de datos. Asegúrate de cargar el archivo
SQL ubicado en /app/config/sql/sessions.sql.
Session.table El nombre de la tabla (sin incluir el prefijo) que guarda los datos de la sesión.

20 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Session.database El nombre de la base de datos que guarda los datos de sesión.


Session.cookie El nombre del cookie utilizado para hacer seguimiento de las sesiones.
El tiempo base de validez de la sesión en segundos. El valor real depende de la variable
Session.timeout
Security.level
Session.start Inicia automáticamente la sesión cuando se asigna true.
Cuando se asigna false, Las sesiones de CakePHP no se asegurarán de que el "user agent" del
Session.checkAgent
usuario no cambie entre peticiones.
El nivel de seguridad de CakePHP. El tiempo de validez de la sesión definido en
'Session.timeout' se multiplica de acuerdo a lo siguiente.

Security.level Valores válidos:


'high' = x 10
'medium' = x 100
'low' = x 300
Security.salt Una palabra aleatoria usada en sumas de seguridad.
Acl.classname, Variables usadas para las Listas de Control de Acceso de CakePHP. Lee el capítulo de listas
Acl.database de control de acceso para más información.

Nota: La configuración de Cache también puede ser encontrada en el archivo core.php — Más adelante cubriremos
este tema.

La clase Configure puede ser utilizada para leer y escribir valores durante la ejecución del programa. Esto puede ser
especialmente útil si desea deshabilitar el nivel de deburacion ("debug") para una sección limita de lógica en tu
aplicación, por ejemplo

3.4.3.3 (#Constantes-de-Configuración-932) Constantes de Configuración

A pesar de que la mayoría de las opciones de configuración se manejan con la clase Configure, existen unas pocas
constantes que utiliza CakePHP durante su ejecución.

Constante Descripción
Constante de error. Usada para diferenciar entre registros de depuración y registros de error.
LOG_ERROR
Actualmente PHP solo soporta LOG_DEBUG.

3.4.4 (#La-Clase-App-933) La Clase App

Cargar clases adicionales se ha vuelto mucho más sencillo con CakePHP. En versiones anteriores existían funciones
diferentes para cargar una clase dependiendo de su tipo. Estas funciones han sido reemplazadas, ahora toda la carga
de clases debería hacerse a través de el método App::import(). Éste método te asegura que una clase ha sido cargada
sólo una vez, que las clases que extiende se hayan cargado apropiadamente, y resuelve las rutas de ubicación
automáticamente en la gran mayoría de los casos

3.4.4.1 (#Usando-App-import-934) Usando App::import()

Plain Text View (#)


1. App::import($type, $name, $parent, $search, $file, $return);

A primera vista App::import parece complejo, sin embargo, en la mayoría de los casos es suficiente con tan sólo dos
parámetros.

3.4.4.2 (#Importando-librerías-del-Core-935) Importando librerías del Core

Las librerías del Core, como Sanitize y Xml pueden ser cargadas mediante:

Plain Text View (#)


1. App::import('Core', 'Sanitize');

Lo anterior hará que la clase Sanitize esté disponible para su uso.

3.4.4.3 (#Importando-Controladores-Modelos-Ayudantes-Comport-936) Importando Controladores, Modelos, Ayudantes, Comportamientos y Componentes

21 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Todas las clases relacionadas con la aplicación pueden ser importadas con App::import(). Los siguientes ejemplos
muestran cómo hacerlo:

3.4.4.3.1 (#Cargando-Controladores-937) Cargando Controladores

App::import('Controller', 'MyController');

Llamando a App::import es equivalente a require. Es importante darse cuenta que la clase posteriormente necesita ser
inicializada.

Plain Text View (#)


1. <?php
2. // Lo mismo que require('controllers/users_controller.php');
3. App::import('Controller', 'Users');
4. // Necesitamos cargar la clase
5. $Users = new UsersController;
6. // If we want the model associations, components, etc to be loaded
7. $Users->constructClasses();
8. ?>

3.4.4.3.2 (#Cargando-Modelos-938) Cargando Modelos

App::import('Model', 'MyModel');

3.4.4.3.3 (#Cargando-Componentes-Components-939) Cargando Componentes [Components]

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/939)


Comparar con el texto original (/es/compare/939/Cargando-Componentes-Components)

Mas info sobre traduciones (/es/view/818)

App::import('Component', 'Auth');

3.4.4.3.4 (#Cargando-Comportamientos-Behaviors-940) Cargando Comportamientos [Behaviors]

App::import('Behavior', 'Tree');

3.4.4.3.5 (#Cargando-Ayudantes-Helpers-941) Cargando Ayudantes[Helpers]

App::import('Helper', 'Html');

3.4.4.4 (#Cargando-desde-Plugins-942) Cargando desde Plugins

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/942)


Comparar con el texto original (/es/compare/942/Cargando-desde-Plugins)

Mas info sobre traduciones (/es/view/818)

Cargar clases en plugins funciona casi igual que cargar clases ubicadas en el Core o en la aplicación principal, a
excepción de que debe especificarse el nombre del plugin donde reside la clase a cargar.

Plain Text View (#)


1. App::import('Modelo', 'NombrePlugin.Comentario');

3.4.4.5 (#Cargando-Archivos-de-Terceros-943) Cargando Archivos de Terceros

La función vendor() ha sido reemplazada. Los archivos de terceros deben ser cargados también mediante
App::import(). La sintaxis y los argumentos adicionales son levemente diferentes, debido a que los archivos de
terceros y su estructura pueden variar inmensamente, y no todos los archivos de terceros contienen clases.

22 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Los siguientes ejemplos ilustran cómo cargar archivos de terceros en diferentes rutas y estructuras. Los archivos de
terceros deben estar ubicados en cualquiera de los directorios vendor .

3.4.4.5.1 (#Ejemplos-de-archivos-de-terceros-944) Ejemplos de archivos de terceros

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/944)


Comparar con el texto original (/es/compare/944/Ejemplos-de-archivos-de-terceros)

Mas info sobre traduciones (/es/view/818)

Para cargar vendors/geshi.php

Plain Text View (#)


1. App::import('Vendor', 'geshi');

Para cargar vendors/flickr/flickr.php

Plain Text View (#)


1. App::import('Vendor', 'flickr/flickr');

Para cargar vendors/cierto.nombre.php

Plain Text View (#)


1. App::import('Vendor', 'CiertoNombre', array('file' => 'cierto.nombre.php'));

Para cargar vendors/services/well.named.php

Plain Text View (#)


1. App::import('Vendor', 'WellNamed', array('file' => 'services'.DS.'well.named.php'));

3.4.5 (#Configuración-de-Rutas-945) Configuración de Rutas

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/945)


Comparar con el texto original (/es/compare/945/Configuración-de-Rutas)

Mas info sobre traduciones (/es/view/818)

El enrutamanieto permite hacer una relación entre URLs y acciones de los controller. Fue añadido a CakePHP para
hacer más bonitos los URLs, más configurables, y más flexibles. Usar el mod_rewrite de Apache no es un requisito
para utilizar el enrutamiento, pero hará lucir mucho mejor tu barra de direcciones.

Las rutas en CakePHP 1.2 han sido mejoradas y pueden llegar a ser muy poderosas.

Enrutamiento por Defecto

Antes de que aprendas a configurar tus propias rutas, deberías saber que CakePHP viene configurado con un
conjunto de rutas por defecto. Estas rutas te llevarán bastante lejos en cualquier aplicación. Puedes acceder a una
acción directamente desde el URL colocando su nombre en la petición. También puedes pasar parámetros a las
acciones de tus controladores usando el URL.

Plain Text View (#)


1. Patron URL de las rutas por defecto:
2. http://example.com/controlador/accion/param1/param2/param3

El URL /articulos/ver dirige a la acciónver() action del ArticulosController, y /productos/listaCompleta dirige a la


accion to the lista_completa() de ProductosController. Si no se especifica ninguna acción en el URL, se asume que se
trata de la acción index().

La configuración inicial de enrutamiento permite pasar parámetros a tus acciones usando el URL. Una petición para
/articulos/ver/25 sería equivalente a llamar ver(25) en el ArticulosController, por ejemplo.

23 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Parámetros con Nombre

Algo novedoso en CakePHP 1.2 es la habilidad de usar parámetros con nombre (named parameters). Puedes nombrar
parámetros y enviar sus valores usando el URL. Una petición para /articulos/ver/titulo:primer+articulo
/categoria:general resultaría en una llmada a la accion view() de ArticulosController. En dicha acción, puedes
encontrar los valores del título y la categoría dentro de $this->passedArgs['titulo'] and $this->passedArgs['categoria']
respectivamente.

Algunos ejemplos que resuman las rutas por defecto puede resultar útil.

Plain Text View (#)


1.
2. URL: /monos/saltar
3. Dirige a: MonosController->saltar();
4.
5. URL: /productos
6. Dirige a: ProductosController->index();
7.
8. URL: /tareas/ver/45
9. Dirige a: TareasController->ver(45);
10.
11. URL: /donaciones/ver/recientes/2001
12. Dirige a: DonacionesController->ver('recientes', '2001');
13. URL: /contenidos/ver/capitulo:modelos/seccion:asociaciones
14. Dirige a: ContenidosController->ver();
15. $this->passedArgs['capitulo'] = 'modelos';
16. $this->passedArgs['seccion'] = 'asociaciones';

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:

Plain Text View (#)


1. Router::connect(
2. 'URL',
3. array('nombreParam' => 'valorPorDefecto'),
4. array('nombreParam' => 'expresionRegular')
5. )

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()

Plain Text View (#)

24 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. Router::connect(
2. '/pages/*',
3. array('controller' => 'pages', 'action' => 'display')
4. );

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.

Plain Text View (#)


1. Router::connect(
2. '/mujeres',
3. array('controller' => 'productos', 'action' => 'mostrar', 5)
4. );

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.

Plain Text View (#)


1. Router::connect(
2. '/:controller/:id',
3. array('action' => 'ver'),
4. array('id' => '[0-9]+')
5. );

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.

Plain Text View (#)


1. Router::connect(
2. '/:controller/:year/:month/:day',
3. array('action' => 'listar', 'day' => null),
4. array(
5. 'year' => '[12][0-9]{3}',
6. 'month' => '(0[1-9]|1[012])',
7. 'day' => '(0[1-9]|[12][0-9]|3[01])'
8. )
9. );

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

25 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

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.

Pasando parámetros a la acción

Asumiendo que tu acción fue definida como se muestra a continuación, y que desea acceder a los argumentos usando
$articuloID en lugar de $this->params['id'], simplemente agrega el tercer parámetro de Router::connect().

Plain Text View (#)


1. // some_controller.php
2. function ver($articuloID = null, $slug = null) {
3. // mi codigo aqui...
4. }
5. // routes.php
6. Router::connect(
7. // E.g. /blog/3-CakePHP_Rocks
8. '/blog/:id-:slug',
9. array('controller' => 'blog', 'action' => 'ver'),
10. array(
11. // el orden importa, puesto que esto enviará ":id" como el parámetro $articuloID de tu acción.
12. 'pass' => array('id', 'slug'),
13. 'id' => '[0-9]+'
14. )
15. )

Y ahora, gracias a las capacidades de enrutamiento inverso, puedes usar el arreglo de url que se muestra a
continuación y Cake sabrá cómo formar el URL tal como fue definido en las rutas.

Plain Text View (#)


1. // ver.ctp
2. // Esto va a devolver un lik a /blog/3-CakePHP_Rocks
3. <?php echo $html->link('CakePHP Rocks', array(
4. 'controller' => 'blog',
5. 'action' => 'view',
6. 'id' => 3,
7. 'slug' => Inflector::slug('CakePHP Rocks')
8. )) ?>

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.

Plain Text View (#)


1. 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

Plain Text View (#)


1. Router::connect('/perfiles/:controller/:action', array('prefix' => 'perfiles'));

26 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

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

Plain Text View (#)


1. 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

3.4.5.1 (#Enrutamiento-por-defecto-946) Enrutamiento por defecto

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/946)


Comparar con el texto original (/es/compare/946/Enrutamiento-por-defecto)

Mas info sobre traduciones (/es/view/818)

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.

3.4.5.2 (#Passed-arguments-1627) Passed arguments

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1627/Passed-arguments) .. Mas
info sobre traduciones (/es/view/818)

Passed arguments are additional arguments or path segments that are used when making a request. They are often
used to pass parameters to your controller methods.

http://localhost/calendars/view/recent/mark

In the above example, both recent and mark are passed arguments to CalendarsController::view(). Passed arguments
are given to your controllers in two ways. First as arguments to the action method called, and secondly they are
available in $this->params['pass'] as a numerically indexed array. When using custom routes you can force
particular parameters to go into the passed arguments as well. See passing parameters to an action (/es/view
/945/Routes-Configuration#Passing-parameters-to-action-949) for more information.

3.4.5.3 (#Parámetros-con-nombre-947) Parámetros con nombre

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/947)


Comparar con el texto original (/es/compare/947/Parámetros-con-nombre)

Mas info sobre traduciones (/es/view/818)

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:

27 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

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';

3.4.5.4 (#Defining-Routes-948) Defining Routes

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/948/Defining-Routes) .. Mas info
sobre traduciones (/es/view/818)

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:

Plain Text View (#)


1. Router::connect(
2. 'URL',
3. array('paramName' => 'defaultValue'),
4. array('paramName' => 'matchingRegex')
5. )

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().

Plain Text View (#)


1. Router::connect(
2. '/pages/*',
3. array('controller' => 'pages', 'action' => 'display')
4. );

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.

Plain Text View (#)

28 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. Router::connect(
2. '/government',
3. array('controller' => 'products', 'action' => 'display', 5)
4. );

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:

Plain Text View (#)


1. Router::connect(
2. '/cooks/:action/*', array('controller' => 'users', 'action' => 'index')
3. );

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:

Plain Text View (#)


1. Router::connectNamed(array('type'));
2. Router::connect(
3. '/cooks/:action/*', array('controller' => 'users', 'action' => 'index')
4. );

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.

Plain Text View (#)


1. Router::connect(
2. '/:controller/:id',
3. array('action' => 'view'),
4. array('id' => '[0-9]+')
5. );

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'].

One more example, and you'll be a routing pro.

Plain Text View (#)

29 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. Router::connect(
2. '/:controller/:year/:month/:day',
3. array('action' => 'index', 'day' => null),
4. array(
5. 'year' => '[12][0-9]{3}',
6. 'month' => '0[1-9]|1[012]',
7. 'day' => '0[1-9]|[12][0-9]|3[01]'
8. )
9. );

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.

3.4.5.5 (#Pasando-parámetros-a-las-acciones-949) 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().

Plain Text View (#)


1. // some_controller.php
2. function view($articleID = null, $slug = null) {
3. // some code here...
4. }
5. // routes.php
6. Router::connect(
7. // E.g. /blog/3-CakePHP_Rocks
8. '/blog/:id-:slug',
9. array('controller' => 'blog', 'action' => 'view'),
10. array(
11. // el orden es importante ya que esto va a mapear ":id" con $articleID en tu action
12. 'pass' => array('id', 'slug'),
13. 'id' => '[0-9]+'
14. )
15. );

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.

Plain Text View (#)


1. // view.ctp
2. // esto devolverá un link a /blog/3-CakePHP_Rocks
3. <?php echo $html->link('CakePHP Rocks', array(
4. 'controller' => 'blog',
5. 'action' => 'view',
6. 'id' => 3,
7. 'slug' => Inflector::slug('CakePHP Rocks')
8. )); ?>

3.4.5.6 (#Prefix-Routing-950) Prefix Routing

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

30 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Ver que ha cambiado (/es/nodes/redirect_to_revision/950)


Comparar con el texto original (/es/compare/950/Prefix-Routing)

Mas info sobre traduciones (/es/view/818)

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.

Plain Text View (#)


1. 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

Plain Text View (#)


1. Router::connect('/admin', array('controller' => 'pages', 'action' => 'index', 'admin' => true));

Puedes configurar el Router usado múltiples prefijos:

Plain Text View (#)


1. 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:

Plain Text View (#)


1. echo $html->link('Edit your profile', array('profiles' => true, 'controller' => 'users', 'action' => 'ed

Puedes ajustar múltiples rutas con prefijos usando esta metodología para crear una estructura de URL flexible para tu
aplicación.

3.4.5.7 (#Rutas-y-plugins-951) 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.

Plain Text View (#)


1. 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.

Plain Text View (#)


1. 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.

3.4.5.8 (#Extensiones-de-archivo-952) 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:

Plain Text View (#)


1. Router::parseExtensions('html', 'rss');

Esto le dirá al router que retire las extensiones de archivo coincidentes y que procese entonces el resto..

31 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Si quieres crear una url como /page/title-of-page.html podrías crear tu ruta como se explica a continuación:

Plain Text View (#)


1. Router::connect(
2. '/page/:title',
3. array('controller' => 'pages', 'action' => 'view'),
4. array(
5. 'pass' => array('title')
6. )
7. );

Para crear enlaces que se mapeen a esas rutas simplemente usamos:

Plain Text View (#)


1. $html->link('Link title', array('controller' => 'pages', 'action' => 'view', 'title' => Inflector::slug(

3.4.5.9 (#Custom-Route-classes-1634) Custom Route classes

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1634/Custom-Route-classes) ..
Mas info sobre traduciones (/es/view/818)

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.

Plain Text View (#)


1. Router::connect(
2. '/:slug',
3. array('controller' => 'posts', 'action' => 'view'),
4. array('routeClass' => 'SlugRoute')
5. );

This route would create an instance of SlugRoute and allow you to implement custom parameter handling

3.4.6 (#Inflexiones-Propias-953) Inflexiones Propias

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/953)


Comparar con el texto original (/es/compare/953/Inflexiones-Propias)

Mas info sobre traduciones (/es/view/818)

Las convenciones de nomenclatura de CakePHP pueden ser muy buenas. Nombras la tabla de base de datos
"usuarios", tu modelo "Usuario", tu controlador "UsuariosController" y todo funcionará automáticamente. La forma en
que CakePHP sabe como atar unas cosas a otras es a través de las inflexiones de palabras entre formas en singular y
plural.

Hay ocasiones, sobre todo para usuarios de habla hispana, en que encontrarás situaciones donde el inflector de
CakePHP no funcione como lo esperas. Si CakePHP no es capaz de reconocer tu Reloj o Ciudad, editar el archivo de
inflexiones propias es la manera de indicarle a CakePHP que existen otros casos especiales. Este archivo se encuentra
en /app/config/inflections.php.

En este archivo encontrarás seis variables. Cada una de ellas te permite definir a un grado muy fino el
comportamiento de inflexiones de CakePHP.

Variable de
Descripción
inflections.php
Este arreglo contienen las expresiones regulares para pluralizar los casos especiales. Las
$pluralRules
claves del arreglo son los patrones y los valores los reemplazos.

32 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Un arreglo que contiene palabras que no han de ser modificadas para obtener su plural,
$uninflectedPlural
como la palabra gente o dinero.
Un arreglo que contiene palabras y su respectivo plural. Las claves de este arreglo contienen
$irregularPlural la forma singular y los valores la forma plural. Este arreglo debe ser utilizado para colocar
palabras que no sigan las reglas definidas en $pluralRules.
$singularRules Igual que $pluralRules, solo que contiene las reglas para singularizar palabras.
Igual que $uninflectedPlural, solo que este arreglo contiene las palabras que no tienen
$uninflectedSingular
singular. Por defecto es igual que $uninflectedPlural.
$irregularSingular Igual que $irregularPlural, solo que con palabras en forma singular.

3.4.7 (#Haciendo-Bootstrap-de-CakePHP-954) Haciendo Bootstrap de CakePHP

Si tienes necesidades de configuración adicionales, usa el archivo de bootstrap de CakePHP que se encuentra en
/app/config/bootstrap.php. Este archivo es ejecutado inmediatamente después de el bootstrap propio de CakePHP.

Este archivo es ideal para un número de tareas comunes:

Definir funciones de conveniencia


Definir constantes globales
Definir rutas adicionales para modelos, controladores, vistas, plugins...

Sé cuidadoso de mantener el patron de diseño MVC cuando agregues cosas al archivo bootstrap, puede resultar
tentador colocar funciones para dar formato a texto allí para luego usarlas en controladores.

Resiste la tentación. Te lo agradecerás más adelante a ti mismo.

Podrías considerar colocar cosas en la clase AppController. Esta clase en poder de todos los controladores de la
aplicación. AppController es útil para colocar funciones que se ejecutan antes o después de eventos definidos
(callbacks), que serán usados en todos tus controladores.

3.5 (#Controladores-955) Controladores

3.5.1 (#Introducción-956) Introducción

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/956)


Comparar con el texto original (/es/compare/956/Introducción)

Mas info sobre traduciones (/es/view/818)

Un controlador (Controller) se usa para manejar la lógica de cierta sección de su aplicación. Comúnmente, los
controladores (Controllers) son usados para manejar la lógica de un solo modelo (Model). Por ejemplo, si estás
construyendo un sitio de una pastelería, podrías tener un RecetasController y un IngredientesController para manejar
las recetas y sus ingredientes. En CakePHP, los controladores se nombran según el modelo que manejan, y se ponen
siempre en plural.

El modelo Receta es manejado por el RecetasController, el modelo Producto es manejado por el ProductosController, y
así sucesivamente.

Los controladores de su aplicación son sub-clases de la clase AppController de CakePHP, que a su vez extiende la
clase principal Controller. La clase AppController puede ser definida en /app/app_controller.php y debe contener
métodos que son compartidos entre todos los controladores de su aplicación. AppController es una sub-clase de
Controller que es una clase de la biblioteca estándar de Cake.

Los controladores pueden tener cualquier cantidad de métodos a los que normalmente se les llama acciones . Las
acciones son métodos de controladores en tu aplicación web para mostrar vistas. Una acción es un único método de
un controlador. El Dispatcher de CakePHP ejecuta acciones cuando una solicitud entrante contiene en su URL el
nombre de una acción del controlador. El controlador estaría ubicado en /app/controllers/recetas_controller.php
con el siguiente contenido:

Plain Text View (#)

33 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <?php
2.
3. # /app/controllers/recetas_controller.php
4. class RecetasController extends AppController {
5. function ver($id) {
6. //la lógica de la acción va aqui...
7. }
8. function compartir($cliente_id, $receta_id) {
9. //la lógica de la acción va aqui...
10. }
11. function buscar($query) {
12. //la lógica de la acción va aqui...
13. }
14. }
15. ?>

Para que puedas usar un controlador de manera productiva en tu propia aplicación, repasaremos algunos de los
atributos y métodos provistos por los controladores de CakePHP.

3.5.2 (#The-App-Controller-957) The App Controller

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/957)


Comparar con el texto original (/es/compare/957/The-App-Controller)

Mas info sobre traduciones (/es/view/818)

Como se comentó en la introducción, la clase AppController es la clase superior a todos los controladores de tu
aplicación. AppController extiende la clase Controller incluida en la libreria base de CakePHP. Así, AppController es
definida en /app/app_controller.php como:

Plain Text View (#)


1. <?php
2. class AppController extends Controller {
3. }
4. ?>

Las propiedades y métodos creados en tu AppController estarán disponibles para todos los controladores de tu
aplicación. Es el sitio ideal para poner el código que será común a todos los controladpres de tu aplicación. Los
Componentes (los cuales veremos después) son lo más utilizado para el código que se utiliza en la mayoría (pero no
necesariamente en todos) los controladores

Cuando se aplica la herencia a los objetos, CakePHP también realiza un trabajo extra cuando existen atributos
especiales en el controlador, como una lista de componentes o ayudantes utilizados por un controlador. En estos
casos, los arrays del AppControler son combinados con los arrays de la clase hijo

CakePHP combina las siguientes variables de AppController con los controladores de tu aplicación:

$components
$helpers
$uses

Por favor, recuerda realizar las llamadas a los callbacks de AppController desde los controladores de tu aplicación
para que todo funcione correctamente:

Plain Text View (#)


1. function beforeFilter(){
2. parent::beforeFilter();
3. }

3.5.3 (#The-Pages-Controller-958) The Pages Controller

El núcleo de CakePHP viene con un controlador por defecto llamado the Pages Controller (el Controlador de Páginas)

34 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

(cake/libs/controller/pages_controller.php). La página de inicio que ves luego de la instalación, es generada


utilizando este controlador. Por ejemplo: Sí creas un archivo de vista app/views/pages/about_us.ctp puedes accesarlo
utilizando la url http://example.com/pages/about_us

Cuando "cocinas" una aplicación utilizando la consola de CakePHP el controlador de páginas es copiado a tu carpeta
app/controllers/ y puedes modificarla a tus necesidades si es necesario. O simplemente puedes copiar el archivo
page_controller.php del núcleo a tu app.

No modifiques directamente NINGUN archivo dentro de la carpeta cake para evitar problemas futuros en la
actualización del núcleo

3.5.4 (#Atributos-del-Controlador-959) Atributos del Controlador

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/959)


Comparar con el texto original (/es/compare/959/Atributos-del-Controlador)

Mas info sobre traduciones (/es/view/818)

Para ver la lista completa de atributos visite la API de CakePHP en la sección http://api.cakephp.org/class/controller
(http://api.cakephp.org/class/controller) .

3.5.4.1 (#name-960) $name

Los usuarios de PHP4 deberían empezar la definición de sus controladores con el atributo $name. Este atributo
debería ser asignado con el nombre del controlador. Usualmente este es simplemente el plural del modelo principal al
que el controlador está asociado. Esto previene algunos problemas de distinción de mayúsculas que tiene PHP4 para
los nombres de las clases.

Plain Text View (#)


1. <?php
2. # $name Ejemplo de uso del atributo $name
3. class RecetasController extends AppController {
4. var $name = 'Recetas';
5. }
6. ?>

3.5.4.2 (#components-helpers-y-uses-961) $components, $helpers y $uses

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/961)


Comparar con el texto original (/es/compare/961/components-helpers-y-uses)

Mas info sobre traduciones (/es/view/818)

Los siguientes atributos más comunmente utilizados del controlador indican a CakePHP qué ayudantes (helpers ),
componentes (components ), y modelos (models ) utilizarás en conjunción con el controlador actual. Utilizar esos
atributos hace que las clases MVC estén disponibles al controlador como variable de clase($this->ModelName, por
ejemplo).

Cada controlador tiene alguna de esas clases disponibles por defecto, así que no necesitarás configurar tu
controlador.

Los controladores tienen acceso a su modelo primario disponible por defecto. Nuestro RecipesController tendrá
disponible la clase modelo Recipe en $this->Recipe, y nuestro ProductsController también posee el modelo Product
en $this->Product.

Los ayudantes (Helpers ) Html , Form, y Session están siempre disponibles por defecto, como lo es SessionComponent.
Para aprender más sobre estas clases, no olvides leer sus respectivas secciones más adelante en este manual.

Veamos cómo decirle a un controlador de CakePHP que planeas utilizar clases MVC adicionales.

Plain Text View (#)

35 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <?php
2. class RecipesController extends AppController {
3. var $name = 'Recipes';
4. var $uses = array('Recipe', 'User');
5. var $helpers = array('Ajax');
6. var $components = array('Email');
7. }
8. ?>

Cada una de estas variables es fusionada con sus valores heredados, por lo tanto no es necesario (por ejemplo)
declarar le ayudante (helper ) Form, o cualquier cosa que es declarada en tu controlador App .

3.5.4.3 (#Atributos-Relacionados-con-la-Página-layout-y-pag-962) Atributos Relacionados con la Página: "$layout" y "$pageTitle"

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/962)


Comparar con el texto original (/es/compare/962/Atributos-Relacionados-con-la-Página-layout-y-pag)

Mas info sobre traduciones (/es/view/818)

Existen unos pocos atributos en los controladores de CakePHP que te dan control sobre cómo se colocan tus vistas
(views ) dentro del diseño (layout).

Al atributo $layout se le puede asignar el nombre de un diseño (layout) guardado en /app/views/layouts. Especificas
un diseño al igualar $layout al nombre del archivo con el diseño excluyendo la extensión .ctp. Si este atributo no ha
sido definido, CakePHP renderiza el diseño por defecto, default.ctp. Si no has definido un diseño en /app/views
/layouts/default.ctp, el diseño por defecto del núcleo de CakePHPʼs será renderizado.

Plain Text View (#)


1. <?php
2. // Usando <em>$layout</em> para definir un diseño alternativo
3. class RecipesController extends AppController {
4. function quickSave() {
5. $this->layout = 'ajax';
6. }
7. }
8. ?>

También puedes cambiar el título de la página (que está localizado en la barra en la parte superior de tu navegador)
utilizando $pageTitle. Para que esto funcione apropiadamente, tu diseño (layout) necesita incluir la variable
$title_for_layout como mínimo entre las etiquetas <title> y </title> en la cabecera del documento HTML.

Plain Text View (#)


1. <?php
2. // Usando <em>$pageTitle</em> para definir el título de la página
3. class RecipesController extends AppController {
4. function quickSave() {
5. $this->pageTitle = 'Mi título del motor de búsquedas optimizado';
6. }
7. }
8. ?>

También puedes establecer el título desde la vista (view) usando $this->pageTitle (Has de incluir la parte $this->; se
recomienda, ya que separa la lógica del diseño y el contenido). Para una página estática has de usar $this->pageTitle
en la vista si quieres un título personalizado.

Si $this->pageTitle no está establecido, se generará automáticamente un título basado en el nombre del controlador,
o el nombre del fichero de la vista en el caso de una página estática.

3.5.4.4 (#El-Atributo-de-Parámetros-params-963) El Atributo de Parámetros ("$params")

36 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Los parámetros del controlador están disponibles en $this->params en tu controlador de CakePHP. Esta variables es
usada para proporcionar acceso a la información sobre la petición actual. El uso más común de $this->params es
obtener acceso a información que ha sido entregada al controlador a través de las operaciones POST o GET.

3.5.4.4.1 (#form-964) form

$this->params['form']

Cualquier dato POST de cualquier formulario se almacena aquí, incluyendo información también hallada en $_FILES.

3.5.4.4.2 (#admin-965) admin

$this->params['admin']

Contiene el valor 1 si la acción (action ) actual fue invocada mediante enrutamiento "admin".

3.5.4.4.3 (#bare-966) bare

$this->params['bare']

Almacena un 1 si el diseño (layout) actual está vacío; 0 si no.

3.5.4.4.4 (#isAjax-967) isAjax

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/967)


Comparar con el texto original (/es/compare/967/isAjax)

Mas info sobre traduciones (/es/view/818)

$this->params['ajax']

Almacena un 1 si la petición actual es una llamada ajax; 0 si no. Esta variables sólo se establece si el componente
RequestHandler es usado en el controlador.

3.5.4.4.5 (#controller-968) controller

$this->params['controller']

Almacena el nombre del controlador actual que está sirviendo la petición. Por ejemplo, si fue pedida la URL /posts
/view/1, $this->params['controller'] será igual a "posts".

3.5.4.4.6 (#action-969) action

$this->params['action']

Almacena el nombre de la acción actual sirviendo la petición. Por ejemplo, si fue pedida la URL /posts/view/1,
entonces $this->params['action'] será igual a "view".

3.5.4.4.7 (#pass-970) pass

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/970)


Comparar con el texto original (/es/compare/970/pass)

Mas info sobre traduciones (/es/view/818)

$this->params['pass']

Almacena la cadena de consulta GET enviada con la petición actual. Por ejemplo, si fue pedida la URL /posts
/view/?var1=3&var2=4, entonces $this->params['pass'] será igual a "?var1=3&var2=4".

3.5.4.4.8 (#url-971) url

37 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

$this->params['url']

Almacena la URL actual pedida, junto con los pares clave-valor de variables get. Por ejemplo, si se llamó a la URL
/posts/view/?var1=3&var2=4, entonces $this->params['url'] debería contener:

[url] => Array


(
[url] => posts/view
[var1] => 3
[var2] => 4
)

3.5.4.4.9 (#data-972) data

$this->data

Usado para manejar datos POST enviados desde los formularios de FormHelper al controlador.

Plain Text View (#)


1. // El helper FormHelper es usado para crear un elemento de formulario:
2. $form->text('User.first_name');

El cual al ser renderizado, se ve parecido a:

<input name="data[User][first_name]" value="" type="text" />

Cuando el formulario es enviado al controlador mediante POST, los datos aparecen en this->data

Plain Text View (#)


1. // El valor first_name enviado se puede encontrar aquí:
2. $this->data['User']['first_name'];

3.5.4.4.10 (#prefix-973) prefix

$this->params['prefix']

Establecido al prefijo de enrutado. Por ejemplo, este atributo contendría la cadena "admin" durante una petición a
/admin/posts/someaction.

3.5.4.4.11 (#named-974) named

$this->params['named']

Almacena cualquier parámetro con nombre /clave:valor/ de la cadena de petición de la URL. Por ejemplo, si se pidió
la URL /posts/view/var1:3/var2:4, entonces $this->params['named'] debería contener el array:

[named] => Array


(
[var1] => 3
[var2] => 4
)

3.5.4.5 (#Otros-Atributos-975) Otros Atributos

Aunque puedes ojear todos los detalles para todos los atributos del controlador en el API, hay otros atributos del
controlador que merecen sus propias secciones en el manual.

El atributo $cacheAction ayuda en el "cacheado" (caching ) de vistas (views ), y el atributo $paginate es usado para
establecer las opciones por defecto de paginado para el controlador. Para más información sobre cómo utilizar esos
atributos, écha un vistazo a sus respectivas secciones más adelante en este manual.

3.5.4.6 (#persistModel-976) persistModel

38 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Usado para crear instancias almacenadas en caché de modelos (Models) un uso de Controlador (Controller). Cuando
se coloca en verdadero (true), todos los modelos relacionados con el controlador (Controller) se almacenan en caché.
Esto puede incrementar el desempeño en muchos casos.

3.5.5 (#Métodos-del-Controlador-977) Métodos del Controlador

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/977)


Comparar con el texto original (/es/compare/977/Métodos-del-Controlador)

Mas info sobre traduciones (/es/view/818)

Para una lista completa de los métodos del controlador y sus descripciones visita el API de CakePHP. Echa un vistazo a
http://api.cakephp.org/1.2/class_controller.html (http://api.cakephp.org/1.2/class_controller.html) .

3.5.5.1 (#Interactuando-con-Vistas-978) Interactuando con Vistas

3.5.5.1.1 (#set-979) set

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/979)


Comparar con el texto original (/es/compare/979/set)

Mas info sobre traduciones (/es/view/818)

set(string $variable, mixed $valor)

El método set() es la principal manera de enviar datos desde tu controlador a tu vista (view). Una vez que has
utilizado set(), la variable puede ser accedida en tu vista.

Plain Text View (#)


1. <?php
2.
3. // Primero pasas datos desde el controlador:
4. $this->set('color', 'azul');
5. // Despueś, en las vista, puedes utilizar el dato:
6. ?>
7.
8. Has seleccionado <?php echo $color; ?>ar la tarta.

El método set() también toma una array asociativo como primer parámetro. A menudo, esto puede ser una manera
rápida de asignar un conjunto de información a la vista.

Las claves (keys ) serán flexionadas (inflected ) antes de ser asignadas a la vista ('clave_con_subrayado' se convierte en
'claveConSubrayado', etc.):

Plain Text View (#)


1. <?php
2.
3. $data = array(
4. 'color' => 'pink',
5. 'type' => 'sugar',
6. 'base_price' => 23.95
7. );
8. // hace que $color, $type, y $basePrice
9. // estén disponibles a la vista:
10. $this->set($data);
11. ?>

3.5.5.1.2 (#render-980) render

39 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

render(string $action, string $layout, string $file)

El método render() es llamado automáticamente al final de cada acción de controlador pedida. Este método lleva a
cabo toda la lógica de la vista (usando los datos que has proporcionado con el método set()), coloca la vista (view)
dentro de su diseño (layout) y lo sirve de vuelta al usuario final.

El fichero de vista por defecto utilizado por render es determinado por convenio. Por ejemplo, si se pide la acción
search() del controlador RecipesController, será renderizado el fichero de vista en /app/views/recipes/search.ctp.

Plain Text View (#)


1. class RecipesController extends AppController {
2. function search() {
3. // Render the view in /views/recipes/search.ctp
4. $this->render();
5. }
6. ...
7. }

A pesar de que CakePHP lo llamará automáticamente (a menos que hayas establecido $this->autoRender a falso)
después de cada lógica de las acciones, puedes utilizar render para especificar un fichero de vista alternativo
indicando un nombre de acción en el controlador usando $action.

Si $action comienza por '/' se asume que es un fichero de vista o elemento relativo a la carpeta /app/views. Esto
permite el renderizado inmediato de elementos, algo muy útil en las llamadas ajax.

Plain Text View (#)


1. // Render the element in /views/elements/ajaxreturn.ctp
2. $this->render('/elements/ajaxreturn');

También puedes especificar un fichero de vista alternativo usando el tercer parámetro, $file. Cuando estés usando
$file, no olvides utilizar unas pocas de las constantes globales de CakePHP (como VIEWS).

El parámetro $layout te permite especificar el diseño en el que la vista es renderizada.

3.5.5.2 (#Control-de-Flujo-981) Control de Flujo

3.5.5.2.1 (#redirect-982) redirect

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/982)


Comparar con el texto original (/es/compare/982/redirect)

Mas info sobre traduciones (/es/view/818)

redirect(string $url, integer $status, boolean $exit)

El método de control de flujo que más frecuentemente utilizarás es redirect(). Este método toma su primer parámetro
en forma de URL relativa de CakePHP. Por ejemplo, cuando un usuario ha hecho un pedido satisfactoriamente,
probablemente desearás redirigirle a una ventana de recibo.

Plain Text View (#)


1. function realizarPedidos() {
2. // La lógina para finalizar el pedido va aquí
3. if($satisfactorio) {
4. $this->redirect(array('controller' => 'pedidos', 'action' => 'gracias'));
5. } else {
6. $this->redirect(array('controller' => 'pedidos', 'action' => 'confirmar'));
7. }
8. }

El segundo parámetro de redirect() te permite definir un código de estado HTTP que acompañe la redirección. Puede
que desees usar 301 (movido permanentemente) o 303 (mirar otro), dependiendo de la naturaleza de la redirección.

40 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

El metodo ejecutará exit() tras la redirección a menos que establezcas el tercer parámetro a false.

3.5.5.2.2 (#flash-983) flash

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/983)


Comparar con el texto original (/es/compare/983/flash)

Mas info sobre traduciones (/es/view/818)

flash(string $message, string $url, integer $pause)

Igualmente, el método flash() es usado para redirigir un usuario a una nueva página tras una operación. El método
flash() es diferente en cuanto que muestra un mensaje antes de enviar al usuario a otra URL.

El primer parámetro debería contener el mensaje a mostrar, y el segundo parámetro es una URL relativa a CakePHP.
CakePHP mostrará el mensaje en $message durante el número de segundos en $pause antes de reenviar al usuario a
otra página.

Para mensajes flash en la página, cerciónate de echarle un ojo al método setFlash() del componente
SessionComponent.

3.5.5.3 (#Retrollamadas-Callbacks-984) Retrollamadas ("Callbacks")

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/984)


Comparar con el texto original (/es/compare/984/Retrollamadas-Callbacks)

Mas info sobre traduciones (/es/view/818)

Los controladores de CakePHP vienen con retrollamas (callbacks ) empotradas que puedes usar para insertar lógica
justo antes o después de que las acciones del controlador sean llevadas a cabo.

beforeFilter()

Esta función se ejecuta antes de toda acción en el controlador. Es un lugar práctico para comprobar una sesión activa
o inspeccionar los permisos del usuario.

beforeRender()

Llamada tras la lógica de acción del controlador, pero antes de que la vista es renderizada. Este callback no es
utilizado a menudo, pero puedes necesitarlo si estás llamando a render() manualmente antes del final de una acción
dada.

afterFilter()

Llamada tras toda acción del controlador.

afterRender()

Llamada tras haber sido renderizada una acción.

CakePHP también soporta callbacks relacionados con el scaffolding .

_beforeScaffold($metodo)

$metodo es el nombre del método llamado, por ejemplo: index, edit, etc.

_afterScaffoldSave($metodo)

$metodo es el nombre del método llamado tras edit o update.

_afterScaffoldSaveError($metodo)

$metodo es el nombre del método llamado tras edit o update.

41 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

_scaffoldError($metodo)

$metodo es el nombre del método llamado, por ejemplo: index, edit, etc.

3.5.5.4 (#Otros-Métodos-Útiles-985) Otros Métodos Útiles

3.5.5.4.1 (#constructClasses-986) constructClasses

Este método carga los modelos requeridos por el controlador. El proceso de carga es realizado por CakePHP
normalmente, pero hay que tener a mano este método cuando se accede a los controladores desde una perspectiva
diferente. Si necesitas CakePHP en un script de línea de comando o algún otro uso externo, constructClasses() será
útil.

3.5.5.4.2 (#referer-987) referer

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/987)


Comparar con el texto original (/es/compare/987/referer)

Mas info sobre traduciones (/es/view/818)

Devuelve la URL remitente de la petición actual. Ver referer (http://en.wikipedia.org/wiki/Referer) en la wikipedia para
más información.

3.5.5.4.3 (#disableCache-988) disableCache

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/988)


Comparar con el texto original (/es/compare/988/disableCache)

Mas info sobre traduciones (/es/view/818)

Usado para indicarle al navegador del usuario que no guarde en caché los resultados de la petición actual. Esto es
diferente que guardar en caché una vista (view caching ), tratado en un capítulo posterior.

3.5.5.4.4 (#postConditions-989) postConditions

42 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/989)


Comparar con el texto original (/es/compare/989/postConditions)

Mas info sobre traduciones (/es/view/818)

postConditions(array $datos, mixed $operadores, string $bool, boolean $exclusivo)

Usa este método para convertir un conjunto de datos de modelo recibidor mediante POST (de inputs compatibles con
HtmlHelper) en un conjunto de condiciones de búsqueda para un modelo. Esta función ofrece un atajo rápido para la
construcción de la lógica de búqueda. Por ejemplo, un usuario administrativo puede querer buscar pedidos para
saber qué elementos necesitan ser enviados. Puedes utilizar los ayudantes FormHelper y HtmlHelper para crear un
formulario rápido basado en el modelo Pedido. Entonces, una acción de un controlador puede usar los datos
recibidos desde ese formulario para encauzar las condiciones de búsqueda:

Plain Text View (#)


1. function index() {
2. $o = $this->Pedidos->findAll($this->postConditions($this->data));
3. $this->set('pedidos', $o);
4. }

Si $this->data[ʻPedidoʼ][ʻdestinoʼ] es igual a “Old Towne Bakery” , postConditions convierte esa condición en un array
compatible para ser usado en un método Model->findAll(). En este caso, array(“pedido.destino” => “Old Towne
Bakery”).

Si deseas usar un operador SQL distinto entre términos, proporciónalos usando el segundo parámetro.

Plain Text View (#)


1. /*
2. contenidos de $this->data
3. array(
4. 'Pedido' => array(
5. 'num_items' => '4',
6. 'referrer' => 'Ye Olde'
7. )
8. )
9. */
10. //Obtengamos los pedidos que tiene como mínimo 4 elementos y contienen ‘Ye Olde’
11. $o = $this->Pedido->findAll($this->postConditions(
12. $this->data,
13. array('>=', 'LIKE')
14. ));

La clave al especificar operadores es el orden de las columnas en el array $this->data. Dado que num_items está de
primero, el operador >= es el que se le aplica.

El tercer parámetro te permite decirle a CakePHP qué operador booleano SQL usar entre condiciones de búsqueda. Una
cadena de carateres como ʻANDʼ, ʻORʼ y ʻXORʼ son valores válidos.

Finalmente, si el último parámetro se establece a true, y el parámetro $operadores es un array, los campos no
incluidos en $operadores no se incluirán en las condiciones devueltas.

3.5.5.4.5 (#paginate-990) paginate

Este método es usado para paginar resultados cargados por tus modelos. Puedes especificar tamaño de páginas,
condiciones de búsqueda del modelo y más. Mira la sección paginación (es/view/164/paginación) para más detalles
sobre cómo usar paginate.

3.5.5.4.6 (#requestAction-991) requestAction

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

43 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Ver que ha cambiado (/es/nodes/redirect_to_revision/991)


Comparar con el texto original (/es/compare/991/requestAction)

Mas info sobre traduciones (/es/view/818)

requestAction(string $url, array $opciones)

Esta función llama a una acción de un controlador de cualquier lugar y devuelve los datos de la acción. La dirección
$url pasada es una URL relativa de CakePHP (/nombrecontrolador/nombreaccion/parametros). Para pasar datos extras a
la acción del controladores receptor, añádelos al array $options.

Puedes usar requestAction() para obtener una vista completamente renderizada pasando 'return' en las opciones:
requestAction($url, array('return'));

Si se utiliza sin caché, requestAction puede llevar a un pobre rendimiento. Es ráramente apropiado usarlo en un
controlador o modelo.

Es mejor usar requestAction junto con elementos en caché, como una manera de obtener datos para un elemento
antes de renderizar. Usemos el ejemplo de poner un elemento "últimos comentarios" en el diseño (layout). Primero
necesitamos crear una función en un controlador que devolverá los datos.

Plain Text View (#)


1. // controllers/comments_controller.php
2. class CommentsController extends AppController {
3. function latest() {
4. return $this->Comment->find('all',
5. array(
6. 'order' => 'Comment.created DESC',
7. 'limit' => 10)
8. );
9. }
10. }

Si ahora creamos un elemento simple para llamar a esa función:

Plain Text View (#)


1. // views/elements/latest_comments.ctp
2. $comments = $this->requestAction('/comments/latest');
3. foreach($comments as $comment) {
4. echo $comment['Comment']['title'];
5. }

Podemos colocar esos elementos en cualquier sitio para obtener la salida usando:

Plain Text View (#)


1. echo $this->element('latest_comments');

Escrito de esta manera, siempre que el elemento sea renderizado, se realizará una petición al controlador para
obtener los datos, los datos serán procesados y devueltos. De todos modos, de acuerdo con el aviso anterior, es
mejor utilizar caché de elementos para prevenir procesamiento innecesario. Modificando la llamada a element para
que se vea así:

Plain Text View (#)


1. echo $this->element('latest_comments', array('cache'=>'+1 hour'));

La llamada a requestAction no se realizará mientras que la el archivo de la vista del elemento en cache exista y sea
válido.

Además, requestAction ahora toma urls con estilo cake basadas en arrays:

Plain Text View (#)

44 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. echo $this->requestAction(
2. array(
3. 'controller' => 'articles',
4. 'action' => 'featured'
5. ),
6. array('return')
7. );

Esto permite a la llamada a requestAction evitar el uso de Router::url lo que puede incrementar el rendimiento. Las
urls basadas en arrays son las mismas que las que HtmlHelper:link usa, con una diferencia. Si estás usando
parámetros con nombre en tu url, entonces el array de url debe envolver los parámetros con nombre en la clave
'named'. Esto es porque requestAction sólo combina los argumentos nombrados del array en el array de miembros de
Controller::params y no coloca los argumentos con nombre en la clave 'named'.

Plain Text View (#)


1. echo $this->requestAction('/articles/featured/limit:3');

Este, como array en requestAction debería ser:

Plain Text View (#)


1. echo $this->requestAction(
2. array(
3. 'controller' => 'articles',
4. 'action' => 'featured',
5. 'named' => array(
6. 'limit' => 3
7. )
8. )
9. );

A diferencia de otros lugares donde las urls de arrays son análogas a urls de cadenas, requestAction las trata de
manera diferente.

Cuando utilices una url de array junto con requestAction() has de especificar todos los parámetros que necesitarás
en la acción pedida. Esto incluye parámetros como $this->data y $this->params['form']

3.5.5.4.7 (#loadModel-992) loadModel

loadModel(string $modelClass, mixed $id)

La función loadModel es útil cuando se necesita usar un modelo que no es propiamente el modelo por defecto del
controlador o uno de sus modelos asociados.

Plain Text View (#)


1. $this->loadModel('Article');
2. $recentArticles = $this->Article->find('all', array('limit' => 5, 'order' => 'Article.created DESC'));

Plain Text View (#)


1. $this->loadModel('User', 2);
2. $user = $this->User->read();

3.6 (#Componentes-993) Componentes

3.6.1 (#Introducción-994) Introducción

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/994)


Comparar con el texto original (/es/compare/994/Introducción)

Mas info sobre traduciones (/es/view/818)

45 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Los componentes son paquetes de lógica que son compartidos entre los controladores. Si tiene ganas de copiar y
pegar código de un controlador a otro, debería antes considerar agrupar algunas funcionalidades en un componente.

CakePHP incluye un conjunto fantástico de componentes listos para usar para conseguir ayuda con:

Seguridad
Sesiones
Lista de control de acceso (ACL)
Emails
Cookies
Autenticación
Manejo de pedidos (Requests)

Cada uno de estos componentes del núcleo (Core) son detallados en su propio capitulo. Por el momento, veremos
como crear sus propios componentes. Con esto ayudará a mantener el código de los controladores limpio y le será
mas sencillo reusar código entre proyectos.

3.6.2 (#Configuración-de-componentes-995) Configuración de componentes.

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/995)


Comparar con el texto original (/es/compare/995/Configuración-de-componentes)

Mas info sobre traduciones (/es/view/818)

Muchos de los componentes básicos requieren ser configurados. Algunos ejemplos de componentes que requieren
ser configurados son: Auth (http://book.cakephp.org/view/172/Authentication) , Cookie (http://book.cakephp.org/view/177
/Cookies) e Email (http://book.cakephp.org/view/176/Email) . Toda la configuración de estos componentes y los
componentes en general se hacen en el método del controlador beforeFilter().

Plain Text View (#)


1. function beforeFilter() {
2. $this->Auth->authorize = 'controller';
3. $this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
4.
5. $this->Cookie->name = 'CookieMonster';
6. }

El código anterior sería un ejemplo de configuración de las variables de componente del controlador beforeFilter()

3.6.3 (#Creando-Componentes-a-medida-996) Creando Componentes a medida

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/996)


Comparar con el texto original (/es/compare/996/Creando-Componentes-a-medida)

Mas info sobre traduciones (/es/view/818)

Supongamos que nuestra aplicación online necesita efectuar una compleja operación matemática en muchas partes de
la aplicación. Creariamos un componente que albergara esa lógica compartida para poder ser usada en diferentes
controladores

El primer paso es crear una nueva clase y fichero de componente. Crea el fichero en /app/controllers/components
/math.php. La estructura básica para el componente quedaría así.

Plain Text View (#)


1. <?php
2. class MathComponent extends Object {
3. function doComplexOperation($amount1, $amount2) {
4. return $amount1 + $amount2;
5. }
6. }
7. ?>

46 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

3.6.3.1 (#Añadiendo-Componentes-a-tus-Controladores-997) Añadiendo Componentes a tus Controladores

Una vez finalizado nuestro componente, podemos usarlo en los controladores de la aplicación añadiendo su nombre
(excepto la parte "Component" al array $components del controlador. Automáticamente, el controlador recibirá un
nuevo atributo con un nombre a partir del nombre del componente, a través del cual podremos acceder a una
instancia del mismo:

Plain Text View (#)


1. /* Hace el nuevo componente accesible en $this->Math,
2. al igual que el standard $this->Session */
3. var $components = array('Math', 'Session');

Los componentes declarados en AppController serán combinados con los de tus otros controladores, así que no hay
necesidad de redeclarar el mismo componente dos veces.

Cuando se incluyen Componentes a un Controlador tambien puedes declarar un conjunto de parámetros que serán
pasados al método intialize() de los Componentes. Estos parámetros pueden ser manejados por el Componente.

Plain Text View (#)


1. var $components = array(
2. 'Math' => array(
3. 'precision' => 2,
4. 'randomGenerator' => 'srand'
5. ),
6. 'Session', 'Auth'
7. );

Este código pasaría el array conteniendo precision y randomGenerator al método intialize() de MathComponent como
segundo parámetro.

Por ahora, esta sintaxis no está implementada por ninguno de los Componentes Core

3.6.3.2 (#Acceso-a-clases-MVC-dentro-de-componentes-998) Acceso a clases MVC dentro de componentes

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/998)


Comparar con el texto original (/es/compare/998/Acceso-a-clases-MVC-dentro-de-componentes)

Mas info sobre traduciones (/es/view/818)

Para acceder a la instancia del controlador desde tu recien creado componente, necesitarás implementar el método
initialize() o el startup(). Estos métodos especiales llevan una referencia al controlador como primer parámetro y son
llamados automáticamente. El método initialize() es llamado antes del método beforeFilter(), y el método startup()
después del método beforeFilter . Si por algún motivo no deseas que el método startup() sea llamado cuando el
controlador está inicializando cosas, dale el valor true a la variable $disableStartup .

Si deseas insertar algún código de lógica antes de que el controlador beforeFilter() sea llamado, necesitarás usar el
método initialize() del componente.

Plain Text View (#)

47 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <?php
2. class CheckComponent extends Object {
3. //llamado antse de Controller::beforeFilter()
4. function initialize(&$controller) {
5. // salvando la referencia al controlador para uso posterior
6. $this->controller =& $controller;
7. }
8. //llamado tras Controller::beforeFilter()
9. function startup(&$controller) {
10. }
11. function redirectSomewhere($value) {
12. // ulizando un método de controlador
13. $this->controller->redirect($value);
14. }
15. }
16. ?>

También podrias querer utilizar otros componentes dentro del componente a medida. Para ello, simplemente crea una
variable de clase $components (tal como lo harías en un controlador ) como un array que contenga los nombres de
los componentes que quieres utilizar.

Plain Text View (#)


1. <?php
2. class MyComponent extends Object {
3. // Este componente usa otros componentes
4. var $components = array('Session', 'Math');
5. function doStuff() {
6. $result = $this->Math->doComplexOperation(1, 2);
7. $this->Session->write('stuff', $result);
8. }
9. }
10. ?>

No es muy recomendable acceder o usar un modelo en un componente, pero si tras sopesar las posibilidades eso es
lo que quieres hacer, tendrás que instanciar tu clase modelo y usarla manualmente. Aquí tienes un ejemplo:

Plain Text View (#)


1. <?php
2. class MathComponent extends Object {
3. function doComplexOperation($amount1, $amount2) {
4. return $amount1 + $amount2;
5. }
6. function doUberComplexOperation ($amount1, $amount2) {
7. $userInstance = ClassRegistry::init('User');
8. $totalUsers = $userInstance->find('count');
9. return ($amount1 + $amount2) / $totalUsers;
10. }
11. }
12. ?>

3.6.3.3 (#Usando-Componentes-en-tu-Componente-999) Usando Componentes en tu Componente

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/999)


Comparar con el texto original (/es/compare/999/Usando-Componentes-en-tu-Componente)

Mas info sobre traduciones (/es/view/818)

A veces uno de tus componentes puede depender de otro. Si las funcionalidades que estos componentes proveen no
están relacionados, excepto por su dependencia el uno del otro, entonces no querrás ponerlos dentro de un solo

48 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

componente.

En cambio puedes hacer que tu componente sea un "Padre" e indicarle con el array $components la lista de sus "Hijos".
Los componentes padres se cargan antes que sus componentes hijos, y cada componente hijo tiene acceso a su
padre.

Declaración del padre:

Plain Text View (#)


1. <?php
2. class PadreComponent extends Object {
3. var $name = "Padre";
4. var $components = array( "Hijo" );
5. function initialize(&$controller) {
6. $this->Hijo->foo();
7. }
8. function bar() {
9. // ...
10. }
11. }

Declaración del hijo:

Plain Text View (#)


1. <?php
2. class HijoComponent extends Object {
3. var $name = "Hijo";
4. function initialize(&$controller) {
5. $this->Padre->bar();
6. }
7. function foo() {
8. // ...
9. }
10. }

3.7 (#Modelos-1000) Modelos

3.7.1 (#La-Comprensión-de-Modelos-1001) La Comprensión de Modelos

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1001)


Comparar con el texto original (/es/compare/1001/La-Comprensión-de-Modelos)

Mas info sobre traduciones (/es/view/818)

Un Modelo representa tu modelo de datos y, en programación orientada a objetos, es un objeto que representa una
"cosa", como un coche, una persona, o una casa. Un blog, por ejemplo, puede contener varios artículos (posts ) y cada
artículo puede contener varios comentarios. Los objetos Blog, Artículo (Post) y Comentario son ejemplos de modelos,
cada uno asociado con el otro.

Aquí presentamos un ejemplo simple de definición de modelo en CakePHP:

Plain Text View (#)


1. <?php
2. class Ingredient extends AppModel {
3. var $name = 'Ingredient';
4. }
5. ?>

Simplemente con esta declaración, se le otorga al modelo Ingredient toda la funcionalidad que necesitarás para crear
consultas junto con guardado y borrado de datos. Estos métodos mágicos provienen del modelo de herencia de
CakePHP. El modelo Ingredient extiende el modelo de aplicaciónm AppModel , el cual extiende la clase Model , interna

49 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

de CakePHP. Es esta clase Model interna la que otorga la funcionalidad a nuestro modelo pesonalizado, Ingredient.

La clase intermedia AppModel está vacía y reside por defecto dentro de la carpeta /cake/. Redefinir AppModel te
permitirá definir funcionalidad que debería estar disponible a todos los modelos dentro de tu aplicación. Para hacer
eso, necesitas crear tu propio fichero app_model.php que reside en la raíz de la carpeta /app/. Creando un proyecto
utilizando Bake (/es/view/113/code-generation-with-bake) , Bake generará automáticamente este fichero por ti.

Crea tu fichero modelo en PHP en el directorio /app/models/ o en un subdirectorio de /app/models/. CakePHP lo


encontrará en cualquier lugar en el directorio. Por convención, debería tener el mismo nombre que la clase; para este
ejemplo, ingredient.php.

CakePHP creará dinamicamente un objeto modelo por ti si no puede encontrar un archivo correspondiente en
/app/models. Esto también significa que si, accidentalmente, nombras tu archivo de manera errónea (p.ej.
Ingredient.php o ingredients.php) CakePHP utilizará AppModel en lugar de tu archivo de modelo con nombre
incorrecto. Si estás tratando de utilizar un método de un modelo personalizado y estás obteniendo errores SQL,
normalmente es porque CakePHP no puede encontrar tu modelo.

Ver también Comportamientos (/es/view/88/Comportamientos) para más información sobre cómo aplicar lógica
similar para múltiples modelos.

La propiedad $name es necesaria para PHP4 pero opcional para PHP5.

Con tu modelo definido, este puede ser accedido dentro de tu Controlador (/es/view/49/Controladores) . CakePHP
automaticamente hará que se pueda acceder al modelo cuando su nombre concuerde con el del controloador. Por
ejemplo, un controlador llamado IngredientsController automaticamente inicializará el modelo Ingredient y será
accesible por el controlador mediante $this->Ingredient.

Plain Text View (#)


1. <?php
2. class IngredientsController extends AppController {
3. function index() {
4. //obtiene todos los ingredientes y los pasa a la vista:
5. $ingredients = $this->Ingredient->find('all');
6. $this->set('ingredients', $ingredients);
7. }
8. }
9. ?>

Están disponibles los modelos asociados a través del modelo principal. En el siguiente ejemplo, el modelo Receta
(Recipe) tiene una asociación con el modelo Ingrediente (Ingredient).

Plain Text View (#)


1. $this->Recipe->Ingredient->find('all');

Como podrás ver en Controllers , puedes atar múltiples modelos al controlador y acceder directamente desde él. En el
siguiente ejemplo, ambos modelos Recipe y User son accesibles desde el controlador actual.

Plain Text View (#)


1. <?php
2. class RecipeController extends AppController {
3. var $uses = array('Recipe', 'User');
4. function index() {
5. $this->Recipe->find('all');
6. $this->User->find('all');
7. }
8. }
9. ?>

Si no has añadido el modelo a través de la propiedad $uses entonces necesitarás importar el modelo manualmente e
instanciarlo dentro de la acción.

Plain Text View (#)

50 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <?php
2. class RecipeController extends AppController {
3. var $uses = array('Recipe');
4. function index() {
5. $this->Recipe->find('all');
6. App::import('Model', 'User');
7. $user = new User();
8. $user->find('all');
9. }
10. }
11. ?>

3.7.2 (#Creando-Tablas-de-Bases-de-D atos-1002) Creando Tablas de Bases de Datos

A pesar de que CakePHP puede tener orígenes de datos (datasources ) que no son manejadas por sistemas de gestión
de bases de datos, la mayoría de las veces lo son. CakePHP está diseñado para ser agnóstico y funcionará con MySQL,
MSSQL, Oracle, PostgreSQL y otros. Puedes crear tus tablas de base de datos como lo harías normalmente. Cuando
creas tus clases del Modelo, automáticamente se mapean a las tablas que has creado.

Los nombres de las tablas son, por convención, en minúsculas y en plural, con las palabras de los nombres de tablas
de varias palabras separadas por guiones de subrayado (_). Por ejemplo, un nombre de Modelo de Ingredient espera
el nombre de tabla ingredients . un nombre de Modelo de EventRegistration debería esperar un nombre de tabla
event_registrations . CakePHP inspeccionará tus tablas para determinar el tipo de dato de cada campo y utiliza esta
información apra automatizar varias características como la salida de campos de formulario en la vista.

Los nombres de los campos son, por convención, en minúscula y separados por guiones de subrayado (_).

Las asociaciones del modelo con el nombre de la tabla pueden ser anuladas con el atributo useTable del modelo,
explicado más adelante en este capítulo.

En el resto de esta sección verás cómo CakePHP "mapea" tipos de campos de bases de datos en tipos de datos PHP y
cómo CakePHP puede automatizar tareas basandose en cómo tus campos están definidos.

CakePHP viene preparado para el inglés. En caso de desear flexiones para el español es necesario modificar eL fichero
cake/libs/inflector.php

3.7.2.1 (#Asociaciones-de-Tipo-de-Dato-por-Base-de-Datos-1003) Asociaciones de Tipo de Dato por Base de Datos

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1003)


Comparar con el texto original (/es/compare/1003/Asociaciones-de-Tipo-de-Dato-por-Base-de-Datos)

Mas info sobre traduciones (/es/view/818)

Todo RDMS (http://es.wikipedia.org/wiki/Sistema_administrador_de_bases_de_datos_relacionales) define tipos de datos de


manera ligeramente diferente. Dentro de la clase de origen de datos (o "fuente de datos", datasource) para cada
sistema de base de datos, CakePHP "mapea" dichos tipos a algo que reconoce y crea una interfaz unificada sin
importar en qué sistema de bases de datos necesitas ejecutarlo.

El siguiente desglose describe cómo está "mapeado" cada uno.

3.7.2.1.1 (#MySQL-1004) MySQL

Tipo CakePHP Propiedades del Campo


primary_key NOT NULL auto_increment
string varchar(255)
text text
integer int(11)
float float
datetime datetime
timestamp datetime
time time

51 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

date date
binary blob
boolean tinyint(1)

Un campo de tipo tinyint(1) es considerado booleano por CakePHP.

3.7.2.1.2 (#MySQLi-1005) MySQLi

Tipo CakePHP Propiedades del Campo


primary_key DEFAULT NULL auto_increment
string varchar(255)
text text
integer int(11)
float float
datetime datetime
timestamp datetime
time time
date date
binary blob
boolean tinyint(1)

3.7.2.1.3 (#ADOdb-1006) ADOdb

Tipo CakePHP Propiedades del Campo


primary_key R(11)
string C(255)
text X
integer I(11)
float N
datetime T (Y-m-d H:i:s)
timestamp T (Y-m-d H:i:s)
time T (H:i:s)
date T (Y-m-d)
binary B
boolean L(1)

3.7.2.1.4 (#DB2-1007) DB2

Tipo CakePHP Propiedades del Campo


primary_key not null generated by default as identity (start with 1, increment by 1)
string varchar(255)
text clob
integer integer(10)
float double
datetime timestamp (Y-m-d-H.i.s)
timestamp timestamp (Y-m-d-H.i.s)
time time (H.i.s)
date date (Y-m-d)
binary blob
boolean smallint(1)

3.7.2.1.5 (#Firebird-Interbase-1008) Firebird/Interbase

52 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Tipo CakePHP Propiedades del Campo


primary_key IDENTITY (1, 1) NOT NULL
string varchar(255)
text BLOB SUB_TYPE 1 SEGMENT SIZE 100 CHARACTER SET NONE
integer integer
float float
datetime timestamp (d.m.Y H:i:s)
timestamp timestamp (d.m.Y H:i:s)
time time (H:i:s)
date date (d.m.Y)
binary blob
boolean smallint

3.7.2.1.6 (#MS-SQL-1009) MS SQL

Tipo CakePHP Propiedades del Campo


primary_key IDENTITY (1, 1) NOT NULL
string varchar(255)
text text
integer int
float numeric
datetime datetime (Y-m-d H:i:s)
timestamp timestamp (Y-m-d H:i:s)
time datetime (H:i:s)
date datetime (Y-m-d)
binary image
boolean bit

3.7.2.1.7 (#Oracle-1010) Oracle

Tipo CakePHP Propiedades del Campo


primary_key number NOT NULL
string varchar2(255)
text varchar2
integer numeric
float float
datetime date (Y-m-d H:i:s)
timestamp date (Y-m-d H:i:s)
time date (H:i:s)
date date (Y-m-d)
binary bytea
boolean boolean
number numeric
inet inet

3.7.2.1.8 (#PostgreSQL-1011) PostgreSQL

Tipo CakePHP Propiedades del Campo


primary_key serial NOT NULL
string varchar(255)
text text
integer integer
float float

53 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

datetime timestamp (Y-m-d H:i:s)


timestamp timestamp (Y-m-d H:i:s)
time time (H:i:s)
date date (Y-m-d)
binary bytea
boolean boolean
number numeric
inet inet

3.7.2.1.9 (#SQLite-1012) SQLite

Tipo CakePHP Propiedades del Campo


primary_key integer primary key
string varchar(255)
text text
integer integer
float float
datetime datetime (Y-m-d H:i:s)
timestamp timestamp (Y-m-d H:i:s)
time time (H:i:s)
date date (Y-m-d)
binary blob
boolean boolean

3.7.2.1.10 (#Sybase-1013) Sybase

Tipo CakePHP Propiedades del Campo


primary_key numeric(9,0) IDENTITY PRIMARY KEY
string varchar(255)
text text
integer int(11)
float float
datetime datetime (Y-m-d H:i:s)
timestamp timestamp (Y-m-d H:i:s)
time datetime (H:i:s)
date datetime (Y-m-d)
binary image
boolean bit

3.7.2.2 (#Titulos-1014) Titulos

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1014)


Comparar con el texto original (/es/compare/1014/Titulos)

Mas info sobre traduciones (/es/view/818)

Un objeto, en sentido físico, a menudo tiene un nombre o un título con el que referirse. Una persona tiene un nombre
como Juan o Ambrosio o Colega. Una entrada de un blog tiene un título. Una categoría tiene un nombre.

Al especificar el campo title (título) o name (nombre), CakePHP automáticamente utilizará esta etiqueta en varias
circunstancias:

Scaffolding (http://en.wikipedia.org/wiki/Scaffold_(programming)) — títulos de páginas, etiquetas de fieldset


Listas - normalmente utilizado para los desplegables <select>
TreeBehavior — reordenación, vistas de árbol

54 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Si tienes un campo title y un campo name en tu tabla, el campo title será el utilizado.

3.7.2.3 (#Creado-y-modificado-created-y-modified-1015) Creado y modificado ("created" y "modified")

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1015)


Comparar con el texto original (/es/compare/1015/Creado-y-modificado-created-y-modified)

Mas info sobre traduciones (/es/view/818)

Al definir un campo created (creado) o modified (modificado) en tu tabla de la base de datos como campo de tipo
datetime, CakePHP reconocerá esos campos y los rellenará automaticamente cuando un registro sea creado o grabado
en la base de datos.

Los campos created y modified serán establecidos a la fecha y hora actuales cuando el registro es inicialmente
añadido. El campo modified será actualizado con la fecha y hora actuales cuando el registro existente sea grabado.

Nota: Un campo llamado updated (actualizado) exhibirá el mismo comportamiento que modified. Estos campos
necesitan ser del tipo datetime con el valor por defecto establecido a NULL para ser reconocidos por CakePHP.

3.7.2.4 (#Utilizando-UUIDs-como-Claves-Primarias-1016) Utilizando UUIDs como Claves Primarias

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1016)


Comparar con el texto original (/es/compare/1016/Utilizando-UUIDs-como-Claves-Primarias)

Mas info sobre traduciones (/es/view/818)

Las claves primarias son normalmente definidas como campos INT. La base de datos incrementará automáticamente el
campo, comenzando en 1, para cada nuevo registro que se añade. Alternativamente, si especificas tu clave primaria
como CHAR(36), CakePHP generará automáticamente UUIDs (http://en.wikipedia.org/wiki/UUID) (Identificadores Únicos
Universales) cuando son creados nuevos registros.

Un UUID es una cadena de 32 bytes separada por guiones, con un total de 36 caracteres. Por ejemplo:

550e8400-e29b-41d4-a716-446655440000

Los UUIDs están diseñados para ser únicos, no sólo dentro de una tabla dada, sino también a través de tablas y bases
de datos. Si necesitas que un campo permanezca único a través de sistemas, los UUIDs son un genial enfoque.

3.7.3 (#Recuperando-tus-D atos-1017) Recuperando tus Datos

3.7.3.1 (#find-1018) find

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1018)


Comparar con el texto original (/es/compare/1018/find)

Mas info sobre traduciones (/es/view/818)

find($tipo, $parametros)

$tipo es 'all', 'first', 'count', 'neighbors', 'list' o 'threaded'. 'first' es el tipo de búsqueda predeterminado.

$parametros es un array con cualquiera de las siguientes opciones disponibles como claves:

Plain Text View (#)

55 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. array(
2. 'conditions' => array('Model.field' => $thisValue), //array de condiciones
3. 'recursive' => 1, //int
4. 'fields' => array('Model.field1', 'Model.field2'), //array de nombres de campos
5. 'order' => 'Model.created', //string o array definiendo el orden
6. 'group' => array('Model.field'), //campos para GROUP BY
7. 'limit' => n, //int
8. 'page' => n //int
9. )

Si estás utilizando find('list'), la clave 'fields' en $parametros define la clave, valor y grupo

Plain Text View (#)


1. // la lista generada será indexada por Post.id, con valor de Post.title
2. $this->Post->find('list', array('fields'=>'Post.title'));
3.
4. // la lista generada será indexada por Post.slug, con valor de Post.title
5. $this->Post->find('list',
6. array(
7. 'fields'=>array('Post.slug',
8. 'Post.title')
9. )
10. );
11.
12. // la lista generada será agrupoada por Post.author_id, y cada grupo indexado por Post.id, con valor de
13. $this->Post->find('list',
14. array(
15. 'fields'=> array('Post.id',
16. 'Post.title',
17. 'Post.author_id')
18. )
19. );

Si estás utilizando find('neighbors'), la clave 'field' en $parametros define el campo a analizar, y la clave 'value'
en el array $parametros define el valor a mirar para determinar el siguiente y el anterior. Notar que las claves 'field'
y 'value' no son usadas para find('all') y este es un caso especial para find('neighbors').

Plain Text View (#)


1. // asumiendo que tenermos id's de 1 a 10, veremos assuming we have id's from 1-10, veremos <em>prev</em
2. $this->Post->id = 2;
3. $one = $this->Post->find('neighbors');
4. // para obtener los datos vecinos utilizando un campo diferente...
5. $two = $this->Post->find('neighbors',
6. array(
7. 'field'=> 'Post.title',
8. 'value'=> $data['Post']['title'])
9. );

Para compatibilidad hacia atraś, find también acepta la sintasix previa:

find(string $condiciones, array $campos, string $orden, int $recursivo)

3.7.3.1.1 (#find-first-1019) find('first')

find('first', $params)

'first' es el tipo find por defecto, y devolverá un solo resultado, deberías utilizar esto para cualquier caso donde
esperes solo un resultado. Abajo hay un par de ejemplos simples (código del controlador [controller]):

Plain Text View (#)

56 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. function some_function() {
2. ...
3. $this->Article->order = null; // reseteando si ya ha sido inicializado
4. $semiRandomArticle = $this->Article->find();
5. $this->Article->order = 'Article.created DESC'; // simulando el modelo teniendo un órden por defecto
6. $lastCreated = $this->Article->find();
7. $alsoLastCreated = $this->Article->find('first', array('order' => array('Article.created DESC')));
8. $specificallyThisOne = $this->Article->find('first', array('conditions' => array('Article.id' => 1)))
9. ...
10. }

En este primer ejemplo, ningún parámetro se le ha pasado a find - por lo tanto ningún criterio de condición o de
ordenamiento será utilizado. El formato devuelto por la llamada a find('first') será de la siguiente forma:

Array
(
[ModelName] => Array
(
[id] => 83
[field1] => value1
[field2] => value2
[field3] => value3
)

[AssociatedModelName] => Array


(
[id] => 1
[field1] => value1
[field2] => value2
[field3] => value3
)
)

No hay parámetros adicionales usador por find('first').

3.7.3.1.2 (#find-count-1020) find('count')

find('count', $params)

find('count', $params) Devuelve un valor entero. Debajo hay un par de ejemplos sencillos (código controlador):

Plain Text View (#)


1. function some_function() {
2. ...
3. $total = $this->Article->find('count');
4. $pending = $this->Article->find('count', array('conditions' => array('Article.status' => 'pending')))
5. $authors = $this->Article->User->find('count');
6. $publishedAuthors = $this->Article->find('count', array(
7. 'fields' => 'DISTINCT Article.user_id',
8. 'conditions' => array('Article.status !=' => 'pending')
9. ));
10. ...
11. }

No pasar campos como arrays a find('count'). Podrías necesitar campos específicos para DISTINCT count (de lo
contrario, count es siempre lo mismo - dictatado por las conditions (condiciones)).

No hay parámetros adicionales usados con find('count').

3.7.3.1.3 (#find-all-1021) find('all')

57 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

find('all', $params)

find('all')devuelve un array de resultados(potentially multiple); es, de hecho, el mecanismo usado por todas las
variantes del método find(), como por ejemplo para paginar. Debajo puedes ver un par de (código controlador)
ejemplos:

Plain Text View (#)


1. function some_function() {
2. ...
3. $allArticles = $this->Article->find('all');
4. $pending = $this->Article->find('all', array('conditions' => array('Article.status' => 'pending')));
5. $allAuthors = $this->Article->User->find('all');
6. $allPublishedAuthors = $this->Article->User->find('all', array('conditions' => array('Article.status
7. ...
8. }

El ejemplo de abajo $allAuthors busca todos los campos de la tabla users, no se le han aplicado condiciones a find.

Los resultados de llamar a find('all') serán de la siguiente forma:

Array
(
[0] => Array
(
[ModelName] => Array
(
[id] => 83
[field1] => value1
[field2] => value2
[field3] => value3
)

[AssociatedModelName] => Array


(
[id] => 1
[field1] => value1
[field2] => value2
[field3] => value3
)

)
)

Aquí no hay parámetros condicionales usados por find('all').

3.7.3.1.4 (#find-list-1022) find('list')

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1022)


Comparar con el texto original (/es/compare/1022/find-list)

Mas info sobre traduciones (/es/view/818)

find('list', $params)

find('list', $params) Devuelve un array indexado, útil para cualquier uso donde podrías querer una lista como los
polulares campos select de los formularios. Debajo hay un par de simples ejemplos (código controlador):

Plain Text View (#)

58 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. function some_function() {
2. ...
3. $allArticles = $this->Article->find('list');
4. $pending = $this->Article->find('list', array('conditions' => array('Article.status' => 'pending')));
5. $allAuthors = $this->Article->User->find('list');
6. $allPublishedAuthors = $this->Article->User->find('list', array('conditions' => array('Article.status
7. ...
8. }

En el ejemplo siguiente $allAuthors va a contener todos los usuarios de la tabalo usuers, no se le aplica ninguna
condición para filtrar la búsqueda que lleva a cabo find.

Los resultado tras llamar al método find('list') tendrán el siguiente aspecto:

Array
(
//[id] => 'displayValue',
[1] => 'displayValue1',
[2] => 'displayValue2',
[4] => 'displayValue4',
[5] => 'displayValue5',
[6] => 'displayValue6',
[3] => 'displayValue3',
)

Cuando find('list') es llamado, los parámetros pasados son usados para determinar que debería ser usado como la
key del array, value y opcionalmente a que grupo pertenecen los resultados. Por defecto la clave primaria para el
modelo es usada por la key, y el valor que se muestra es el usado por el value. Algunos ejemplos aclarará un poco
más:

Plain Text View (#)


1. function some_function() {
2. ...
3. $justusernames = $this->Article->User->find('list', array('fields' => array('User.username'));
4. $usernameMap = $this->Article->User->find('list', array('fields' => array('User.username', 'User.firs
5. $usernameGroups = $this->Article->User->find('list', array('fields' => array('User.username', 'User.f
6. ...
7. }

En el anterior ejemplo, el resultado devuelto se parecería a esto:

$justusernames = Array
(
//[id] => 'username',
[213] => 'AD7six',
[25] => '_psychic_',
[1] => 'PHPNut',
[2] => 'gwoo',
[400] => 'jperras',
)

$usernameMap = Array
(
//[username] => 'firstname',
['AD7six'] => 'Andy',
['_psychic_'] => 'John',
['PHPNut'] => 'Larry',
['gwoo'] => 'Gwoo',
['jperras'] => 'Joël',
)

59 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

$usernameGroups = Array
(
['Uber'] => Array
(
['PHPNut'] => 'Larry',
['gwoo'] => 'Gwoo',
)

['Admin'] => Array


(
['_psychic_'] => 'John',
['AD7six'] => 'Andy',
['jperras'] => 'Joël',
)

3.7.3.1.5 (#find-threaded-1023) find('threaded')

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1023)


Comparar con el texto original (/es/compare/1023/find-threaded)

Mas info sobre traduciones (/es/view/818)

find('threaded', $params)

find('threaded', $params)Devuelve un array anidado, y es apropiado si quieres usar el campo parent_id de tu


modelo de datos para construir resultados anidados. Abajo se muestran un par de ejemplos (código controlador):

Plain Text View (#)


1. function some_function() {
2. ...
3. $allCategories = $this->Category->find('threaded');
4. $aCategory = $this->Category->find('first', array('conditions' => array('parent_id' => 42)); // not t
5. $someCategories = $this->Category->find('threaded', array(
6. 'conditions' => array(
7. 'Article.lft >=' => $aCategory['Category']['lft'],
8. 'Article.rght <=' => $aCategory['Category']['rght']
9. )
10. ));
11. ...
12. }

No es necesario utilizar el comportamiento en árbol (/es/view/91/Tree) para usar este método, pero todos los
resultados deseados deben poderse encontrar en una sencilla consulta.

El anterior ejemplo, $allCategories contendría un array anidado representando la estuctura entera de la categoría. El
segundo ejemplo hace uso de la estructura de datos Tree behavior (/es/view/91/Tree) the return a partial, nested,
result for $aCategory and everything below it. The results of a call to find('threaded') will be of the following form:

Array
(
[0] => Array
(
[ModelName] => Array
(
[id] => 83
[parent_id] => null
[field1] => value1

60 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

[field2] => value2


[field3] => value3
)

[AssociatedModelName] => Array


(
[id] => 1
[field1] => value1
[field2] => value2
[field3] => value3
)
[children] => Array
(
[0] => Array
(
[ModelName] => Array
(
[id] => 42
[parent_id] => 83
[field1] => value1
[field2] => value2
[field3] => value3
)

[AssociatedModelName] => Array


(
[id] => 2
[field1] => value1
[field2] => value2
[field3] => value3
)
[children] => Array
(
)
)
...
)
)
)

El orden en el que aparecen los resultados puede ser cambiado como lo es la influencia de la orden de
procesamiento. Por ejemplo, si 'order' => 'name ASC' es pasado en los parámetros a find('threaded'), los
resultados van a aparecer en orden según el nombre. Del mismo modo cualquier orden puede ser usado, there is no
inbuilt requirement of this method for the top result to be returned first.

No hay parámetros adicionales usados por find('threaded').

3.7.3.1.6 (#find-neighbors-1024) find('neighbors')

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1024)


Comparar con el texto original (/es/compare/1024/find-neighbors)

Mas info sobre traduciones (/es/view/818)

find('neighbors', $params)

'neighbors' realiza una búsqueda similar a 'first', a diferencia que devuelve el registro precedente y posterior del
solicitado. A continuación un (código en controlador) ejemplo:

Plain Text View (#)

61 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. function some_function() {
2. $neighbors = $this->Article->find('neighbors', array('field' => 'id', 'value' => 3));
3. }

En este ejemplo podemos ver dos elementos esenciales del arreglo $params: 'field' y 'value'. Además de estos, se
pueden utilizar otros elementos que se utilizan en las demás implementaciones del método find (Por ejemplo: Si tu
modelo actúa como contenedor, deberías de utilizar 'contain' en el arreglo $params). El formato de salida para una
llamada find('neighbors') es de la siguiente forma:

Array
(
[prev] => Array
(
[ModelName] => Array
(
[id] => 2
[field1] => value1
[field2] => value2
...
)
[AssociatedModelName] => Array
(
[id] => 151
[field1] => value1
[field2] => value2
...
)
)
[next] => Array
(
[ModelName] => Array
(
[id] => 4
[field1] => value1
[field2] => value2
...
)
[AssociatedModelName] => Array
(
[id] => 122
[field1] => value1
[field2] => value2
...
)
)
)

Note que el resultado siempre tendrá dos arreglos principales: prev y next.

3.7.3.2 (#findAllBy-1025) findAllBy

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1025)


Comparar con el texto original (/es/compare/1025/findAllBy)

Mas info sobre traduciones (/es/view/818)

findAllBy<nombreCampo>(string $valor)

Estas funciones mágias pueden ser usadas como atajos para buscar en tus tablas por cierto campo. Simplemente
añade el nombre del campo (en formato CamelCase) al final del nombre de esas funciones (<nombreCampo>) y
proporciona los criterios para ese campo como primer parámetro.

62 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

3.7.3.3 (#findBy-1026) findBy

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1026)


Comparar con el texto original (/es/compare/1026/findBy)

Mas info sobre traduciones (/es/view/818)

findBy<nombreCampo>(string $valor)

Estas funciones mágicas pueden ser usadas como atajo en la búsqueda en tus tablas por cierto campo. Simplemente
añade el nombre del campo (en forma CamelCase) al final de las funciones (<nombreCampo>), y proporciona los
criterios para ese campo como primer parámetro.

Ejemplo findAllBy<x> en PHP5 Fragmento SQL Correspondiente


$this->Product->findAllByOrderStatus(ʻ3ʼ); Product.order_status = 3
$this->Recipe->findAllByType(ʻCookieʼ); Recipe.type = ʻCookieʼ
$this->User->findAllByLastName(ʻAndersonʼ); User.last_name = ʻAndersonʼ
$this->Cake->findById(7); Cake.id = 7
$this->User->findByUserName(ʻpsychicʼ); User.user_name = ʻpsychicʼ

Los usuarios de PHP4 han de utilizar esta función de manera un poco diferente debido a cierto case-insensitivity en
PHP4:

Ejemplo findAllBy<x> en PHP4 Fragmento SQL Correspondiente


$this->Product->findAllByOrder_status(ʻ3ʼ); Product.order_status = 3
$this->Recipe->findAllByType(ʻCookieʼ); Recipe.type = ʻCookieʼ
$this->User->findAllByLast_name(ʻAndersonʼ); User.last_name = ʻAndersonʼ
$this->Cake->findById(7); Cake.id = 7
$this->User->findByUser_name(ʻpsychicʼ); User.user_name = ʻpsychicʼ

El resultado devuelto es un array formateado tal y como sería en find() o findAll().

3.7.3.4 (#query-1027) query

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1027)


Comparar con el texto original (/es/compare/1027/query)

Mas info sobre traduciones (/es/view/818)

query(string $consulta)

Se pueden realizar llamadas SQL personalizadas usando el método query() del modelo.

Si alguna vez usas consultas SQL personalizadas en tu aplicación, no olvides leer la sección Desinfección de Datos
(/es/view/153/Sanitizaci%C3%B3n-de-Datos) (Sanitization ) de CakePHP, la cual ayuda a limpiar datos de usuario de
injection y ataques de cross-site scripting .

query() utiliza el nombre de la tabla en la consulta como clave del array de datos devueltos, en vez del nombre del
modelo. Por ejemplo:

Plain Text View (#)


1. $this->Fotografia->query("SELECT * FROM fotografias LIMIT 2;");

debería devolver

Plain Text View (#)

63 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. Array
2. (
3. [0] => Array
4. (
5. [fotografías] => Array
6. (
7. [id] => 1304
8. [user_id] => 759
9. )
10. )
11. [1] => Array
12. (
13. [fotografías] => Array
14. (
15. [id] => 1305
16. [user_id] => 759
17. )
18. )
19. )

Para usar el nombre del modelo como clave del array, y obtener un resultado consistente con el devuelto por los
métodos Find , la consulta puede ser reescrita:

Plain Text View (#)


1. $this->Fotografia->query("SELECT * FROM fotografia AS Fotografia LIMIT 2;");

la cual devuelve

Plain Text View (#)


1. Array
2. (
3. [0] => Array
4. (
5. [Fotografia] => Array
6. (
7. [id] => 1304
8. [user_id] => 759
9. )
10. )
11. [1] => Array
12. (
13. [Fotografia] => Array
14. (
15. [id] => 1305
16. [user_id] => 759
17. )
18. )
19. )

3.7.3.5 (#field-1028) field

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1028)


Comparar con el texto original (/es/compare/1028/field)

Mas info sobre traduciones (/es/view/818)

field(string $nombre, string $condiciones, string $orden)

Devuelve el valor de un campo singular, especificado en $name, del primer registro que cumpla $condiciones estando

64 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

ordenado por $orden.

3.7.3.6 (#read-1029) read()

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1029)


Comparar con el texto original (/es/compare/1029/read)

Mas info sobre traduciones (/es/view/818)

read($fields, $id)

read() es un método usado para establecer los datos del modelo actual (Model::$data)--así también mientras se está
editando--pero también puede ser usado en otras circunstancias para obtener un solo registro de la base de datos.

$fields es usado para especificar un nombre de campo, como cadena, o un arreglo de nombres de campo que serán
incluidos en la consulta; si no se especifica un valor, entonces todos los campos serán incluidos.

$id especifica el ID de registro que será leído. Por defecto, el registro actualmente seleccionado, especificado por
Model::$id, es usado. Si se especifica un valor diferente a $id causará que el registro que cumpla con la condición
será seleccionado.

Plain Text View (#)


1. function beforeDelete($cascade) {
2. ...
3. $rating = $this->read('rating'); // obtiene el <em>rating</em> del registro que será borrado.
4. $name = $this->read('name', $id2); // obtiene el nombre un segundo registro.
5. $rating = $this->read('rating'); // obtiene el <em>rating</em> del segundo registro
6. $this->id = $id3; //
7. $this->Article->read(); // lee un tercer registro, especificado por <code>$id3</code>.
8. $record = $this->data // almacena el tercer registro en <code>$record</code>
9. ...
10. }

Notar que la tercera llamada a read() obtiene el rating del mismo registro leído anteriormente por la llamada
$this->read('name', $id2). Esto es porque read() cambia el valor en Model::$id a cualquier valor pasado como $id.
Las lineas 6-8 demuestran como read() cambia los datos del modelo actual.

3.7.3.7 (#Condiciones-Complejas-de-Búsqueda-1030) Condiciones Complejas de Búsqueda

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1030)


Comparar con el texto original (/es/compare/1030/Condiciones-Complejas-de-Búsqueda)

Mas info sobre traduciones (/es/view/818)

La mayoría de las llamadas de búsqueda del modelo involucran pasar conjuntos de condiciones de una u otra
manera. La aproximación más simple a ello es utilizar la cláusula WHERE de SQL. Si ves que necesitas más control,
puedes utilizar arrays.

Usar arrays permite una lectura más clara y fácil, y también hace muy fácil la construcción de consultas. Esta sintaxis
también particiona los elementos de tu consulta (campos, valores, operadores, etc.) en partes discretas y
manipulables. Esto permite a CakePHP generar la consulta más eficiente posible, asegurar una sintaxis SQL apropiada,
y formatear apropiadamente cada parte individual de la consulta.

En su forma más básica, una consulta basada en array es así:

Plain Text View (#)


1. $condiciones = array("Articulo.title" => "Esto es un artículo");
2. // Ejemplo de uso con un modelo:
3. $this->Articulo->find($condiciones);

65 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

La estructura aquí es bastante autoexplicativa: buscará cualquier artículo donde el título sea igual a "Esto es un
artículo". Notar que podríamos haber utilizado como nombre de campo simplemente 'title', pero cuando se construyen
consultas es buena práctica especificar siempre el nombre del modelo (en este caso, Articulo), ya que mejora la
claridad del código y ayuda a prevenir colisiones en el futuro, en cuyo caso deberías modificar tu esquema de tablas.

¿Qué hay sobre otros tipos de condiciones? Estas son igualmente simples. Digamos que queremos buscar todos los
artículos donde el título no sea 'Esto no es un artículo':

Plain Text View (#)


1. array("Articulo.title <>" => "Esto no es un artículo")

Notar el '<>' que está detrás del nombre del campo. CakePHP puede analizar sintácticamente cualquier operador de
comparación en SQL, incluyendo las expresiones usando LIKE, BETWEEN, o REGEX, siempre y cuando dejes un espacio
entre el nombre del campo y el operador. La unica excepción aquí es la condición de búsqueda del tipo IN (...).
Digamos que querías buscar artículos donde el título estaba dentro de un conjunto dado de valores:

Plain Text View (#)


1. array(
2. "Articulo.title" => array("Primer artículo", "Segundo artículo", "Tercer artículo")
3. )

Para realizar una búsqueda con condición NOT IN(...) para encontrar artículos cuyo título no está en el conjunto de
valores dado:

Plain Text View (#)


1. array(
2. "NOT" => array( "Articulo.title" => array("Primer artículo", "Segundo artículo", "Tercer artículo")
3. )

Añadir filtros adicionales a las condiciones es tan simple como añadir pares clave/valor adicionales al array:

Plain Text View (#)


1. array (
2. "Articulo.title" => array("Primer artículo", "Segundo artículo", "Tercer artículo"),
3. "Articulo.created >" => date('Y-m-d', strtotime("-2 weeks"))
4. )

También puedes crear búsquedas que comparen dos campos en la base de datos:

Plain Text View (#)


1. array("Articulo.created = Articulo.modified")

Este ejemplo de arriba devolverá artículos en los cuales la fecha de creación es igual a la fecha de modificación (p.e.
devolverá artículos que nunca han sido modificados).

Por defecto, CakePHP junta múltiples condiciones con AND booleano; es decir, las condiciones de más arriba sólo
coincidirán con artículos que han sido creados en las últimas dos semanas (-2 weeks ), y posean un título que
coincida con alguno de los dados en el conjunto ("Primer artículo",...). No obstante, podemos igualmente buscar
artículos que coincidan con cualquiera de las condiciones:

Plain Text View (#)


1. array(
2. "or" => array (
3. "Articulo.title" => array("Primer artículo", "Segundo artículo", "Tercer artículo"),
4. "Articulo.created >" => date('Y-m-d', strtotime("-2 weeks"))
5. )
6. )

Cake acepta todas las operaciones booleanas de SQL válidas, incluyendo AND, OR , NOT , XOR , etc..., y pueden estar en
mayúsculas o minúsculas, como prefieras. Estas condiciones son también infinitamente anidables. Digamos que
tienes una relación belongsTo entre Articulos y Autores. Digamos que quieres buscar todos los artículos que
contienen una cierta palabra (p.e. "magico") o que han sido creados en las últimas dos semanas, pero quieres

66 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

restringir tu búsqueda a artículos escritos por Pedro:

Plain Text View (#)


1. array (
2. "Autor.name" => "Pedro",
3. "or" => array (
4. "Articulo.title LIKE" => "%magico%",
5. "Articulo.created >" => date('Y-m-d', strtotime("-2 weeks"))
6. )
7. )

Cake también puede comprobar campos nulos (null ). En este ejemplo, la consulta devolverá registros en los que el
título del artículo no es nulo:

Plain Text View (#)


1. array (
2. "not" => array (
3. "Articulo.title" => null,
4. )
5. )

Para manejar consultas con BETWEEN , puedes usar lo siguiente:

Plain Text View (#)


1. array('Articulo.id BETWEEN ? AND ?' => array(1,10))

Nota: CakePHP entrecomillará los valores numéricos dependiendo del tipo de campo definido en tu base de datos.

Puedes crear condiciones muy complejas anidando múltiples arrays de condiciones:

Plain Text View (#)


1. array(
2. 'OR' => array(
3. array('Compania.name' => 'Emporio Futuro'),
4. array('Compania.name' => 'Megatrabajos de Acero')
5. ),
6. 'AND' => array(
7. array(
8. 'OR'=>array(
9. array('Compania.status' => 'activo'),
10. 'NOT'=>array(
11. array('Compania.status'=> array('inactivo', 'suspendido'))
12. )
13. )
14. )
15. )
16. );

Las cuales producen el siguiente código SQL:

Plain Text View (#)

67 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. SELECT `Compania`.`id`, `Compania`.`name`,


2. `Compania`.`description`, `Compania`.`location`,
3. `Compania`.`created`, `Compania`.`status`, `Compania`.`size`
4. FROM
5. `companias` AS `Compania`
6. WHERE
7. ((`Compania`.`name` = 'Emporio Futuro')
8. OR
9. (`Compania`.`name` = 'Megatrabajos de Acero'))
10. AND
11. ((`Compania`.`status` = 'activo')
12. OR (NOT (`Compania`.`status` IN ('inactivo', 'suspendido'))))

3.7.4 (#Guardando-Tus-Datos-1031) Guardando Tus Datos

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1031)


Comparar con el texto original (/es/compare/1031/Guardando-Tus-Datos)

Mas info sobre traduciones (/es/view/818)

CakePHP hace que el salvado de los datos del modelo sea instantáneo. Los datos listos para ser salvados deberán ser
pasados al método save() del modelo usando el formato básico siguiente:

Array
(
[NombreModelo] => Array
(
[nombrecampo1] => 'valor'
[nombrecampo2] => 'valor'
)
)

La mayoría de las veces no necesitarás preocuparte por este formato: los ayudantes de CakePHP HtmlHelper,
FormHelper, y métodos de búsqueda empaquetan los datos en este formato. Si estás usando alguno de los ayudantes,
los datos también están convenientemente disponibles en $this->data para su uso rápido.

Aquí está un ejemplo rápido de una acción de un controlador que usa un modelo de CakePHP para salvar datos en
una tabla de una base de datos:

Plain Text View (#)


1. function edit($id) {
2. // Ha POSTeado algún dormulario datos?
3. if(!empty($this->data)) {
4. // Si el formulario puede ser validado y salvado...
5. if($this->Receta->save($this->data)) {
6. // Establede un mensaje flash y redirige.
7. $this->Session->setFlash("Receta guardada!");
8. $this->redirect('/recetas');
9. }
10. }
11.
12. // Si no hay datos de formularo, busca la receta a editar y pásala a la vista
13. $this->set('receta', $this->Receta->findById($id));
14. }

Una nota adicional: cuando se llama a save(), los datos pasados a la función como primer parámetro son validados
usando el mecanismo de validación de CakePHP (ver el capítulo de validación de datos (/es/view/125) para más
información). Si por alguna razón tus datos no se graban, comprueba si alguna regla de validación se está
incumpliendo.

Hay unos pocos métodos relacionados con el salvado que encontrarás útiles:

68 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

save(array $datos = null, boolean $validar = true, array $listaCampos = array())

Mostrado arriba, este método graba datos formateados en array. El segundo parámetro ($validar) te permite eludir la
validación, y el tercero ($listaCampos) te permite proveer una lista de campos del modelo a ser grabados. Como
seguridad añadida, puedes limitar los campos grabados a aquellos listados en $listaCampos.

Una vez que un salvado ha sido completado, el identificador ID del objeto se encuentra en el atributo $id del objeto
del modelo (algo especialmente útil cuando se crean nuevos objetos).

Plain Text View (#)


1. $this->Ingrediente->save($datosNuevos);
2. $nuevoIngredienteId = $this->Ingrediente->id;

Cuando se llama a save() en un bucle, no olvides llamar a create().

create(array $datos = array())

Este método resetea el estado del modelo para grabar nueva información.

Si se pasa el parámetro $datos (usando el formato de array descrito arriba), la instancia del modelo estará lista para
salvar con esos datos (accesibles en $this->data).

saveField(string $nombreCampo, string $valorCampo, $validar = false)

Usado para salvar un único valor de un campo. Establece el ID del modelo ($this->nombreModelo->id = $id) antes de
llamar a saveField(). Cuando usas este método, $nombreCampo debería contener sólo el nombre del campo, no el
nombre del modelo y campo.

Por ejemplo, para actualizar el título de una entrada de un blog, la llamada a saveField desde un controlador debería
parecerse a esto:

Plain Text View (#)


1. $this->Entrada->saveField('titulo', 'Un Nuevo Título para un Nuevo Día');

updateAll(array $campos, array $condiciones)

Actualiza varios registros en una única llamada. Los registros a ser actalizados están identificados por el array
$conditions, y los campos a ser actualizados, así como sus valores, están identificados por el array $fields.

Por ejemplo, para aprobar a todos los panaderos que han sido miembros durante más de un año, la llamada de
actualización debería ser algo como:

Plain Text View (#)


1. $este_año = date('Y-m-d h:i:s', strtotime('-1 year'));
2. $this->Panadero->updateAll(
3. array('Panadero.approved' => true),
4. array('Panadero.created <=' => "$este_año")
5. );

El array $campos acepta expresiones SQL. Los valores literales deberían ser entrecomillados manualmente.

Por ejemplo, para cerrar todos los tickets que pertenecen a cierto vendedor:

Plain Text View (#)


1. $this->Ticket->updateAll(
2. array('Ticket.estado' => "'cerrado'"),
3. array('Ticket.vendedor_id' => 453)
4. );

saveAll(array $datos = null, array $opciones = array())

Usado para salvar (a) múltiples registros individuales para un único modelo o (b) este registro así como todos los
registros asociados.

69 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Para salvar múltiples registros de un único modelo, $data necesita ser un array de registros indexado numéricamente
como esto:

Array
(
[0] => Array
(
[titulo] => titulo 1
)
[1] => Array
(
[titulo] => titulo 2
)
)

Para salvar un registro junto con su registro relacionado teniendo una asociación hasOne o belognsTo, el array de
datos debería ser como:

Array
(
[Usuario] => Array
(
[nombreusuario] => billy
)
[Perfil] => Array
(
[sexo] => Varon
[ocupacion] => Programador
)
)

Para salvar un registro junto con sus registros relacionados teniendo una asociación hasMany, el array de datos
debería ser como:

Array
(
[Articulo] => Array
(
[titulo] => Mi primer artículo
)
[Comentario] => Array
(
[0] => Array
(
[comentario] => Comment 1
[comentario] => 1
)
[1] => Array
(
[comentario] => Comment 2
[comentario] => 2
)
)
)

3.7.4.1 (#Guardando-Datos-de-Modelos-Relacionados-hasOne-has-1032) Guardando Datos de Modelos Relacionados (hasOne, hasMany, belongsTo)

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1032)


Comparar con el texto original (/es/compare/1032/Guardando-Datos-de-Modelos-Relacionados-hasOne-has)

Mas info sobre traduciones (/es/view/818)

70 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Cuando estamos trabajando con modelos asociados, es importante tener en cuenta que al guardar los datos de un
modelo hay que hacerlo con el correspondiente modelo de CakePHP. Si estás guardando una nueva Entrada y sus
Comentarios asociados, entonces deberías usar ambos modelos, Entrada y Comentario, durante la operación de
guardado.

Si ninguno de los registros de los modelos asociados existe aún (por ejemplo, quieres guardar registros de un nuevo
Usuario y su Perfil relacionado a la vez ), primero necesitarás guardar el modelo primario o padre.

Para tener una idea de cómo funciona esto, imaginemos que tenemos una acción en nuestro controlador de usuarios
UsersController que maneja el guardado de un nuevo usuario y su perfil correspondiente. En la acción de ejemplo
mostrada abajo se asumirá que has POSTeado sufientes datos (usando el FormHelper) para crear un solo Usuario y un
solo Perfil.

Plain Text View (#)


1. <?php
2. function add() {
3. if (!empty($this->data)) {
4. // Podemos guardar los datos de Usuario
5. // deberían estar en: $this->data['Usuario']
6. $this->Usuario->save($this->data);
7. // El ID del nuevo Usuario está ahora en $this->User->id, así que lo
8. // añadimos a los datos a grabar y grabamos el Perfil
9. $this->data['Perfil']['usuario_id'] = $this->Usuario->id;
10. // Como nuestro "Usuario hasOne Perfil", podemos acceder
11. // al modelo Perfil a través del modelo Usuario
12. $this->Usuario->Perfil->save($this->data);
13. }
14. }
15. ?>

Como norma general, cuando trabajamos con asociaciones hasOne, hasMany y belongsTo ('tiene un', 'tiene varios', y
'pertenece a'), todo es cuestión de las claves. La idea básica es coger la clave de un modelo y ponerla en el campo de
clave foránea en el otro. A veces esto puede implica usar el atributo $id de la clase del modelo después de save(),
pero otras veces podría simplemente implicar obtener el ID desde un campo oculto de un formulario POSTeado a una
acción del controlador.

Para complementar el enfoque básico usado arriba, CakePHP también ofrece el método muy útil saveAll, el cual te
permite validar y grabar múltiples modelos de golpe. Además, saveAll provee de soporte transaccional para asegurar
la integridad de los datos en tu base de datos (p.ej. si un modelo falla en la grabación, los otros modelos tampoco
serán grabados).

Para que las transacciones funcionen correctametne en MySQL, tus tablas han de usar el mecanismo InnoDB. Recuerda
que las tablas MyISAM no soportan transacciones.

Veamos cómo podemos usar saveAll() para grabar modelos de Compañía (utilizamos este nombre incorrecto por
motivos didácticos) y Cuenta al mismo tiempo.

Primero, necesitas construir tu formulario tanto para el modelo Compañía como el modelo Cuenta (asumismo que
Compañía hasMany Cuenta).

Plain Text View (#)


1. echo $form->create(Compañía, array('action'=>'add'));
2. echo $form->input('Compañía.nombre', array('label'=>'Nombre de compañía'));
3. echo $form->input('Compañía.descripción');
4. echo $form->input('Compañía.localización');
5. echo $form->input('Cuenta.0.nombre', array('label'=>'Nombre de cuenta'));
6. echo $form->input('Cuenta.0.nombreusuario');
7. echo $form->input('Cuenta.0.email');
8. echo $form->end('Añadir');

Echemos un vistazo a la manera en que hemos nombrado los campos del formulario para el modelo Cuenta. Si
Compañía es nuestro modelo principal, saveAll esperará que los datos de los modelos relacionados (en este caso,
Cuenta) llegue en un formado específico, y teniendo Cuenta.0.nombreCampo es exactamente lo que necesitamos.

71 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

El nombrado de campos de arriba es necesario para la asociación hasMany . Si la asociación entre los modelos es
hasOne, necesitarás usar la notación NombreModelo.nombreCampo para el modelo asociado.

Ahora, en nuestro compañias_controler.php podemos crear una acción add():

Plain Text View (#)


1. function add() {
2. if(!empty($this->data)) {
3. $this->Compañia->saveAll($this->data, array('validate'=>'first'));
4. }
5. }

Esto es todo para ello. Ahora nuestros modelos Compañía y Cuenta serán validados y grabados al mismo tiempo. Una
cosa rápida que comentar aquí es el uso de array('validate'=>'first'): esa opción asegurará que ambos modelos
son validados.

3.7.4.1.1 (#counterCache-Cache-your-count-1033) counterCache - Cache your count()

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1033/counterCache-Cache-
your-count) .. Mas info sobre traduciones (/es/view/818)

This function helps you cache the count of related data. Instead of counting the records manually via find('count'),
the model itself tracks any addition/deleting towards the associated $hasMany model and increases/decreases a
dedicated integer field within the parent model table.

The name of the field consists of the singular model name followed by a underscore and the word "count".

Plain Text View (#)


1. my_model_count

Let's say you have a model called ImageComment and a model called Image, you would add a new INT-field to the image
table and name it image_comment_count.

Here are some more examples:

Model Associated Model Example


User Image users.image_count
Image ImageComment images.image_comment_count
BlogEntry BlogEntryComment blog_entries.blog_entry_comment_count

Once you have added the counter field you are good to go. Activate counter-cache in your association by adding a
counterCache key and set the value to true.

Plain Text View (#)


1. class Image extends AppModel {
2. var $belongsTo = array(
3. 'ImageAlbum' => array('counterCache' => true)
4. );
5. }

From now on, every time you add or remove a Image associated to ImageAlbum, the number within image_count is
adjusted automatically.

You can also specify counterScope. It allows you to specify a simple condition which tells the model when to update
(or when not to, depending on how you look at it) the counter value.

Using our Image model example, we can specify it like so:

Plain Text View (#)

72 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. class Image extends AppModel {


2. var $belongsTo = array(
3. 'ImageAlbum' => array(
4. 'counterCache' => true,
5. 'counterScope' => array('Image.active' => 1) // only count if "Image" is active = 1
6. ));
7. }

3.7.4.2 (#Guardando-Datos-de-Modelos-Relacionados-HABTM-1034) Guardando Datos de Modelos Relacionados (HABTM)

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1034)


Comparar con el texto original (/es/compare/1034/Guardando-Datos-de-Modelos-Relacionados-HABTM)

Mas info sobre traduciones (/es/view/818)

Grabar modelos que están asociados por hasOne, belongsTo y hasMany es bastante simple: simplemente rellenas el
campo de clave foránea con el ID del modelo asociado. Una vez que está hecho, simplemente llamas al método save()
del modelo y todo queda enlazado correctamente.

Con HABTM (Has And Belongs To Many ), necesitas establecer el ID del modelo asociado en tu array de datos.
Construiremos un formulario que crea una nueva etiqueta y la asocia al vuelo con alguna receta.

El formulario más simple debería parecerse al algo como esto (asumimos que $receta_id ya está establecido a algo):

Plain Text View (#)


1. <?php
2. echo $form->create('Etiqueta');
3. echo $form->input('Receta.id', array('type'=>'hidden', 'value' => $receta_id));
4. echo $form->input('Etiqueta.nombre');
5. echo $form->end('Añadir etiqueta');
6. ?>

En este ejemplo, puedes ver el campo oculto Receta.id cuyo valor se establece al ID de la receta a la que queremos
enlazar la etiqueta. La acción del controlador que se encarga de guardar este formulario es muy simple:

Plain Text View (#)


1. function add() {
2. // Graba la asociación
3. if ($this->Etiqueta->save($this->data)) {
4. // Hacer algo si todo fue bien
5. }
6. }

Y de esa manera, nuestra nueva Etiqueta es creada y asociada con Receta, cuyo ID estaba en $this->data['Receta']['id'].

3.7.5 (#Borrando-Datos-1035) Borrando Datos

Estos métodos pueden ser usados para eliminar datos.

3.7.5.1 (#del-1036) del

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1036)


Comparar con el texto original (/es/compare/1036/del)

Mas info sobre traduciones (/es/view/818)

del(int $id = null, boolean $cascada = true);

Borra el registro identificado por $id. Por defecto, también borra los registros dependientes del registro especificado
a ser borrado.

73 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Por ejemplo, cuando se borra un registro Usuario que está ligado a varios registros Receta:

si $cascada está establecido a true, los registros Receta relacionados también son borrados si el valor de
dependent (ver la sección hasMany (/es/view/82/hasMany) ) en el modelo está establecida a true.
si $cascada está establecido a false, los registros Receta permanecerán después de que el Usuario haya sido
borrado.

3.7.5.2 (#deleteAll-1038) deleteAll

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1038)


Comparar con el texto original (/es/compare/1038/deleteAll)

Mas info sobre traduciones (/es/view/818)

deleteAll(mixed $condiciones, $cascada = true)

De la misma manera que del() y remove(), excepto que deleteAll() borra todos los registros que cumplen las
condiciones dadas. El array $condiciones debería ser pasado como un fragmento SQL o array.

3.7.6 (#Asociaciones-Enlazando-Modelos-1039) Asociaciones: Enlazando Modelos

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1039)


Comparar con el texto original (/es/compare/1039/Asociaciones-Enlazando-Modelos)

Mas info sobre traduciones (/es/view/818)

Una de las características más potentes de CakePHP es la habilidad para enlazar el mapeado relacional proporcionado
por el modelo. En CakePHP, los enlaces entre modelos son manejados mediante asociaciones.

Definir relaciones entre diferentes objetos en tu aplicación debería ser un proceso natural. Por ejemplo, en una base
de datos de recetas, una receta puede tener varias revisiones, las revisiones tienen un único autor, y los autores
pueden tener varias recetas. El definir la manera en que funcionan estas relaciones te permite acceder a tus datos de
manera intuitiva y potente.

El propósito de esta sección es mostrarte cómo diseñar, definir y utilizar asociaciones entre modelos en CakePHP.

Mientras que los datos pueden provenir de una variedad de orígenes, la formá más común de almacenamiento en
aplicaciones web es una base de datos relacional. La mayoría de cosas que cubre esta sección estará en ese contexto.

Para obtener información sobre asociaciones con modelos de Plugin, ver Plugin Models (/view/117/Plugin-Models) .

3.7.6.1 (#Tipos-de-Relaciones-1040) Tipos de Relaciones

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1040)


Comparar con el texto original (/es/compare/1040/Tipos-de-Relaciones)

Mas info sobre traduciones (/es/view/818)

Los cuatro tipos de relaciones en CakePHP son: hasOne, hasMany , belongsTo y hasAndBelongsToMany (HABTM),
"tiene un", "tiene muchos", "pertenece a" y "tiene y pertenece a muchos", respectivamente.

Relación Tipo de Asociación Ejemplo


uno a uno hasOne ("tiene un") Un usuario tiene un perfil.
Los usuarios en un sistema pueden tener múltiples
uno a muchos hasMany ("tiene muchos")
recetas.
muchos a uno belongsTo ("pertenece a") Una receta pertenece a un usuario.
muchos a hasAndBelongsToMany ("tiene y pertenece a Las recetas tienen, y pertenecen, a muchas
muchos muchos") etiquetas.

Las asociaciones son definidas creando una variable de clase nombrada tras la asociación que estás definiendo. La

74 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

variable de clase puede, a veces, ser tan simple como una cadena de caracteres, pero puede ser tan completa como un
array multidimensional usado para definir asociaciones concretas.

Plain Text View (#)


1. <?php
2. class Usuario extends AppModel {
3. var $name = 'Usuario';
4. var $hasOne = 'Pefil';
5. var $hasMany = array(
6. 'Receta' => array(
7. 'className' => 'Receta',
8. 'conditions' => array('Receta.aprobada' => '1'),
9. 'order' => 'Receta.created DESC'
10. )
11. );
12. }
13. ?>

En el ejemplo de arriba, la primera instancia de la palabra 'Receta' es lo que se llama un 'Alias'. Este es un identificador
para la relación y puede ser cualquier cosa que escojas. Normalmente, escogerás el mismo nombre que la clase que
referencia. De todos modos, los alias han de ser únicos dentro de un modelo dado y en ambas partes de una relación
belongsTo / hasMany o belongsTo/hasOne. Escoger nombres no únicos para alias puede causar comportamiento
inesperados.

3.7.6.2 (#hasOne-1041) hasOne

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1041)


Comparar con el texto original (/es/compare/1041/hasOne)

Mas info sobre traduciones (/es/view/818)

Configuremos un modelo Usuario con una relación hasOne con un modelo Perfil.

Primero, necesitas establecer las claves de tus tablas de base de datos correctamente. Para que funcione una relación
hasOne correctamente, una tabla ha de contener una clave foránea que apunte a un registro en la otra. En este caso, la
tabla 'perfiles' contendrá un campo llamado usuario_id. El patrón básico es:

hasOne: el otro modelo contiene la clave


foránea.
Relación Esquema
Manzana hasOne Plátano plananos.manzana_id
Usuario hasOne Perfil perfiles.usuario_id
Doctor hasOne Mentor mentores.doctor_id

El archivo del modelo Usuario será grabado en /app/models/usuario.php. Para definir la asociación 'Usuario hasOne
Perfil', añade la propiedad $hasOne a la clase del modelo. Recuerda tener un modelo Perfil en /app/models/perfil.php,
o la asociación no funcionará.

Plain Text View (#)


1. <?php
2. class Usuario extends AppModel {
3. var $name = 'Usuario';
4. var $hasOne = 'Perfil';
5. }
6. ?>

Hay dos manera de describir esta relación en tus archivos del modelo. La manera más simple es establecer el atributo
$hasOne a una cadena de caracteres conteniendo el nombre de la clase del modelo asociado, como hemos hecho
arriba.

Si necesitas más control, puedes definir tus asociaciones utilizando sintaxis de arrays. Por ejemplo, podrías desear

75 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

limitar la asociación para incluir sólo ciertos registros.

Plain Text View (#)


1. <?php
2. class Usuario extends AppModel {
3. var $name = 'Usuario';
4. var $hasOne = array(
5. 'Perfil' => array(
6. 'className' => 'Perfil',
7. 'conditions' => array('Perfil.publicado' => '1'),
8. 'dependent' => true
9. )
10. );
11. }
12. ?>

Las claves posibles para los arrays de asociaciones hasOne incluyen:

className: el nombre de la clase del modelo que está siendo asociado al modelo actual. si estás definiendo
una relación 'Usuario hasOne Perfil', la clave className debería ser igual a 'Perfil'.
foreignKey: el nombre de la clave foránea que se encuentra en el otro modelo. Esto es especialmente útil si
necesitas definir múltiples relaciones hasOne. El valor por defecto para esta clave es el nombre en singular del
modelo actual, seguido del sufijo '_id'. En el ejemplo de arriba, debería ser por defecto 'usuario_id'.
conditions: Un fragmento SQL usado para filtrar registros del modelo relacionado. Es buena práctica usar
nombres de modelos en los fragmentos SQL: 'Perfil.aprobado = 1' siempre es mejor que simplemente 'aprobado
= 1'.
fields: Una lista de campos a ser devueltos cuando se traen los datos del modelo asociado. Por defecto
devuelve todos los campos.
dependent: Cuando la clave dependent se establece a true, y el método delete() del modelo es llamado con el
parámetro $cascada con valor true, los registros del modelo asociado también son borrados. En este caso lo
ponemos a true de manera que borrando un Usuario también borrará su Perfil asociado.

Una vez que esta asociación ha sido definida, las operaciones de búsqueda en el modelo usuario traerán también el
registro Perfil relacionado si existe:

// Resultados de ejemplo de una llamada a $this->Usuario->find()


Array
(
[Usuario] => Array
(
[id] => 121
[name] => Gwoo the Kungwoo
[created] => 2007-05-01 10:31:01
)
[Perfil] => Array
(
[id] => 12
[user_id] => 121
[habilidad] => Hornear Pasteles
[created] => 2007-05-01 10:31:01
)
)

3.7.6.3 (#belongsTo-1042) belongsTo

Ahora que tenemos acceso a los datos de Perfil desde el modelo Usuario, definamos la asociación belongsTo
(perteneceA) en el modelo Perfil para tener acceso a los datos de Usario relacionados. La asociación belongsTo es un
complemento natural a las asociaciones hasOne (tieneUn) y hasMany (tieneMuchos): nos permite ver los datos de la
otra dirección.

A la hora de establecer las claves de las tablas de tu base de datos para una relación belongsTo , sigue estas
convenciones:

76 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

belongsTo: el modelo actual contiene la clave


foránea.
Relación Esquema
Platano belongsTo Manzana platanos.manzana_id
Perfil belongsTo Usuario perfiles.usuarios_id
Mentor belongsTo Doctor mentores.doctores_id

Si un modelo (tabla) contiene una clave foránea, "perteneceA" (belongsTo ) el otro modelo (tabla).

Podemos definir la asociación belongsTo en nuestro modelo Perfil en /app/models/perfil.php usando la sintaxis de
cadena de caracteres así:

Plain Text View (#)


1. <?php
2. class Perfil extends AppModel {
3. var $name = 'Perfil';
4. var $belongsTo = 'Usuario';
5. }
6. ?>

También podemos definir una relación más específica usando sintaxis de arrays:

Plain Text View (#)


1. <?php
2. class Perfil extends AppModel {
3. var $name = 'Perfil';
4. var $belongsTo = array(
5. 'Usuario' => array(
6. 'className' => 'Usuario',
7. 'foreignKey' => 'usuario_id'
8. )
9. );
10. }
11. ?>

Claves posibles para los arrays de la asociación belongsTo son:

className: el nombre de la clase del modelo que se está asociando al modelo actual. Si estás definiendo una
relación 'Perfil belongsTo Usuario', la clave className ha de tener el valor 'Usuario'.
foreignKey: el nombre de la clave foránea que se encuentra en el modelo actual. Esto es especialmente útil si
necesitas definir múltiples relaciones belongsTo . El valor por defecto de esta clave es el nombre en singular
del otro modelo (separado por guiones de subrayado) con el sufijo '_id'.
conditions: el fragmento SQL filtra los registros del modelo relacionado. Es buena práctica usar el nombre de
los modelos en los fragmentos SQL: 'Usuario.activo = 1' siempre es mejor que simplemente 'activo = 1'.
fields: lista de campos a ser recuperados cuando los datos del modelo asociado se traen de la base de datos.
Por defecto devuelve todos los campos.
counterCache: (booleano) si se establece a true, el modelo asociado automáticamente incrementará o
decrementará el campo '[nombre_modelo_en_singular]_count' de la tabla foránea siempre que hagas un save()
o delete() (ver counterCache (/es/view/490/counterCache-Cachea-tu-count) ). El valor en el campo contador
representa el número de filas relacionadas.

Una vez que esta asociación ha sido definida, las operaciones de búsqueda en el modelo Perfil también traerán el
registro de Usuario relacionado si existe:

// Resultados de ejemplo de la llamada a $this->Perfil->find().


Array
(
[Perfil] => Array
(
[id] => 12
[usuario_id] => 121
[habilidad] => Baking Cakes

77 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

[created] => 2007-05-01 10:31:01


)
[Usuario] => Array
(
[id] => 121
[name] => Gwoo the Kungwoo
[created] => 2007-05-01 10:31:01
)
)

3.7.6.4 (#hasMany-1043) hasMany

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1043)


Comparar con el texto original (/es/compare/1043/hasMany)

Mas info sobre traduciones (/es/view/818)

Siguiente paso: definiendo una asociación "Usuario hasMany Comentario". Una asociación hasMany (tieneMuchos) nos
permitirá traer los comentarios del usuario cuando se trae un registro Usuario.

A la hora de establecer las claves de las tablas de tu base de datos para una relación hasMany , sigue estas
convenciones:

hasMany: el otro modelo contiene la clave foránea.


Relación Esquema
Usuario hasMany Comentario comentarios.usuario_id
Cake hasMany Virtud virtudes.cake_id
Producto hasMany Opcion opciones.producto_id

Podemos definir la asociación hasMany en nuestro modelo Usuario en /app/models/usuario.php usando la sintaxis de
cadena de caracteres así:

Plain Text View (#)


1. <?php
2. class Usuario extends AppModel {
3. var $name = 'Usuario';
4. var $hasMany = 'Comentario';
5. }
6. ?>

También podemos definir una relación más específica usando sintaxis de arrays:

Plain Text View (#)


1. <?php
2. class Usuario extends AppModel {
3. var $name = 'Usuario';
4. var $hasMany = array(
5. 'Comentario' => array(
6. 'className' => 'Comentario',
7. 'foreignKey' => 'usuario_id',
8. 'conditions' => array('Comentario.estado' => '1'),
9. 'order' => 'Comentario.created DESC',
10. 'limit' => '5',
11. 'dependent'=> true
12. )
13. );
14. }
15. ?>

Las claves posibles para los arrays de la asociación hasMany son:

78 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

className: el nombre de la clase del modelo que está siendo relacionado con el modelo actual. Si estás
definiendo una relación 'Usuario hasMany Comentario', el valor de clasName ha de ser 'Comentario'.
foreignKey: el nombre de la clave foránea en el otro modelo. Esto es especialmente útil si necesitas definir
múltiples relaciones hasMany . El valor por defecto para esta clave es el nombre en singular del otro modelo
(separado por guiones de subrayado), con el sufijo '_id'.
conditions: un fragmento SQL filtra los registros del modelo relacionado. Es buena práctica usar el nombre de
los modelos en los fragmentos SQL: 'Usuario.activo = 1' siempre es mejor que simplemente 'activo = 1'.
fields: lista de campos a ser recuperados cuando los datos del modelo asociado se traen de la base de datos.
Por defecto devuelve todos los campos.
order: un fragmento SQL que define el orden de las filas asociadas devueltas.
limit: el número máximo de filas asociadas que quieres que devuelva.
offset: el número de filas asociadas que quieres saltarte (dadas las condiciones y orden actuales) antes de traer
las filas y asociarlas.
dependent: Cuando dependent se establece a true, es posible el borrado recursivo del modelo. En este ejemplo,
los registros Comentario serán borrados cuando sus registros Usuario asociados han sido borrados.

El segundo parámetro del método Modelo->delete() ha de establecerse a true para que ocurra un borrado
recursivo.

finderQuery: Una consulta SQL completa que CakePHP puede usar para traer los registros del modelo asociado.
Esto debería ser usado en situaciones que requieren unos resultados muy personalizados.

Una vez que esta asociación ha sido definida, las operaciones de búsqueda en el modelo Usuario también traerán los
registros Comentario relacionados si existen:

// Resultados de ejemplo de llamada a $this->Usuario->find().


Array
(
[Usuario] => Array
(
[id] => 121
[name] => Gwoo the Kungwoo
[created] => 2007-05-01 10:31:01
)
[Comentario] => Array
(
[0] => Array
(
[id] => 123
[usuario_id] => 121
[title] => On Gwoo the Kungwoo
[cuerpo] => The Kungwooness is not so Gwooish
[created] => 2006-05-01 10:31:01
)
[1] => Array
(
[id] => 123
[usuario_id] => 121
[title] => More on Gwoo
[cuerpo] => But what of the ‘Nut?
[created] => 2006-05-01 10:41:01
)
)
)

Algo a recordar es que necesitarás la asociación complementaria 'Comentario belongsTo Usuario' para obtener los
datos en ambas direcciones. Lo que hemos esbozado en esta sección te permite obtener datos de Comentario desde
Usuario. Añadir la asociación 'Comentario belongsTo Usuario' en el modelo comentario te permite obtener los datos
de Usuario desde el modelo Comentario, completando la conexión y permitiendo el flujo de la información desde
ambas perspectivas del modelo.

3.7.6.5 (#hasAndBelongsToMany-HABTM-1044) hasAndBelongsToMany (HABTM)

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

79 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Ver que ha cambiado (/es/nodes/redirect_to_revision/1044)


Comparar con el texto original (/es/compare/1044/hasAndBelongsToMany-HABTM)

Mas info sobre traduciones (/es/view/818)

Perfecto. En este punto puedes llamarte "profesional de asociaciones del modelo de CakePHP". Ya estás versado en tres
de las asociaciones que tratan la mayoría de las relaciones de objetos.

Tratemos el último tipo de relación: hasAndBelongsToMany (tieneYPerteneceAMuchos), o HABTM. Esta asociación es


usada cuando tienes dos modelos que necesitas unir, repetidamente, muchas veces, de muchas maneras distintas.

La principal diferencia entre hasMany y HABTM es que un enlace entre modelos en HABTM no es exclusivo. Por
ejemplo, vamos a unir nuestro modelo Receta con un modelo Etiqueta usando HABTM. Atando la etiqueta 'Italiano' a la
receta 'Gnocci' de mi abuela no 'acapara' la etiqueta; también puedo etiquetar con 'Italiano' mis 'Espaguettis a la
barbacoa con miel glaseada".

Los enlaces entre objetos asociados mediante hasMany son exclusivos. Si mi 'Usuario hasMany Comentarios', un
comentario está sólo enlazado a un usuario específico. Deja de estar disponible para todos.

Andando. Necesitaremos establecer una tabla extra en la base de datos para manejar las asociaciones HABTM. El
nombre de esta nueva tabla de unión necesita incluir los nombres de ambos modelos involucrados en plural, en
orden alfabético, y separados por un guión de subrayado ( _ ). El esquema de la tabla debería contener como mínimo
dos campos, cada uno clave foránea (que deberían ser enteros) apuntando a ambas claves primarias de los modelos
involucrados.

HABTM necesita una tabla de unión separada que incluya los nombres de ambos modelos.

Relación Esquema
Receta HABTM Etiqueta id, etiquetas_recetas.receta_id, etiquetas_recetas.etiqueta_id
Cake HABTM Fan id, cakes_fans.cake_id, cakes_fans.fan_id
Foo HABTM Bar id, bars_foos.foo_id, bars_foos.bar_id

Los nombres de las tablas están, por convención, en orden alfabético.

Una vez que esta nueva tabla ha sido creada, podemos definir las asociaciones HABTM en los ficheros del modelo.
Vamos a saltar directamente a la sintaxis de arrays esta vez:

Plain Text View (#)


1. <?php
2. class Receta extends AppModel {
3. var $name = 'Receta';
4. var $hasAndBelongsToMany = array(
5. 'Etiqueta' =>
6. array('className' => 'Etiqueta',
7. 'joinTable' => 'etiquetas_recetas',
8. 'foreignKey' => 'receta_id',
9. 'associationForeignKey' => 'etiqueta_id',
10. 'with' => '',
11. 'conditions' => '',
12. 'order' => '',
13. 'limit' => '',
14. 'unique' => true,
15. 'finderQuery' => '',
16. 'deleteQuery' => '',
17. 'insertQuery' => ''
18. )
19. );
20. }
21. ?>

Claves posibles para los arrays de asociaciones HABTM son:

className: el nombre de la clase del modelo que se está asociando al modelo actual. Si estás definiendo una
relación 'Usuario hasAndBelongsToMany Comentarios', className debería ser igual a 'Comentario'.

80 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

joinTable: el nombre de la tabla de unión usuada en esta asociación (si si la tabla actual no se adhiere a la
convención de nombrado para tablas de unión HABTM).
foreignKey: el nombre de la clave foránea que se encuentra en el modelo actual. Esto es especialmente útil si
necesitas definir múltiples relaciones HABTM. El valor por defecto para esta clave es el nombre en singular,
separado por guiones de subrayado (_), del modelo actual con el sufijo '_id'.
associationForeignKey: el nombre de la clave foránea que se encuentra en el otro modelo. Esto es
especialmente útil si necesitas definir múltiples relaciones HABTM. El valor por defecto para esta clave es el
nombre en singulas, separado por guiones de subrayado (_), del modelo actual con el sufijo '_id'.
with: define el nombre del modelo para la tabla de unión. Por defecto, CakePHP autocreará un modelo por ti.
Usando el ejemplo de arriba, se llamaría EtiquetaReceta. Usando esta clave puedes sustituir este nombre por
defecto. El modelo de la tabla de unión puede ser usado como cualquier modelo 'regular' para acceder a la
tabla de unión directamente
conditions: fragmento SQL usado para filtrar registros del modelo relacionado. Es buena práctica usar nombres
de modelos en los fragmentos SQL: 'Comentario.estado = 1' siempre es preferible a simplemente 'estado = 1'.
fields: lista de campos a ser devueltos cuando los datos del modelo asociado son traídos. Devuelve todos los
campos por defecto.
order: fragmento SQL que define el orden de las filas asociadas devueltas.
limit: el número máximo de filas asociadas que deseas que sean devueltas.
unique: si tiene el valor true (valor por defecto) Cake borrará primero los registros de relación existentes en la
tabla de claves foráneas antes de insertar nuevas filas, cuando se actualiza un registro. Así, las asociaciones
existentes deberán ser pasadas de nuevo durante las actualizaciones.
offset: el número de filas asociadas que omitir (dadas las condiciones actuales y orden) antes de buscar y
asociar.
finderQuery, deleteQuery, insertQuery: una consulta SQL completa que CakePHP puede usar para buscar, borrar
o crear nuevos registros del modelo asociado. Esto debería ser usado en situaciones que requieren resultados
muy personalizados.

Una vez que esta asociación ha sido definida, las operaciones de búsqueda en el modelo Receta también devolverán
los registros Etiqueta relacionados si existen:

// Resultados de ejemplo de una llamada a $this->Receta->find().

Array
(
[Receta] => Array
(
[id] => 2745
[name] => Bombas de Cholocate con Azúcar Glaseada
[created] => 2007-05-01 10:31:01
[usuario_id] => 2346
)
[Etiqueta] => Array
(
[0] => Array
(
[id] => 123
[name] => Desayuno
)
[1] => Array
(
[id] => 124
[name] => Postre
)
[2] => Array
(
[id] => 125
[name] => Enfermedad del Corazón
)
)
)

Recuerda definir una asociación HABTM en el modelo Etiqueta si quieres traer datos de Receta cuando uses el modelo
Etiqueta.

81 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

También es posible ejecutar consultas de búsqueda personalizadas basadas en relaciones HABTM. Considera los
ejemplos siguientes:

Asumiendo la misma estructura en el ejemplo de arriba (Receta HABTM Etiqueta), digamos que queremos obtener
todas las Recetas con la etiqueta 'Postre', una manera potencial (pero errónea) de conseguirlo sería aplicar una
condición a la misma asociación:

Plain Text View (#)


1. $this->Receta->bindModel(array(
2. 'hasAndBelongsToMany' => array(
3. 'Etiqueta' => array(
4. 'conditions'=>array('Etiqueta.name'=>'Postre') )
5. )
6. )
7. );
8. $this->Receta->find('all');

// Datos devueltos
Array
(
0 => Array
{
[Receta] => Array
(
[id] => 2745
[name] => Bombas de Cholocate con Azúcar Glaseada
[created] => 2007-05-01 10:31:01
[usuario_id] => 2346
)
[Etiqueta] => Array
(
[0] => Array
(
[id] => 124
[name] => Postre
)
)
)
1 => Array
{
[Receta] => Array
(
[id] => 2745
[name] => Pasteles de Cangrejo
[created] => 2008-05-01 10:31:01
[usuario_id] => 2349
)
[Etiqueta] => Array
(
}
}
}

Notar que este ejemplo devuelve TODAS las recetas pero sólo la etiqueta 'Postre'. Para conseguir nuestro objetivo
adecuadamente, hay diversas maneras de hacerlo. Una opción es buscar en el modelo Etiqueta (en vez de Receta), lo
que nos dará también todas las Recetas asociadas.

Plain Text View (#)


1. $this->Receta->Tag->find('all', array('conditions'=>array('Etiqueta.name'=>'Postre')));

Podríamos también usar el modelo de tabla de unión (que CakePHP nos provee), para buscar por un ID dado.

82 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Plain Text View (#)


1. $this->Receta->bindModel(array('hasOne' => array('EtiquetaReceta')));
2. $this->Receta->find('all', array(
3. 'fields' => array('Receta.*'),
4. 'conditions'=>array('EtiquetaReceta.etiqueta_id'=>124) // id de Postre
5. ));

También es posible crear una asociación exótica con el propósito de crear tantas uniones como necesarias para
permitir el filtrado, por ejemplo:

Plain Text View (#)


1. $this->Receta->bindModel(
2. array(
3. 'hasOne' => array(
4. 'EtiquetaReceta',
5. 'EtiquetaFiltro' => array(
6. 'className' => 'Tag',
7. 'foreignKey' => false,
8. 'conditions' => array('EtiquetaFiltro.id = EtiquetaReceta.id')
9. )
10. )
11. )
12. );
13. $this->Receta->find('all', array(
14. 'fields' => array('Receta.*'),
15. 'conditions'=>array('EtiquetaReceta.name'=>'Postre')
16. ));

Ambos devolverán los siguientes datos:

// Datos devueltos
Array
(
0 => Array
{
[Receta] => Array
(
[id] => 2745
[name] => Bombas de Cholocate con Azúcar Glaseada
[created] => 2007-05-01 10:31:01
[usuario_id] => 2346
)
[Etiqueta] => Array
(
[0] => Array
(
[id] => 123
[name] => Desayuno
)
[1] => Array
(
[id] => 124
[name] => Postre
)
[2] => Array
(
[id] => 125
[name] => Enfermedad del corazón
)
)

83 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Para más información sobre asociaciones de modelo ligadas al vuelo mira Creando y Destruyendo Asociaciones al
Vuelo (/es/view/86/)

Mezcla y encaja técnicas para conseguir tu objetivo específico.

3.7.6.6 (#Creando-y-Destruyendo-Asociaciones-al-Vuelo-1045) Creando y Destruyendo Asociaciones al Vuelo

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1045)


Comparar con el texto original (/es/compare/1045/Creando-y-Destruyendo-Asociaciones-al-Vuelo)

Mas info sobre traduciones (/es/view/818)

Algunas veces es necesario crear y destruir asociaciones del modelo al vuelo. Esto puede ser por varias razones:

Quieres reducir la cantidad de datos asociados buscados, pero todas tus asociaciones están en el primer nivel
de recursión.
Deseas cambiar la manera en que la asociación está definida para ordenar o filtar los datos asociados.

Esta creación y destrucción de asociaciones se realiza usando los métodos del modelo de CakePHP bindModel() y
unbindModel(). También hay un comportamiento muy útil llamado 'Containable', mirar la sección del manual sobre
comportamientos empotrados para más información. Establezcamos unos pocos modelos para que podamos ver
cómo funcionan bindModel() y unbindModel(). Empezaremos con dos modelos:

Plain Text View (#)


1. <?php
2. class Lider extends AppModel {
3. var $name = 'Lider';
4.
5. var $hasMany = array(
6. 'Seguidor' => array(
7. 'className' => 'Seguidor',
8. 'order' => 'Seguidor.rango'
9. )
10. );
11. }
12. ?>
13.
14. <?php
15. class Seguidor extends AppModel {
16. var $name = 'Seguidor';
17. }
18. ?>

Ahora, en el LideresController podemos usar el método find() en el modelo Lider para obtener un lider y sus
seguidores asociados. Como puedes ver arriba, el array de asociación en el modelo Lider define una relación 'Lider
hasMany Seguidores'. Por motivos demostrativos, usemos unbindModel() para eliminar esa asociación en una acción
de un controlador

Plain Text View (#)

84 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. function algunaAccion() {
2. // Esto obtiene Lideres, y sus Seguidores asociados
3. $this->Lider->findAll();
4.
5. // Eliminemos el hasMany...
6. $this->Lider->unbindModel(
7. array('hasMany' => array('Seguidor'))
8. );
9.
10. // Ahora usar una funcion find devolverá
11. // Lideres, sin Seguidores
12. $this->Lider->findAll();
13.
14. // NOTE: unbindModel sólo afecta la siguiente función
15. // function. Una llamada adicional a find usará la
16. // información de la asociación configurada.
17.
18. // Hemos uado findAll() tras unbindModel(),
19. // así que esto obtendrá Lideres con Seguidores asociados
20. // una vez más...
21. $this->Lider->findAll();
22. }

Eliminar o añadir asociaciones usando bind- y unbindModel() sólo funciona para la operación del modelo next() a
menos que el segundo parámetro haya sido establecido a false. Si el segundo parámetro ha sido establecido a false,
la unión se mantiene para el resto de la petición.

Aquí está el patrón básico de uso para unbindModel():

Plain Text View (#)


1. $this->Modelo->unbindModel(
2. array('tipoAsociacion' => array('nombreDeClaseDelModeloAsociado'))
3. );

Ahora que hemos eliminado satisfactoriamente una asociación al vuelo, añadamos otra. Nuestro Lider 'sin todavía'
principios necesita algunos Principios asociados. El fichero del modelo para nuestro modelo Principio está vacío,
excepto por la declaración var $name. Asociemos algunos Principios a nuestro Lider al vuelo (pero recuerda, sólo
para la siguiente operación de búsqueda). Esta función aparece en LiderController:

Plain Text View (#)

85 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. function otraAccion() {
2. // No hay 'Lider hasMany Principio' en
3. // el fichero de modelo lider.php, asi que una búsqueda
4. // aquí sólo obtiene Lideres.
5. $this->Lider->findAll();
6.
7. // Usemod bindModel() para añadir una nueva asociación
8. // al modelo Lider:
9. $this->Lider->bindModel(
10. array('hasMany' => array(
11. 'Principio' => array(
12. 'className' => 'Principio'
13. )
14. )
15. )
16. );
17.
18. // Ahora que hemos asociado correctamente,
19. // podemos usar una función de búsqueda para obtener
20. // Lideres con sus principios asociados:
21. $this->Lider->findAll();
22. }

Ahí lo tienes. El uso básico para bindModel() es la encapsulación de un array normal de asociación dentro de un
array cuya clave es nombrada tras el tipo de asociación que estás tratando de crear:

Plain Text View (#)


1. $this->Modelo->bindModel(
2. array('nombreAsociacion' => array(
3. 'nombreDeClaseDelModeloAsociado' => array(
4. // claves de asociacion normales van aquí...
5. )
6. )
7. )
8. );

A pesar de que el nuevo modelo unido no necesita ningún tipo de asociación en la definición de su fichero de
modelo, todavía necesitará tener la clave correcta para que la nueva asociación funcione correctamente.

3.7.6.7 (#Multiples-relaciones-al-mismo-modelo-1046) Multiples relaciones al mismo modelo

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1046)


Comparar con el texto original (/es/compare/1046/Multiples-relaciones-al-mismo-modelo)

Mas info sobre traduciones (/es/view/818)

Hay casos en los que un Modelo tiene más de una relación a otro Modelo. Por ejemplo podrías tener un Modelo
Mensaje que tiene dos relaciones al Modelo Usuario. Una relación con el usuario que envía el mensaje y una segunda
relación con el usuario que recibe el mensaje. La tabla mensaje tendrá el campo usuario_id, pero tendrá además un
campo receptor_id. Tu Modelo Mensaje luciría así::

Plain Text View (#)

86 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <?php
2. class Mensaje extends AppModel {
3. var $name = 'Mensaje';
4. var $belongsTo = array(
5. 'Emisor' => array(
6. 'className' => 'Usuario',
7. 'foreignKey' => 'usuario_id'
8. ),
9. 'Receptor' => array(
10. 'className' => 'Usuario',
11. 'foreignKey' => 'receptor_id'
12. )
13. );
14. }
15. ?>

Receptor es un alias para el Modelo Usuario. Ahora veamos como se vería el Modelo Usuario.

Plain Text View (#)


1. <?php
2. class Usuario extends AppModel {
3. var $name = 'Usuario';
4. var $hasMany = array(
5. 'MensajeEnviado' => array(
6. 'className' => 'Mensaje',
7. 'foreignKey' => 'usuario_id'
8. ),
9. 'MensajeRecibido' => array(
10. 'className' => 'Mensaje',
11. 'foreignKey' => 'receptor_id'
12. )
13. );
14. }
15. ?>

3.7.6.8 (#Joining-tables-1047) Joining tables

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1047/Joining-tables) .. Mas info
sobre traduciones (/es/view/818)

In SQL you can combine related tables using the JOIN statement. This allows you to perform complex searches across
multiples tables (i.e: search posts given several tags).

In CakePHP some associations (belongsTo and hasOne) performs automatic joins to retrieve data, so you can issue
queries to retrieve models based on data in the related one.

But this is not the case with hasMany and hasAndBelongsToMany associations. Here is where forcing joins comes to
the rescue. You only have to define the necessary joins to combine tables and get the desired results for your query.

To force a join between tables you need to use the "modern" syntax for Model::find(), adding a 'joins' key to the
$options array. For example:

Plain Text View (#)

87 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. $options['joins'] = array(
2. array('table' => 'channels',
3. 'alias' => 'Channel',
4. 'type' => 'LEFT',
5. 'conditions' => array(
6. 'Channel.id = Item.channel_id',
7. )
8. )
9. );
10. $Item->find('all', $options);

Note that the 'join' arrays are not keyed.

In the above example, a model called Item is left joined to the channels table. You can alias the table with the Model
name, so the retrieved data complies with the CakePHP data structure.

The keys that define the join are the following:

table: The table for the join.


alias: An alias to the table. The name of the model associated with the table is the best bet.
type: The type of join: inner, left or right.
conditions: The conditions to perform the join.

With joins, you could add conditions based on Related model fields:

Plain Text View (#)


1. $options['joins'] = array(
2. array('table' => 'channels',
3. 'alias' => 'Channel',
4. 'type' => 'LEFT',
5. 'conditions' => array(
6. 'Channel.id = Item.channel_id',
7. )
8. )
9. );
10. $options['conditions'] = array(
11. 'Channel.private' => 1
12. );
13. $privateItems = $Item->find('all', $options);

You could perform several joins as needed in hasBelongsToMany:

Suppose a Book hasAndBelongsToMany Tag association. This relation uses a books_tags table as join table, so you
need to join the books table to the books_tags table, and this with the tags table:

Plain Text View (#)

88 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. $options['joins'] = array(
2. array('table' => 'books_tags',
3. 'alias' => 'BooksTag',
4. 'type' => 'inner',
5. 'conditions' => array(
6. 'Books.id = BooksTag.books_id'
7. )
8. ),
9. array('table' => 'tags',
10. 'alias' => 'Tag',
11. 'type' => 'inner',
12. 'conditions' => array(
13. 'BooksTag.tag_id = Tag.id'
14. )
15. )
16. );
17. $options['conditions'] = array(
18. 'Tag.tag' => 'Novel'
19. );
20. $books = $Book->find('all', $options);

Using joins with Containable behavior could lead to some SQL errors (duplicate tables), so you need to use the joins
method as an alternative for Containable if your main goal is to perform searches based on related data. Containable
is best suited to restricting the amount of related data brought by a find statement.

3.7.7 (#Métodos-Callback-1048) Métodos Callback

Si necesitas colar alguna lógica justo antes o después de una operación de modelo de CakePHP, utiliza los callbacks
del modelo (funciones de retrollamada). Estas funciones pueden ser definidas en clases del modelo (incluido tu
AppModel). Asegúrate de mirar el valor de retorno esperado para cada una de estas funciones especiales.

3.7.7.1 (#beforeFind-1049) beforeFind

beforeFind(mixed $datosConsulta)

Llamado antes de cualquier operación relacionada con búsquedas. Los datos de consulta $datosConsulta pasados a
este callback contienen información sobre la consulta actual: condiciones, campos, etc.

Si no deseas que la operación de búsqueda comience (posiblemente basado en una decisión relacionada con las
opciones de $datosConsulta), devuelve false. De lo contrario, devuleve $datosConsulta posiblemente modificado, o
cualquier cosa que quieras pasar a la búsquea y sus homólogos.

Deberías usar este callback para restringir las operaciones de búsqueda basado en el rol de un usuario, o llevar a
cabo decisiones de cacheo basadas en la carga actual.

3.7.7.2 (#afterFind-1050) afterFind

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1050)


Comparar con el texto original (/es/compare/1050/afterFind)

Mas info sobre traduciones (/es/view/818)

afterFind(array $resultados, bool $primario)

Usa este callback para modficar los resultados que han sido devueltos de una operación de búsqueda, o para realizar
cualquier otra lógica tras la búsqueda. El parámetro $resultados pasado a este callback contiene los resultados
devueltos por la operación de búsqueda del modelo, p.ej. algo como:

Plain Text View (#)

89 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. $resultados = array(
2. 0 => array(
3. 'NombreModelo' => array(
4. 'campo1' => 'valor1',
5. 'campo2' => 'valor2',
6. ),
7. ),
8. );

Los valores devueltos por este callback deberían ser los resulados (posiblemente modificados) de la operación de
búsqueda que dispararon este callback.

Si $primario es false, el formato de $resultados será un poco diferente de lo que uno debería esperar; en vez del
resultado que obtendrías normalmente de una operación de búsqueda, obtendrías esto:

Plain Text View (#)


1. $resultados = array(
2. 'campo_1' => 'valor',
3. 'campo_2' => 'valor2'
4. );

El código que espera que $primario sea true probablemente obtedrá un error falta "Cannot use string offset as an
array" de PHP si se usa una búsqueda recursiva

Abajo se muestra un ejemplo de cómo afterFind puede ser usado para formateo de datos:

Plain Text View (#)


1. function afterFind($resultados) {
2. foreach ($resultados as $clave => $valor) {
3. if (isset($valor['Evento']['fechainicio'])) {
4. $resultados[$clave]['Evento']['fechainicio'] = $this->formatoFechaAfterFind($valor['Evento']
5. }
6. }
7. return $resultados;
8. }
9. function formatoFechatAfterFind($cadenaFecha) {
10. return date('d-m-Y', strtotime($cadenaFecha));
11. }

3.7.7.3 (#beforeValidate-1051) beforeValidate

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1051)


Comparar con el texto original (/es/compare/1051/beforeValidate)

Mas info sobre traduciones (/es/view/818)

beforeValidate()

Usa este callback para modificar datos del modelo antes de que sean validados. También puede ser usado para añadir
reglas de validación adicionales más complejas usando Model::invalidate(). En este contexto, los datos del modelo
son accesibles via $this->data. Esta función también debe devolver true, de lo contrario la ejecución actual de save()
será abortada.

3.7.7.4 (#beforeSave-1052) beforeSave

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1052)


Comparar con el texto original (/es/compare/1052/beforeSave)

Mas info sobre traduciones (/es/view/818)

90 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

beforeSave()

Sitúa cualquier lógica de antes de grabar en esta función. Esta función se ejecuta inmediatamente después de que los
datos del modelo han sido satisfactoriamente validados, pero justo antes de que los datos sean grabados. Esta
función debería también devolver true si deseas que continúe la operación de grabado.

Este callback es especialmente útil para cualquier lógica de tratamiento de datos que necesita ocurrir antes de que tus
datos sean almacenados. Si tu mecanismo de almacenamiento necesita datos en un formato específico, accede a ellos
mediante $this->data y modifícalos.

Abajo se muestra un ejemplo de cómo beforeSave puede ser usado para conversión de fechas. El código en el
ejemplo es usado para una aplicación con una fechainicio formateada como AAAA-MM-DD en la base de datos y es
mostrada como DD-MM-AAAA en la aplicación. Por supuesto, esto puede ser cambiado muy facilmente. Usa el código
siguiente en el modelo apropiado.

Plain Text View (#)


1. function beforeSave() {
2. if(!empty($this->data['Evento']['fechainicio']) && !empty($this->data['Evento']['fechafin'])) {
3. $this->data['Evento']['fechainicio'] = $this->formatoFechaBeforeSave($this->data['Evento']['
4. $this->data['Evento']['fechafin'] = $this->formatoFechaBeforeSave($this->data['Evento']['fec
5. }
6. return true;
7. }
8. function formatoFechaBeforeSave($cadenaFecha) {
9. return date('Y-m-d', strtotime($cadenaFecha)); // Direction is from
10. }

Asegúrate de que beforeSave() devuelve true, o tu grabado fallará.

3.7.7.5 (#afterSave-1053) afterSave

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1053)


Comparar con el texto original (/es/compare/1053/afterSave)

Mas info sobre traduciones (/es/view/818)

afterSave(boolean $creado)

Si tienes lógica que necesitas que sea ejecutada justo después de cada operación de grabación, colócala en este
método callback.

El valor de $creado será true si fue creado un nuevo objeto (en vez de una actualización).

3.7.7.6 (#beforeDelete-1054) beforeDelete

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1054)


Comparar con el texto original (/es/compare/1054/beforeDelete)

Mas info sobre traduciones (/es/view/818)

beforeDelete(boolean $cascada)

Coloca en esta función cualquier lógica de antes de borrar. Esta función debería devolver true si deseas que continúe
el borrado, y false si quieres que aborte.

El valor de $cascada será true si los registros que dependen de este registro también serán borrados.

3.7.7.7 (#afterDelete-1055) afterDelete

afterDelete()

91 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Coloca en este método callback cualquier lógica que quieras que sea ejecutada después de cada borrado.

3.7.7.8 (#onError-1056) onError

onError()

Callback llamado si ocurre cualquier problema.

3.7.8 (#Atributos-del-Modelo-1057) Atributos del Modelo

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1057)


Comparar con el texto original (/es/compare/1057/Atributos-del-Modelo)

Mas info sobre traduciones (/es/view/818)

Los atributos del modelo te permiten establecer propiedades que pueden redefinir el comportamiento por defecto del
modelo.

Para una lista completa de los atributos del modelo y sus respectivas descripciones, visita la API del CakePHP. Echa un
vistazo a http://api.cakephp.org/1.2/class_model.html (http://api.cakephp.org/1.2/class_model.html) .

3.7.8.1 (#useDbConfig-1058) useDbConfig

La propiedad useDbConfig es un cadena de caracteres que especifica el nombre de la conexión a la base de datos
usada para enlazar tu clase modelo a la tabla de la base de datos relacionada. Puedes estabecer el valor a cualquiera
de las conexiones definidas dentro de tu fichero de configuración de tu base de datos. El fichero de configuración de
la base de datos se encuentra en /app/config/database.php.

La propiedad useDbConfig tiene por defecto la conexión a la base de datos 'default' ( $useDbConfig = 'default'; )

Ejemplo de uso:

Plain Text View (#)


1. class Ejemplo extends AppModel {
2. var $useDbConfig = 'alternativo';
3. }

3.7.8.2 (#useTable-1059) useTable

La propiedad $useTable especifica el nombre de la tabla de la base de datos. Por defecto, el modelo usa la forma
plural y en minúsculas del nombre de la clase del modelo. Establece este atributo al nombre de una tabla alternativa,
o dale el valor false si deseas que el modelo no use una tabla de base de datos.

Ejemplo de uso:

Plain Text View (#)


1. class Ejemplo extends AppModel {
2. var $useTable = false; // Este modelo no usa una tabla de base de datos
3. }

Alternativamente:

Plain Text View (#)


1. class Ejemplo extends AppModel {
2. var $useTable = 'exmp'; // Este modelo usa la tabla 'exmp' de la base de datos
3. }

3.7.8.3 (#tablePrefix-1060) tablePrefix

El nombre del prefijo de tabla usado para el modelo. El prefijo de tabla se establece inicialmente en el fichero de
conexión a la base de datos /app/config/database.php. Por defecto es sin prefijo. Puedes sustituir la configuración

92 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

por defecto estableciendo el atributo tablePrefix en el modelo.

Ejemplo de uso:

Plain Text View (#)


1. class Ejemplo extends AppModel {
2. var $tablePrefix = 'otros_'; // buscará la tabla 'otros_ejemplos'
3. }

3.7.8.4 (#primaryKey-1061) primaryKey

Normalmente cada tabla tiene una clave primaria id. Puedes cambiar qué nombre de campo usará el modelo como
clave primaria. Esto es común cuando se configura CakePHP para usar una tabla de base de datos ya existente.

Ejemplo de uso:

Plain Text View (#)


1. class Ejemplo extends AppModel {
2. var $primaryKey = 'ejemplo_id'; // ejemplo_id es el nombre del campo en la base de datos
3. }

3.7.8.5 (#displayField-1062) displayField

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1062)


Comparar con el texto original (/es/compare/1062/displayField)

Mas info sobre traduciones (/es/view/818)

El atributo displayField ('visualizarCampo') especifica qué campo de la base de datos debería ser usado como
etiqueta para el registro. La etiqueta se utiliza en scaffolding y en llamadas find('lista'). El modelo usará por
defecto el campo name o title.

Por ejemplo, para utilizar el campo nombre_de_usuario:

Plain Text View (#)


1. class Ejemplo extends AppModel {
2. var $displayField = 'nombre_de_usuario';
3. }

No se pueden combinar nombres de campos múltiples en un único campo de display (de visualización). Por ejemplo,
no puedes especificar array('nombre', 'apellido') como campo de visualización.

3.7.8.6 (#recursive-1063) recursive

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1063)


Comparar con el texto original (/es/compare/1063/recursive)

Mas info sobre traduciones (/es/view/818)

La propiedad $recursive define la profundidad a la que CakePHP ha de llegar para obtener los datos de modelos
asociados mediante los métodos find() y findAll().

Imagina que tu aplicación muestra Grupos que pertenecen a un Dominio que tiene muchos Usuarios que, a su vez,
tienen muchos Artículos. Puedes establecer $recursive con diferentes valores basados en la cantidad de datos
quieres obtener con una llamada a $this->Grupo->find():

Profundidad Descripción
-1 Cake obtiene sólo los datos de Grupo, no realiza uniones (joins ).
0 Cake obtiene datos de Grupo y su Dominio

93 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1 Cake obtiene un Grupo, su Dominio y sus Usuarios asociados


2 Cake obtiene un Grupo, su Dominio, sus Usuarios asociados y los Artículos asociados a los Usuarios

No lo establezcas a un valor mayor de lo que necesites. Hacer que CakePHP obtenga datos que no vas a utilizar
ralentiza tu aplicacióń innecesariamente.

Si deseas combinar $recursive con la funcionalidad de $fields, necesitarás añadir las columnas que contienen las
claves foráneas necesarias al array fields manualmente. En el ejemplo de arriba, esto podría significar añadir
domain_id.

3.7.8.7 (#order-1064) order

El criterio de ordenación de datos por defecto para cualquier operación de búsqueda. Algunos valores posibles son:

Plain Text View (#)


1. $order = "campo"
2. $order = "Modelo.campo";
3. $order = "Modelo.campo asc";
4. $order = "Modelo.campo ASC";
5. $order = "Modelo.campo DESC";
6. $order = array("Modelo.campo" => "asc", "Modelo.campo2" => "DESC");

3.7.8.8 (#data-1065) data

El contenedor para los datos del modelo que se han obtenido. A pesar de que los datos devueltos por una clase del
modelo normalmente se utilizan como los devueltos por una llamada a find(), dentro de un callback del modelo
necesitarás acceder a la información almacenadana a través de $data.

3.7.8.9 (#_schema-1066) _schema

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1066)


Comparar con el texto original (/es/compare/1066/_schema)

Mas info sobre traduciones (/es/view/818)

Contiene metadatos describiendo los campos de tabla de la base de datos del modelo. Cada campo es descrito por:

nombre
tipo (integer, string, datetime, etc.)
null
valor por defecto
longitud

3.7.8.10 (#validate-1067) validate

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1067)


Comparar con el texto original (/es/compare/1067/validate)

Mas info sobre traduciones (/es/view/818)

Este atributo contiene reglas que permiten al modelo realizar decisiones de validación de datos antes de grabar. Las
claves nombradas tras los campos contienen expresiones regulares permitiendo al modelo buscar correspondencias.

Para más información, mira el capítulo Validación de Datos (/es/view/125/Validaci%C3%B3n-de-Datos) más adelante en
este manual.

3.7.8.11 (#virtualFields-1588) virtualFields

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1588/virtualFields) .. Mas info
sobre traduciones (/es/view/818)

94 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Array of virtual fields this model has. Virtual fields are aliased SQL expressions. Fields added to this property will be
read as other fields in a model but will not be saveable.

Example usage for MySQL:

Plain Text View (#)


1. var $virtualFields = array(
2. 'name' => "CONCAT(User.first_name, ' ', User.last_name)"
3. );

In subsequent find operations, your User results would contain a name key with the result of the concatenation. It is
not advisable to create virtual fields with the same names as columns on the database, this can cause SQL errors.

For more information on the virtualFields property, its proper usage, as well as limitations, see the section on
virtual fields (/es/view/1608/Virtual-fields) .

3.7.8.12 (#name-1068) name

Como habrás visto antes en este capítulo, el atributo $name es una característica de compatibilidad para los usuarios
de PHP4 y se establece el valor al nombre del modelo.

Ejemplo de uso:

Plain Text View (#)


1. class Ejemplo extends AppModel {
2. var $name = 'Ejemplo';
3. }

3.7.8.13 (#cacheQueries-1069) cacheQueries

Si se establece a true, los datos obtenidos por el modelo durante una petición son cacheados (cached ). Este cacheo
es sólo en memoria, y dura sólo el tiempo de duración de la petición. Cualquier petición duplicada de los mismos
datos es tratada por la caché.

3.7.9 (#Métodos-Personalizados-y-Propiedades-1070) Métodos Personalizados y Propiedades

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1070)


Comparar con el texto original (/es/compare/1070/Métodos-Personalizados-y-Propiedades)

Mas info sobre traduciones (/es/view/818)

Aunque las funciones de modelo de CakePHP deberían llevarte donde necesites ir, no olvides que las clases modelos
son justamente eso: clases que te permiten escribir tus propios métodos o definir tus propias propiedades.

Cualquier operación que maneja la grabación o búsqueda de datos es mejor que esté alojada en tus clases modelo.
Este concepto es a menudo referido como "fat model".

Plain Text View (#)


1. class Ejemplo extends AppModel {
2. function getReciente() {
3. $condiciones = array(
4. 'created BETWEEN (curdate() - interval 7 day) and (curdate() - interval 0 day))'
5. );
6. return $this->find('all', compact($condiciones));
7. }
8. }

Ahora, este método getReciente() puede ser usado dentro del controlador.

Plain Text View (#)


1. $reciente = $this->Ejemplo->getReciente();

95 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

3.7.9.1 (#Using-virtualFields-1590) Using virtualFields

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1590/Using-virtualFields) .. Mas
info sobre traduciones (/es/view/818)

Virtual fields are a new feature in the Model for CakePHP 1.3. Virtual fields allow you to create arbitrary SQL
expressions and assign them as fields in a Model. These fields cannot be saved, but will be treated like other model
fields for read operations. They will be indexed under the model's key alongside other model fields.

How to create virtual fields

Creating virtual fields is easy. In each model you can define a $virtualFields property that contains an array of field
=> expressions. An example of virtual field definitions would be:

Plain Text View (#)


1. var $virtualFields = array(
2. 'name' => 'CONCAT(User.first_name, ' ', User.last_name)'
3. );

In subsequent find operations, your User results would contain a name key with the result of the concatenation. It is
not advisable to create virtual fields with the same names as columns on the database, this can cause SQL errors.

Using virtual fields

Creating virtual fields is straightforward and easy, interacting with virtual fields can be done through a few different
methods.

Model::hasField()

Model::hasField() has been updated so that it can will return true if the model has a virtualField with the correct
name. By setting the second parameter of hasField to true, virtualFields will also be checked when checking if a
model has a field. Using the example field above,

Plain Text View (#)


1. $this->User->hasField('name'); // Will return false, as there is no concrete field called name
2. $this->User->hasField('name', true); // Will return true as there is a virtual field called name

Model::isVirtualField()

This method can be used to check if a field/column is a virtual field or a concrete field. Will return true if the column
is virtual.

Plain Text View (#)


1. $this->User->isVirtualField('name'); //true
2. $this->User->isVirtualField('first_nname'); //false

Model::getVirtualField()

This method can be used to access the SQL expression that comprises a virtual field. If no argument is supplied it will
return all virtual fields in a Model.

Plain Text View (#)


1. $this->User->getVirtualField('name'); //returns 'CONCAT(User.first_name, ' ', User.last_name)'

Model::find() and virtual fields

As stated earlier Model::find() will treat virtual fields much like any other field in a model. The value of a virtual field
will be placed under the model's key in the resultset. Unlike the behavior of calculated fields in 1.2

Plain Text View (#)

96 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. $results = $this->User->find('first');
2. // results contains the following
3. array(
4. 'User' => array(
5. 'first_name' => 'Mark',
6. 'last_name' => 'Story',
7. 'name' => 'Mark Story',
8. //more fields.
9. )
10. );

Pagination and virtual fields

Since virtual fields behave much like regular fields when doing find's, Controller::paginate() has been updated to
allows sorting by virtual fields.

3.7.10 (#Virtual-fields-1608) Virtual fields

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1608/Virtual-fields) .. Mas info
sobre traduciones (/es/view/818)

Virtual fields are a new feature in the Model for CakePHP 1.3. Virtual fields allow you to create arbitrary SQL
expressions and assign them as fields in a Model. These fields cannot be saved, but will be treated like other model
fields for read operations. They will be indexed under the model's key alongside other model fields.

3.7.10.1 (#Creating-virtual-fields-1609) Creating virtual fields

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1609/Creating-virtual-fields) ..
Mas info sobre traduciones (/es/view/818)

Creating virtual fields is easy. In each model you can define a $virtualFields property that contains an array of field
=> expressions. An example of a virtual field definition using MySQL would be:

Plain Text View (#)


1. var $virtualFields = array(
2. 'full_name' => 'CONCAT(User.first_name, " ", User.last_name)'
3. );

And with PostgreSQL: Plain Text View (#)


1. var $virtualFields = array(
2. 'name' => 'User.first_name || \' \' || User.last_name'
3. );

In subsequent find operations, your User results would contain a name key with the result of the concatenation. It is
not advisable to create virtual fields with the same names as columns on the database, this can cause SQL errors.

It is not always useful to have User.first_name fully qualified. If you do not follow the convention (i.e. you have
multiple relations to other tables) this would result in an error. In this case it may be better to just use first_name ||
\'\' || last_name without the Model Name.

3.7.10.2 (#Using-virtual-fields-1610) Using virtual fields

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1610/Using-virtual-fields) .. Mas
info sobre traduciones (/es/view/818)

Creating virtual fields is straightforward and easy, interacting with virtual fields can be done through a few different
methods.

Model::hasField()

Model::hasField() has been updated so that it can return true if the model has a virtualField with the correct name. By
setting the second parameter of hasField to true, virtualFields will also be checked when checking if a model has a
field. Using the example field above,

97 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Plain Text View (#)


1. $this->User->hasField('name'); // Will return false, as there is no concrete field called name
2. $this->User->hasField('name', true); // Will return true as there is a virtual field called name

Model::isVirtualField()

This method can be used to check if a field/column is a virtual field or a concrete field. Will return true if the column
is virtual.

Plain Text View (#)


1. $this->User->isVirtualField('name'); //true
2. $this->User->isVirtualField('first_name'); //false

Model::getVirtualField()

This method can be used to access the SQL expression that comprises a virtual field. If no argument is supplied it will
return all virtual fields in a Model.

Plain Text View (#)


1. $this->User->getVirtualField('name'); //returns 'CONCAT(User.first_name, ' ', User.last_name)'

Model::find() and virtual fields

As stated earlier Model::find() will treat virtual fields much like any other field in a model. The value of a virtual field
will be placed under the model's key in the resultset. Unlike the behavior of calculated fields in 1.2

Plain Text View (#)


1. $results = $this->User->find('first');
2. // results contains the following
3. array(
4. 'User' => array(
5. 'first_name' => 'Mark',
6. 'last_name' => 'Story',
7. 'name' => 'Mark Story',
8. //more fields.
9. )
10. );

Pagination and virtual fields

Since virtual fields behave much like regular fields when doing find's, Controller::paginate() has been updated to
allows sorting by virtual fields.

3.7.10.3 (#Virtual-fields-and-model-aliases-1632) Virtual fields and model aliases

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1632/Virtual-fields-and-model-
aliases) .. Mas info sobre traduciones (/es/view/818)

When you are using virtualFields and models with aliases that are not the same as their name, you can run into
problems as virtualFields do not update to reflect the bound alias. If you are using virtualFields in models that have
more than one alias it is best to define the virtualFields in your model's constructor

Plain Text View (#)


1. function __construct($id = false, $table = null, $ds = null) {
2. parent::__construct($id, $table, $ds);
3. $this->virtualFields['name'] = sprintf('CONCAT(%s.first_name, " ", %s.last_name)', $this->alias, $th
4. }

This will allow your virtualFields to work for any alias you give a model.

3.7.10.4 (#Limitations-of-virtualFields-1642) Limitations of virtualFields

98 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1642/Limitations-
of-virtualFields) .. Mas info sobre traduciones (/es/view/818)

The implementation of virtualFields in 1.3 has a few limitations. First you cannot use virtualFields on associated
models for conditions, order, or fields arrays. Doing so will generally result in an SQL error as the fields are not
replaced by the ORM. This is because it difficult to estimate the depth at which an associated model might be found.

A common workaround for this implementation issue is to copy virtualFields from one model to another at runtime
when you need to access them.

Plain Text View (#)


1. $this->virtualFields['full_name'] = $this->Author->virtualFields['full_name'];

Alternatively, you can define $virtualFields in your model's constructor, using $this->alias, like so:

Plain Text View (#)


1. public function __construct($id=false,$table=null,$ds=null){
2. parent::__construct($id,$table,$ds);
3. $this->virtualFields = array(
4. 'name'=>"CONCAT($this->alias.first_name,' ',$this->alias.last_name)"
5. );
6. }

3.7.11 (#Transactions-1633) Transactions

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1633/Transactions) .. Mas info
sobre traduciones (/es/view/818)

To perform a transaction, a model's tables must be of a type that supports transactions.

All transaction methods must be performed on a model's DataSource object. To get a model's DataSource from within
the model, use:

Plain Text View (#)


1. $dataSource = $this->getDataSource();

You can then use the data source to start, commit, or roll back transactions.

Plain Text View (#)


1. $dataSource->begin($this);
2.
3. //Perform some tasks
4. if(/*all's well*/) {
5. $dataSource->commit($this);
6. } else {
7. $dataSource->rollback($this);
8. }

Nested transactions are currently not supported. If a nested transaction is started, a commit will return false on the
parent transaction.

3.8 (#Comportamientos-1071) Comportamientos

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1071)


Comparar con el texto original (/es/compare/1071/Comportamientos)

Mas info sobre traduciones (/es/view/818)

Los comportamientos del modelo (Model behaviors ) son una manera de organizar parte de la funcionalidad definida
en los modelos de CakePHP. Nos permiten separar la lógica que puede no estar relacionada directamente con un
modelo, pero que necesita estar ahí. Proveyendo una manera simple pero potente manera de extender modelos, los

99 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

comportamientos nos permiten atar funcionalidad a los modelos definiendo una simple variable de clase. Así es como
los comportamientos permiten a los modelos deshacerse de todo el peso extra que no debería ser parte de contrato
de negocio que están modelando, o al menos es necesario en diferentes modelos y puede, entonces, ser extrapolado.

Como ejemplo, considera un modelo que nos da acceso a una tabla de una base de datos la cual almacena
información estructural de un árbol. Eliminando, añadiendo y migrando nodos en el árbol no es tan simple como
borrar, insertar y editar filas en una tabla. Muchos registros deberán ser actualizados según las cosas se mueven. En
vez de crear esos métodos de manipulación del árbol en cada base de modelo (para todo modelo que necesita dicha
funcionalidad), podríamos simplemente decirle a nuestro modelo que utilize el TreeBehavior (ArbolComportamiento),
o en términos más formales, decirle a nuestro modelo que se comporte como un Árbol. Esto es conocido como atar
un comportamiento a un modelo. Con sólo una línea de código, nuestro modelo de CakePHP toma todo un nuevo
conjunto de métodos que le permiten interactuar con la estructura subyacente.

CakePHP ya incluye comportamientos para estructuras de árbol, contenido traducido, interacción con listas de control
de acceso, sin comentar los comportamientos aportados por la comunidad disponibles en CakePHP Bakery
(http://bakery.cakephp.org) . En esta sección cubriremos el patrón básico de uso para añadir comportamientos a
modelos, cómo utilizar los comportamientos de CakePHP incorporados y cómo crear uno nosotros mismos.

3.8.1 (#Utilizando-Comportamientos-1072) Utilizando Comportamientos

Los comportamientos son atados a modelos mediante la variable de clase del modelo $actsAs:

Plain Text View (#)


1. <?php
2. class Category extends AppModel {
3. var $name = 'Category';
4. var $actsAs = array('Tree');
5. }
6. ?>

Este ejemplo muestra cómo un modelo de Category puede ser manejado en una estructura de árbol utilizando el
comportamiento de árbol (TreeBehavior ). Una vez que un comportamiento ha sido especificado, utiliza los métodos
añadidos por el comportamiento como si siempre existiesen como parte del modelo original:

Plain Text View (#)


1. // Set ID
2. $this->Category->id = 42;
3. // Utilizar un método de comportamiento, children():
4. $kids = $this->Category->children();

Algunos comportamientos pueden requerir o permitir opciones a ser definidas cuando el comportamiento es atado al
modelo. Aquí, decimos a nuestro TreeBehavior (comportamiento de árbol) los nombres de los campos left (izquierdo)
y right (derecho) en la tabla de base de datos subyacente:

Plain Text View (#)


1. <?php
2. class Category extends AppModel {
3. var $name = 'Category';
4. var $actsAs = array(
5. 'Tree' => array(
6. 'left' => 'left_node',
7. 'right' => 'right_node'
8. )
9. );
10. }
11. ?>

Podemos también atar varios comportamientos a un modelo. No hay razón por la que, por ejemplo, nuestro modelo
Category deba sólo comportarse como un árbol, también puede necesitar soporte de internacionalización:

Plain Text View (#)

100 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <?php
2. class Category extends AppModel {
3. var $name = 'Category';
4. var $actsAs = array(
5. 'Tree' => array(
6. 'left' => 'left_node',
7. 'right' => 'right_node'
8. ),
9. 'Translate'
10. );
11. }
12. ?>

Hasta el momento hemos estado añadiendo comportamientos a modelos utilizando una variable de la clase. Eso
significa que nuestros comportamientos serán atados a muestros modelos durante todo el tiempo de vida del modelo.
Sin embargo, puede ser que necesitemos "desatar" comportamientos de nuestros modelos en tiempo de ejecución.
Digamos que en nuestro modelo Category anterior, el cual está actuando como un modelo Tree y Translate,
necesitamos por alguna razón forzar a que deje de actuar como un modelo Translate:

Plain Text View (#)


1. // Desata un comportamiento de nuestro modelo:
2. $this->Category->Behaviors->detach('Translate');

Eso hará que nuestro modelo Category deje de comportarse como un modelo Translate desde ese momento. Tal vez
necesitemos, en cambio, simplemente desactivar el comportamiento Translate de actuar sobre operaciones normales
del modelo: nuestras búsquedas, grabados, etc. De hecho, estamos buscando desactivar el comportamiento de actuar
sobre nuestros callbacks del modelo de CakePHP. En vez de desatar el comportamiento, le decimos a nuestro modelo
que pare de informar sobre dichos callbacks al comportamiento Translate:

Plain Text View (#)


1. // Parar de dejar al comportamiento manejar los callbacks de nuestro modelo
2. $this->Category->Behaviors->disable('Translate');

También necesitaremos saber si nuestro comportamiento está manejando los callbacks del modelo, y si no,
restauramos su habilidad para reaccionar a ellos:

Plain Text View (#)


1. // Si nuestro comportamiento no está manejando los callbacks del modelo
2. if (!$this->Category->Behaviors->enabled('Translate')) {
3. // Decirle que comience a hacerlo
4. $this->Category->Behaviors->enable('Translate');
5. }

Tal como podemos desatar completamente un comportamiento de un modelo en tiempo de ejecución, también
podemos atar nuevos comportamientos. Digamos que nuestro modelo Category necesita empezar a comportarse como
un modelo Christmas (Navidad), pero sólo en el día de Navidad:

Plain Text View (#)


1. // Si hoy es 25 de diciembre
2. if (date('m/d') == '12/25') {
3. // Nuestro modelo necesita comportarse como un modelo Christmas
4. $this->Category->Behaviors->attach('Christmas');
5. }

Podemos también utilizar el método attach() para sobreescribir las opciones de comportamiento:

Plain Text View (#)


1. // Cambiaremos una opción de nuestro ya atado comportamiento
2. $this->Category->Behaviors->attach('Tree', array('left' => 'new_left_node'));

También hay un método para obtener la lista de comportamientos atados a un modelo: attached(). Si pasamos el

101 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

nombre de un comportamiento al método, nos dirá si dicho comportamiento está atado al modelo; de cualquier otra
manera nos dará una lista de los comportamientos atados.

Plain Text View (#)


1. // Si el comportamiento "Translate" no está atado al modelo
2. if (!$this->Category->Behaviors->attached('Translate')) {
3. // Obtener la lista de todos los comportamientos atados al modelo
4. $behaviors = $this->Category->Behaviors->attached();
5. }

3.8.2 (#Creando-Comportamientos-Personalizados-1073) Creando Comportamientos Personalizados

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1073)


Comparar con el texto original (/es/compare/1073/Creando-Comportamientos-Personalizados)

Mas info sobre traduciones (/es/view/818)

Este es el contenedor del contenido.

3.8.3 (#Creating-behavior-methods-1074) Creating behavior methods

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1074/Creating-behavior-
methods) .. Mas info sobre traduciones (/es/view/818)

Behavior methods are automatically available on any model acting as the behavior. For example if you had:

Plain Text View (#)


1. class Duck extends AppModel {
2. var $name = 'Duck';
3. var $actsAs = array('Flying');
4. }

You would be able to call FlyingBehavior methods as if they were methods on your Duck model. When creating
behavior methods you automatically get passed a reference of the calling model as the first parameter. All other
supplied parameters are shifted one place to the right. For example

Plain Text View (#)


1. $this->Category->fly('toronto', 'montreal');

Although this method takes two parameters, the method signature should look like: Plain Text View (#)
1. function fly(&$Model, $from, $to) {
2. // Do some flying.
3. }

Keep in mind that methods called in a $this->doIt() fashion from inside a behavior method will not get the $model
parameter automatically appended.

3.8.4 (#Behavior-callbacks-1640) Behavior callbacks

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1640/Behavior-callbacks) .. Mas
info sobre traduciones (/es/view/818)

Model Behaviors can define a number of callbacks that are triggered before/after the model callbacks of the same
name. Behavior callbacks allow your behaviors to capture events in attached models and augment the parameters or
splice in additional behavior.

The available callbacks are:

beforeValidate is fired before a model's beforeValidate


beforeFind is fired before a model's beforeFind
afterFind is fired before a model's afterFind
beforeSave is fired before a model's beforeSave

102 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

afterSave is fired before a model's afterSave


beforeDelete is fired after a model's beforeDelete
afterDelete is fired before a model's afterDelete

3.8.5 (#Creating-a-behavior-callback-1641) Creating a behavior callback

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1641/Creating-a-behavior-
callback) .. Mas info sobre traduciones (/es/view/818)

Model behavior callbacks are defined as simple methods in your behavior class. Much like regular behavior methods,
they receive a $Model parameter as the first argument. This parameter is the model that the behavior method was
invoked on.

function beforeFind(&$model, $query)

If a behavior's beforeFind return's false it will abort the find(). Returning an array will augment the query parameters
used for the find operation.

afterFind(&$model, $results, $primary)

You can use the afterFind to augment the results of a find. The return value will be passed on as the results to either
the next behavior in the chain or the model's afterFind.

beforeDelete(&$model, $cascade = true)

You can return false from a behavior's beforeDelete to abort the delete. Return true to allow it continue.

afterDelete(&$model)

You can use afterDelete to perform clean up operations related to your behavior.

beforeValidate(&$model)

You can use beforeValidate to modify a model's validate array or handle any other pre-validation logic. Returning
false from a beforeValidate callback will abort the validation and cause it to fail.

3.9 (#DataSources-fuentes-de-datos-1075) DataSources (fuentes de datos)

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1075)


Comparar con el texto original (/es/compare/1075/DataSources-fuentes-de-datos)

Mas info sobre traduciones (/es/view/818)

DataSources son el enlace entre los modelos y la fuente de datos que cada modelo representa. En muchos caos, los
datos son recuperados de una base de datos relacional, como MySQL, PostgreSQL o MSSQL. CakePHP se distribuye
con varias datasources específicas para varias bases de datos (consulta los archivos de clases dbo_* class files en
cake/libs/model/datasources/dbo/), aquí se lista un resumen de los mismos para tu comodidad:

dbo_adodb.php
dbo_db2.php
dbo_firebird.php
dbo_mssql.php
dbo_mysql.php
dbo_mysqli.php
dbo_odbc.php
dbo_oracle.php
dbo_postgres.php
dbo_sqlite.php
dbo_sybase.php

Cuando se especifica una configuración de conexión a base de datos en app/config/database.php, CakePHP usa de
forma transparente la datasource correspondiente a la base de datos para todas las operaciones con modelos. Por
eso, aunque creas que no sabes nada de datasources, ya las has estado usando desde siempre.

Todas las fuentes de datos indicadas arriba derivan de una clase base DboSource la cual añade alguna lógica común a
la mayoría de bases de datos relaciones. Si decides crear una datasource RDBMS, tu mejor apuesta es trabajar a paritr

103 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

de una de ellas (por ejemeplo: dbo_mysql.php o dbo_mssql.php) La mayor parte de la gente, sin embargo, está
interesada en escribir datasources para fuentes de datos externas, como APIs REST remotas o incluso servidores
LDAP. Así que eso es lo que vamos a examinar en adelante.

3.9.1 (#API-básica-para-DataSources-1076) API básica para DataSources

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1076)


Comparar con el texto original (/es/compare/1076/API-básica-para-DataSources)

Mas info sobre traduciones (/es/view/818)

Una datasource puede, y debería implementar al menos uno de los siguientes métodos: create, read, update y/o
delete (la signatura y detalles de implementación no son importantes en este momento, y serán descritos más tarde).
No necesitas implementar más métodos de los necesarios de los descritos arriba - si estás escribiendo una
datasource de sólo-lectura, no hay razón para implementar create y update.

Métodos que deben ser implementados

describe($model)
listSources()
Al menos uno de:
create($model, $fields = array(), $values = array())
read($model, $queryData = array())
update($model, $fields = array(), $values = array())
delete($model, $id = null)

Es posible también (y muchas veces bastante útil) definir el atributo de clase $_schema dentro la datasource misma, en
lugar de en el modelo. Y esto es casi todo lo que hay. Emparejando una datasource a un modelo podrás utilizar
Model::find()/save/() como harías normalmentem y los datos y/o parámetros adecuados serán usados para llamar a
esos métodos serán pasados a la propia datasource, donde puedes decidir implementar cualquier prestación que
necesites (por ejemplo: opciones para Model::find como procesasr 'conditions', 'limit' o incluso tus propios
parámetros a medida).

3.9.2 (#Un-ejemplo-1077) Un ejemplo

Lo que sigue es un ejemplo simple de como usar dataSources y HttpSocket para implementar una fuente muy básica
de Twitter (http://twitter.com) que nos permita utilizar la API de twitter y enviar nuestras actualizaciones.

Este ejemplo sólo funcionará sobre PHP 5.2 o superior, debido al uso de json_decode para procesar los datos en
formato JSON.

Tendrás que colocar la datasource para Twitter en tu app/models/datasources/twitter_source.php:

Plain Text View (#)

104 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <?php
2. /**
3. * Twitter DataSource
4. *
5. * Utilizada para leer y escribir en Twitter usando modelos.
6. *
7. * PHP Version 5.x
8. *
9. * CakePHP(tm) : Rapid Development Framework (http://www.cakephp.org)
10. * Copyright 2005-2009, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
11. *
12. * Licensed under The MIT License
13. * Redistributions of files must retain the above copyright notice.
14. *
15. * @filesource
16. * @copyright Copyright 2009, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
17. * @link http://cakephp.org CakePHP(tm) Project
18. * @license http://www.opensource.org/licenses/mit-license.php The MIT License
19. */
20. App::import('Core', 'HttpSocket');
21. class TwitterSource extends DataSource {
22. protected $_schema = array(
23. 'tweets' => array(
24. 'id' => array(
25. 'type' => 'integer',
26. 'null' => true,
27. 'key' => 'primary',
28. 'length' => 11,
29. ),
30. 'text' => array(
31. 'type' => 'string',
32. 'null' => true,
33. 'key' => 'primary',
34. 'length' => 140
35. ),
36. 'status' => array(
37. 'type' => 'string',
38. 'null' => true,
39. 'key' => 'primary',
40. 'length' => 140
41. ),
42. )
43. );
44. public function __construct($config) {
45. $auth = "{$config['login']}:{$config['password']}";
46. $this->connection = new HttpSocket(
47. "http://{$auth}@twitter.com/"
48. );
49. parent::__construct($config);
50. }
51. public function listSources() {
52. return array('tweets');
53. }
54. public function read($model, $queryData = array()) {
55. if (!isset($queryData['conditions']['username'])) {
56. $queryData['conditions']['username'] = $this->config['login'];
57. }
58. $url = "/statuses/user_timeline/";
59. $url .= "{$queryData['conditions']['username']}.json";
60.
61. $response = json_decode($this->connection->get($url), true);

105 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

La implementación de tu modelo puede ser tan simple como:

Plain Text View (#)


1. <?php
2. class Tweet extends AppModel {
3. public $useDbConfig = 'twitter';
4. }
5. ?>

Si no hemos definido nuestro esquema en la propia datasource, nos dará un mensaje de error al efecto aquí.

Y los ajustes de configuración en tu app/config/database.php se parecerán a estos:

Plain Text View (#)


1. <?php
2. var $twitter = array(
3. 'datasource' => 'twitter',
4. 'login' => 'username',
5. 'password' => 'password',
6. );
7. ?>

Usando los familiares métodos de modelo desde un controlador:

Plain Text View (#)


1. <?php
2. // Usará el nombre de usuario definido en $twitter como se mostró arriba:
3. $tweets = $this->Tweet->find('all');
4. // Encontrar tweets de otros usuario
5. $conditions= array('username' => 'caketest');
6. $otherTweets = $this->Tweet->find('all', compact('conditions'));
7. ?>

De forma similar, guardando una actualización del estatus:

Plain Text View (#)


1. <?php
2. $this->Tweet->save(array('status' => 'This is an update'));
3. ?>

3.10 (#Vistas-1078) Vistas

3.10.1 (#Plantillas-de-la-Vista-1079) Plantillas de la Vista

La capa vista de CakePHP es cómo hablas a tus usuarios. La mayor parte del tiempo tu vista estará mostrando
documentos (X)HTML a los navegadores, pero tal vez necesites servir datos AMF a un objeto Flash, responder a una
aplicación remota mediante SOAP o producir un fichero CSV para un usuario.

Los ficheros de vista de CakePHP están escritos en PHP plano y tienen la extensión .ctp (CakePHP Template) por
defecto . Estos ficheros contienen toda la lógica de representación necesaria para obtener los datos recibidos del
controlador en un formato que está preparado para la audiencia a la que estás atendiendo.

Los ficheros de vista se almacenan en /app/views/, en una carpeta nombrada tras el controlador que usa los ficheros,
y nombrada tras la acción a la que corresponde. Por ejemplo, el fichero de vista para el la acción view() del
controlador Productos, normalmente, se encontraría en /app/views/productos/view.ctp.

La capa vista en CakePHP puede estar formada por un número diferentes de partes. Cada parte tiene usos diferentes, y
será tratado en este capítulo:

layouts (diseños): ficheros de vista que contienen el código de presentación que se encuentra envolviendo
muchas interfaces en tu aplicación. La mayoría de vistas son 'renderizadas' (presentadas) dentro de un layout
(diseño).

106 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

elements (elementos): trozo de código de vista más pequeño y reutilizable. Los elementos generalmente son
renderizados dentro de vistas.
helpers (ayudantes): estas clases encapsulan lógica de vista que es necesaria en muchas partes en la capa vista.
Además de otras cosas, los ayudantes en CakePHP pueden ayudarte a construir formularios, construir
funcionalidad AJAX, paginar los datos del modelo o servir feeds RSS.

3.10.2 (#Layouts-1080) Layouts

Un diseño contiene el código de presentación que envuelve una vista. Cualquier cosa que quieras ver en todas tus
vistas debería estar situada en un layout.

Los ficheros de diseño deberían situarse en /app/views/layouts. El diseño por defecto de CakePHP puede ser
sustituido creando un nuevo diseño por defecto en /app/views/layouts/default.ctp. Una vez que ha sido creado un
nuevo diseño, el código de la vista renderizado por el controlador se coloca dentro del diseño por defecto cuando la
página es renderizada.

Cuando creas un diseño, necesitas decirle a CakePHP dónde colocar el código para tus vistas. Para hacer eso, estate
seguro que tu diseño incluye un lugar para $content_for_layout (y opcionalmente, $title_for_layout). Aquí está un
ejemplo de a lo que debería parecerse un diseño por defecto:

Plain Text View (#)


1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2. "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3. <html xmlns="http://www.w3.org/1999/xhtml">
4. <head>
5. <title><?php echo $title_for_layout?></title>
6. <link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
7. <!-- Incluir ficheros y scripts externos aquí (Mirar el ayudante HTML para más información -->
8. <?php echo $scripts_for_layout ?>
9. </head>
10. <body>
11. <!-- Si quieres algún tipo de menú que mostrar en todas tus vistas, incluyelo aquí -->
12. <div id="cabecera">
13. <div id="menu">...</div>
14. </div>
15. <!-- Aquí es donde quiero que se vean mis vistas -->
16. <?php echo $content_for_layout ?>
17.
18. <!-- Añadir un pie de página a cada página mostrada -->
19. <div id="pie">...</div>
20. </body>
21. </html>

$scripts_for_layout contiene cualquier fichero externo y scripts incluidos con el ayudante HTML incrustado. Es últil
para incluir ficheros javascript y CSS de las vistas.

Cuando uses $html->css() o $javascript->link() en los ficheros de vista, especifica false en el argumento 'in-line'
para colocar el fuente html en $scripts_for_layout. (Mirar API para más detalles de uso).

$content_for_layout contiene la vista. Aquí es donde será colocado el código de la vista.

$title_for_layout contiene el título de la página.

Para establecer el título para el diseño, es fácil hacerlo en el controlador, estableciendo el valor de la variable
$title_for_layout.

Plain Text View (#)

107 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <?php
2. class UsuariosController extends AppController {
3. function verActivos() {
4. $this->set('title_for_layout', 'Ver Usuarios Activos');
5. }
6. }
7. ?>

Puedes crear tantos diseños como desees: simplemente colócalos en el directorio app/views/layouts e intercambialos
dentro de tus acciones del controlador usando la variable $layout del cotrolador, o la función setLayout().

Por ejemplo, si una sección de mi site incluye un espacio menor con banner de publicidad, debería crear un nuevo
diseño (layout) con el espacio publicitario menor, especificándolo como el diseño para todas las acciones del
controlador haciendo algo como:

var $layout = 'publicidad_pequena_pordefecto';

Plain Text View (#)


1. <?php
2. class UsuariosController extends AppController {
3. function verActivos() {
4. $this->set('title_for_layout', 'Ver Usuarios Activos');
5. $this->layout = 'publicidad_pequena_pordefecto';
6. }
7. function verImagen() {
8. $this->layout = 'imagen';
9. //mostrar la imagen del usuario
10. }
11. }
12. ?>

CakePHP ofrece dos diseños comunes (además del diseño por defecto de CakePHP) que puedes usar en tus propias
aplicaciones: 'ajax' y 'flash'. El diseño Ajax es útil para contruir las respuestas Ajax; es un diseño vacío (la mayoría de
las llamadas ajax sólo requiren una pocas etiquetas como respuesta, más que una interfaz completa). El diseño flash
es usado por mensajes mostrados por el método flash() del controlador.

Existen otros tres diseños: xml, js y rss en el núcleo como una manera rápida y fácil de servir contenido que no sea
text/html.

3.10.3 (#Elementos-1081) Elementos

Muchas aplicaciones tienen pequeños bloques de código de presentación que necesita ser repetido de página en
página, algunas veces en diferentes lugares del diseño. CakePHP puede ayudarte a repetir partes de tu website que
necesitan ser reutilizadas. Estar partes reutilizadas son llamadas Elementos. Anuncios, cajas de ayuda, controles de
navegación, menús extras, formularios de login y llamadas están a menudo implementadas en CakePHP en forma de
elementos. Un elemento es básicamente una minivista que puede ser incluido en otras vistas, en diseños, e incluso
dentro de otros elementos. Los elementos pueden ser usados para hacer una vista más legible, situando el
renderizado de elementos que se repiten en sus propios ficheros. Pueden también ayudarte a reutilizar fragmentos de
contenido en tus aplicaciones.

Los elementos están en la carpeta /app/views/elements/ y tienen la extensión de archivo .ctp. Son mostrados usando
el método element() de la vista.

Plain Text View (#)


1. <?php echo $this->element('cajaayuda'); ?>

3.10.3.1 (#Pasar-Variables-a-un-elemento-1082) Pasar Variables a un elemento

Puedes pasarle datos a un elemento usando el segundo argumento de element():

Plain Text View (#)

108 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <?php echo
2. $this->element('helpbox',
3. array("helptext" => "Oh, this text is very helpful."));
4. ?>

Dentro del archivo del elemento, todas las variables pasadas estan disponibles como miembros del array de
parámetros (de la misma manera que set() en el controlador funciona con los archivos de las vistas). En el ejemplo
siguiente, el archivo /app/views/elements/helpbox.ctp puede usar la variable $helptext.

Plain Text View (#)


1. <?php
2. echo $helptext; //outputs "Oh, this text is very helpful."
3. ?>

La función element() combina opciones para el elemento con los datos a pasar en element. Las dos opciones son
'cache' y 'plugin'. Un ejemplo:

Plain Text View (#)


1. <?php echo
2. $this->element('helpbox',
3. array(
4. "helptext" => "Esto es pasado al elemento como $helptext"
5. "foobar" => "Esto es pasado al elemento como $foobar"
6. "cache" => "+2 days" //setea el 'cacheo' a +2 días.
7. "plugin" => "" //para renderizar un elemento desde un plugin
8. )
9. );
10. ?>

Para tener en cache distintas versiones del mismo elemento en una aplicación, provee una clave única de cache
usando el siguiente formato:

Plain Text View (#)


1. <?php
2. $this->element('helpbox',
3. array(
4. "cache" => array('time'=> "+7 days",'key'=>'unique value')
5. )
6. );
7. ?>

Puedes aprovechar bien los elementos usando requestAction(). La función requestAction() trae las variables desde
una acción de controlador y las retorna como un array. Esto permite que tus elementos cumplan con el diseño MVC.
Crea una acción de controlador que prepare las variables de la vista para tus elementos, luego haz la llamada
requestAction() dentro del segundo parámetro de element() para proveerle al elemento las variables de vista desde
tu controlador.

Para hacer esto, en tu controlador añade algo como lo siguiente, para el ejemplo de Post.

Plain Text View (#)

109 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <?php
2. class PostsController extends AppController {
3. ...
4. function index() {
5. $posts = $this->paginate();
6. if (isset($this->params['requested'])) {
7. return $posts;
8. } else {
9. $this->set(compact('posts'));
10. }
11. }
12. }
13. ?>

Ahora en el elemento podemos acceder el modelo de posts paginados. Para tener los últimos cinco posts en una lista
ordenada deberíamos hacer lo siguiente:

Plain Text View (#)


1. <h2>Latest Posts</h2>
2. <?php $posts = $this->requestAction('posts/index/sort:created/order:asc/limit:5'); ?>
3. <?php foreach($posts as $post): ?>
4. <ol>
5. <li><?php echo $post['Post']['title']; ?></li>
6. </ol>
7. <?php endforeach; ?>

3.10.3.2 (#Cache-de-Elements-1083) Cache de Elements

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1083)


Comparar con el texto original (/es/compare/1083/Cache-de-Elements)

Mas info sobre traduciones (/es/view/818)

Puedes aprovechar el cache de vistas de CakePHP si aportas un parámetro 'cache'. Si lo ajustas a true, mantendrá en
cache durante un día. De otro modo, puedes ajustar tiempos de caducidad alternativos. Lee Cache (/es/view
/156/caching) para más información sobre cómo fijar la caducidad.

Plain Text View (#)


1. <?php echo $this->element('helpbox', array('cache' => true)); ?>

Si dibujas el mismo elemento más de una vez en una vista y tienes el cache activado, asegúrate de ajustar el parámetro
'key' con un nombre diferente cada vez. Esto evitará que cada sucesiva llamada sobreescriba el resultado almacenado
en cache de la anterior llamada element(). Por ejemplo:

Plain Text View (#)


1. <?php
2. echo $this->element('helpbox', array('cache' => array('key' => 'first_use', 'time' => '+1 day'), 'var' =
3. echo $this->element('helpbox', array('cache' => array('key' => 'second_use', 'time' => '+1 day'), 'var'
4. ?>

Lo anterior asegura que ambos elementos son almacenados en cache de forma separada.

3.10.3.3 (#Utilizar-Elements-de-un-Plugin-1084) Utilizar Elements de un Plugin

Si estás usando un plugin y deseas usar elements dentro de ese plugin, simplemente especifica el parámetro plugin.
Si la vista está siendo dibujada para un controlador/acción de un plugin, se usará el elemento del plugin. Si el
elemento no existe en el plugin, se buscará en la carpeta APP principal.

Plain Text View (#)

110 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <?php echo $this->element('helpbox', array('plugin' => 'pluginname')); ?>

3.10.4 (#Métodos-de-la-vista-1085) Métodos de la vista

Los métodos de la Vista están disponibles para todos los archivos de vistas, elementos y plantillas. Para llamar a
cualquier método de la vista utilice: $this->method()

3.10.4.1 (#set-1086) set()

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1086)


Comparar con el texto original (/es/compare/1086/set)

Mas info sobre traduciones (/es/view/818)

set(string $var, mixed $value)

Las Vistas tienen un metodo set() que es análogo al set() encontrado en los objetos Controller . Te permite agregar
variables al viewVars (#) . Usando set() desde tu archivo de vista, agregará las variables a la capa (layout) y elementos
(elements ) que luego serán renderizados. Ver Controller::set() (/es/view/57/Controller-Methods#set-427) para mas
información en el uso de set().

En tu archivo vista puedes hacer

Plain Text View (#)


1. $this->set('activeMenuButton', 'posts');

Luego en tu capa (layout) la variable $activeMenuButton estará disponible y contendrá el valor: 'posts'.

3.10.4.2 (#getVar-1087) getVar()

getVar(string $var)

Obtiene el valor de la viewVar con el nombre $var

3.10.4.3 (#getVars-1088) getVars()

getVars()

Obtiene una lista con todas las variables disponibles en el ámbito de la vista actual. Devuelve un arreglo con los
nombres de las variables.

3.10.4.4 (#error-1089) error()

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1089/error) .. Mas info sobre
traduciones (/es/view/818)

error(int $code, string $name, string $message)

Displays an error page to the user. Uses layouts/error.ctp to render the page.

Plain Text View (#)


1. $this->error(404, 'Not found', 'This page was not found, sorry');

This will render an error page with the title and messages specified. Its important to note that script execution is not
stopped by View::error() So you will have to stop code execution yourself if you want to halt the script.

3.10.4.5 (#element-1090) element()

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1090/element) .. Mas info sobre
traduciones (/es/view/818)

element(string $elementPath, array $data, bool $loadHelpers)

111 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Renders an element or view partial. See the section on View Elements (/es/view/1081/Elements) for more information
and examples.

3.10.4.6 (#uuid-1091) uuid

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1091/uuid) .. Mas info sobre
traduciones (/es/view/818)

uuid(string $object, mixed $url)

Generates a unique non-random DOM ID for an object, based on the object type and url. This method is often used by
helpers that need to generate unique DOM ID's for elements such as the AjaxHelper.

Plain Text View (#)


1. $uuid = $this->uuid('form', array('controller' => 'posts', 'action' => 'index'));
2. //$uuid contains 'form0425fe3bad'

3.10.4.7 (#addScript-1092) addScript()

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1092/addScript) .. Mas info
sobre traduciones (/es/view/818)

addScript(string $name, string $content)

Adds content to the internal scripts buffer. This buffer is made available in the layout as $scripts_for_layout. This
method is helpful when creating helpers that need to add javascript or css directly to the layout. Keep in mind that
scripts added from the layout, or elements in the layout will not be added to $scripts_for_layout. This method is
most often used from inside helpers, like the Javascript (/es/view/1450/Javascript) and Html (/es/view/1434/HTML)
Helpers.

3.10.5 (#Temas-1093) Temas

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1093)


Comparar con el texto original (/es/compare/1093/Temas)

Mas info sobre traduciones (/es/view/818)

Puedes aprovechar los temas (themes), haciendo sencillo el cambio de la apariencia de tu página de una forma rápida
y fácil.

Para usar los temas, necesitas decirle a tu controlador que use la clase ThemeView en lugar de la clase por defecto
View.

Plain Text View (#)


1. class ExampleController extends AppController {
2. var $view = 'Theme';
3. }

Para declarar qué tema usar por defecto, especifica el nombre del tema en tu controlador.

Plain Text View (#)


1. class ExampleController extends AppController {
2. var $view = 'Theme';
3. var $theme = 'ejemplo';
4. }

También puedes setear o cambiar el nombre del tema dentro de una acción o en las funciones de callback
beforeFilter() o beforeRender().

Plain Text View (#)


1. $this->theme = 'otro_ejemplo';

112 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Los archivos de vista de los temas deben estar dentro de la carpeta /app/views/themed/ . Dentro de la carpeta
themed , crea una carpeta usando el nombre de tu tema. Después de eso, la estructura de carpetas dentro de
/app/views/themed/example/ es exactamente igual a /app/views/.

Por ejemplo, el archivo de vista de una acción de edición de un controlador de Posts estaría ubicado en /app/views
/themed/example/posts/edit.ctp. Los archivos de Layout estarían en /app/views/themed/example/layouts/.

Si un archivo de vista no puede ser encontrado en el tema, CakePHP tratará de localizarlo en la carpeta /app/views/.
De esta forma, puedes crear archivos de vista maestros y simplemente sobreescribirlos según cada caso dentro de la
carpeta de tu tema.

Si tienes archivos CSS o JavaScript que son específicos para tu tema, puedes almacenarlos en una carpeta de tema
dentro de la carpetawebroot/ . Por ejemplo, tus hojas de estilo serían almacenadas en /app/webroot/themed
/example/css/ y tus archivos JavaScript estarían en /app/webroot/themed/example/js/.

Todos los helpers de CakePHP son concientes de los temas y crearán las rutas correctas automáticamente. Como con
los archivos de vistas, si un archivo no está en la carpeta del tema, se ubicará por defecto en la carpeta webroot
principal.

3.10.5.1 (#Increasing-performance-of-plugin-and-theme-assets-1614) Increasing performance of plugin and theme assets

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1614/Increasing-performance-
of-plugin-and-theme-assets) .. Mas info sobre traduciones (/es/view/818)

Its a well known fact that serving assets through PHP is guaranteed to be slower than serving those assets without
invoking PHP. And while the core team has taken steps to make plugin and theme asset serving as fast as possible,
there may be situations where more performance is required. In these situations its recommended that you either
symlink or copy out plugin/theme assets to directories in app/webroot with paths matching those used by cakephp.

app/plugins/debug_kit/webroot/js/my_file.js becomes app/webroot/debug_kit/js/my_file.js


app/views/themed/navy/webroot/css/navy.css becomes app/webroot/theme/navy/css/navy.css

3.10.6 (#Vistas-de-Medios-1094) Vistas de Medios

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1094)


Comparar con el texto original (/es/compare/1094/Vistas-de-Medios)

Mas info sobre traduciones (/es/view/818)

Las vistas de medios te permiten enviar archivos binarios al usuario. Por ejemplo, puedes querer tener un directorio
de archivos fuera de la carpeta /webroot para prevenir que los usuarios tengan acceso directo a ellos. Puedes usar
vistas Media para traer el archivo desde una carpeta especial dentro de /app/, pudiendo hacer autenticación antes de
entregar el archivo al usuario.

Para usar vistas Media, necesitas decirle a tu controlador que use la clase MediaView en vez de la clase por defecto
View. Después de esto, sólo pasa los parámetros adicionales para especificar dónde está ubicado tu archivo.

Plain Text View (#)


1. class EjemploController extends AppController {
2. function download () {
3. $this->view = 'Media';
4. $params = array(
5. 'id' => 'ejemplo.zip',
6. 'name' => 'ejemplo',
7. 'download' => true,
8. 'extension' => 'zip',
9. 'path' => 'files' . DS
10. );
11. $this->set($params);
12. }
13. }

Parámetros Descripción

113 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

id El ID es el nombre del archivo tal como está en el servidor, incluyendo su extensión.


El nombre (name) te permite especificar un nombre de archivo alternativo para ser enviado al usuario.
name
Especifica el nombre sin la extensión del archivo.
download Un valor booleano que indica si los encabezados deben forzar la descarga.
La extensión del archivo. Esto se compara con una lista interna de tipos MIME aceptados. Si el tipo MIME
extension
especificado no está en la lista, el archivo no será descargado.
El nombre del archivo, incluyendo el separador del directorio final. La ruta (path es relativa a la carpeta
path
app/.
Un arreglo con tipos MIME adicionales que serán mezclados con la lista interna de tipos MIME
mimeType
aceptados.

3.11 (#Helpers-1095) Helpers

Helpers son las clases simil-componentes para la capa de aplicación de tu aplicación. Ellos contienen la lógica
presentacional que es compartida entre vistas, elementos, o layouts. Este capítulo te mostrará cómo crear tus propios
helpers, abarcando las tareas básicas en las que los helpers del núcleo CakePHP pueden ayudarte a lograr. Para más
información sobre los helpers del núcleo, dirígete a Helpers 'de fábrica' (/es/view/181/built-in-helpers) .

3.11.1 (#Usando-Helpers-1096) Usando Helpers

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1096)


Comparar con el texto original (/es/compare/1096/Usando-Helpers)

Mas info sobre traduciones (/es/view/818)

Tú usas helpers en CakePHP haciendo que un controlador sepa de su existencia. Cada controlador tiene una
propiedad $helpers que lista los helpers que estarán disponibles en la vista. Para habilitar un helper en tu vista,
agrega el nombre del helper en el arreglo $helpers del controlador.

Plain Text View (#)


1. <?php
2. class BakeriesController extends AppController {
3. var $helpers = array('Form', 'Html', 'Javascript', 'Time');
4. }
5. ?>

También pueden agregar helpers desde dentro de una acción, de esta forma sólo estarán disponibles para esa acción
y no para las demás acciones que permanezcan a ese controlador. Esto ahorra poder de procesamiento para las
demás acciones que no usan el helper, y mantinen al controlador mejor organizado.

Plain Text View (#)


1. <?php
2. class BakeriesController extends AppController {
3. function bake {
4. $this->helpers[] = 'Time';
5. }
6. function mix {
7. // El helper Time no es cargado aquí, no estará disponible.
8. }
9. }
10. ?>

3.11.2 (#Creando-Helpers-1097) Creando Helpers

Si un helper del core (o alguno mostrado en Cakeforge o en la Bakery) no se ajusta a tus necesidades, los helpers son
fáciles de crear.

Digamos que quisieramos crear un helper que pudiera ser usado para mostrar como salida un link específicamente
creado con CSS que lo necesitas en diferentes partes de tu aplicación. Para poder ajustar tu lógica dentro de la
estructura existente de helpers de CakePHP, necesitarás crear una nueva clase en /app/views/helpers. Llamemos a

114 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

nuestro helper LinkHelper. El archivo de clase se verá algo como esto:

Plain Text View (#)


1. <?php
2. /* /app/views/helpers/link.php */
3. class LinkHelper extends AppHelper {
4. function makeEdit($title, $url) {
5. // Lógica para crear un link con un formato específico va aqui...
6. }
7. }
8. ?>

Existen algunos métodos incluidos en la clase de Helper en CakePHP de la cual quisieras sacar ventaja:

output(string $string)

Usa esta función para enviar cualquier información de regreso a tu vista.

Plain Text View (#)


1. <?php
2. function makeEdit($title, $url) {
3. // Usa la función de salida del helper para enviar
4. // datos con formato de regreso a la vista:
5. return $this->output(
6. "<div class=\"editOuter\">
7. <a href=\"$url\" class=\"edit\">$title</a>
8. </div>"
9. );
10. }
11. ?>

3.11.2.1 (#Including-other-Helpers-1098) Including other Helpers

Es posible que necesites usar alguna funcionalidad existente en otro helper. Para hacerlo, puedes especificar los
helpers que deseas utilizar con un arreglo $helpers, con el formato que usarías en un controlador.

Plain Text View (#)


1. <?php
2. /* /app/views/helpers/link.php (usando otros helpers) */
3. class LinkHelper extends AppHelper {
4. var $helpers = array('Html');
5. function makeEdit($title, $url) {
6. // Usa el helper de HTML para mostrar
7. // información con formato:
8. $link = $this->Html->link($title, $url, array('class' => 'edit'));
9. return $this->output("<div class=\"editOuter\">$link</div>");
10. }
11. }
12. ?>

3.11.2.2 (#Callback-method-1099) Callback method

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1099/Callback-method) .. Mas
info sobre traduciones (/es/view/818)

Helpers feature a callback used by the parent controller class.

beforeRender()

The beforeRender method is called after the controller's beforeRender method but before the controller's renders
views and layout.

115 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

3.11.2.3 (#Usando-tu-Helper-1100) Usando tu Helper

Una vez hayas creado tu helper y de haberlo colocado dentro de /app/views/helpers/, podrás incluirlo dentro de tus
controllers usando la variable especial $helpers.

Una vez tu controller se haya dado cuenta de esta nueva clase, podrás usarla en los views accesando mediante una
variable llamada por ese helper:

Plain Text View (#)


1. <!-- crear un link usando el nuevo helper -->
2. <?php echo $link->makeEdit('Change this Recipe', '/recipes/edit/5') ?>

Recuerda incluir el FormHelper en el array de $helpers si es apropiado. Los ayudantes Html y Session (si esta activa
una sesión) siempre estarán disponibles.

3.11.3 (#Creando-Funcionalidad-para-todos-los-Helpers-1101) Creando Funcionalidad para todos los Helpers

Todos los helpers extienden a una clase especial, AppHelper (así como los modelos extienden AppModel y los
controladores extienden AppController). Para crear funcionalidad que podría estar disponible para todos los helpers,
crea /app/app_helper.php.

Plain Text View (#)


1. <?php
2. class AppHelper extends Helper {
3. function customMethod () {
4. }
5. }
6. ?>

3.11.4 (#Helpers-del-Core-1102) Helpers del Core

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1102)


Comparar con el texto original (/es/compare/1102/Helpers-del-Core)

Mas info sobre traduciones (/es/view/818)

CakePHP contiene un buen número de helpers que ayudan en la creación de la vista. Ellos asisten en crear notación
(markup) con buen formato (incluyendo formas), ayudan a dar formato a texto, tiempo y números, y también pueden
acelerar la funcionalidad de Ajax. Aquí está un resumen de los helpers disponibles por defecto. Para más imformación
revisa Helpers del Core (/es/view/181/Core-Helpers) .

Helper de CakePHP Descripción


Usado en conjunto con Prototype Javascript Library para crear funcionalidad en las vistas.
Ajax (/es/view
Contiene métodos rápidos para drag/drop (levantar/tirar), formularios ajax & enlaces,
/208/AJAX)
observadores, y más.
Cache (/es/view
Es usado por el núcleo (core) para almacenar el contenido de las vistas en caché.
/213/Cache)
Form (/es/view Crea formularios HTML y elementos de formulario que se poblan solas y manejan problemas
/182/Form) de validación.
Html (/es/view Métodos convenientes para crear código (markup) bien formateado. Imágenes, links, tablas,
/205/HTML) tags de headers y más.
Javascript (/es/view Usado para 'escapar' valores para usarse en JavaScript, escribir tus propios objetos JSON, y
/207/Javascript) dar formato a bloques de código.
Number (/es/view
Formato para números y tipo de cambio.
/215/Number)
Paginator (/es/view
Paginar y ordenar información de modelos.
/496/Paginator)
Rss (/es/view/494/RSS) Métodos convenientes para regresar datos RSS feed XML.
Session (/es/view
Aceso para escribir valores de la sesión en las vistas.
/484/Session)

116 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Text (/es/view
Enlaces inteligentes, marcadores, truncado inteligente de palabras.
/216/Text)
Time (/es/view Detección de proximidad (es este siguiente año?), buen formateo de cadenas de caracteres
/217/Time) (Hoy, 10:20 am) y conversiones de usos horarios.
Xml (/es/view/380/XML) Métodos convenientes para crear elementos y headers XML.

3.12 (#Scaffolding-1103) Scaffolding

El scaffolding (creación de plataformas temporales) en aplicaciones es una técnica que permite a un desarrollador
definir y crear aplicaciones básicas que pueden crear, retirar, actualizar y borrar objetos. El scaffolding en CakePHP
también permite a los desarrolladores definir cómo los objetos están relacionados unos con otros, y para crear y
romper estos enlaces.

Todo lo que se necesita para crear un scaffold (plataforma temporal) es un modelo y su controlador. Una vez que se
declare la variable $scaffold en el controlador, ya estas listo y corriendo.

El scaffolding de CakePHP es bastante agradable. Te permite tener una aplicación CRUD básica funcional en minutos.
Es tan agradable, que querrás usarla en aplicaciones de producción. Ahora, nosotros pensamos que es agradable
también, pero por favor, ese cuenta lo que el scaffoldding (plataforma temporal) es... bueno... es solo una plataforma
temporal. Su estructura flexible la deshaces rápidamente al inicio de un proyecto para poder iniciar. No fue pensada
para ser completamente flexible, fue pensada como una manera temporal de iniciar un proyecto rápidamente. Si usted
se encuentra realmente tratando de personalizar la lógica en sus vistas, es momento de derrumbar su scaffolding para
poder escribir más código. La consola Bake de CakePHP, vista en la siguiente sección, es un gran segundo paso:
genera todo el código que produciría el mismo resultado que el más reciente escalonado.

Scaffolding es una gran manera de iniciar las primeras partes de una aplicación web iniciada. Los esquemas de bases
de datos tempranos son sujetos a cambios, lo cual es perfectamente normal en una parte temprana del proceso de
diseño. Esto tiene su inconveniente: un desarrollador web detesta formas que nunca serán utilizadas. Para reducir el
estrés en el desarrollador, el scaffolding ha sido incluido en CakePHP. El scaffolding analiza sus tablas en la base de
datos y crea listas estandard con botones de agregar, borrar y editar, forms estandar para editar y vistas estandar
para inspeccionar un único elemento en la base de datos.

Para agregar scaffolding a tu aplicación, en el controlador, , agrega la variable $scaffold:

Plain Text View (#)


1. <?php
2. class CategoriesController extends AppController {
3. var $scaffold;
4. }
5. ?>

Si has creado la clase basica del modelo Category en el archivo /app/models/category.php, ya estás listo para
comenzar!. Visita http://example.com/categories para ver tu nuevo scaffold.

El crear métodos en controladores que se hayan sido "scaffoldeados" pueden causar resultados no deseados. Por
ejemplo, si crea un método index() en un controlador "scaffoldeado", su método index será mostrado en lugar que la
funcionalidad de scaffoling.

El scaffolding es reconocido por sus asociaciones de modelos, así que si tu modelo Category pertenece a un User
["belongsTo" User], usted verá las IDs del modelo User relacionadas en el listado del modelo Category. Si usted
quisiera ver algo aparte de un ID (como el apellido del usuario), lo logrará activando la variable $displayField en el
modelo.

Inicializaremos la variable $displayField en nuestra clase de User para que los usuarios relacionados con categorías
serán mostrados por el primer nombre en lugar de solo el ID en el scaffolding. Esta característica hace el scaffolding
más leíble en muchas instancias.

Plain Text View (#)


1. <?php
2. class User extends AppModel {
3. var $name = 'User';
4. var $displayField = 'first_name';
5. }
6. ?>

117 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

3.12.1 (#Creating-a-simple-admin-interface-with-scaffolding-1104) Creating a simple admin interface with scaffolding

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1104/Creating-a-simple-admin-
interface-with-scaffolding) .. Mas info sobre traduciones (/es/view/818)

If you have enabled admin routing in your app/config/core.php, with Configure::write('Routing.prefixes',


array('admin')); you can use scaffolding to generate an admin interface.

Once you have enabled admin routing assign your admin prefix to the scaffolding variable.

Plain Text View (#)


1. var $scaffold = 'admin';

You will now be able to access admin scaffolded actions: Plain Text View (#)
1. http://example.com/admin/controller/index
2. http://example.com/admin/controller/view
3. http://example.com/admin/controller/edit
4. http://example.com/admin/controller/add
5. http://example.com/admin/controller/delete

This is an easy way to create a simple backend interface quickly. Keep in mind that you cannot have both admin and
non-admin methods scaffolded at the same time. As with normal scaffolding you can override individual methods and
replace them with your own.

Plain Text View (#)


1. function admin_view($id = null) {
2. //custom code here
3. }

Once you have replaced a scaffolded action you will need to create a view file for the action as well.

3.12.2 (#Personalizando-Vistas-Scaffold-1105) Personalizando Vistas Scaffold

Si estás buscando para algo un poco diferente a tus vistas scaffolded, puees crear templetes. Nosotros aún no
recomendamos esta técnica para aplicaciones de producción, pero semejante personalización puede ser muy útil
durante el esarrollo e prototipos.

La personalización se hace creando templetes de vistas:

Vistas personalizadas para un controlador específico (para este ejemplo PostsController) debe ser colocado como

/app/views/posts/scaffold.index.ctp
/app/views/posts/scaffold.show.ctp
/app/views/posts/scaffold.edit.ctp
/app/views/posts/scaffold.new.ctp

Las vistas scaffolding personalizadas para todos los controladores deberían ser colocadas como las siguientes:

/app/views/scaffolds/index.ctp
/app/views/scaffolds/show.ctp
/app/views/scaffolds/edit.ctp
/app/views/scaffolds/new.ctp
/app/views/scaffolds/add.ctp

3.13 (#La-consola-de-CakePHP-1106) La consola de CakePHP

Esta sección provee una introducción a CakePHP en la línea de comandos. Si tu alguna vez has utilizado tus clases
MVC de CakePHP en un cron job o cualquier otro script de línea de comandos, esta sección es para ti.

PHP provee un poderoso cliente CLI que hace que crear interfases entre tus archivos de sistema y tus aplicaciones sea
mucho más sencillo. La Consola CakePHP provee un framework para crear scritps de shell. La Consola usa una
configuración del tipo despachador para cargar una un shell o una tarea, y para regresar sus parámetros.

118 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Una versión de línea de comandos (cli) de PHP debe de estar disponible en el sistema si planeas usar la Consola.

Antes de que nos metamos en cosas más específicas, hay que asegurarnos de que podemos correr CakePHP en
consola. Primero, necesitas abrir una terminal el sistema. Los ejemplos mostrados en esta sección serán en bash,
pero la Consola e CakePHP es compatible con Windows también. Ejecutemos el programa de Consola desde bash. Este
ejemplo asume que el usuario ya esta logeado en una sesión de bash y se encuentra en la raíz de la instalación de
CakePHP.

Puedes técnicamente correr la consola usando algo similar a esto:

$ cd /my/cake/app_folder
$ ../cake/console/cake

Pero el uso preferido es agregando el directorio de consola a tu ruta para que puedas usar el comando cake en
cualquier lado:

$ cake

Ejecutar la Consola sin argumentos produce el siguiente mensaje de ayuda:

Hello user,

Welcome to CakePHP v1.2 Console


---------------------------------------------------------------
Current Paths:
-working: /path/to/cake/
-root: /path/to/cake/
-app: /path/to/cake/app/
-core: /path/to/cake/

Changing Paths:
your working path should be the same as your application path
to change your path use the '-app' param.
Example: -app relative/path/to/myapp or -app /absolute/path/to/myapp

Available Shells:

app/vendors/shells/:
- none

vendors/shells/:
- none

cake/console/libs/:
acl
api
bake
console
extract

To run a command, type 'cake shell_name [args]'


To get help on a specific command, type 'cake shell_name help'

La primera información mostrada se relaciona con las rutas. Esto es epecialmente útil si estas ejecutando la consola
de diferentes partes del sistema de archivos.

Muchos usuarios agregan la Consola de CakePHP a sus rutas del sistema operativo para que pueda ser ejecutado
fácilmente. Imprimiendo las rutas del directorio de trabajo root, app, y core te permite ver donde la Consola hará los
cambios. Para cambiar la carpeta de app con el que deseas trabajar, puedes proporcionar su ruta como el primer
argumento al comando cake. Este siguiente ejemplo nos muestra como especificar un folder de app, asumiendo que
ya has agregado el carpeta de la consola en tu PATH:

$ cake -app /path/to/app

La ruta provista puede ser relativa al directorio de trabajo actual o provista como una ruta absoluta.

119 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

3.13.1 (#Creando-Shells-y-Tasks-1107) Creando Shells y Tasks

3.13.1.1 (#Creando-tus-Propios-Shells-1108) Creando tus Propios Shells

Crearemos una shell para usarla en la Consola. Para este ejemplo, crearemos una ʻreport' shell que imprima datos de
un modelo. Primero, crea un report.php en /vendors/shells/.

Plain Text View (#)


1. <?php
2. class ReportShell extends Shell {
3. function main() {}
4. }
5. ?>

Desde este punto, ya podemos correr el shell, pero no hará mucho. Agreguemos algunos modelos al shell para que
podamos crear un reporte de algún tipo. Esto se hace de la misma forma que en el controlador: al agregar los
nombres de los modelos a la variable $uses;

Plain Text View (#)


1. <?php
2. class ReportShell extends Shell {
3. var $uses = array('Order');
4. function main() {
5. }
6. }
7. ?>

Una vez que agregamos nuestro modelo al arreglo $uses, podemos usarlo en el método main(); En este ejemplo,
nuestro modelo Order debe de ahora ser accesible como $this->Order en el método main() de nuestro nuevo shell.

Aquí hay un ejemplo simple de la lógica que podemos usar en este shell:

Plain Text View (#)


1. class ReportShell extends Shell {
2. var $uses = array('Order');
3. function main() {
4. //Agrega las órdenes enviadas el mes pasado.
5. $month_ago = date('Y-m-d H:i:s', strtotime('-1 month'));
6. $orders = $this->Order->find("all",array('conditions'=>"Order.shipped >= '$month_ago'"));
7. //Imprime la información de cada orden.
8. foreach($orders as $order) {
9. $this->out('Order date: ' . $order['Order']['created'] . "\n");
10. $this->out('Amount: $' . number_format($order['Order']['amount'], 2) . "\n");
11. $this->out('----------------------------------------' . "\n");
12.
13. $total += $order['Order']['amount'];
14. }
15. //Imprime el total de las ordenes seleccionadas.
16. $this->out("Total: $" . number_format($total, 2) . "\n");
17. }
18. }

Debes de ser capás de correr este reporte ejecutando este comando (si el comando cake esta en tu PATH):

$ cake report

donde report es el nombre del archivo shell en /vendor/shells/ sin la extensión .php. Esto deberá regresar lo
siguiente:

Hello user,
Welcome to CakePHP v1.2 Console
---------------------------------------------------------------

120 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

App : app
Path: /path/to/cake/app
---------------------------------------------------------------
Order date: 2007-07-30 10:31:12
Amount: $42.78
----------------------------------------
Order date: 2007-07-30 21:16:03
Amount: $83.63
----------------------------------------
Order date: 2007-07-29 15:52:42
Amount: $423.26
----------------------------------------
Order date: 2007-07-29 01:42:22
Amount: $134.52
----------------------------------------
Order date: 2007-07-29 01:40:52
Amount: $183.56
----------------------------------------
Total: $867.75

3.13.1.2 (#Tasks-Tareas-1109) Tasks (Tareas)

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1109)


Comparar con el texto original (/es/compare/1109/Tasks-Tareas)

Mas info sobre traduciones (/es/view/818)

Los tasks (tareas) son pequeñas extensiones para los shells. Nos permiten que haya lógica comapartida entre shells, y
son agregadas a nuestros shells usando una variable de clase especial $task. Por ejemplo en la shell core de bake,
hay un cierto número de tasks definidos:

Plain Text View (#)


1. <?php
2. class BakeShell extends Shell {
3. var $tasks = array('Project', 'DbConfig', 'Model', 'View', 'Controller');
4. }
5. ?>

Los tasks son almacenados en /vendors/shells/tasks/ en archivos con el nombre de sus clases. Así que si
quisiéramos crear una nueva tarea ʻcoolʼ , la clase CookTask (que extiende de Shell) sería colocada en /vendors
/shells/tasks/cool.php. La clase VeryCoolTask (que extiende Shell) sería colocada en /vendors/shells/tasks
/cool.php.

Cada task debe de tener por lo menos un método execute() - los shells llamarán a este método para iniciar la lógica
del task.

Plain Text View (#)


1. <?php
2. class SoundTask extends Shell {
3. var $uses = array('Model'); // Lo mismo que en el controlador var $uses
4. function execute() {}
5. }
6. ?>

Puedes acceder a tasks dentro de tus clases de shell y ejecutarlas desde ahí:

Plain Text View (#)

121 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <?php
2. class SeaShell extends Shell // Se encuentra en /vendors/shells/sea.php {
3. var $tasks = array('Sound'); //Se encuentra en /vendors/shells/tasks/sound.php
4. function main() {
5. $this->Sound->execute();
6. }
7. }
8. ?>

Un método llamado “sound” en la clase SeaShell podría sustituir la habilidad de acceder a la funcionalidad de la tarea
Sound especificada en el arreglo $tasks.

Puedes también acceder a los tasks directamente desde la línea de comados:

$ cake sea sound

3.13.2 (#Running-Shells-as-cronjobs-1110) Running Shells as cronjobs

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1110/Running-Shells-
as-cronjobs) .. Mas info sobre traduciones (/es/view/818)

A common thing to do with a shell is making it run as a cronjob to clean up the database once in a while or send
newsletters. However, when you have added the console path to the PATH variable via ~/.profile, it will be
unavailable to the cronjob.

The following BASH script will call your shell and append the needed paths to $PATH. Copy and save this to your
vendors folder as 'cakeshell' and don't forget to make it executable. (chmod +x cakeshell)

#!/bin/bash
TERM=dumb
export TERM
cmd="cake"
while [ $# -ne 0 ]; do
if [ "$1" = "-cli" ] || [ "$1" = "-console" ]; then
PATH=$PATH:$2
shift
else
cmd="${cmd} $1"
fi
shift
done
$cmd

You can call it like:

$ ./vendors/cakeshell myshell myparam -cli /usr/bin -console /cakes/1.2.x.x/cake/console

The -cli parameter takes a path which points to the php cli executable and the -console parameter takes a path which
points to the CakePHP console.

As a cronjob this would look like:

# m h dom mon dow command


*/5 * * * * /full/path/to/cakeshell myshell myparam -cli /usr/bin -console /cakes/1.2.x.x/cake/console -a

A simple trick to debug a crontab is to set it up to dump it's output to a logfile. You can do this like:

# m h dom mon dow command


*/5 * * * * /full/path/to/cakeshell myshell myparam -cli /usr/bin -console /cakes/1.2.x.x/cake/console -a

3.14 (#Plugins-1111) Plugins

CakePHP nos permite combinar una serie de controladores, modelos y vistas y publicarlos como una aplicación
empaquetada, plugin , que otros pueden integrar en sus aplicaciones CakePHP. ¿Has desarrolado un módulo de
administración de usuarios amigable, un blog sencillo o un web service en alguna de tus aplicaciones? Empaquétalo

122 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

como un plugin de CakePHP e inclúyelo en otras aplicaciones.

El principal vínculo entre un plugin y la aplicación en la que se instala es la configuración de la aplicación (conexión
a la base de datos, etc.). Por lo demás, el plugin opera en su propio espacio, comportándose como si fuese una
aplicación en sí mismo.

3.14.1 (#Crear-un-Plugin-1112) Crear un Plugin

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1112)


Comparar con el texto original (/es/compare/1112/Crear-un-Plugin)

Mas info sobre traduciones (/es/view/818)

Como ejemplo, vamos a crear un nuevo plugin que encargue pizzas. Para empezar tendremos que colocar todos los
archivos de nuestro plugin en el directorio /app/plugins. El nombre del directorio padre del plugin es importante y
se referenciará muy a menudo, así que conviene escogerlo con prudencia. Para este ejemplo utilizaremos el nombre
'pizza'. La estructura de archivos será la siguiente:

/app
/plugins
/pizza
/controllers <- controladores del plugin
/models <- modelos del plugin
/views <- vistas del plugin
/pizza_app_controller.php <- clase AppController del plugin
/pizza_app_model.php <- clase AppModel del plugin

Si queremos acceder a nuestro plugin a través de una URL, es necesario definir las clases AppController y AppModel
para el mismo. Estas dos clases especiales tienen el nombre del plugin y extienden las clases AppController y
AppModel de la aplicación principal. En nuestro ejemplo:

Plain Text View (#)


1. // /app/plugins/pizza/pizza_app_controller.php:
2. <?php
3. class PizzaAppController extends AppController {
4. //...
5. }
6. ?>

Plain Text View (#)


1. // /app/plugins/pizza/pizza_app_model.php:
2. <?php
3. class PizzaAppModel extends AppModel {
4. //...
5. }
6. ?>

Si olvidamos definir estas clases, CakePHP nos mostrará el error "Missing Controller".

3.14.2 (#Controladores-del-Plugin-1113) Controladores del Plugin

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1113)


Comparar con el texto original (/es/compare/1113/Controladores-del-Plugin)

Mas info sobre traduciones (/es/view/818)

Los controladores de nuestro plugin pizza se almacenan en /app/plugins/pizza/controllers/. Puesto que las
acciones que más trataremos son las peticiones de pizza, necesitaremos el controlador PeticionesController para este
plugin.

Aunque no es necesario, conviene llamar los controladores de los plugin con un nombre relativamente único, con el

123 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

fin de evitar conflictos de espacios de nombre con la aplicación principal. No es extraño pensar que una aplicación
podría tener controladores como UsuariosController, PeticionesController o ProductosController: deberíamos ser
creativos con los nombres de los controladores, o anteponer el nombre del plugin al nombre de la clase
(PizzaPeticionesController en nuestro ejemplo).

Así, ubicamos nuestro nuevo controlador, PizzaPeticionesController, en /app/plugins/pizza/controllers, quedando:

Plain Text View (#)


1. // /app/plugins/pizza/controllers/pizza_peticiones_controller.php
2. class PizzaPeticionesController extends PizzaAppController {
3. var $name = 'PizzaPeticiones';
4. var $uses = array('Pizza.PizzaPeticion');
5. function index() {
6. //...
7. }
8. }

Observa cómo este controlador extiende el controlador AppController del plugin (llamado PizzaAppController) en
lugar del controlador AppController de la aplicación principal.

Además, al nombre del modelo se añade como prefijo el nombre del plugin. Esta línea de código se añade por
claridad, pero no es necesaria en este caso.

Si quieres acceder a lo que hemos hecho hasta ahora, visita /pizza/pizzaPeticiones. Deberías obtener un error
“Missing Model”, porque no hemos definido todavía el modelo PizzaPeticion.

3.14.3 (#Modelos-del-Plugin-1114) Modelos del Plugin

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1114)


Comparar con el texto original (/es/compare/1114/Modelos-del-Plugin)

Mas info sobre traduciones (/es/view/818)

Los modelos de un plugin son almacenados en /app/plugins/pizza/models. En el apartado anterior, definimos el


controlador PizzaPeticionesController para nuestro plugin de ejemplo. Ahora crearemos el modelo para ese
controlador, PizzaPeticion, definición consistente con el esquema de nombres que establecimos previamente,
anteponiendo a todas las clases de nuestro plugin el nombre del mismo, Pizza.

Plain Text View (#)


1. // /app/plugins/pizza/models/pizza_peticion.php:
2. class PizzaPeticion extends PizzaAppModel {
3. var $name = 'PizzaPeticion';
4. }
5. ?>

Acceder a /pizza/pizzaPeticiones ahora (suponiendo que tenemos una tabla en nuestra base de datos llamada
ʻpizza_peticionesʼ) nos debería dar un error “Missing View”. Este será el próximo paso.

Si necesitamos referenciar un modelo dentro de nuestro plugin, tenemos que incluir el nombre del plugin junto con
el nombre del modelo, separados por un punto.

Plain Text View (#)


1. // /app/plugins/pizza/models/pizza_peticion.php:
2. class ExampleModel extends PizzaAppModel {
3. var $name = 'ExampleModel';
4. var $hasMany = array('Pizza.PizzaPeticion');
5. }
6. ?>

3.14.4 (#Vistas-del-Plugin-1115) Vistas del Plugin

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

124 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Ver que ha cambiado (/es/nodes/redirect_to_revision/1115)


Comparar con el texto original (/es/compare/1115/Vistas-del-Plugin)

Mas info sobre traduciones (/es/view/818)

Las vistas se comportan en un plugin exactamente igual a como lo hacen en una aplicación normal. Basta con
colocarlas en la carpeta adecuada en /app/plugins/[plugin]/views/. Para nuestro plugin encargado de pedir pizza,
necesitaremos una vista para la acción PizzaPeticionesController::index():

Plain Text View (#)


1. // /app/plugins/pizza/views/pizza_peticiones/index.ctp:
2. <h1>Pide una Pizza</h1>
3. <p>¡Nada combina con Cake mejor que una buena pizza!</p>
4. <!-- Aquí debería ir un formulario para solicitar pizza...-->

3.14.5 (#Componentes-Ayudantes-y-Comportamientos-1116) Componentes, Ayudantes y Comportamientos

Al igual que una aplicación típica, un plugin puede tener Componentes (Components), Ayudantes (Helpers) y
Comportamientos (Behaviors). Incluso podemos crear plugins que incluyan únicamente estas clases, siendo un
mecanismo excelente para construir módulos reutilizables que pueden añadirse fácilmente en cualquier proyecto.

Los componentes se desarrollan exactamente de la misma manera a como se desarrollan en una aplicación normal,
sin ninguna convención de nombres especial. Hacer referencia a nuestros componentes desde el mismo plugin no
requiere ninguna notación especial.

Plain Text View (#)


1. // Componente
2. class EjemploComponent extends Object {
3. }
4. // desde los controladores de nuestro plugin:
5. var $components = array('Ejemplo');

Para invocar el Componente desde fuera del entorno del plugin, tenemos que indicar el nombre del mismo.

Plain Text View (#)


1. var $components = array('PluginNombre.Ejemplo');
2. var $components = array('Pizza.Ejemplo'); // referencia al componente EjemploComponent en el plugin Pizz

La misma técnica se aplica a los Ayudantes y Comportamientos.

3.14.6 (#CSS-y-Javascript-en-los-Plugins-1117) CSS y Javascript en los Plugins

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1117)


Comparar con el texto original (/es/compare/1117/CSS-y-Javascript-en-los-Plugins)

Mas info sobre traduciones (/es/view/818)

Podemos incluir archivos CSS y Javascript en nuestros plugins, colocándolos, respectivamente, en


nuestro_plugin/vendors/css y nuestro_plugin/vendors/js. Pueden incluirse en nuestras vistas usando los ayudantes
nativos del framework.

Plain Text View (#)


1. <?php echo $html->css('/nuestro_plugin/css/mi_css'); ?>
2.
3. <?php echo $javascript->link('/nuestro_plugin/js/mi_javascript');

Las líneas anteriores son ejemplos de como incluir archivos javascript y css en nuestro plugin.

Es importante observar como se incluye en la ruta del arhivo js o css /nuestro_plugin/. Esto hace que la magia
funcione

3.14.7 (#Consejos-para-desarrollar-Plugins-1118) Consejos para desarrollar Plugins

125 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1118)


Comparar con el texto original (/es/compare/1118/Consejos-para-desarrollar-Plugins)

Mas info sobre traduciones (/es/view/818)

Una vez que ya hemos desarrollado todo lo necesario, nuestro plugin está listo para ser distribuido (aunque sería
conveniente añadir unos cuantos extras, como un readme o un fichero SQL).

Después de instalar el plugin en /app/plugins, podemos acceder al mismo siguiendo la URL /nombreplugin
/nombrecontrolador/accion. En nuestro plugin de ejemplo para ordenar pizza, accedemos a PizzaPeticionesController
en /pizza/pizzaPeticiones.

Algunos consejos útiles a tener en cuenta cuando trabajamos con plugins en nuestras aplicaciones CakePHP:

Si no definimos [Plugin]AppController y [Plugin]AppModel, recibiremos errores "Missing Controller" cuando


intentemos accede a un controlador del plugin.
Podemos tener un controlador por defecto con el mismo nombre de nuestro plugin. Podemos acceder a él via
/[plugin]/accion. Por ejemplo, a un plugin llamado 'usuarios' con un controlador UsuariosController podemos
acceder en /usuarios/add si no hay ningún plugin llamado AddController en la carpeta [plugin]/controllers.
Podemos definir el diseño de nuestros plugins en app/plugin/views/layouts. En caso contrario, los plugins
usarán, por defecto, los diseños en /app/views/layouts folder by default.
Usando $this->requestAction('/plugin/controller/accion'); en los controladores logramos comunicar distintos
plugins.
Si pretendemos usar requestAction, debemos asegurarnos de que los nombres de modelos y controladores son
tan únicos como sea posible. Si no fuera así, pueden surgir errores PHP del tipo "clase redefinida ..."

3.15 (#Constantes-y-Funciones-Globales-1119) Constantes y Funciones Globales

Aunque en la mayor parte de nuestro trabajo diario en CakePHP utilizaremos clases y métodos nativos, es útil conocer
una serie de funciones globales que ofrece CakePHP. Muchas de ellas están orientadas al trabajo con las clases de
CakePHP (cargando las clases de modelo o componente), pero muchas otras hacen más sencillo trabajar con matrices
o cadenas.

También veremos en esta sección algunas de las constantes disponibles en las aplicaciones CakePHP. Usarlas ayuda a
realizar actualizaciones menos complicadas, además de ser útiles a la hora de referenciar ciertos archivos o
directorios en nuestras aplicaciones CakePHP.

3.15.1 (#Funciones-globales-1120) Funciones globales

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1120)


Comparar con el texto original (/es/compare/1120/Funciones-globales)

Mas info sobre traduciones (/es/view/818)

Éstas son las funciones globales disponibles en CakePHP. Muchas de ellas simplemente facilitan la llamada a
funciones de PHP con nombres largos, pero otras (como vendor() y uses()) se pueden usar para incluir código o
realizar otras funciones útiles. Lo más probable es que si estás buscando una función para realizar una tarea con
mucha frecuencia, la encuentres aquí.

3.15.1.1 (#__-1121) __

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1121)


Comparar con el texto original (/es/compare/1121/__)

Mas info sobre traduciones (/es/view/818)

__(string $string_id, boolean $return = false)

Esta función gestiona la localización en las aplicaciones CakePHP. El parámetro $string_id identifica la ID de una
traducción, mientras que el segundo parámetro indica si se debe mostrar automáticamente la cadena (por defecto), o
devolverla para su procesamiento (pasar el valor true para que esto suceda).

126 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Visita la sección Localización e Internacionalización (/es/view/161/localization-internationalizat) para más


información.

3.15.1.2 (#a-1122) a

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1122)


Comparar con el texto original (/es/compare/1122/a)

Mas info sobre traduciones (/es/view/818)

a(mixed $uno, $dos, $tres...)

Devuelve un array con los parámetros pasados a la función.

Plain Text View (#)


1. print_r(a('foo', 'bar'));
2. // salida:
3. array(
4. [0] => 'foo',
5. [1] => 'bar'
6. )

3.15.1.3 (#aa-1123) aa

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1123)


Comparar con el texto original (/es/compare/1123/aa)

Mas info sobre traduciones (/es/view/818)

aa(array $uno, $dos, $tres...)

Crea arrays asociativos a partir de los parámetros enviados a la función.

Plain Text View (#)


1. echo aa('a','b');
2. // salida:
3. array(
4. 'a' => 'b'
5. )

3.15.1.4 (#am-1124) am

am(array $uno, $dos, $tres...)

Combina todos los arrays pasados como parámetros y devuelve el array resultante.

3.15.1.5 (#config-1125) config

Puede ser usado para cargar archivos desde el directorio config mediante include_once. La función checa si existe el
archivo antes de incluir y regresa un booleano. Toma un número opcional de argumento.

Ejemplo: config('some_file', 'myconfig');

3.15.1.6 (#convertSlash-1126) convertSlash

convertSlash(string $cadena)

Sustituye las barras ("/") por subrayados ("_") y elimina el primer y el último subrayados en una cadena. Devuelve la
cadena convertida.

127 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

3.15.1.7 (#debug-1128) debug

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1128)


Comparar con el texto original (/es/compare/1128/debug)

Mas info sobre traduciones (/es/view/818)

debug(mixed $var, boolean $showHtml = false)

Si el nivel de depuración, variable de configuración DEBUG, es distinto de cero, se muestra $var. Si $showHTML es true,
los datos se formatean para mostrarlos adecuadamente en los navegadores web.

3.15.1.8 (#e-1129) e

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1129)


Comparar con el texto original (/es/compare/1129/e)

Mas info sobre traduciones (/es/view/818)

e(mixed $datos)

Simplifica la llamada a la función echo().

3.15.1.9 (#env-1130) env

env(string $key)

Obtiene una variable de entorno a partir de las fuentes disponibles. Alternativa si las variables $_SERVER o $_ENV están
deshabilitadas.

También permite emular las variables PHP_SELF y DOCUMENT_ROOT en los servidores que no permitan su uso. De
hecho, es una buena práctica usar env() en lugar de $_SERVER o getenv() (sobretodo si pensamos distribuir el
código), ya que ofrece la misma funcionalidad y es totalmente compatible.

3.15.1.10 (#fileExistsInPath-1131) fileExistsInPath

fileExistsInPath(string $archivo)

Comprueba que el fichero $archivo está en el include_path actual de PHP. Devuelve un valor booleano.

3.15.1.11 (#h-1132) h

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1132)


Comparar con el texto original (/es/compare/1132/h)

Mas info sobre traduciones (/es/view/818)

h(string $texto, string $charset)

Alias de la función htmlspecialchars().

3.15.1.12 (#ife-1133) ife

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1133)


Comparar con el texto original (/es/compare/1133/ife)

Mas info sobre traduciones (/es/view/818)

ife($condicion, $siNoVacia, $siVacia)

128 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Útil en operaciones ternarias. Si $condicion no es vacía, devuelve $siNoVacia; si no, devuelve $siVacia.

3.15.1.13 (#low-1134) low

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1134)


Comparar con el texto original (/es/compare/1134/low)

Mas info sobre traduciones (/es/view/818)

low(string $cadena)

Alias de la función strtolower().

3.15.1.14 (#pr-1136) pr

pr(mixed $var)

Alias de la función print_r(), añadiendo la etiqueta <pre> a la salida.

3.15.1.15 (#r-1137) r

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1137)


Comparar con el texto original (/es/compare/1137/r)

Mas info sobre traduciones (/es/view/818)

r(string $cadena_buscada, string $cadena_sustituta, string $cadena_original)

Alias de la función str_replace().

3.15.1.16 (#stripslashes_deep-1138) stripslashes_deep

stripslashes_deep(array $valor)

Elimina recursivamente las barras invertidas de $valor. Devuelve el array modificado.

3.15.1.17 (#up-1139) up

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1139)


Comparar con el texto original (/es/compare/1139/up)

Mas info sobre traduciones (/es/view/818)

up(string $cadena)

Alias de la función strtoupper().

3.15.1.18 (#uses-1140) uses

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1140)


Comparar con el texto original (/es/compare/1140/uses)

Mas info sobre traduciones (/es/view/818)

uses(string $lib1, $lib2, $lib3...)

Permite cargar las librerías nativas de CakePHP (localizadas en cake/libs/). Pasar como parámetro el nombre de la
librería sin la extensión '.php'.

129 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

3.15.2 (#Constantes-predefinidas-1141) Constantes predefinidas

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1141)


Comparar con el texto original (/es/compare/1141/Constantes-predefinidas)

Mas info sobre traduciones (/es/view/818)

constante Ruta absoluta dentro de la aplicación al ...

APP directorio raíz.

APP_PATH directorio app.

CACHE directorio de archivos de cache.

CAKE directorio cake.

COMPONENTS directorio components.

CONFIGS directorio de archivos de configuración.

CONTROLLER_TESTS directorio controller de los tests.

CONTROLLERS directorio controllers.

CSS directorio de archivos CSS.

ELEMENTS directorio elements.

HELPER_TESTS directorio helper de los tests.

HELPERS directorio helpers.

INFLECTIONS directorio inflections (normalmente dentro del directorio de configuración).

JS directorio de archivos JavaScript (en webroot).

LAYOUTS directorio layouts.

LIB_TESTS directorio CakePHP Library de los tests.

LIBS directorio de librerías CakePHP.

LOGS directorio de logs (en app).

MODEL_TESTS directorio model de los tests.

MODELS directorio models.

SCRIPTS directorio de scripts de Cake.

130 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

TESTS directorio tests (directorio padre de los directorios de test para los modelos,
controladores, etc.)

TMP directorio tmp.

VENDORS directorio vendors.

VIEWS directorio views.

WWW_ROOT ruta completa a webroot.

3.16 (#Vendor-packages-1612) Vendor packages

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1612/Vendor-packages) .. Mas
info sobre traduciones (/es/view/818)

Vendor file information goes here.

3.16.1 (#Vendor-assets-1613) Vendor assets

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1613/Vendor-assets) .. Mas info
sobre traduciones (/es/view/818)

Support for vendor assets have been removed for 1.3. It is recommended that you take any vendor assets you have
and repackage them into plugins. See Plugin assets (/es/view/1117/Plugin-assets) for more information.

4 (#Tareas-comunes-con-CakePHP-1142) Tareas comunes con CakePHP

4.1 (#Validación-de-Datos-1143) Validación de Datos

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1143)


Comparar con el texto original (/es/compare/1143/Validación-de-Datos)

Mas info sobre traduciones (/es/view/818)

La validación de los datos es una parte importante de cualquier aplicación, ya que asegura que los datos en un
modelo están conformes a las reglas de negocio de la aplicación. Por ejemplo, tu podrias querer que los passwords
tengan a lo menos un largo de ocho caracteres, o asegurar que los username sean únicos. Definir reglas de
validación hace que el manejo de los formularios sea muchísimo más fácil.

Hay muchos diferentes aspectos del proceso de validación. En esta sección cubriremos el lado del modelo, es decir,
lo que ocurre cuando tu llamas al método save() de tu modelo. Para más información acerca de cómo manejar el
despliegue de errores de validación, revisa la sección que cubre el FormHelper.

El primer paso en la validación de datos es la creación de las reglas de validación en el Modelo. Para hacer eso, usa el
arreglo Model::validate en la definición del Modelo, por ejemplo:

Plain Text View (#)


1. <?php
2. class User extends AppModel {
3. var $name = 'User';
4. var $validate = array();
5. }
6. ?>

En el ejemplo de arriba, el arreglo $validate se agrega al modelo User, pero el arreglo no contiene reglas de
validación. Asumiendo que la tabla users tiene los campos login , password , email y born , el ejemplo de abajo
muestra algunas simples reglas de validación que se aplican a esos campos:

131 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Plain Text View (#)


1. <?php
2. class User extends AppModel {
3. var $name = 'User';
4. var $validate = array(
5. 'login' => 'alphaNumeric',
6. 'email' => 'email',
7. 'born' => 'date'
8. );
9. }
10. ?>

El ejemplo muestra cómo se pueden agregar reglas de validación a los campos de un modelo. Para el campo login
serán aceptadas sólo letras y números, el email debe ser válido, y born debe ser una fecha válida. La definición de
reglas de validación habilitan en CakePHP el despliegue automático de mensajes de error en formularos si los datos
enviados no cumplen las reglas de validación.

CakePHP incluye muchas reglas de validación y usarlas puede ser bastante simple. Algunas de las reglas incluidas
permiten verificar el formato de los emails, URLs, y números de tarjeta de crédito - las cubriremos en detalle más
adelante.

Acá tenemos un ejemplo de validación más complejo que aprovecha algunas de las reglas incluidas:

Plain Text View (#)


1. <?php
2. class User extends AppModel {
3. var $name = 'User';
4. var $validate = array(
5. 'login' => array(
6. 'alphaNumeric' => array(
7. 'rule' => 'alphaNumeric',
8. 'required' => true,
9. 'message' => 'Sólo letras y números'
10. ),
11. 'between' => array(
12. 'rule' => array('between', 5, 15),
13. 'message' => 'Entre 5 y 15 caracteres'
14. )
15. ),
16. 'password' => array(
17. 'rule' => array('minLength', '8'),
18. 'message' => 'Largo mínimo de 8 caracteres'
19. ),
20. 'email' => 'email',
21. 'born' => array(
22. 'rule' => 'date',
23. 'message' => 'Ingrese una fecha válida',
24. 'allowEmpty' => true
25. )
26. );
27. }
28. ?>

Dos reglas de validación son definidas para login : debería contener sólo letras y números, y su largo debe ser de 5 a
15. El campo password debe tener un largo mínimo de 8 caracteres. El email debe contener una dirección de correo
válida, y born debe ser una fecha válida. Además, notar que puedes agregar mensajes de error propios que CakePHP
mostrará cuando estas reglas de validación no se cumplan.

Como lo muestra el ejemplo de arriba, un único campo puede tener múltiples reglas de validación. Y si las reglas
incluidas no coinciden con lo que necesitas, puedes agregar tus propias reglas de validación según tus
requerimientos.

132 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Ahora que viste a grandes rasgos cómo funciona la validación, veamos cómo estas reglas son definidas en el modelo.
Hay tres diferentes maneras para definir reglas de validación: arreglos simples, una única regla por campo, y
múltiples reglas por campo.

4.1.1 (#Reglas-Simples-1144) Reglas Simples

Tal como el nombre lo sugiere, esta es la manera más simple de definir una regla de validación. La sintaxis para la
definición de reglas usando esta manera es:

Plain Text View (#)


1. var $validate = array('fieldName' => 'ruleName');

Donde, 'fieldName' es el nombre del campo para el cual se está definiendo una regla, y 'ruleName' es el nombre de
una regla pre-definida (cubriremos esto en la siguiente sección).

4.1.2 (#Una-regla-por-campo-1145) Una regla por campo

Ésta técnica de definición permite un mejor control del funcionamiento de las reglas de validación. Pero antes de su
discusión, veamos el patrón de uso general para agregar una regla a un solo campo:

Plain Text View (#)


1. var $validate = array(
2. 'fieldName1' => array(
3. 'rule' => 'ruleName', // ó: array('ruleName', 'param1', 'param2' ...)
4. 'required' => true,
5. 'allowEmpty' => false,
6. 'on' => 'create', // ó: 'update'
7. 'message' => 'Su mensaje de error'
8. )
9. );

El índice 'rule' es requerido. Si sólo se setea 'required' => true la validación del formulario no funcionará
correctamente. Esto debido a que 'required' no es en realidad una regla.

Como puedes ver, cada campo (arriba se está mostrando sólo un campo) es asociado con un arreglo que contiene
cinco índice: ʻruleʼ, ʻrequiredʼ, ʻallowEmptyʼ, ʻonʼ y ʻmessageʼ. Veamos con más detalle cada uno de estos índices.

4.1.2.1 (#rule-1146) rule

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1146)


Comparar con el texto original (/es/compare/1146/rule)

Mas info sobre traduciones (/es/view/818)

El índice ʻruleʼ define el método de validación y acepta un sólo valor o un arreglo. El valor para ʻruleʼ especificado
puede ser el nombre de un método en tu modelo, un método de la clase core Validation, o una expresión regular.
Para un completo listado de todas las reglas incorporadas ver la sección llamada "Reglas de Validación Incorporadas".

Si la regla no requiere parámetros, ʻruleʼ puede ser un sólo valor, por ejemplo:

Plain Text View (#)


1. var $validate = array(
2. 'login' => array(
3. 'rule' => 'alphaNumeric'
4. )
5. );

Si la regla requiere algunos parámetros (como max, min o range), entonces ʻruleʼ debería ser un arreglo:

Plain Text View (#)

133 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. var $validate = array(


2. 'password' => array(
3. 'rule' => array('minLength', 8)
4. )
5. );

Recuerda, el índice ʻruleʼ es requerido para la definición de reglas basadas en arreglos.

4.1.2.2 (#required-1147) required

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1147)


Comparar con el texto original (/es/compare/1147/required)

Mas info sobre traduciones (/es/view/818)

Este índice debería tener asignado un valor booleano. Si ʻrequiredʼ es true, el campo debe estar presente en el arreglo
de datos. Por ejemplo, si la regla de validación ha sido definida de la siguiente manera:

Plain Text View (#)


1. var $validate = array(
2. 'login' => array(
3. 'rule' => 'alphaNumeric',
4. 'required' => true
5. )
6. );

Los datos enviados al método save() del modelo deben contener un valor para el campo login . Si no es así, la
validación falla (la regla no se cumple). El valor por defecto para este índice es un false booleano.

Si el índice login están presente pero no tiene un valor asignado, la validación será exitosa. Setear ʻrequiredʼ a true
sólo verifica que el índice del campo este presente.

4.1.2.3 (#allowEmpty-1148) allowEmpty

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1148)


Comparar con el texto original (/es/compare/1148/allowEmpty)

Mas info sobre traduciones (/es/view/818)

Al índice allowEmpty se le debería asignar un valor booleano. Si allowEmpty es false, los datos pasados al método
save() del modelo deben incluir el campo a un valor no-vacío para ese campo. Cuando se deja en true, un campo
vacío pasará exitosamente la validación de ese campo.

El valor por defecto de allowEmpty es null. Esto significa que el campo siempre procesará las reglas de validación
incluyendo la ejecución de funciones de validación propias.

4.1.2.4 (#on-1149) on

El índice ʻonʼ puede ser seteado con uno de los siguientes valores: ʻupdateʼ o ʻcreateʼ. Esto provee un mecanismo que
permite que cierta regla sea aplicada ya sea durante la creación de un nuevo registro, o durante la actualización de un
registro.

Si la regla fue definida como ʻonʼ => ʻcreateʼ, entonces la regla sólo será verificada durante la creación de un nuevo
registro. De igual manera, si es definida como ʻonʼ => ʻupdateʼ, la regla sólo será verificada durante la actualización
de un registro.

El valor por defecto de ʻonʼ es null. Cuando ʻonʼ es null, la regla será verificada durante la creación y actualización de
un registro.

4.1.2.5 (#message-1150) message

134 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

El índice ʻmessageʼ permite definir un mensaje de error de validación para la regla:

Plain Text View (#)


1. var $validate = array(
2. 'password' => array(
3. 'rule' => array('minLength', 8),
4. 'message' => 'Password debe tener a lo menos 8 caracteres'
5. )
6. );

4.1.3 (#Múltiples-Reglas-por-Campo-1151) Múltiples Reglas por Campo

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1151)


Comparar con el texto original (/es/compare/1151/Múltiples-Reglas-por-Campo)

Mas info sobre traduciones (/es/view/818)

La técnica descrita anteriormente nos entrega mayor flexibilidad que la asignación de reglas simples, pero hay un
paso adicional que podemos tomar para lograr un control más fino de la validación de datos. La siguiente técnica que
revisaremos nos permite asignar múltiples reglas de validación por cada campo de un modelo.

Si quieres asignar múltiples reglas de validación a un sólo campo, básicamente así es cómo se verá:

Plain Text View (#)


1.
2. var $validate = array(
3. 'nombreCampo' => array(
4. 'nombreRegla' => array(
5. 'rule' => 'nombreRegla',
6. // acá van índices extra como on, required, etc.
7. ),
8. 'nombreRegla2' => array(
9. 'rule' => 'nombreRegla2',
10. // acá van índices extra como on, required, etc.
11. )
12. )
13. );

Como puedes ver, esto es bastante similar a lo que hicimos en la sección previa. Anteriormente, por cada campo
teníamos un sólo arreglo con parámetros de validación. En este caso, cada ʻnombreCampoʼ consiste en un arreglo de
índices de reglas. Cada ʻnombreReglaʼ contiene un arreglo distinto con parámetros de validación.

Esto se entiende mejor con un ejemplo práctico:

Plain Text View (#)


1. var $validate = array(
2. 'login' => array(
3. 'alphanumeric' => array(
4. 'rule' => 'alphaNumeric',
5. 'message' => 'Se permiten sólo letras y números',
6. 'last' => true
7. ),
8. 'minlength' => array(
9. 'rule' => array('minLength', '8'),
10. 'message' => 'Largo mínimo de 8 caracteres'
11. ),
12. )
13. );

El ejemplo de arriba define dos reglas para el campo login: alphanumeric y minLength. Como puedes ver, cada regla

135 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

se identifica con un nombre de índice. En este caso particular, los nombres de índice son similares a las reglas que
usan, pero el nombre de índice puede ser cualquier nombre.

Por defecto CakePHP trata de validar un campo usando todas las reglas de validación declaradas para él y retorna un
mensaje de error para la última regla no satisfecha. Pero si el índice last es dejado como true y la regla no es
satisfecha, entonces se mostrará el mensaje de error para esa regla y no se validará ninguna regla adicional. Asi que
si prefieres mostrar un mensaje de error para la primera regla no satisfecha entonces debes dejar 'last' => true por
cada regla.

Si vas a usar mensajes de error internacionalizados podrias quierer especificar los mensajes de error en las vistas:

Plain Text View (#)


1. echo $form->input('login', array(
2. 'label' => __('Login', true),
3. 'error' => array(
4. 'alphanumeric' => __('Se permiten sólo letras y números', true),
5. 'minlength' => __('Largo mínimo de 8 caracteres', true)
6. )
7. )
8. );

El campo ahora está totalmente internacionalizado, y puedes eliminar los mensajes del modelo. Para más información
acerca de la función __() ver "Localization & Internationalization"

4.1.4 (#Reglas-de-Validación-Incorporadas-1152) Reglas de Validación Incorporadas

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1152)


Comparar con el texto original (/es/compare/1152/Reglas-de-Validación-Incorporadas)

Mas info sobre traduciones (/es/view/818)

La clase Validation de CakePHP contiene muchas reglas de validación incorporadas que pueden hacer mucho más fácil
la validación de datos. Esta clase contiene muchas técnicas de validación frecuentemente usadas que no necesitarás
escribir por tu cuenta. Abajo encontrarás una lista completa de todas las reglas, junto ejemplos de uso.

4.1.4.1 (#alphaNumeric-1153) alphaNumeric

Los datos para el campo deben contener sólo letras y números.

Plain Text View (#)


1. var $validate = array(
2. 'login' => array(
3. 'rule' => 'alphaNumeric',
4. 'message' => 'Los nombres de usuario deben contener sólo letras y números.'
5. )
6. );

4.1.4.2 (#between-1154) between

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1154)


Comparar con el texto original (/es/compare/1154/between)

Mas info sobre traduciones (/es/view/818)

El largo de los datos para el campo debe estar dentro de un rango numérico específico. Se debe indicar un valor
mínimo y máximo.

Plain Text View (#)

136 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. var $validate = array(


2. 'password' => array(
3. 'rule' => array('between', 5, 15),
4. 'message' => 'Las contraseñas deben tener un largo entre 5 y 15 caracteres.'
5. )
6. );

4.1.4.3 (#blank-1155) blank

Esta regla es usada para asegurar que el campo es dejado en blanco o con sólo espacios en blanco como su valor.
Los espacios en blanco incluyen los caracteres de la barra espaciadora, tabulador, retorno de carro y nueva línea.

Plain Text View (#)


1. var $validate = array(
2. 'id' => array(
3. 'rule' => 'blank',
4. 'on' => 'create'
5. )
6. );

4.1.4.4 (#boolean-1156) boolean

El campo debe contener un valor booleano. Los valores aceptados son “true” o “false”, los enteros 0 o 1 y las cadenas
"0" o "1".

Plain Text View (#)


1. var $validate = array(
2. 'myCheckbox' => array(
3. 'rule' => array('boolean'),
4. 'message' => 'Valor incorrecto en myCheckbox'
5. )
6. );

4.1.4.5 (#cc-1157) cc

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1157)


Comparar con el texto original (/es/compare/1157/cc)

Mas info sobre traduciones (/es/view/818)

Esta regla es usada para verificar si los datos corresponden a un número de tarjeta de credito válido. Acepta tres
parámetros: ʻtypeʼ, ʻdeepʼ y ʻregexʼ.

El ʻtypeʼ puede ser ʻfastʼ, ʻallʼ o cualquiera de los siguientes:

bankcard
diners
disc
electron
enroute
jcb
maestro
mc
solo
switch
visa
voyager

Si ʻtypeʼ es dejado en ʻfastʼ, se validan los datos contra el formato numérico de las principales tarjetas de crédito.
También se puede dejar ʻtypeʼ como un arreglo con todos los tipos de validaciones que se quiere satisfacer.

137 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

El índice ʻdeepʼ debería dejarse con un valor booleano. Si es verdadero, la validación usará el algoritmo de Luhn para
tarjetas de crédito (http://en.wikipedia.org/wiki/Luhn_algorithm (http://en.wikipedia.org/wiki/Luhn_algorithm) ). Por
defecto el valor se asume como falso.

El índice ʻregexʼ permite indicar una expersión regular propia que será usada para validar el número de tarjeta de
credito.

Plain Text View (#)


1. var $validate = array(
2. 'ccnumber' => array(
3. 'rule' => array('cc', array('visa', 'maestro'), false, null),
4. 'message' => 'El número de tarjeta de crédito que ha suministrado no es válido.'
5. )
6. );

4.1.4.6 (#comparison-1158) comparison

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1158)


Comparar con el texto original (/es/compare/1158/comparison)

Mas info sobre traduciones (/es/view/818)

Esta regla es usada para comparar valores numéricos. Soporta “is greater”, “is less”, “greater or equal”, “less or
equal”, “is less”, “equal to”, y “not equal”. A continuación algunos ejemplos:

Plain Text View (#)


1. var $validate = array(
2. 'age' => array(
3. 'rule' => array('comparison', '>=', 18),
4. 'message' => 'Debe tener al menos 18 años para calificar.'
5. )
6. );
7. var $validate = array(
8. 'age' => array(
9. 'rule' => array('comparison', 'greater or equal', 18),
10. 'message' => 'Debe tener al menos 18 años para calificar.'
11. )
12. );

4.1.4.7 (#date-1159) date

Esta regla asegura que los datos enviados esten en un formato de fecha válido. Un único parámetro (que puede ser un
arreglo) puede ser pasado y que será usado para verificar el formato de la fecha indicada. El valor del parámetro
puede ser uno de los siguientes formatos:

ʻdmyʼ por ejemplo 27-12-2006 o 27-12-06 (los separadores pueden ser espacio, punto, guion, slash)
ʻmdyʼ por ejemplo 12-27-2006 or 12-27-06 (los separadores pueden ser espacio, punto, guion, slash)
ʻymdʼ por ejemplo 2006-12-27 or 06-12-27 (los separadores pueden ser espacio, punto, guion, slash)
ʻdMyʼ por ejemplo 27 December 2006 o 27 Dec 2006
ʻMdyʼ por ejemplo December 27, 2006 o Dec 27, 2006 (la coma es opcional)
ʻMyʼ por ejemplo (December 2006 o Dec 2006)
ʻmyʼ por ejemplo 12/2006 o 12/06 (los separadores pueden ser espacio, punto, guion, slash)

Si no especifica ningún índice, se usará el índice por defecto ʻymdʼ.

Plain Text View (#)

138 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. var $validate = array(


2. 'born' => array(
3. 'rule' => 'date',
4. 'message' => 'Ingrese una fecha válida usando el formato AA-MM-DD.',
5. 'allowEmpty' => true
6. )
7. );

Mientras que muchos almacenes de datos (motores de bases de datos) requieren cierto formato de datos, podrias
considerar aceptar una amplia variedad de formatos de fechas y luego convertirlos, en vez de forzar a los usuarios a
ingresar cierto formato. Entre más trabajo puedas hacer por tus usuarios, mejor.

4.1.4.8 (#decimal-1160) decimal

Esta regla asegura que el dato es un número decimal válido. Se puede pasar un parámetro para especificar la cantidad
de dígitos requeridos después del punto decimal. Si no se pasa ningún parámetro, el dato será validado como un
número de punto flotante científico, que causará que la validación no sea satisfecha si es que no se encuentra ningún
dígito después del punto decimal.

Plain Text View (#)


1. var $validate = array(
2. 'price' => array(
3. 'rule' => array('decimal', 2)
4. )
5. );

4.1.4.9 (#email-1161) email

Esta regla verifica que el dato sea una dirección de correo electrónico válida. Al pasar un valor booleano verdadero
como segundo parámetro se tratará también de verificar que el host de la dirección sea válido.

Plain Text View (#)


1. var $validate = array('email' => array('rule' => 'email'));
2.
3. var $validate = array(
4. 'email' => array(
5. 'rule' => array('email', true),
6. 'message' => 'Por favor indique una dirección de correo electrónico válida.'
7. )
8. );

4.1.4.10 (#equalTo-1162) equalTo

Esta regla asegura que el valor sea equivalente a, y del mismo tipo que el valor indicado.

Plain Text View (#)


1. var $validate = array(
2. 'food' => array(
3. 'rule' => array('equalTo', 'cake'),
4. 'message' => 'El valor debe ser el string cake'
5. )
6. );

4.1.4.11 (#extension-1163) extension

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1163)


Comparar con el texto original (/es/compare/1163/extension)

Mas info sobre traduciones (/es/view/818)

139 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Esta regla verifica que la extensión de archivo sea como .jpg o .png. Para permitir múltiples extensiones estas se
deben pasar dentro de un arreglo.

Plain Text View (#)


1. var $validate = array(
2. 'image' => array(
3. 'rule' => array('extension', array('gif', 'jpeg', 'png', 'jpg'),
4. 'message' => 'Por favor indique una imágen válida.'
5. )
6. );

4.1.4.12 (#file-1164) file

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1164)


Comparar con el texto original (/es/compare/1164/file)

Mas info sobre traduciones (/es/view/818)

Esta sección aún tiene que ser escrita, si tienes una idea de qué poner aqui, por favor usa los links y déjanos saber tu
sugerencia!

4.1.4.13 (#ip-1165) ip

Esta regla asegura que haya sido ingresada una dirección IPv4 válida.

Plain Text View (#)


1. var $validate = array(
2. 'clientip' => array(
3. 'rule' => 'ip',
4. 'message' => 'Por favor ingrese una dirección IP válida.'
5. )
6. );

4.1.4.14 (#isUnique-1166) isUnique

El dato para este campo debe ser único, no puede ser usado por ningún otro registro.

Plain Text View (#)


1. var $validate = array(
2. 'login' => array(
3. 'rule' => 'isUnique',
4. 'message' => 'Este nombre de usuario ya ha sido asignado.'
5. )
6. );

4.1.4.15 (#minLength-1167) minLength

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1167)


Comparar con el texto original (/es/compare/1167/minLength)

Mas info sobre traduciones (/es/view/818)

Esta regla asegura que el dato cumple con un requisito de largo mínimo.

Plain Text View (#)

140 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. var $validate = array(


2. 'login' => array(
3. 'rule' => array('minLength', '8'),
4. 'message' => 'Los nombres de usuario deben tener un largo de al menos 8 caracteres.'
5. )
6. );

4.1.4.16 (#maxLength-1168) maxLength

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1168)


Comparar con el texto original (/es/compare/1168/maxLength)

Mas info sobre traduciones (/es/view/818)

Esta regla asegura que el dato siempre esté dentro del requisito de largo máximo.

Plain Text View (#)


1. var $validate = array(
2. 'login' => array(
3. 'rule' => array('maxLength', '15'),
4. 'message' => 'Los nombres de usuario no pueden tener un largo mayor a 15 caracteres.'
5. )
6. );

4.1.4.17 (#money-1169) money

Esta regla asegura que el valor sea una cantidad en formato monetario válido.

El segundo parámetro define dónde se ubica el símbolo: left/right (izquierda/derecha).

Plain Text View (#)


1. var $validate = array(
2. 'salary' => array(
3. 'rule' => array('money', 'left'),
4. 'message' => 'Por favor ingrere una cantidad monetaria válida.'
5. )
6. );

4.1.4.18 (#multiple-1170) multiple

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1170)


Comparar con el texto original (/es/compare/1170/multiple)

Mas info sobre traduciones (/es/view/818)

Empleado para validar campos input select multiple. Soporta los paramentros "in", "max" y "min".

Plain Text View (#)


1. var $validate = array(
2. 'multiple' => array(
3. 'rule' => array('multiple', array('in' => array('foo', 'bar'), 'min' => 1, 'max' => 3)),
4. 'message' => 'Por favor seleccione una, dos o tres opciones'
5. )
6. );

4.1.4.19 (#inList-1171) inList

Esta regla asegura que el valor está dentro de un conjunto dado. Necesita de un arreglo de valores. El valor es válido

141 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

si coincide con uno de los valores del arreglo indicado.

Example: Plain Text View (#)


1. var $validate = array(
2. 'function' => array(
3. 'allowedChoice' => array(
4. 'rule' => array('inList', array('Foo', 'Bar')),
5. 'message' => 'Ingreso Foo o ingrese Bar.'
6. )
7. )
8. );

4.1.4.20 (#numeric-1172) numeric

Verifica si el dato ingresado es un número válido.

Plain Text View (#)


1. var $validate = array(
2. 'cars' => array(
3. 'rule' => 'numeric',
4. 'message' => 'Por favor indique la cantidad de vehículos.'
5. )
6. );

4.1.4.21 (#notEmpty-1173) notEmpty

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1173)


Comparar con el texto original (/es/compare/1173/notEmpty)

Mas info sobre traduciones (/es/view/818)

Regla básica para asegurar que un campo no este vacío.

Plain Text View (#)


1. var $validate = array(
2. 'title' => array(
3. 'rule' => 'notEmpty',
4. 'message' => 'Este campo no puede quedar vacío.'
5. )
6. );

4.1.4.22 (#phone-1174) phone

Phone valida números telefónicos de EE.UU. Si quieres validar números telefónicos que no sean de EE.UU. puedes
proveer una expresión regular como segundo parámetro para cubrir formatos adicionales.

Plain Text View (#)


1. var $validate = array(
2. 'phone' => array(
3. 'rule' => array('phone', null, 'us')
4. )
5. );

4.1.4.23 (#postal-1175) postal

Postal es usado para validar códigos ZIP de EE.UU. (us), Canada (ca), Reino Unido (uk), Italia (it), Alemania (de) y
Bélgica (be). Para otros formatos ZIP puedes proveer una expersión regular como segundo parámetro.

Plain Text View (#)

142 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. var $validate = array(


2. 'zipcode' => array(
3. 'rule' => array('postal', null, 'us')
4. )
5. );

4.1.4.24 (#range-1176) range

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1176)


Comparar con el texto original (/es/compare/1176/range)

Mas info sobre traduciones (/es/view/818)

Esta regla asegura que el valor esté dentro de un rango dado. Si no se indica un rango, la regla va a verificar si el
valor es un número finito válido en la actual plataforma.

Plain Text View (#)


1. var $validate = array(
2. 'number' => array(
3. 'rule' => array('range', 0, 10),
4. 'message' => 'Por favor ingrese un número entre 0 y 10'
5. )
6. );

El ejemplo de arriba aceptará cualquier valor mayor a 0 (por ejemplo 0.01) y menor a 10 (por ejemplo 9.99).

4.1.4.25 (#ssn-1177) ssn

Ssn valida los números de seguridad social de EE.UU. (us), Dinamarca (dk), y los Paises Bajos (nl). Para otros formatos
de números de seguridad social puedes proveer una expersión regular.

Plain Text View (#)


1. var $validate = array(
2. 'ssn' => array(
3. 'rule' => array('ssn', null, 'us')
4. )
5. );

4.1.4.26 (#url-1178) url

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1178)


Comparar con el texto original (/es/compare/1178/url)

Mas info sobre traduciones (/es/view/818)

Esta regla verifica formatos de URL válidos. Soporta los protocolos http(s), ftp(s), file, news, y gopher.

Plain Text View (#)


1. var $validate = array(
2. 'website' => array(
3. 'rule' => 'url'
4. )
5. );

4.1.5 (#Reglas-de-Validación-Personalizadas-1179) Reglas de Validación Personalizadas

Si hasta el momento no has encontrado lo que buscabas, siempre podrás crear tus propias reglas de validación
personalizadas. Hay dos maneras de hacer esto: definiendo expresiones regulares personalizadas, o creando

143 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

métodos de validación personalizados.

4.1.5.1 (#Validación-Personalizada-Mediante-Expresiones-Rel-1180) Validación Personalizada Mediante Expresiones Relugares

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1180)


Comparar con el texto original (/es/compare/1180/Validación-Personalizada-Mediante-Expresiones-Rel)

Mas info sobre traduciones (/es/view/818)

Si la técnica de validación que necesitas usar puede ser completada usando expresiones regulares, puedes definir
una expresión personalizada como una regla de validación de un campo.

Plain Text View (#)


1. var $validate = array(
2. 'login' => array(
3. 'rule' => array('custom', '/^[a-z0-9]{3,}$/i'),
4. 'message' => 'Sólo letras y enteros, mínimo 3 caracteres'
5. )
6. );

El ejemplo de arriba verifica si login contiene sólo letras y enteros, con un largo mínimo de tres caracteres.

4.1.5.2 (#Validación-Mediante-Métodos-Personalizados-1181) Validación Mediante Métodos Personalizados

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1181)


Comparar con el texto original (/es/compare/1181/Validación-Mediante-Métodos-Personalizados)

Mas info sobre traduciones (/es/view/818)

Algunas veces revisar los datos usando expresiones regulares no es suficiente. Por ejemplo, si quieres asegurar que
un código promocional sólo pueda ser usado 25 veces, necesitas agregar una función de validación personalizada,
como se muestra más abajo:

Plain Text View (#)


1. <?php
2. class User extends AppModel {
3. var $name = 'User';
4.
5. var $validate = array(
6. 'promotion_code' => array(
7. 'rule' => array('limitDuplicates', 25),
8. 'message' => 'Este código ha sido usado demasiadas veces.'
9. )
10. );
11.
12. function limitDuplicates($data, $limit){
13. $existing_promo_count = $this->find( 'count', array('conditions' => $data, 'recursive' => -1) )
14. return $existing_promo_count < $limit;
15. }
16. }
17. ?>

Si quieres pasar parámetros a tu función de validación personalizada, agrega elementos extra al arreglo ʻruleʼ y
trátalos como parámetros extra (despúes del parámetro principal $data) en tu función personalizada.

Tu función de validación personalizada puede estar en el modelo (como en el ejemplo de arriba), o en un behavior
implementado por el modelo. Esto incluye los modelos mapeados.

Notar que los métodos del model/behavior son verificados primero, antes de buscar un método en la clase
Validation. Esto significa que puedes sobreescribir métodos de validación existentes (como por ejemplo

144 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

alphaNumeric()) en el nivel de aplicación (agregando el método a AppModel), o en el nivel de modelo.

4.1.6 (#Validando-datos-desde-el-Controlador-1182) Validando datos desde el Controlador

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1182)


Comparar con el texto original (/es/compare/1182/Validando-datos-desde-el-Controlador)

Mas info sobre traduciones (/es/view/818)

Mientras que normalmente sólo usarás el método save del modelo, habrán veces que te gustaría validar los datos sin
guardarlos. Por ejemplo, podrías querer mostrar algo de información adicional al usuario antes de guardar los datos
a la base de datos. Validar datos requiere de un proceso ligeramente distinto al de sólo guardar los datos.

Primero, debes setear los datos al modelo:

Plain Text View (#)


1. $this->ModelName->set( $this->data );

Luego, para verificar si los datos se validan correctamente, usa el método validates del modelo, que retornará true si
es que se valida y false si es que no:

Plain Text View (#)


1. if ($this->ModelName->validates()) {
2. // paso la lógica de validación
3. } else {
4. // no paso la lógica de validadición
5. }

El método validates invoca el método invalidFields que le asignará un valor a la propiedad validationErrors del
modelo. El método invalidFields también retorna los datos como su resultado.

Plain Text View (#)


1. $errors = $this->ModelName->invalidFields(); // contiene el arrego validationErrors

Es importante notar que los datos se deben primero setear al modelo antes de poder validarlos. Esto es diferente al
método save que permite pasar los datos como un parámetro. También, ten en cuenta que no es necesario llamar a
validates antes de llamar a save ya que save validará automáticamente los datos antes realmente de guardarlos.

4.2 (#Limpieza-de-Datos-1183) Limpieza de Datos

La clase Sanitize de CakePHP puede ser usada para eliminar datos maliciosos y otra información no deseada desde los
datos enviados por un usuario. Sanitize es una librería del núcleo, por lo que puede ser usada en cualquier parte de
tu código, pero probablemente será mejor usada en los controladores y modelos.

CakePHP te protege automáticamente contra Inyección SQL si usas los métodos ORM de CakePHP (como find() y save())
y la notación de arrays apropiada (ejemplo array('campo' => $valor)) en lugar de sentencias SQL incrustadas en el
código. Para la limpieza de datos contra XSS generalmente es mejor guardar el HTML sin tratar en la base de datos y
posteriormente limpiar los datos en el momento de mostrarlos.

Todo lo que necesitas hacer es incluír la librería del núcleo Sanitize (p.ej. antes de la definición de la clase
controlador):

Plain Text View (#)


1. App::import('Sanitize');
2. class MiController extends AppController {
3. ...
4. ...
5. }

Una vez hecho eso, puedes hacer llamadas estáticas a Sanitize.

4.2.1 (#paranoid-1184) paranoid

145 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1184)


Comparar con el texto original (/es/compare/1184/paranoid)

Mas info sobre traduciones (/es/view/818)

paranoid(string $string, array $allowedChars);

Esta función elimina cualquier cosa desde $string que no sean caracteres alfanuméricos. Esta función no eliminará
ciertos caracteres al pasarlos en el arreglo $allowedChars.

Plain Text View (#)


1. $badString = ";:<script><html>< // >@@#";
2. echo Sanitize::paranoid($badString);
3. // salida: scripthtml
4. echo Sanitize::paranoid($badString, array(' ', '@'));
5. // salida: scripthtml @@

4.2.2 (#html-1185) html

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1185)


Comparar con el texto original (/es/compare/1185/html)

Mas info sobre traduciones (/es/view/818)

html(string $string, boolean $remove = false)

Este método prepara los datos enviados por un usuario para desplegarlos dentro de HTML. Esto es especialmente útil
si no quieres que los usuarios quiebren tus layouts o inserten imágenes o scripts dentro de las páginas HTML. Si la
opción $remove se deja en true, el contenido HTML detectado es eliminado en vez de mostrado como entidades
HTML.

Plain Text View (#)


1. $badString = '<font size="99" color="#FF0000">HEY</font><script>...</script>';
2. echo Sanitize::html($badString);
3. // salida: &lt;font size=&quot;99&quot; color=&quot;#FF0000&quot;&gt;HEY&lt;/font&gt;&lt;script&gt;...&l
4. echo Sanitize::html($badString, true);
5. // salida: HEY...

4.2.3 (#escape-1186) escape

escape(string $string, string $connection)

Usado para escapar sentencias SQL agregándole barras invertidas, dependiendo de la configuración de
magic_quotes_gpc del sistema. $connection es el nombre de la base de datos para la cual escapar el string, según el
nombre definido en app/config/database.php.

4.2.4 (#clean-1187) clean

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1187)


Comparar con el texto original (/es/compare/1187/clean)

Mas info sobre traduciones (/es/view/818)

Sanitize::clean(mixed $data, mixed $options)

Esta función es un limpiador multi-propósito y de potencia industrial, y sirve para ser usado en arreglos (como
$this->data, por ejemplo). La función recibe un arreglo (o string) y retorna su versión limpia. Las siguientes
operaciones de limpieza son realizadas en cada elemento del arreglo (recursivamente):

Los espacios raros (incluyendo 0xCA) son reemplazados con espacios regulares.

146 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Verificación doble de caracteres especiales y remoción de retornos de carro para una mayor seguridad SQL.
Se agregan barras para SQL (sólo llama a la función sql explicada anteriormente).
Se reemplazan las barras invertidas ingresadas por el usuario por barras invertidas confiables.

4.3 (#Manejo-de-Errores-1188) Manejo de Errores

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1188)


Comparar con el texto original (/es/compare/1188/Manejo-de-Errores)

Mas info sobre traduciones (/es/view/818)

En caso de un error irrecuperable en tu aplicación, es común detener el procesamiento y mostrar una página de error
al usuario. Para ahorrarte tener que codificar el manejo de esto en cada uno de tus controladores y componentes,
puedes usar el método:

Plain Text View (#)


1. $this->cakeError(<string errorType>, [array parameters]);

Al llamar este método se mostrará una página de error al usuario y se detendrá cualquier tipo de procesamiento en tu
aplicacion.

CakePHP pre-define un conjunto de tipos de error, pero en estos momentos (escritura de este manual), la mayoría son
realmente útiles para el mismo framework. Uno que es más útil para el desarrollador de aplicaciones es el viejo y
querido error 404. Puede ser llamado sin ningún parámetro de la siguiente manera:

Plain Text View (#)


1. $this->cakeError('error404');

De manera alternativa, puedes hacer que la página reporte que el error fue en una URL específica pasando el
parámetro url:

Plain Text View (#)


1. $this->cakeError('error404', array('url' => 'some/other.url'));

Todo esto comienza a ser mucho más útil al extender el administrador de errores para que use tus propios tipos de
error. Los administradores de error customizados son principalmente como acciones de un controlador. Típicamente
vas a usar set() para dejar disponibles sus parámetros en la vista y luego mostrar (render) un fichero tipo vista desde
el directorio app/views/errors.

Crea un fichero app/app_error.php con la siguiente definición.

Plain Text View (#)


1. <?php
2. class AppError extends ErrorHandler {
3. }
4. ?>

Se pueden implementar administradores (handlers) para nuevos tipos de error agregando métodos a esta clase.
Simplemente crea un nuevo método con el nombre que quieres usar como tu tipo de error.

Digamos que tenemos una aplicación que escribe cierta cantidad de ficheros a disco y que es apropiado mostrale al
usuario los errores de escritura. No quieremos agregar código para esto en diferentas partes de la aplicación, así que
es un buen caso para usar un nuevo tipo de error.

Agrega un nuevo método a tu clase AppError. Vamos a aceptar un parámetro llamado file que será la ruta al fichero
cuya escritura fallo.

Plain Text View (#)


1. function cannotWriteFile($params) {
2. $this->controller->set('file', $params['file']);
3. $this->__outputMessage('cannot_write_file');
4. }

147 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Crea la vista en app/views/errors/cannot_write_file.ctp

Plain Text View (#)


1. <h2>No fue posible escribir en el fichero</h2>
2. <p>No se pudo escribir el fichero <?php echo $file ?> en el disco.</p>

y lanza el error en tu controllador/componente

Plain Text View (#)


1. $this->cakeError('cannotWriteFile', array('file'=>'somefilename'));

La implementación por defecto de $this->__outputMessage() sólo mostrará la vista en views/errors/.ctp. Si quieres


cambiar este comportamiento, puedes redefinir __outputMessage($template) en tu clase AppError.

4.4 (#Depuración-1189) Depuración

La depuración es una parte necesaria e inevitable de cualquier ciclo de desarrollo. Mientras que CakePHP no ofrece
ninguna herramienta que se conecte directamente con ningún editor o IDE, provee de varias herramientas para ayudar
en la depuración y exponer lo que se esta ejecutando dentro de su aplicación.

4.4.1 (#Depuración-básica-1190) Depuración básica

debug($var, $showHTML = false, $showFrom = true)

La función debug() está disponible de forma global, esta trabaja similar a la función de PHP print_r(). La función
debug() permite mostrar el contenido de una variable en diferente número de formas. Primero, si quieres que la data
se muestre en formato HTML amigable, establece el segundo parámetro a true. Por defecto la función muestra la línea
y el archivo donde se origina.

La salida de esta función solo se muestra si la variable debug del core (app/config/core.php, línea 43) se ha
establecido a un valor mayor que 0.

4.4.2 (#Usando-la-clase-Debugger-1191) Usando la clase Debugger

Para usar el depurador hay que primero asegurarse que Configure::read('debug') este seteado a un valor mayor a 0.

dump($var)

Dump muestra el contenido de una variable. Desplegará todas las propiedades y métodos (si existen) de la variable
que se indique.

Plain Text View (#)

148 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. $foo = array(1,2,3);
2.
3. Debugger::dump($foo);
4.
5. //outputs
6. array(
7. 1,
8. 2,
9. 3
10. )
11.
12. //objeto simple
13. $car = new Car();
14.
15. Debugger::dump($car);
16.
17. //despliegue
18. Car::
19. Car::colour = 'red'
20. Car::make = 'Toyota'
21. Car::model = 'Camry'
22. Car::mileage = '15000'
23. Car::acclerate()
24. Car::decelerate()
25. Car::stop()

log($var, $level = 7)

Crea un log detallado de la traza de ejecución al momento de su invocación. El método log() genera datos similares a
los de Debugger::dump() pero los envía al archivo debug.log en vez del buffer de salida. Notar que el directorio
app/tmp (y su contenido) debe tener permisos de escritura para el servidor web para que log() funcione
correctamente.

trace($options)

Retorna la traza de ejecución actual. Cada línea de la traza incluye el método que fue llamado, incluyendo desde cuál
archivo y desde que línea la llamada se originó.

Plain Text View (#)


1. //En PostsController::index()
2. pr( Debugger::trace() );
3.
4. //despliege
5. PostsController::index() - APP/controllers/downloads_controller.php, line 48
6. Dispatcher::_invoke() - CORE/cake/dispatcher.php, line 265
7. Dispatcher::dispatch() - CORE/cake/dispatcher.php, line 237
8. [main] - APP/webroot/index.php, line 84

Arriba se muestra una traza de ejecución generada llamando a Debugger::trace() desde una acción de un controlador.
Al leer la traza de ejecución desde abajo hacia arriba se muestra el orden de las funciones actualmente en ejecución
(stack frames). En el ejemplo de arriba, index.php llamó a Dispatcher::dispatch(), que a su vez llamó a
Dispatcher::_invoke(). Luego el método _invoke() llamó a PostsController::index(). Esta información es útil cuando se
trabaja con operaciones recursivas, ya que se identifican las funciones que estaban en ejecución al momento de
llamar a trace().

excerpt($file, $line, $context)

Toma un extracto desde un archivo en $path (que es una ruta absoluta), destaca la línea número $line con la cantidad
de $context líneas a su alrededor.

Plain Text View (#)

149 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. pr( Debugger::excerpt(ROOT.DS.LIBS.'debugger.php', 321, 2) );


2.
3. //se despliegará lo siguiente
4. Array
5. (
6. [0] => <code><span style="color: #000000"> * @access public</span></code>
7. [1] => <code><span style="color: #000000"> */</span></code>
8. [2] => <code><span style="color: #000000"> function excerpt($file, $line, $context = 2) {</sp
9. [3] => <span class="code-highlight"><code><span style="color: #000000"> $data = $lines =
10. [4] => <code><span style="color: #000000"> $data = @explode("\n", file_get_contents($fil
11. )

Aunque este método es usado internamente, te puede ser práctico si estas creando tus propios mensajes de error o
entradas de log en ocasiones especiales.

exportVar($var, $recursion = 0)

Convierte una variable de cualquier tipo a un string para su uso en el despliegue del depurador. Este método también
es usado mucho por Debugger para conversiones internas de variables, y puede ser usado también en tus propios
Debuggers.

invoke($debugger)

Reemplazar el Debugger de CakePHP con un nuevo Administrador de Errores.

4.4.3 (#Clase-Debugger-1192) Clase Debugger

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1192)


Comparar con el texto original (/es/compare/1192/Clase-Debugger)

Mas info sobre traduciones (/es/view/818)

La clase Debugger es nueva en CakePHP 1.2, ofrece muchas opciones para obtener información de depuración. Tiene
muchos métodos que pueden ser invocados de forma estática, proveyendo volcado, trazabilidad, y funciones de
gestión de errores.

La clase Debugger sobreescribe el manejo de errores por defecto de PHP, reemplazándolo con información de errores
mucho más útil. La depuración de errores está activa por defecto en CakePHP. Al igual que con todas las funciones de
depuración, se debe establecer Configure::debug a un valor mayor que 0.

Cuando ocurre un error, el depurador genera dos salidas de información, una a la página y la otra crea una entrada
en el archivo error.log. El reporte de errores generado contiene tanto la pila de llamadas como un extracto del código
donde ocurrió el error. Haga clic en el enlace "Error" para ver la pila de llamadas, y el enlace "Code" para ver las líneas
de código causantes del error.

4.5 (#Caching-1193) Caching

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1193)


Comparar con el texto original (/es/compare/1193/Caching)

Mas info sobre traduciones (/es/view/818)

Almacenamiento en caché se puede hacer en diferentes niveles en una aplicación de CakePHP. Para obtener más
información, consulte cómo deshabilitar la memoria caché del navegador (/es/view/431/disablecache) , página
completa o elemento de caché (/es/view/213/cache) , el almacenamiento en caché de consultas o la memoria caché
(/es/view/445/cachequeries) o también la función - caché a cualquier cosa. (http://api.cakephp.org
/basics_8php.html#ecfdc6dd4cf228b43bd3c55e11be23f5) Para más información.

4.6 (#Logging-1194) Logging

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1194)

150 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Comparar con el texto original (/es/compare/1194/Logging)

Mas info sobre traduciones (/es/view/818)

Aunque los ajustes de Configuración de la clase desde el corazón de CakePHP realmente puede ayudarle a ver qué
pasa en el fondo, usted necesitará algún tiempo para grabar datos en el disco para saber lo que pasa. En un mundo
cada vez más dependientes de tecnologías como SOAP y AJAX, la depuración puede ser difíícil. .

La grabación (registro) puede ser también una manera de descubrir es que ocurrió en su solicitud en cualquier
momento. ¿Qué términos de búsqueda se utilizaron? ¿Qué tipo de errores de mis usuarios que han visto? ¿Con qué
frecuencia se ejecuta una consulta?

En CakePHP la grabación (registro) es fácil - la función log () es un elemento de la clase Object, que es el ancestro
común de la mayoría de las clases CakePHP. Si el contexto es una clase CakePHP (Modelo, Controlador, Componente ...
lo que sea), puede guardar sus datos.

4.6.1 (#Uso-de-la-función-log-1195) Uso de la función log

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1195)


Comparar con el texto original (/es/compare/1195/Uso-de-la-función-log)

Mas info sobre traduciones (/es/view/818)

La función log() toma dos parámetros. El primero es el mensaje que se desea escribir en el archivo de log. Por
defecto, este mensaje de error es escrito en el log de errores ubicado en app/tmp/logs/error.log.

Plain Text View (#)


1. //Ejecutando esto dentro de una clase CakePHP:
2.
3. $this->log("Algo que no hace nada!");
4.
5. //El resultado de esto se agrega a app/tmp/logs/error.log
6.
7. 2007-11-02 10:22:02 Error: Algo que no hace nada!

El segundo parámetro es usado para definir el tipo de log con el se quiere escribir el mensaje. Si no se suministra, el
valor por defecto es LOG_ERROR, el cual escribe en el log de errores previamente mensionado. Como alternativa, Se
puede establecer este segundo parámetro a LOG_DEBUG, para escribir su mensaje en el log de depuración ubicado en
app/tmp/logs/debug.log:

Plain Text View (#)


1. ///Ejecutando esto dentro de una clase CakePHP:
2.
3. $this->log('Un mensaje de depuración.', LOG_DEBUG);
4.
5. //El resultado de esto se agrega a app/tmp/logs/debug.log (en lugar de error.log)
6.
7. 2007-11-02 10:22:02 Error: Un mensaje de depuración.

El usuario del servidor web debe poder escribir en el directorio app/tmp para que el log pueda funcionar
correctamente.

4.6.2 (#Using-the-default-FileLog-class-1585) Using the default FileLog class

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1585/Using-the-default-FileLog-
class) .. Mas info sobre traduciones (/es/view/818)

While CakeLog can be configured to write to a number of user configured logging adapters, it also comes with a
default logging configuration. This configuration is identical to how CakeLog behaved in CakePHP 1.2. The default
logging configuration will be used any time there are no other logging adapters configured. Once a logging adapter
has been configured you will need to also configure FileLog if you want file logging to continue.

As its name implies FileLog writes log messages to files. The type of log message being written determines the name

151 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

of the file the message is stored in. If a type is not supplied, LOG_ERROR is used which writes to the error log. The
default log location is app/tmp/logs/$type.log

Plain Text View (#)


1. //Executing this inside a CakePHP class:
2. $this->log("Something didn't work!");
3.
4. //Results in this being appended to app/tmp/logs/error.log
5. 2007-11-02 10:22:02 Error: Something didnt work!

You can specify a custom log names, using the second parameter. The default built-in FileLog class will treat this log
name as the file you wish to write logs to.

Plain Text View (#)


1. //called statically
2. CakeLog::write('activity', 'A special message for activity logging');
3.
4. //Results in this being appended to app/tmp/logs/activity.log (rather than error.log)
5. 2007-11-02 10:22:02 Activity: A special message for activity logging

The configured directory must be writable by the web server user in order for logging to work correctly.

You can configure additional/alternate FileLog locations using CakeLog::config(). FileLog accepts a path which
allows for custom paths to be used.

Plain Text View (#)


1. CakeLog::config('custom_path', array(
2. 'engine' => 'FileLog',
3. 'path' => '/path/to/custom/place/'
4. ));

4.6.3 (#Creating-and-configuring-log-streams-1582) Creating and configuring log streams

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1582/Creating-and-configuring-
log-streams) .. Mas info sobre traduciones (/es/view/818)

Log stream handlers can be part of your application, or part of plugins. If for example you had a database logger
called DataBaseLogger. As part of your application it would be placed in app/libs/log/data_base_logger.php. As part
of a plugin it would be placed in app/plugins/my_plugin/libs/log/data_base_logger.php. When configured CakeLog
will attempt to load Configuring log streams is done by calling CakeLog::config(). Configuring our DataBaseLogger
would look like

Plain Text View (#)


1. //for app/libs
2. CakeLog::config('otherFile', array(
3. 'engine' => 'DataBaseLogger',
4. 'model' => 'LogEntry',
5. ...
6. ));
7. //for plugin called LoggingPack
8. CakeLog::config('otherFile', array(
9. 'engine' => 'LoggingPack.DataBaseLogger',
10. 'model' => 'LogEntry',
11. ...
12. ));

When configuring a log stream the engine parameter is used to locate and load the log handler. All of the other
configuration properties are passed to the log stream's constructor as an array.

Plain Text View (#)

152 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. class DataBaseLogger {
2. function __construct($options = array()) {
3. //...
4. }
5. }

CakePHP has no requirements for Log streams other than that they must implement a write method. This write method
must take two parameters $type, $message in that order. $type is the string type of the logged message, core values
are error, warning, info and debug. In addition you can define your own types by using them when you call
CakeLog::write.

It should be noted that you will encounter errors when trying to configure application level loggers from app/config
/core.php. This is because paths are not yet bootstrapped. Configuring of loggers should be done in app/config
/bootstrap.php to ensure classes are properly loaded.

4.6.4 (#Interacting-with-log-streams-1583) Interacting with log streams

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1583/Interacting-with-log-
streams) .. Mas info sobre traduciones (/es/view/818)

You can introspect the configured streams with CakeLog::configured(). The return of configured() is an array of all
the currently configured streams. You can remove streams using CakeLog::drop($key). Once a log stream has been
dropped it will no longer receive messages.

4.6.5 (#Error-logging-1584) Error logging

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1584/Error-logging) .. Mas info
sobre traduciones (/es/view/818)

Errors are now logged when Configure::write('debug', 0);. You can use Configure::write('log', $val), to control
which errors are logged when debug is off. By default all errors are logged.

Plain Text View (#)


1. Configure::write('log', E_WARNING);

Would log only warning and fatal errors. Setting Configure::write('log', false); will disable error logging when
debug = 0.

4.7 (#Testing-1196) Testing

A partir de CakePHP 1.2 disponemos de soporte para un completo entorno de testing incorporado en CakePHP. Este
entorno es una extensión del entorno SimpleTest para PHP. En esta sección discutiremos cómo preparar la aplicación
para testing y cómo construir y ejecutar tus tests.

4.7.1 (#Preparándose-para-el-testing-1197) Preparándose para el testing

¿Preparado/a para empezar a hacer test? ¡Bien! ¡Vamos allá entonces!

4.7.1.1 (#Installing-SimpleTest-1198) Installing SimpleTest

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1198)


Comparar con el texto original (/es/compare/1198/Installing-SimpleTest)

Mas info sobre traduciones (/es/view/818)

El entorno de testing provisto con CakePHP 1.2 está construido sobre el entorno de testing SimpleTest. SimpleTest no
se distribuye con la instalación por defecto de CakePHP por lo que debemos descargarlo primero. Lo puedes
encontrar aquí: http://simpletest.sourceforge.net/ (http://simpletest.sourceforge.net/)

Consigue la última versión y descomprime el código en tu carpeta cake/vendors, o en tu carpeta app/vendors, según
tus preferencias. Ahora deberías tener un directorio vendors/simpletest con todos los archivos y carpetas de
SimpleTest dentro. ¡Recuerda tener el nivel de DEBUG al menos a 1 en tu archivo app/config/core.php antes de

153 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

ejecutar cualquier test!

Si no tienes una conexión de base de datos para test definida en app/config/database.php, las tablas de test se
crearán con un prefijo test_suite_. Puedes crear una conexión de base de adtos $test para que contenga sólo las
tablas de test como la que te mostramos debajo:

Plain Text View (#)


1. var $test = array(
2. 'driver' => 'mysql',
3. 'persistent' => false,
4. 'host' => 'dbhost',
5. 'login' => 'dblogin',
6. 'password' => 'dbpassword',
7. 'database' => 'databaseName'
8. );

Si la base de datosd e test está disponible y CakePHP puede conectarse a ella, todas las tablas serán creadas en esta
base de datos.

4.7.1.2 (#Ejecutando-los-test-cases-incorporados-1199) Ejecutando los test-cases incorporados

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1199)


Comparar con el texto original (/es/compare/1199/Ejecutando-los-test-cases-incorporados)

Mas info sobre traduciones (/es/view/818)

CakePHP 1.2 se distribuye con un gran paquete de test-cases sobre la funcionalidad del núcleo de CakePHP

Puedes acceder a estos test navegando a http://your.cake.domain/cake_folder/test.php - dependiendo de como sea la


disposición específica de tu aplicación. Intenta ejecutar alguno de los grupos de test del núcleo haciendo click en el
enlace correspondiente. Ejecutar un test puede llevar un rato, pero deberías ver algo parecido a "2/2 test casese
complete: 49 passes, 0 fails and 0 exceptions.".

¡Felicidades, ya estás listo/a para empezar a escribir tests!

4.7.2 (#Introducción-a-los-test-Unit-testing-vs-Web-testi-1200) Introducción a los test - Unit testing vs. Web testing

El entorno de test de CakePHP soporta dos tipos de testing. Uno es el Unit Testing, en el cual tú pruebas pequeñas
partes de tu código, como pueden ser un método en un componente o una acción en un controlador. El otro tipo de
testing soportado es el Web Testing, en el cual automatizas el trabajo de evaluar tu aplicación mediante la navegación
por las páginas, relleno de formularios, hacer clic en enlaces y demás.

4.7.3 (#Preparando-datos-de-prueba-1201) Preparando datos de prueba

4.7.3.1 (#Acerca-de-las-fixtures-1202) Acerca de las fixtures

Cuando pruebes código que dependa de modelos y datos, puedes usar fixtures como una forma de generar tablas
temporales de datos cargados con datos de ejemplo que pueden ser utilizados por el test. El beneficio de usar
fixtures es que tus test no pueden de ningún modo alterar los datos de la aplicación en marcha. Además, así puedes
empezar a probar tu código antes de desarrollar contenido en vivo para tu aplicación.

CakePHP intenta utilizar la conexión denominada $test en tu archivo app/config/database.php. Si esta conexión no es
utilizable, usará la configuración de base de datos $default y creará las tablas de test en la base de datos definida en
esa configuración. En cualquier caso, añadirá el prefijo "test_suite_" a tu propio prefijo para las tablas (si es que hay
alguno) para evitar colisiones con las tablas existentes.

CakePHP realiza los siguientes pasos durante el curso de un test case basado en fixture:

1. Crea tablas para cada una de las fixtures necesarias


2. Rellena las tablas con datos, si es que se han proporcionado éstos en la fixture
3. Ejecuta los métodos de los test
4. Vacía las tablas fixture
5. Elimina las tablas fixture de la base de datos

154 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

4.7.3.2 (#Creando-fixtures-1203) Creando fixtures

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1203)


Comparar con el texto original (/es/compare/1203/Creando-fixtures)

Mas info sobre traduciones (/es/view/818)

Cuando se crea un fixture se deben definir 2 cosas:


1) cómo se crea la tabla (que campos serán parte de la tabla)
2) cómo se guardarán los registros en la tabla de prueba. Luego podremos crear nuestro primer fixture, que
utilizaremos para testear nuestro modelo Article. Creamos un archivo llamado article_fixture.php en la carpeta
app/tests/fixtures, con el siguiente código:

Plain Text View (#)


1. <?php
2. class ArticleFixture extends CakeTestFixture {
3. var $name = 'Article';
4.
5. var $fields = array(
6. 'id' => array('type' => 'integer', 'key' => 'primary'),
7. 'title' => array('type' => 'string', 'length' => 255, 'null' => false),
8. 'body' => 'text',
9. 'published' => array('type' => 'integer', 'default' => '0', 'null' => false),
10. 'created' => 'datetime',
11. 'updated' => 'datetime'
12. );
13. var $records = array(
14. array ('id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' =>
15. array ('id' => 2, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' =
16. array ('id' => 3, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' =>
17. );
18. }
19. ?>

Usamos $fields para indicar los campos que serán parte de la tabla, y cómo serán definidos. El formato que se usa
para definir los campos es el mismo que usamos en la funcion generateColumnSchema() definida en el motor de base
de datos de Cake (por ejemplo en dbo_mysql.php.) Los atributos que un campo puede tenes son los siguientes:

type
es el tipo de dato de CakePHP. Actualmente los soportados son: string (mapea como VARCHAR), text (mapea
como TEXT), integer (mapea como INT), float (mapea como FLOAT), datetime (mapea como DATETIME),
timestamp (mapea como TIMESTAMP), time (mapea como TIME), date (mapea como DATE), y binary (mapea como
BLOB)
key
setea el campo como primary para hacerlo auto-incrementable (AUTO_INCREMENT), y clave primaria (PRIMARY
KEY) de la tabla.
length
setea el tamaño del campo.
null
setea true o false. Si puede ser nulo indicamos true, si no se permiten nulos va false
default
el valor por defecto del campo.

Finalmente podemos setear un conjunto de registros que seran cargados luego de que la tabla de testeo se crea. El
formato es bastante simple, sin embargo necesita un poco más de expilcación. Solo ten en cuenta que cada registro
del array $records debe tener una key para cada campo del array $fields. Si un campo para un registro en particular
necesita tener el valor nulo, solo especifica el valor de ese campo como nulo (NULL true).

4.7.3.3 (#Importar-información-de-tabla-y-registros-1204) Importar información de tabla y registros

Tu aplicación puede tener ya modelos funcionando con datos reales asociados, y puedes decidir probar tu modelo
con esos datos. Sería entonces un esfuerzo doble tener que definir la tabla y/o los registros en tus fixtures. Por

155 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

suerte, hay una forma de hacer que la definición de la tabla y/o los registros para una fixture en particular vengan de
un modelo o una tabla ya existentes.

Comencemos con un ejemplo. Asumiento que tienes un modelo llamado Article disponible en tu aplicación (que se
corresponde con una tabla llamada articles), cambiamos la fixture de ejemplo que dimos en la sección anterior
(app/tests/fixtures/article_fixture.php) a:

Plain Text View (#)


1. <?php
2. class ArticleFixture extends CakeTestFixture {
3. var $name = 'Article';
4. var $import = 'Article';
5. }
6. ?>

Esta sentencia le dice a la test suite que importe tu definición de tabla de la tabla asociada al modelo llamado Article.
Puedes usar cualquier modelo disponible en tu aplicación. La expresión anterior no importa registros, pero puedes
hacerlo cambiandola para que sea:

Plain Text View (#)


1. <?php
2. class ArticleFixture extends CakeTestFixture {
3. var $name = 'Article';
4. var $import = array('model' => 'Article', 'records' => true);
5. }
6. ?>

Si, por otro lado, tienes una tabla creada pero no un modelo disponible para ella, puedes especificar que tu
importación consistirá en leer la información de la tabla. Por ejemplo:

Plain Text View (#)


1. <?php
2. class ArticleFixture extends CakeTestFixture {
3. var $name = 'Article';
4. var $import = array('table' => 'articles');
5. }
6. ?>

Esto importará la definición de una tabla llamada 'articles' usando tu conexión de base de datos denominada 'default'.
Si quieres cambiar la conexión sólo tienes que hacer:

Plain Text View (#)


1. <?php
2. class ArticleFixture extends CakeTestFixture {
3. var $name = 'Article';
4. var $import = array('table' => 'articles', 'connection' => 'other');
5. }
6. ?>

Ya que se usa tu conexión a la base de datos, si hay algún prefijo de tabla declarado, este será usado
automáticamente al recabar la información de tabla. Los dos fragmentos anteriores no importan registros de la tabla.
Para forzar a la fixture a importar también los registros, cambialo a:

Plain Text View (#)


1. <?php
2. class ArticleFixture extends CakeTestFixture {
3. var $name = 'Article';
4. var $import = array('table' => 'articles', 'records' => true);
5. }
6. ?>

156 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Naturalmente puedes importar tus definiciones de tabla de un modelo o tabla existente, pero tener tus registros
definidos directamente en la fixture, como se mostraba en la sección anterior. Por ejemplo:

Plain Text View (#)


1. <?php
2. class ArticleFixture extends CakeTestFixture {
3. var $name = 'Article';
4. var $import = 'Article';
5.
6. var $records = array(
7. array ('id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published'
8. array ('id' => 2, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published
9. array ('id' => 3, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published'
10. );
11. }
12. ?>

4.7.4 (#Creando-los-tests-1205) Creando los tests

En primer lugar, revisar una serie de normas y directrices para los tests:

1. Los archivos de PHP que contiene los tests deben estar en : app/tests/cases/[algun_ archivo].
2. Los nombres de estos archivos deben terminar con un .test.php en lugar de sólo .php.
3. Las clases que contienen los tests debe extender o heredar de CakeTestCase o CakeWebTestCase.
4. El nombre de cualquier método que contenga un test (por ejemplo, que contiene una afirmación) debería
comenzar con test, como en testPublished().

Cuando se crea un caso test, puede ejecutarce por medio del navegador en la siguiente dirección
http://tu.dominio.cake/carpeta_cake/test.php (dependiendo de cómo se ve específicamente tu configuración) y
haciendo clic en App casos de test, y a continuación, haga clic en el enlace a su archivo.

4.7.4.1 (#CakeTestCase-Callback-Methods-1206) CakeTestCase Callback Methods

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1206/CakeTestCase-Callback-
Methods) .. Mas info sobre traduciones (/es/view/818)

If you want to sneak in some logic just before or after an individual CakeTestCase method, and/or before or after your
entire CakeTestCase, the following callbacks are available:

start()
First method called in a test case.

end()
Last method called in a test case.

startCase()
called before a test case is started.

endCase()
called after a test case has run.

before($method)
Announces the start of a test method .

after($method)
Announces the end of a test method .

startTest($method)
Called just before a test method is executed.

endTest($method)
Called just after a test method has completed.

4.7.5 (#Testing-models-1207) Testing models

4.7.5.1 (#Creating-a-test-case-1208) Creating a test case

157 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1208/Creating-a-test-case) ..
Mas info sobre traduciones (/es/view/818)

Let's say we already have our Article model defined on app/models/article.php, which looks like this:

Plain Text View (#)


1. <?php
2. class Article extends AppModel {
3. var $name = 'Article';
4.
5. function published($fields = null) {
6. $params = array(
7. 'conditions' => array(
8. $this->name . '.published' => 1
9. ),
10. 'fields' => $fields
11. );
12.
13. return $this->find('all',$params);
14. }
15.
16. }
17. ?>

We now want to set up a test that will use this model definition, but through fixtures, to test some functionality in the
model. CakePHP test suite loads a very minimum set of files (to keep tests isolated), so we have to start by loading our
parent model (in this case the Article model which we already defined), and then inform the test suite that we want to
test this model by specifying which DB configuration it should use. CakePHP test suite enables a DB configuration
named test_suite that is used for all models that rely on fixtures. Setting $useDbConfig to this configuration will let
CakePHP know that this model uses the test suite database connection.

CakePHP Models will only use the test_suite DB config if they rely on fixtures in your testcase!

Since we also want to reuse all our existing model code we will create a test model that will extend from Article, set
$useDbConfig and $name appropiately. Let's now create a file named article.test.php in your app/tests/cases/models
directory, with the following contents: Plain Text View (#)
1. <?php
2. App::import('Model','Article');
3.
4. class ArticleTestCase extends CakeTestCase {
5. var $fixtures = array( 'app.article' );
6. }
7. ?>

We have created the ArticleTestCase. In variable $fixtures we define the set of fixtures that we'll use.

If your model is associated with other models, you will need to include ALL the fixtures for each associated model
even if you don't use them. For example: A hasMany B hasMany C hasMany D. In ATestCase you will have to include
fixtures for a, b, c and d.

4.7.5.2 (#Creating-a-test-method-1209) Creating a test method

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1209/Creating-a-test-method) ..
Mas info sobre traduciones (/es/view/818)

Let's now add a method to test the function published() in the Article model. Edit the file app/tests/cases/models
/article.test.php so it now looks like this:

Plain Text View (#)

158 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <?php
2. App::import('Model', 'Article');
3.
4. class ArticleTestCase extends CakeTestCase {
5. var $fixtures = array( 'app.article' );
6.
7. function testPublished() {
8. $this->Article =& ClassRegistry::init('Article');
9.
10. $result = $this->Article->published(array('id', 'title'));
11. $expected = array(
12. array('Article' => array( 'id' => 1, 'title' => 'First Article' )),
13. array('Article' => array( 'id' => 2, 'title' => 'Second Article' )),
14. array('Article' => array( 'id' => 3, 'title' => 'Third Article' ))
15. );
16.
17. $this->assertEqual($result, $expected);
18. }
19. }
20. ?>

You can see we have added a method called testPublished(). We start by creating an instance of our fixture based
Article model, and then run our published() method. In $expected we set what we expect should be the proper result
(that we know since we have defined which records are initally populated to the article table.) We test that the result
equals our expectation by using the assertEqual method. See the section Creating Tests for information on how to run
the test.

4.7.6 (#Testing-controllers-1210) Testing controllers

4.7.6.1 (#Creando-un-test-case-1211) Creando un test case

Digamos que tienes un típico controlador de artículos, con su correspondiente modelo, y que se parece a éste:

Plain Text View (#)


1. <?php
2. class ArticlesController extends AppController {
3. var $name = 'Articles';
4. var $helpers = array('Ajax', 'Form', 'Html');
5.
6. function index($short = null) {
7. if (!empty($this->data)) {
8. $this->Article->save($this->data);
9. }
10. if (!empty($short)) {
11. $result = $this->Article->findAll(null, array('id',
12. 'title'));
13. } else {
14. $result = $this->Article->findAll();
15. }
16.
17. if (isset($this->params['requested'])) {
18. return $result;
19. }
20.
21. $this->set('title', 'Articles');
22. $this->set('articles', $result);
23. }
24. }
25. ?>

159 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Crea un archivo llamado articles_controller.test.php y pon lo siguiente dentro:

Plain Text View (#)


1. <?php
2. class ArticlesControllerTest extends CakeTestCase {
3. function startCase() {
4. echo '<h1>Comenzando Test Case</h1>';
5. }
6. function endCase() {
7. echo '<h1>Terminado Test Case</h1>';
8. }
9. function startTest($method) {
10. echo '<h3>Comenzando método ' . $method . '</h3>';
11. }
12. function endTest($method) {
13. echo '<hr />';
14. }
15. function testIndex() {
16. $result = $this->testAction('/articles/index');
17. debug($result);
18. }
19. function testIndexShort() {
20. $result = $this->testAction('/articles/index/short');
21. debug($result);
22. }
23. function testIndexShortGetRenderedHtml() {
24. $result = $this->testAction('/articles/index/short',
25. array('return' => 'render'));
26. debug(htmlentities($result));
27. }
28. function testIndexShortGetViewVars() {
29. $result = $this->testAction('/articles/index/short',
30. array('return' => 'vars'));
31. debug($result);
32. }
33. function testIndexFixturized() {
34. $result = $this->testAction('/articles/index/short',
35. array('fixturize' => true));
36. debug($result);
37. }
38. function testIndexPostFixturized() {
39. $data = array('Article' => array('user_id' => 1, 'published'
40. => 1, 'slug'=>'new-article', 'title' => 'New Article', 'body' => 'New Body'));
41. $result = $this->testAction('/articles/index',
42. array('fixturize' => true, 'data' => $data, 'method' => 'post'));
43. debug($result);
44. }
45. }
46. ?>

4.7.6.2 (#El-método-testAction-1212) El método testAction

La novedad aquí es el método testAction. El primer argumento de este método es la URL "en formato Cake" de la
acción del controlador que se quiere probar, como en '/articles/index/short'.

El segundo argumento es un array de parámetros, consistente en:

return
Indica lo que se va a devolver.
Los valores válidos son:
'vars' - Obtienes las variables de la vista disponibles tras ejecutar la acción

160 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

'view' - Obtienes la vista generada, sin layout


'contents' - Obtienes todo el html de la vista, incluyendo layout
'result' - Obtienes el valor de retorno de la acción como cuando se usa $this->params['requested'].
El valor por defecto es 'result'.
fixturize
Ponlo a true si quieres que tus modelos se "auto-simulen" (de modo que las tablas de la aplicación se copian,
junto con los registros, para que al probar las tablas si cambias datos no afecten a tu aplicación real.) Si en
'fixturize' pones un array de modelos, entonces sólo esos modelos se auto-simularán mientras que los demás
utilizarán las tablas reales. Si quieres usar tus archivos de fixtures con testAction() no uses fixturize, y en su
lugar usa las fixtures como harías normalmente.
method
Ajustalo a 'post' o 'get' si quieres pasarle datos al controlador
data
Los datos que se pasarán. Será un array asociativo consistente en pares de campo => valor. Échale un vistazo a
function testIndexPostFixturized() en el case test de arriba para ver cómo emulamos pasar datos de
formulario como post para un nuevo artículo.

4.7.6.3 (#Pitfalls-1213) Pitfalls

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1213/Pitfalls) .. Mas info sobre
traduciones (/es/view/818)

If you use testAction to test a method in a controller that does a redirect, your test will terminate immediately, not
yielding any results.
See https://trac.cakephp.org/ticket/4154 (https://trac.cakephp.org/ticket/4154) for a possible fix.

4.7.7 (#Testing-Helpers-1214) Testing Helpers

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1214/Testing-Helpers) .. Mas
info sobre traduciones (/es/view/818)

Since a decent amount of logic resides in Helper classes, it's important to make sure those classes are covered by test
cases.

Helper testing is a bit similar to the same approach for Components. Suppose we have a helper called
CurrencyRendererHelper located in app/views/helpers/currency_renderer.php with its accompanying test case file
located in app/tests/cases/helpers/currency_renderer.test.php

4.7.7.1 (#Creating-Helper-test-part-I-1215) Creating Helper test, part I

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1215/Creating-Helper-
test-part-I) .. Mas info sobre traduciones (/es/view/818)

First of all we will define the responsibilities of our CurrencyRendererHelper. Basically, it will have two methods just
for demonstration purpose:

function usd($amount)

This function will receive the amount to render. It will take 2 decimal digits filling empty space with zeros and prefix
'USD'.

function euro($amount)

This function will do the same as usd() but prefix the output with 'EUR'. Just to make it a bit more complex, we will also
wrap the result in span tags:

Plain Text View (#)


1. <span class="euro"></span>

Let's create the tests first:

Plain Text View (#)

161 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <?php
2. //Import the helper to be tested.
3. //If the tested helper were using some other helper, like Html,
4. //it should be impoorted in this line, and instantialized in startTest().
5. App::import('Helper', 'CurrencyRenderer');
6. class CurrencyRendererTest extends CakeTestCase {
7. private $currencyRenderer = null;
8. //Here we instantiate our helper, and all other helpers we need.
9. public function startTest() {
10. $this->currencyRenderer = new CurrencyRendererHelper();
11. }
12. //testing usd() function.
13. public function testUsd() {
14. $this->assertEqual('USD 5.30', $this->currencyRenderer->usd(5.30));
15. //We should always have 2 decimal digits.
16. $this->assertEqual('USD 1.00', $this->currencyRenderer->usd(1));
17. $this->assertEqual('USD 2.05', $this->currencyRenderer->usd(2.05));
18. //Testing the thousands separator
19. $this->assertEqual('USD 12,000.70', $this->currencyRenderer->usd(12000.70));
20. }
21. }

Here, we call usd() with different parameters and tell the test suite to check if the returned values are equal to what is
expected.

Executing the test now will result in errors (because currencyRendererHelper doesn't even exist yet) showing that we
have 3 fails.

Once we know what our method should do, we can write the method itself:

Plain Text View (#)


1. <?php
2. class CurrencyRendererHelper extends AppHelper {
3. public function usd($amount) {
4. return 'USD ' . number_format($amount, 2, '.', ',');
5. }
6. }

Here we set the decimal places to 2, decimal separator to dot, thousands separator to comma, and prefix the formatted
number with 'USD' string.

Save this in app/views/helpers/currency_renderer.php and execute the test. You should see a green bar and
messaging indicating 4 passes.

4.7.8 (#Probando-componentes-1216) Probando componentes

Supongamos que queremos hacer test a un componente llamado TransporterComponent, el cual usa un modelo
llamado Transporter para proporcionar funcionalidad a otros controladores. Utilizaremos cuatro archivos:

Un componente llamado Transporters que se encuentra en app/controllers/components/transporter.php


Un modelo llamado Transporte que está en app/models/transporter.php
Una fixture llamada TransporterTestFixture situada en app/tests/fixtures/transporter_fixture.php
El código para el test, en app/tests/cases/transporter.test.php

4.7.8.1 (#Initializing-the-component-1217) Initializing the component

Ya que CakePHP desaliante importar modelos directamente en los componentes (/es/view/62/components)


necesitamos un controlador para acceder a los datos en el mmodelo.

Si el método startup() del componente tiene este aspecto:

Plain Text View (#)

162 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. public function startup(&$controller){


2. $this->Transporter = $controller->Transporter;
3. }

entonces podemos simplemente crear una clase sencilla:

Plain Text View (#)


1. class FakeTransporterController {}

y asignarle valores dentro de ella como aquí:

Plain Text View (#)


1. $this->TransporterComponentTest = new TransporterComponent();
2. $controller = new FakeTransporterController();
3. $controller->Transporter = new TransporterTest();
4. $this->TransporterComponentTest->startup(&$controller);

4.7.8.2 (#Creando-un-método-de-prueba-1218) Creando un método de prueba

Simplemente crea una clase que extienda CakeTestCase y ¡comienza a escribir tests!

Plain Text View (#)


1. class TransporterTestCase extends CakeTestCase {
2. var $fixtures = array('transporter');
3. function testGetTransporter() {
4. $this->TransporterComponentTest = new TransporterComponent();
5. $controller = new FakeTransporterController();
6. $controller->Transporter = new TransporterTest();
7. $this->TransporterComponentTest->startup(&$controller);
8.
9. $result = $this->TransporterComponentTest->getTransporter("12345", "Sweden", "54321", "Sweden"
10. $this->assertEqual($result, 1, "SP is best for 1xxxx-5xxxx");
11.
12. $result = $this->TransporterComponentTest->getTransporter("41234", "Sweden", "44321", "Sweden
13. $this->assertEqual($result, 2, "WSTS is best for 41xxx-44xxx");
14.
15. $result = $this->TransporterComponentTest->getTransporter("41001", "Sweden", "41870", "Sweden
16. $this->assertEqual($result, 3, "GL is best for 410xx-419xx");
17.
18. $result = $this->TransporterComponentTest->getTransporter("12345", "Sweden", "54321", "Norway
19. $this->assertEqual($result, 0, "Noone can service Norway");
20. }
21. }
22.

4.7.9 (#Web-testing-Testeando-las-vistas-1219) Web testing - Testeando las vistas

La mayoria, si no es que lo son todos, los proyectos CakePHP son aplicaciones web. Aunque el testeo unitario es una
excelente manera de testear pequeñas porciones de nuestro código, hay ocaciones en la que querriamos hacer un
testeo a gran escala. La clase CakeWebTestCase nos brinda una muy buena manera de hacer éste tipo de testing,
desde el punto de vista del usuario.

4.7.9.1 (#About-CakeWebTestCase-1220) About CakeWebTestCase

CakeWebTestCase es una extensión directa de SimpleTest WebTestCase, sin ninguna funcionalidad extra. Toda la
funcionalidad encontrada en la documentación de SimpleTest para Testeo Web (Web testing)
(http://simpletest.sourceforge.net/en/web_tester_documentation.html) tambien están disponibles aqui. Esto quiere decir
que no se pueden usar los fixtures, y que todos los casos de testeo involucrados en un ABM (alta, baja o
modificación) a la base de datos modificarán permanentemente los valores. Los resultados del Test son comparados
frecuentemente con los qe tiene la base de datos, por lo tanto, asegurarse que la bd tenga los valores que se esperan,
es parte del proceso de construcción del test.

163 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

4.7.9.2 (#Creando-un-test-1221) Creando un test

Manteniendo las convenciones de los otros tests, los archivos de testeo de vistas se deberán crear en la carpeta
tests/cases/views. Claro que se podrian guardar en otra ubicación, pero siempre es bueno seguir las convenciones.
Entonces, crearemos el archivo: tests/cases/views/complete_web.test.php

Para escribir testeos web, deberás extender la clase CakeWebTestCase y no CakeTestCase, tal como era en los otros
tests:

Plain Text View (#)


1. class CompleteWebTestCase extends CakeWebTestCase

Si necesitas hacer alguna inicialización antes de que comience el test, crea el constructor:

Plain Text View (#)


1. function CompleteWebTestCase(){
2. //Do stuff here
3. }

Cuando escribes los test cases, lo primero que vas a necesitar hacer es capturar algun tipo de salida o resultado
donde ver y analizar. Ésto puede ser realizado haciendo un request get o post, usando los métodos get() o post()
respectivamente. A ambos métodos se le pasa como primer parámetro la url, aunque puede ser traida dinámicamente
si asumimos que script de testing está en http://your.domain/cake/folder/webroot/test.php tipeando:

Plain Text View (#)


1. $this->baseurl = current(split("webroot", $_SERVER['PHP_SELF']));

Entonces podremos hacer gets y posts usando las urls de Cake, por ejemplo:

Plain Text View (#)


1. $this->get($this->baseurl."/products/index/");
2. $this->post($this->baseurl."/customers/login", $data);

El segundo parámetro del método post, $data, es un array asociativo que contiene post data en el formato de Cake:

Plain Text View (#)


1. $data = array(
2. "data[Customer][mail]" => "user@user.com",
3. "data[Customer][password]" => "userpass");

Una vez que se hizo el request a la página, se pueden utilizar todos los mismos asserts que veniamos usando en
SimpleTest.

4.7.9.3 (#Walking-through-a-page-1222) Walking through a page

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1222/Walking-through-a-page) ..
Mas info sobre traduciones (/es/view/818)

CakeWebTest also gives you an option to navigate through your page by clicking links or images, filling forms and
clicking buttons. Please refer to the SimpleTest documentation for more information on that.

4.7.10 (#Testing-plugins-1223) Testing plugins

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1223/Testing-plugins) .. Mas
info sobre traduciones (/es/view/818)

Tests for plugins are created in their own directory inside the plugins folder.

/app
/plugins
/pizza
/tests
/cases

164 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

/fixtures
/groups

They work just like normal tests but you have to remember to use the naming conventions for plugins when importing
classes. This is an example of a testcase for the PizzaOrder model from the plugins chapter of this manual. A
difference from other tests is in the first line where 'Pizza.PizzaOrder' is imported. You also need to prefix your plugin
fixtures with 'plugin.plugin_name.'.

Plain Text View (#)


1. <?php
2. App::import('Model', 'Pizza.PizzaOrder');
3. class PizzaOrderCase extends CakeTestCase {
4. // Plugin fixtures located in /app/plugins/pizza/tests/fixtures/
5. var $fixtures = array('plugin.pizza.pizza_order');
6. var $PizzaOrderTest;
7.
8. function testSomething() {
9. // ClassRegistry makes the model use the test database connection
10. $this->PizzaOrderTest =& ClassRegistry::init('PizzaOrder');
11. // do some useful test here
12. $this->assertTrue(is_object($this->PizzaOrderTest));
13. }
14. }
15. ?>

If you want to use plugin fixtures in the app tests you can reference them using 'plugin.pluginName.fixtureName'
syntax in the $fixtures array.

That is all there is to it.

4.7.11 (#Miscellaneous-1224) Miscellaneous

4.7.11.1 (#Customizing-the-test-reporter-1225) Customizing the test reporter

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1225/Customizing-the-test-
reporter) .. Mas info sobre traduciones (/es/view/818)

The standard test reporter is very minimalistic. If you want more shiny output to impress someone, fear not, it is
actually very easy to extend. By creating a new reporter and making a request with a matching output GET parameter
you can get test results with a custom reporter.

Reporters generate the visible output from the test suite. There are two built in reporters: Text and Html. By default all
web requests use the Html reporter. You can create your own reporters by creating files in your app/libs. For example
you could create the file app/libs/test_suite/reporters/my_reporter.php and in it create the following:

Plain Text View (#)


1. require_once CAKE_TEST_LIB . 'reporter' . DS . 'cake_base_reporter.php';
2. class MyReporter extends CakeBaseReporter {
3. //methods go here.
4. }

Extending CakeBaseReporter or one of its subclasses is not required, but strongly suggested as you may get missing
errors otherwise. CakeBaseReporter encapsulates a few common test suite features such as test case timing and code
coverage report generation. You can use your custom reporter by setting the output query string parameter to the
reporter name minus 'reporter'. For the example above you would set output=my to use your custom reporter.

4.7.11.2 (#Test-Reporter-methods-1587) Test Reporter methods

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1587/Test-Reporter-methods) ..
Mas info sobre traduciones (/es/view/818)

Reporters have a number of methods used to generate the various parts of a Test suite response.

165 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

paintDocumentStart()
Paints the start of the response from the test suite. Used to paint things like head elements in an html page.
paintTestMenu()
Paints a menu of available test cases.
testCaseList()
Retrieves and paints the list of tests cases.
groupCaseList()
Retrieves and paints the list of group tests.
paintHeader()
Prints before the test case/group test is started.
paintPass()
Prints everytime a test case has passed. Use $this->getTestList() to get an array of information pertaining to the
test, and $message to get the test result. Remember to call parent::paintPass($message).
paintFail()
Prints everytime a test case has failed. Remember to call parent::paintFail($message).
paintSkip()
Prints everytime a test case has been skipped. Remember to call parent::paintSkip($message).
paintException()
Prints everytime there is an uncaught exception. Remember to call parent::paintException($message).
paintError()
Prints everytime an error is raised. Remember to call parent::paintError($message).
paintFooter()
Prints when the test case/group test is over, i.e. when all test cases has been executed.
paintDocumentEnd()
Paints the end of the response from the test suite. Used to paint things like footer elements in an html page.

4.7.11.3 (#Grouping-tests-1226) Grouping tests

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1226/Grouping-tests) .. Mas info
sobre traduciones (/es/view/818)

If you want several of your test to run at the same time, you can try creating a test group. Create a file in /app/tests
/groups/ and name it something like your_test_group_name.group.php. In this file, extend GroupTest and import
test as follows:

Plain Text View (#)


1. <?php
2. class TryGroupTest extends TestSuite {
3. var $label = 'try';
4. function tryGroupTest() {
5. TestManager::addTestCasesFromDirectory($this, APP_TEST_CASES . DS . 'models');
6. }
7. }
8. ?>

The code above will group all test cases found in the /app/tests/cases/models/ folder. To add an individual file, use
TestManager::addTestFile($this, filename).

4.7.12 (#Running-tests-in-the-Command-Line-1227) Running tests in the Command Line

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1227/Running-tests-in-the-
Command-Line) .. Mas info sobre traduciones (/es/view/818)

If you have simpletest installed you can run your tests from the command line of your application.

from app/

cake testsuite help

Usage:
cake testsuite category test_type file
- category - "app", "core" or name of a plugin
- test_type - "case", "group" or "all"
- test_file - file name with folder prefix and without the (test|group).php suffix

166 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Examples:
cake testsuite app all
cake testsuite core all

cake testsuite app case behaviors/debuggable


cake testsuite app case models/my_model
cake testsuite app case controllers/my_controller

cake testsuite core case file


cake testsuite core case router
cake testsuite core case set

cake testsuite app group mygroup


cake testsuite core group acl
cake testsuite core group socket

cake testsuite bugs case models/bug


// for the plugin 'bugs' and its test case 'models/bug'
cake testsuite bugs group bug
// for the plugin bugs and its test group 'bug'

Code Coverage Analysis:

Append 'cov' to any of the above in order to enable code coverage analysis

As the help menu suggests, you'll be able to run all, part, or just a single test case from your app, plugin, or core,
right from the command line.

If you have a model test of test/models/my_model.test.php you'd run just that test case by running:

cake testsuite app models/my_model

4.7.13 (#Test-Suite-changes-in-1-3-1586) Test Suite changes in 1.3

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1586/Test-Suite-changes-in-1-3)
.. Mas info sobre traduciones (/es/view/818)

The TestSuite harness for 1.3 was heavily refactored and partially rebuilt. The number of constants and global
functions have been greatly reduced. Also the number of classes used by the test suite has been reduced and
refactored. You must update app/webroot/test.php to continue using the test suite. We hope that this will be the last
time that a change is required to app/webroot/test.php.

Removed Constants

CAKE_TEST_OUTPUT
RUN_TEST_LINK
BASE
CAKE_TEST_OUTPUT_TEXT
CAKE_TEST_OUTPUT_HTML

These constants have all been replaced with instance variables on the reporters and the ability to switch reporters.

Removed functions

CakePHPTestHeader()
CakePHPTestSuiteHeader()
CakePHPTestSuiteFooter()
CakeTestsGetReporter()
CakePHPTestRunMore()
CakePHPTestAnalyzeCodeCoverage()
CakePHPTestGroupTestList()
CakePHPTestCaseList()

167 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

These methods and the logic they contained have been refactored/rewritten into CakeTestSuiteDispatcher and the
relevant reporter classes. This made the test suite more modular and easier to extend.

Removed Classes

HtmlTestManager
TextTestManager
CliTestManager

These classes became obsolete as logic was consolidated into the reporter classes.

Modified methods/classes

The following methods have been changed as noted.

TestManager::getExtension() is no longer static.


TestManager::runAllTests() is no longer static.
TestManager::runGroupTest() is no longer static.
TestManager::runTestCase() is no longer static.
TestManager::getTestCaseList() is no longer static.
TestManager::getGroupTestList() is no longer static.

testsuite Console changes

The output of errors, exceptions, and failures from the testsuite console tool have been updated to remove redundant
information and increase readability of the messages. If you have other tools built upon the testsuite console, be sure
to update those tools with the new formatting.

CodeCoverageManager changes

CodeCoverageManager::start()'s functionality has been moved to CodeCoverageManager::init()


CodeCoverageManager::start() now starts coverage generation.
CodeCoverageManager::stop() pauses collection
CodeCoverageManager::clear() stops and clears collected coverage reports.

4.8 (#Internacionalización-Localización-1228) Internacionalización & Localización

Una de las mejores maneras para que tus aplicaciones lleguen a un público más amplio es brindarlo en varios
idiomas. Esto a menudo puede resultar ser una tarea de enormes proporciones, pero las funciones de
internacionalización y localización en CakePHP lo hace mucho más fácil.

En primer lugar, es importante comprender algunos términos. Internacionalización se refiere a la capacidad de una
aplicación para ser localiza. El término localización se refiere a la adaptación de una aplicación para responder a los
requerimientos de un lenguaje (o cultura) específico (es decir, un "lugar"). La internacionalización y localización son a
menudo abreviados como i18n y l10n, respectivamente, 18 y 10 son el número de caracteres entre el primero y el
último carácter.

4.8.1 (#Internacionalizando-su-aplicación-1229) Internacionalizando su aplicación

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1229)


Comparar con el texto original (/es/compare/1229/Internacionalizando-su-aplicación)

Mas info sobre traduciones (/es/view/818)

Hay sólo unos pocos pasos para pasar de una aplicación de un solo idioma a una aplicación multi-idioma, la primera
de ellas es hacer uso de la función __() (http://api.cakephp.org/file/basics.php#function-__) en su código. A continuación
se muestra un ejemplo de código para una aplicación de un solo idioma:

Plain Text View (#)


1. <h2>Posts</h2>

Para internacionalizar su código todo lo que necesitas hacer es envolver las cadenas de texto en la función translate
(http://api.cakephp.org/file/basics.php#function-__) como se muestra a continuación:

Plain Text View (#)

168 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <h2><?php __('Posts') ?></h2>

Si no hace nada más, estos dos ejemplos de código son funcionalmente idénticos – ambos envían el mismo contenido
al navegador. La función __() (http://api.cakephp.org/file/basics.php#function-__) traducirá la cadena de texto que se
pasa si la traducción está disponible, si no, devolverá la cadena sin modificar. Funciona de manera similar a otras
implementaciones de Gettext (http://en.wikipedia.org/wiki/Gettext) (igual que otras funciones de traducción como
__d() (http://api.cakephp.org/file/basics.php#function-__d) , __n() (http://api.cakephp.org/file/basics.php#function-__n) etc)

Con el código listo para ser multi-idioma, el siguiente paso es crear su archivo pot (http://en.wikipedia.org
/wiki/Gettext) , que es el modelo para todas las cadenas de texto traducibles en su aplicación. Para generar archivos
pot(s) todo lo que necesita es ejecutar la tarea i18n en la consola (http://book.cakephp.org/view/620/Core-Console-
Applications) , que buscará las funciones translate utilizadas en su código y creará los archivos por usted. Usted
puede y debe volver a ejecutar esta tarea cada vez que se produzca algún cambio de las traducciones en el código.

Los archivos pot(s) en si mismos no son utilizados por CakePHP, son las plantillas utilizadas para crear o actualizar
los archivos po (http://en.wikipedia.org/wiki/Gettext) , que contienen las traducciones. Cake buscará los archivos po en
la siguiente ubicación:

Plain Text View (#)


1. /app/locale/<locale>/LC_MESSAGES/<domain>.po

El dominio por defecto es 'default', por lo tanto en su carpeta locale se verá algo como esto:

Plain Text View (#)


1. /app/locale/eng/LC_MESSAGES/default.po (English)
2. /app/locale/fre/LC_MESSAGES/default.po (French)
3. /app/locale/por/LC_MESSAGES/default.po (Portuguese)

Para crear o editar su archivo po no se recomienda que utilice su editor favorito. Para crear un archivo po por primera
vez es recomendable copiar el archivo pot a la ubicación correcta y cambiar la extensión, a menos que usted esté
familiarizado con su formato. Es muy fácil crear un archivo po inválido o guardarlos con una codificación errónea (si
está editando manualmente el archivo po use UTF-8 para evitar problemas). Existen herramientas gratuitas como
PoEdit (http://www.poedit.net) que hacen de la edición y actualización de sus archivos po una tarea fácil.

Los códigos de localización correctos son los de tres caracteres conforme al estandar ISO 639-2 (http://www.loc.gov
/standards/iso639-2/php/code_list.php) aunque si crea locales regionales (en_US, en_GB, etc.) Cake los utiliza si
procede.

hay un límite de 1.014 caracteres para cada valor msgstr.

Recuerde que los archivos po son útiles para mensajes cortos, si necesita traducir párrafos largos, o incluso páginas
completas, debe considerar aplicar una solución diferente. Por ejemplo:

Plain Text View (#)


1. // App Controller Code.
2. function beforeFilter() {
3. $locale = Configure::read('Config.language');
4. if ($locale && file_exists(VIEWS . $locale . DS . $this->viewPath)) {
5. // e.g. use /app/views/fre/pages/tos.ctp instead of /app/views/pages/tos.ctp
6. $this->viewPath = $locale . DS . $this->viewPath;
7. }
8. }

Plain Text View (#)


1. // View code
2. echo $this->element(Configure::read('Config.language') . '/tos')

4.8.2 (#Localización-en-CakePHP-1230) Localización en CakePHP

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1230)

169 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Comparar con el texto original (/es/compare/1230/Localización-en-CakePHP)

Mas info sobre traduciones (/es/view/818)

Para cambiar o definir el idioma para su aplicación sólo necesita hacer lo siguiente:

Plain Text View (#)


1. Configure::write('Config.language', 'fre');

Esto le dice a Cake qué localización debe usar (si usa una localización regional como fr_FR, como alternativa en caso
que no exista, se utilizará la localización de la norma ISO 639-2 (http://www.loc.gov/standards/iso639-2
/php/code_list.php) ). Puede cambiar el idioma en cualquier momento, por ejemplo en el bootstrap si desea definir el
idioma por defecto para su aplicación, en el beforeFilter del controlador si el idioma es específico para una petición o
un usuario o en cualquier otro momento si desea mostrar un mensaje en un idioma diferente.

Es una buena idea mostrar contenido disponible en varios idiomas a partir de una URL diferente – esto hace que sea
fácil para los usuarios (y los motores de búsqueda) encontrar lo que están buscando en el idioma esperado. Hay
varias formas de hacer esto, puede ser utilizando subdominios específicos para cada idioma, (en.example.com,
fra.example.com, etc), o usando un prefijo en la URL, como se hace en esta aplicación. Usted también podría obtener
la información del navegador del usuario, entre otras cosas.

Como se menciona en la sección anterior, para mostrar el contenido localizado se utiliza la función __() o una de las
funciones de traducción disponibles a nivel mundial. El primer parámetro de la función se utiliza como msgid
definidos en los archivos .po.

Recuerde que debe usar el parámetro return de la función __() si no desea que se muestre la cadena de texto
directamente. Por ejemplo:

Plain Text View (#)


1. <?php
2. echo $form->error(
3. 'Card.cardNumber',
4. __("errorCardNumber", true),
5. array('escape' => false)
6. );
7. ?>

Si a usted le gusta tener todos los mensajes de error de validación traducidos por defecto, una solución simple sería
añadir el siguiente código en el app_model.php:

Plain Text View (#)


1. function invalidate($field, $value = true) {
2. return parent::invalidate($field, __($value, true));
3. }

La tarea i18n de la consola no será capaz de determinar el id del mensaje del ejemplo anterior, lo que significa que
tendrá que añadir las entradas a su archivo po manualmente (o a través de su propio script). Para evitar la necesidad
de editar los archivos default.po cada vez que ejecute la tarea i18n de la consola, puede utilizar un dominio diferente,
tal como:

Plain Text View (#)


1. function invalidate($field, $value = true) {
2. return parent::invalidate($field, __d('validation_errors', $value, true));
3. }

Hay otro aspecto de la localización de su aplicación que no está cubierto por el uso de las funciones de traducción,
estos son los formatos de fecha y moneda. No olvide que CakePHP es PHP :), por lo tanto para establecer los formatos
para este tipo de cosas deberá utilizar setlocale (http://www.php.net/setlocale) .

Si pasa una localización que no existe en su computadora a setlocale (http://www.php.net/setlocale) , no tendrá


ningún efecto. Puede encontrar la lista de localizaciones disponibles ejecutando el comando $locale -a

4.9 (#Paginación-1231) Paginación

170 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Uno de los obstáculos principales al crear aplicaciones web flexibles y amigables al usuario (user-friendly ) es diseñar
una Interfaz de Usuario intuitiva. Muchas aplicaciones tienden a crecer en tamaño y complejidad rápidamente, y tanto
diseñadores como programadores se encuentran conque no pueden arreglárselas para visualizar cientos o miles de
registros. Refactorizar lleva tiempo, y el rendimiento y la satisfacción del usuario pueden sufrir.

Visualizar un número razonable de registros por página ha sido siempre una parte crítica de toda aplicación y solía
causar muchos dolores de cabeza a los desarrolladores. CakePHP aligera la carga del desarrollador proveyendo una
manera rápida y fácil de paginar los datos.

El ayudante PaginatorHelper ofrece una genial solución porque es fácil de usar. Además de paginación, empaqueta
algunas características de ordenación muy fáciles de usar. Por último, pero no menos importante, también están
soportados el paginado y la ordenación Ajax.

4.9.1 (#Preparación-del-controlador-1232) Preparación del controlador

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1232)


Comparar con el texto original (/es/compare/1232/Preparación-del-controlador)

Mas info sobre traduciones (/es/view/818)

En el controlador comenzamos definiendo los valores de paginación por defecto en la variable $paginate. Es
importante señalar que la clave 'order' debe estar definida en la estructura de array dada.

Plain Text View (#)


1. class RecipesController extends AppController {
2. var $paginate = array(
3. 'limit' => 25,
4. 'order' => array(
5. 'Post.title' => 'asc'
6. )
7. );
8. }

También puedes incluir otras opciones para find(), como fields

Plain Text View (#)


1. class RecipesController extends AppController {
2. var $paginate = array(
3. 'fields' => array('Post.id', 'Post.created'),
4. 'limit' => 25,
5. 'order' => array(
6. 'Post.title' => 'asc'
7. )
8. );
9. }

Pueden incluirse otras claves en el array $paginate similares a los parámetos del método Model->find('all'), esto es:
conditons , fields , order , limit, page, contain y recursive. De hecho, puedes definir más de un conjunto de valores de
paginación por defecto en el controllador, simplemente nombra cada parte del array según el modelo que desees
configurar:

Plain Text View (#)


1. class RecipesController extends AppController {
2. var $paginate = array(
3. 'Recipe' => array (...),
4. 'Author' => array (...)
5. );
6. }

Ejemplo de sintaxis usando Containable Behavior:

171 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Plain Text View (#)


1. class RecipesController extends AppController {
2. var $paginate = array(
3. 'limit' => 25,
4. 'contain' => array('Article')
5. );
6. }

Una vez que la variable $paginate ha sido definida, podemos llamar al método paginate() en las acciones del
controlador. Este método devuelve los resultados de find('all') del modelo (aplicándoles los parámetros de la
paginación), y obtiene algunas estadísticas de paginación adicionales, que son pasadas a la Vista de forma invisible.
Este método también añade PaginatorHelper a la lista de helpers en tu controlador, si es que no estaba ya.

Plain Text View (#)


1. function list_recipes() {
2. // similar to findAll(), but fetches paged results
3. $data = $this->paginate('Recipe');
4. $this->set(compact('data'));
5. }

Puedes filtrar los registros pasando condiciones como segundo parámetro al método paginate()

Plain Text View (#)


1. $data = $this->paginate('Recipe', array('Recipe.title LIKE' => 'a%'));

O también puedes ajustar la clave conditions en la variable paginate.

4.9.2 (#Pagination-in-Views-1233) Pagination in Views

172 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1233)


Comparar con el texto original (/es/compare/1233/Pagination-in-Views)

Mas info sobre traduciones (/es/view/818)

Es cosa tuya decidir cómo mostrar los registros al usuario, aunque lo más habitual es hacerlo mediante tablas HTML.
Los ejemplos que siguen asumen una disposición tabular, pero el PaginatorHelper, disponible en las vistas, no
siempre necesita restringirse de ese modo.

Como ya se ha dicho, PaginatorHelper ofrece capacidades para ordenación que pueden integrarse fácilmente en las
cabeceras de las columnas de tus tablas:

Plain Text View (#)


1. // app/views/recipes/list_recipes.ctp
2. <table>
3. <tr>
4. <th><?php echo $paginator->sort('ID', 'id'); ?></th>
5. <th><?php echo $paginator->sort('Title', 'title'); ?></th>
6. </tr>
7. <?php foreach($data as $recipe): ?>
8. <tr>
9. <td><?php echo $recipe['Recipe']['id']; ?> </td>
10. <td><?php echo $recipe['Recipe']['title']; ?> </td>
11. </tr>
12. <?php endforeach; ?>
13. </table>

Los enlaces generados por el método sort() de PaginatorHelper permiten a los usuarios hacer click en las cabeceras
de las tablas y alternar la ordenación de los datos por un campo dado.

También es posible ordenar una columna en base a asociaciones:

Plain Text View (#)


1. <table>
2. <tr>
3. <th><?php echo $paginator->sort('Title', 'title'); ?></th>
4. <th><?php echo $paginator->sort('Author', 'Author.name'); ?></th>
5. </tr>
6. <?php foreach($data as $recipe): ?>
7. <tr>
8. <td><?php echo $recipe['Recipe']['title']; ?> </td>
9. <td><?php echo $recipe['Author']['name']; ?> </td>
10. </tr>
11. <?php endforeach; ?>
12. </table>

El ingrediente final de la paginación en las vistas es añadir la navegación de páginas, que también viene
proporcionada por PaginationHelper.

Plain Text View (#)


1. <!-- Muestra los números de página -->
2. <?php echo $paginator->numbers(); ?>
3. <!-- Muestra los enlaces para Anterior y Siguiente -->
4. <?php
5. echo $paginator->prev('« Previous ', null, null, array('class' => 'disabled'));
6. echo $paginator->next(' Next »', null, null, array('class' => 'disabled'));
7. ?>
8. <!-- Muestra X de Y, donde X es la página actual e Y el total del páginas -->
9. <?php echo $paginator->counter(); ?>

173 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

El texto generado por el método counter() puede personalizarse usando marcadores especiales:

Plain Text View (#)


1. <?php
2. echo $paginator->counter(array(
3. 'format' => 'Page %page% of %pages%, showing %current% records out of
4. %count% total, starting on record %start%, ending on %end%'
5. ));
6. ?>

Para pasar todos los argumentos de la URL a las funciones del paginador, añade lo siguiente a tu vista:

Plain Text View (#)


1. $paginator->options(array('url' => $this->passedArgs));

También puedes especificar qué parámetros pasar manualmente:

Plain Text View (#)


1. $paginator->options(array('url' => array("0", "1")));

4.9.3 (#Paginación-AJAX-1234) Paginación AJAX

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1234)


Comparar con el texto original (/es/compare/1234/Paginación-AJAX)

Mas info sobre traduciones (/es/view/818)

Es muy fácil incorporar funcionalidad Ajax en la paginación. El único código extra que necesitas es incluir la librería
JavaScript Prototype, ajustar el indicador (el icono de carga dentro la DIV) y especificar la DIV que será actualizada en
lugar de recargar la página.

No olvides añadir el componente RequestHandler para poder usar llamadas Ajax en tu controlador:

Plain Text View (#)


1. var $components = array('RequestHandler');

# (#Configuring-the-PaginatorHelper-to-use-a-custom-he-1603) Configuring the PaginatorHelper to use a custom helper

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1603/Configuring-
the-PaginatorHelper-to-use-a-custom-he) .. Mas info sobre traduciones (/es/view/818)

By default in 1.3 the PaginatorHelper uses JsHelper to do ajax features. However, if you don't want that and want to
use the AjaxHelper or a custom helper for ajax links, you can do so by changing the $helpers array in your
controller. After running paginate() do the following.

Plain Text View (#)


1. $this->set('posts', $this->paginate());
2. $this->helpers['Paginator'] = array('ajax' => 'Ajax');

Will change the PaginatorHelper to use the AjaxHelper for ajax operations. You could also set the 'ajax' key to be any
helper, as long as that class implements a link() method that behaves like HtmlHelper::link()

4.9.4 (#Custom-Query-Pagination-1237) Custom Query Pagination

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1237/Custom-Query-Pagination)
.. Mas info sobre traduciones (/es/view/818)

Fix me: Please add an example where overriding paginate is justified

A good example of when you would need this is if the underlying DB does not support the SQL LIMIT syntax. This is
true of IBM's DB2. You can still use the CakePHP pagination by adding the custom query to the model.

174 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Should you need to create custom queries to generate the data you want to paginate, you can override the paginate()
and paginateCount() model methods used by the pagination controller logic.

Before continuing check you can't achieve your goal with the core model methods.

The paginate() method uses the same parameters as Model::find(). To use your own method/logic override it in the
model you wish to get the data from.

Plain Text View (#)


1. /**
2. * Overridden paginate method - group by week, away_team_id and home_team_id
3. */
4. function paginate($conditions, $fields, $order, $limit, $page = 1, $recursive = null, $extra = array())
5. $recursive = -1;
6. $group = $fields = array('week', 'away_team_id', 'home_team_id');
7. return $this->find('all', compact('conditions', 'fields', 'order', 'limit', 'page', 'recursive', 'g
8. }

You also need to override the core paginateCount(), this method expects the same arguments as
Model::find('count'). The example below uses some Postgres-specifc features, so please adjust accordingly
depending on what database you are using.

Plain Text View (#)


1. /**
2. * Overridden paginateCount method
3. */
4. function paginateCount($conditions = null, $recursive = 0, $extra = array()) {
5. $sql = "SELECT DISTINCT ON(week, home_team_id, away_team_id) week, home_team_id, away_team_id FROM g
6. $this->recursive = $recursive;
7. $results = $this->query($sql);
8. return count($results);
9. }

The observant reader will have noticed that the paginate method we've defined wasn't actually necessary - All you have
to do is add the keyword in controller's $paginate class variable.

Plain Text View (#)


1. /**
2. * Add GROUP BY clause
3. */
4. var $paginate = array(
5. 'MyModel' => array('limit' => 20,
6. 'order' => array('week' => 'desc'),
7. 'group' => array('week', 'home_team_id', 'away_team_id'))
8. );
9. /**
10. * Or on-the-fly from within the action
11. */
12. function index() {
13. $this->paginate = array(
14. 'MyModel' => array('limit' => 20,
15. 'order' => array('week' => 'desc'),
16. 'group' => array('week', 'home_team_id', 'away_team_id'))
17. );

However, it will still be necessary to override the paginateCount() method to get an accurate value.

4.10 (#REST-1238) REST

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1238/REST) .. Mas info sobre
traduciones (/es/view/818)

175 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Many newer application programmers are realizing the need to open their core functionality to a greater audience.
Providing easy, unfettered access to your core API can help get your platform accepted, and allows for mashups and
easy integration with other systems.

While other solutions exist, REST is a great way to provide easy access to the logic you've created in your application.
It's simple, usually XML-based (we're talking simple XML, nothing like a SOAP envelope), and depends on HTTP
headers for direction. Exposing an API via REST in CakePHP is simple.

4.10.1 (#The-Simple-Setup-1239) The Simple Setup

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1239/The-Simple-Setup) .. Mas
info sobre traduciones (/es/view/818)

The fastest way to get up and running with REST is to add a few lines to your routes.php file, found in app/config.
The Router object features a method called mapResources(), that is used to set up a number of default routes for REST
access to your controllers. If we wanted to allow REST access to a recipe database, we'd do something like this:

Plain Text View (#)


1. //In app/config/routes.php...
2.
3. Router::mapResources('recipes');
4. Router::parseExtensions();

The first line sets up a number of default routes for easy REST access where method specifies the desired result format
(e.g. xml, json, rss). These routes are HTTP Request Method sensitive.

HTTP Method URL.method Controller action invoked


GET /recipes .method RecipesController::index()
GET /recipes/ 123.method RecipesController::view(123)
POST /recipes .method RecipesController::add()
PUT /recipes/123 .method RecipesController::edit(123)
DELETE /recipes/ 123.method RecipesController::delete(123)
POST /recipes/123 .method RecipesController::edit(123)

CakePHP's Router class uses a number of different indicators to detect the HTTP method being used. Here they are in
order of preference:

1. The _method POST variable


2. The X_HTTP_METHOD_OVERRIDE
3. The REQUEST_METHOD header

The _method POST variable is helpful in using a browser as a REST client (or anything else that can do POST easily).
Just set the value of _method to the name of the HTTP request method you wish to emulate.

Once the router has been set up to map REST requests to certain controller actions, we can move on to creating the
logic in our controller actions. A basic controller might look something like this:

Plain Text View (#)

176 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. // controllers/recipes_controller.php
2. class RecipesController extends AppController {
3. var $components = array('RequestHandler');
4. function index() {
5. $recipes = $this->Recipe->find('all');
6. $this->set(compact('recipes'));
7. }
8. function view($id) {
9. $recipe = $this->Recipe->findById($id);
10. $this->set(compact('recipe'));
11. }
12. function edit($id) {
13. $this->Recipe->id = $id;
14. if ($this->Recipe->save($this->data)) {
15. $message = 'Saved';
16. } else {
17. $message = 'Error';
18. }
19. $this->set(compact("message"));
20. }
21. function delete($id) {
22. if($this->Recipe->delete($id)) {
23. $message = 'Deleted';
24. } else {
25. $message = 'Error';
26. }
27. $this->set(compact("message"));
28. }
29. }

Since we've added a call to Router::parseExtensions(), the CakePHP router is already primed to serve up different views
based on different kinds of requests. Since we're dealing with REST requests, the view type is XML. We place the REST
views for our RecipesController inside app/views/xml. We can also use the XmlHelper for quick-and-easy XML output
in those views. Here's what our index view might look like:

Plain Text View (#)


1. // app/views/recipes/xml/index.ctp
2. <recipes>
3. <?php echo $xml->serialize($recipes); ?>
4. </recipes>

Experienced CakePHP users might notice that we haven't included the XmlHelper in our RecipesController $helpers
array. This is on purpose - when serving up a specific content type using parseExtensions(), CakePHP automatically
looks for a view helper that matches the type. Since we're using XML as the content type, the XmlHelper is
automatically loaded up for our use in those views.

The rendered XML will end up looking something like this:

Plain Text View (#)


1. <posts>
2. <post id="234" created="2008-06-13" modified="2008-06-14">
3. <author id="23423" first_name="Billy" last_name="Bob"></author>
4. <comment id="245" body="This is a comment for this post."></comment>
5. </post>
6. <post id="3247" created="2008-06-15" modified="2008-06-15">
7. <author id="625" first_name="Nate" last_name="Johnson"></author>
8. <comment id="654" body="This is a comment for this post."></comment>
9. </post>
10. </posts>

Creating the logic for the edit action is a bit trickier, but not by much. Since you're providing an API that outputs XML,

177 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

it's a natural choice to receive XML as input. Not to worry, however: the RequestHandler and Router classes make
things much easier. If a POST or PUT request has an XML content-type, then the input is taken and passed to an
instance of Cake's Xml object, which is assigned to the $data property of the controller. Because of this feature,
handling XML and POST data in parallel is seamless: no changes are required to the controller or model code.
Everything you need should end up in $this->data.

4.10.2 (#Custom-REST-Routing-1240) Custom REST Routing

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1240/Custom-REST-Routing) ..
Mas info sobre traduciones (/es/view/818)

If the default routes created by mapResources() don't work for you, use the Router::connect() method to define a
custom set of REST routes. The connect() method allows you to define a number of different options for a given URL.
The first parameter is the URL itself, and the second parameter allows you to supply those options. The third
parameter allows you to specify regex patterns to help CakePHP identify certain markers in the specified URL.

We'll provide a simple example here, and allow you to tailor this route for your other RESTful purposes. Here's what
our edit REST route would look like, without using mapResources():

Plain Text View (#)


1. Router::connect(
2. "/:controller/:id",
3. array("action" => "edit", "[method]" => "PUT"),
4. array("id" => "[0-9]+")
5. )

Advanced routing techniques are covered elsewhere, so we'll focus on the most important point for our purposes
here: the [method] key of the options array in the second parameter. Once that key has been set, the specified route
works only for that HTTP request method (which could also be GET, DELETE, etc.)

5 (#Componentes-del-Núcleo-1241) Componentes del Núcleo

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1241)


Comparar con el texto original (/es/compare/1241/Componentes-del-Núcleo)

Mas info sobre traduciones (/es/view/818)

CakePHP posee una serie de componentes integrados. Éstos proveen distintas funcionalidades para tareas realizadas
comunmente.

El componente Acl provee una sencilla interfaz para listas de control de acceso (access control list)
Acl
basadas en archivos ini o base de datos.
El componente Auth provee un sistema de autenticación fácil de utilizar usando diferentes procesos
Auth
de validación, como ser callbacks en los controladores, Acl u callbacks en los objetos.
Session El componente Session provee un wrapper de almacenamiento independiente a las sesiones de PHP.
El componente RequestHandler permite analizar las peticiones HTTP para informarle a la aplicación
RequestHandler
acerca del tipo de contenido y la información requerida por el usuario.
Security El componente Security permite aumentar la seguridad y gestionar autenticación HTTP.
Una interfaz que puede ser utilizada para enviar emails usando distintos MTA (mail transfer agent)
Email
incluyendo la función mail() de PHP y el protocolo SMTP.
El componente Cookie se comporta en cierta forma similar al Session ya que provee un wrapper para
Cookie
el soporte nativo de cookies en PHP.

Para aprender más acerca de cada componente mira en el menu a la izquierda, o aprende acerca de cómo crear tus
propios componentes (/es/view/62/components) .

5.1 (#Listas-de-Control-de-Acceso-1242) Listas de Control de Acceso

La funcionalidad de listas de control de acceso en CakePHP es una de las más comentadas, en parte porque es una de
las más solicitadas, y en parte porque puede ser algo confusa al principio. Si estás buscando un buen lugar para
comenzar a utilizar ACL en general, continúa leyendo.

178 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Debes ser valiente, incluso cuando las cosas se compliquen. Una vez que asimiles estos conceptos, las listas de
control de acceso son una herramienta extremadamente poderosa para tener a mano al desarrollar tu aplicación.

5.1.1 (#Entendiendo-cómo-funciona-ACL-1243) Entendiendo cómo funciona ACL

Las listas de control de acceso permiten gestionar detalladamente los permisos de una aplicación de forma sencilla y
escalable.

Las listas de control de acceso, o ACL, manejan principalmente dos cosas: las entidades que solicitan el control de
algo y las entidades que se quiere controlar. En la jerga de ACL, las entidades que quieren controlar algo, que la
mayoría de las veces son los usuarios, son los ARO (en inglés access request objects ), y las entidades del sistema que
se quiere controlar, que normalmente son acciones o datos, son los ACO (en inglés access control objects ). A los ARO
se les llama 'objetos' porque quien realiza la petición no siempre es una persona; los ACO son cualquier cosa que
desees controlar: desde la acción de un controlador o un servicio Web, hasta el diario en línea íntimo de tu abuela.

En resumen:

ACO - Access Control Object - Objeto que se quiere controlar


ARO - Access Request Object - Objeto que solicita el control de algo

Esencialmente, las ACL se utilizan para decidir cuándo un ARO puede acceder a un ACO.

Vamos a utilizar un ejemplo práctico para ver cómo encajan todas estas piezas. Imaginemos que el grupo de
aventureros de la novela de fantasía El señor de los Anillos trabaja con una aplicación CakePHP, y que el líder,
Gandalf, se encarga de gestionar los elementos del grupo. Para garantizar la privacidad y la seguridad de los
miembros del grupo, pues, lo primero que hace Gandalf es crear la lista de AROs involucrados:

Gandalf
Aragorn
Bilbo
Frodo
Gollum
Legolas
Gimli
Pippin
Merry

Fíjate que ACL no es lo mismo que la autenticación; ACL es lo que ocurre después de que el usuario se autentica.
Aunque suelen utilizarse los dos a la vez, es importante ver la diferencia entre saber quién es alguien (autenticación)
y saber qué puede hacer (ACL).

A continuación, Gandalf tiene que crear una lista con las cosas, o ACOs, que el sistema maneja. Esta lista puede ser
como la siguiente:

Armas
El Anillo
Jamón
Diplomacia
Cerveza

Armas El Anillo Jamón Diplomacia Cerveza


Gandalf Permitir Permitir Permitir
Aragorn Permitir Permitir Permitir Permitir
Bilbo Permitir
Frodo Permitir Permitir
Gollum Permitir
Legolas Permitir Permitir Permitir Permitir
Gimli Permitir Permitir
Pippin Permitir Permitir
Merry Permitir

A simple vista, parece que este tipo de sistema funciona bastante bien. En efecto, las asignaciones garantizan la
seguridad (sólo Frodo puede acceder al anillo) y previenen los accidentes (los Hobbits se mantienen lejos del jamón y

179 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

de las armas). Parece bastante detallado y fácil de leer, ¿verdad?

Sin embargo, una matriz como esta sólo funciona en un sistema pequeño; en un sistema que tenga previsto crecer, o
que tenga muchos recursos (ACOs) y usuarios (AROs), es difícil mantenerla. Ciertamente, ¿te imaginas, en este
ejemplo, cómo se controlaría el acceso a cientos de campamentos de guerra, gestionándolos por unidad? Otro
inconveniente de las matrices es que no permiten formar grupos lógicos de usuarios ni aplicar cambios de permiso
en cascada a estos grupos. En otras palabras, estaría muy bien que, una vez terminada la batalla, los hobbits
pudieran acceder a la cerveza y al jamón; en otras palabras, otorgar individualmente permisos a hobbits es tedioso y
propenso a errores, mientras que aplicarles un cambio en cascada es mucho más fácil.

ACL se suele implementar en una estructura de árbol, y, generalmente, existe un árbol de AROs y un árbol de ACOs.
Organizando los objetos así, los permisos se gestionan de forma granular y se mantiene una visión general; en
consecuencia, siendo el sabio líder que es, Gandalf decide utilizar ACL en su sistema y organiza los objetos de la
siguiente manera:

Comunidad del Anillo™


Guerreros
Aragorn
Legolas
Gimli
MAgos
Gandalf
Hobbits
Frodo
Bilbo
Merry
Pippin
Visitantes
Gollum

Utilizar una estructura de árbol en los AROs permite a Gandalf definir permisos que se aplican a un grupo de
usuarios, de una sola vez. Por lo tanto, Gandalf añade ahora estos permisos a los grupos:

Comunidad del Anillo


(Denegar: todo)
Guerreros
(Permitir: Armas, Cerveza, Raciones, Jamón)
Aragorn
Legolas
Gimli
Magos
(Permitir: Jamón, Diplomacia, Cerveza)
Gandalf
Hobbits
(Permitir: Cerveza)
Frodo
Bilbo
Merry
Pippin
Visitantes
(Permitir: Jamón)
Gollum

Para ver si Pippin tiene acceso a la cerveza, lo primero que tenemos que hacer es obtener su camino en el árbol:
Comunidad del Anillo->Hobbits->Pippin. A continuación, hay que ver los permisos que residen en cada uno de esos
puntos, y, finalmente, se utiliza el más específico relacionado con Pippin y la Cerveza.

Nodo ARO Información de Permisos Resultado


Comunidad del Anillo Denegar todo Acceso a la Cerveza denegado.
Hobbits Permitir 'Cerveza' Acceso a la Cerveza permitido!
Pippin -- Todavía se le permite la Cerveza!

Como el nodo de 'Pippin' del árbol ACL no deniega específicamente el acceso al ACO 'Cerveza', el resultado final es
que se permite el acceso a ese ACO.

Además, el árbol permite realizar ajustes más finos para tener un control más granular y no pierda la capacidad de

180 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

realizar cambios importantes en los grupos de AROs:

Comunidad del Anillo


(Denegar: todo)
Guerreros
(Permitir: Armas, Cerveza, Raciones, Jamón)
Aragorn
(Permitir: Diplomacia)
Legolas
Gimli
MAgos
(Permitir: Jamón, Diplomacia, Cerveza)
Gandalf
Hobbits
(Permitir: Cerveza)
Frodo
(Permitir: Anillo)
Bilbo
Merry
(Denegar: Cerveza)
Pippin
(Permitir: Diplomacia)
Visitantes
(Permitir: Jamón)
Gollum

Esta aproximación permite realizar cambios de permisos globales y, al mismo tiempo, ajustes granulares. Por lo tanto,
podemos decir que, a excepción de Merry, todos los hobbits tienen acceso a la cerveza. De nuevo, para saber si
Merry tiene acceso a la Cerveza, primero debemos encontrar su camino en el árbol, Comunidad del
Anillo->Hobbits->Merry, bajar, y analizar los premisos relacionados con la Cerveza:

Nodo ARO Información de Permisos Resultado


Comunidad del Anillo Denegar todo Acceso a la Cerveza denegado.
Hobbits Permitir 'Cerveza' Acceso a la Cerveza permitido!
Merry Denegar 'Cerveza' Cerveza denegada.

5.1.2 (#Definiendo-Permisos-ACL-basado-en-INI-1244) Definiendo Permisos: ACL basado en INI

La primer implementación de ACL en Cake fue basada en archivos INI almacenados en el directorio de instalación de
Cake. Si bien es útil y estable, recomendamos que utilices la solución de ACL apoyada en la base de datos, sobre todo
por la posibilidad de crear nuevos ACOs y AROs dentro de la aplicación. La implementación con archivos INI fue
pensada para ser utilizada en aplicaciones simples, especialmente en aquellas que por alguna razón podrían no
utilizar una base de datos.

Por defecto, CakePHP utiliza el sistema de ACL apoyado en la base de datos. Para habilitar el uso de ACL con archivos
INI, tiene que decirle a CakePHP qué sistema vas a usar editando las siguientes líneas en app/config/core.php

Plain Text View (#)


1. //Cambiar éstas líneas:
2. Configure::write('Acl.classname', 'DbAcl');
3. Configure::write('Acl.database', 'default');
4. //Para que se vean como éstas:
5. Configure::write('Acl.classname', 'IniAcl');
6. //Configure::write('Acl.database', 'default');

Los permisos ARO/ACO son especificados en /app/config/acl.ini.php. Básicamente los AROs se deben especificar en
la sección del INI que tiene tres propiedades: grupos, permitir y denegar.

grupos: nombres de los grupos de AROs a los que pertenece este ARO.
permitir: nombres de los ACOs a los que tiene acceso este ARO.
denegar: nombres de los ACOs a los que este ARO no tiene acceso.

Los ACOs se definen en la sección del INI que sólo incluye las propiedades permitir y denegar.

Como ejemplo, veamos cómo se vería la estructura de AROs de la Comunidad del Anillo en la sintaxis del INI:

181 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

;-------------------------------------
; AROs
;-------------------------------------
[aragorn]
grupos = guerreros
permitir = diplomacia

[legolas]
grupos = guerreros

[gimli]
grupos = guerreros

[gandalf]
grupos = magos

[frodo]
grupos = hobbits
permitir = ring

[bilbo]
grupos = hobbits

[merry]
grupos = hobbits
deny = cerveza

[pippin]
grupos = hobbits

[gollum]
grupos = visitantes

;-------------------------------------
; ARO Groups
;-------------------------------------
[guerreros]
permitir = armas, cerveza, jamón

[magos]
permitir = jamón, diplomacia, cerveza

[hobbits]
permitir = cerveza

[visitantes]
permitir = jamón

Ahora que ya has definido los permisos, puede saltar a la sección de verificación de permisos (/es/view
/471/checking-permissions-the-acl-c) utilizando el componente ACL.

5.1.3 (#Definiendo-Permisos-ACL-en-la-base-de-datos-1245) Definiendo Permisos: ACL en la base de datos

Ahora que ya hemos cubierto los permisos de ACL basados en archivos INI, veamos los permisos (más comúnmente
utilizados) basados en base de datos.

5.1.3.1 (#Comenzando-1246) Comenzando

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1246)


Comparar con el texto original (/es/compare/1246/Comenzando)

182 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Mas info sobre traduciones (/es/view/818)

La implementación de ACL por defecto está basada en la base de datos. Ésta consiste en un conjunto de modelos y
una aplicación de consola que viene con la instalación de Cake. Los modelos son usados por Cake para interactuar
con la base de datos para poder almacenar y recuperar los nodos en forma de árbol. La aplicación de consola se
utiliza para inicializar la base de datos e interacturar con los árboles de ACOs y AROs

Para comenzar, lo primero que deber asegurarte es que /app/config/database.php exista y esté correctamente
configurado. Referirse a la sección 4.1 para más información acerca de la configuración de la base de datos.

Una vez que hayas hecho esto, tienes que utilizar la consola de CakePHP para crear las tablas de ACL:

$ cake schema run create DbAcl

Ejecutando este comando recreará las tablas necesarias para almacenar los árbols de ACOs y AROs (si las tablas ya
existían, este comando las elimina y las vuelve a crear). La salida de la consola debería verse algo así:

---------------------------------------------------------------
Cake Schema Shell
---------------------------------------------------------------

The following tables will be dropped.


acos
aros
aros_acos

Are you sure you want to drop the tables? (y/n)


[n] > y
Dropping tables.
acos updated.
aros updated.
aros_acos updated.

The following tables will be created.


acos
aros
aros_acos

Are you sure you want to create the tables? (y/n)


[y] > y
Creating tables.
acos updated.
aros updated.
aros_acos updated.
End create.

Ésto reemplaza al viejo comando "initdb", el cuál ya es obsoleto.

También puedes utilizar el archivo SQL que se encuentra en app/config/sql/db_acl.sql, pero está lejos de ser tan
divertido.

Cuando finalices, deberías tener tres nuevas tablas en tu sistema: acos, aros, and aros_acos (la tabla de la relación n a
n donde se definen los permisos entre los dos árboles).

Si eres curioso en saber cómo Cake almacena la información de los árboles en esas tablas, debes leer acerca del
recorrido de árboles en bases de datos (en inglés modified database tree traversal ). El componente ACL utiliza el
Comportamiento de Árbol (/es/view/91/tree-behavior) para gestionar la herencia dentro del árbol. Las clases
pertenecientes a los modelos de ACL están contenidas en un único archivo db_acl.php (http://api.cakephp.org
/1.2/cake_2libs_2model_2db__acl_8php-source.html) .

Ahora que ya hemos configurado todo, creemos algunos árboles de AROs y ACOs

5.1.3.2 (#Creando-Access-Request-Objects-AROs-y-Access-Contr-1247) Creando Access Request Objects (AROs) y Access Control Objects (ACOs)

Al crear nuevos objetos ACL (ACOs y AROs), hay dos formas de nombrar y acceder a los nodos. El primer método

183 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

consiste en realizar un enlace entre el objeto ACL directamente con el registro de la base de datos, especificando el
nombre del modelo y el valor de la clave externa. El segundo método puede usarse cuando un objeto no tiene
relación con un registro en la base de datos; puedes proveer un alias para este tipo de objetos.

En general, cuando estás creando un grupo o un nivel más alto de objetos, deber usar un alias. Si estás gestionando
el acceso a un registro específico de la base de datos, debes usar el método de modelo/clave externa.

Para crear nuevos objetos ACL debes utilizar los modelos de ACL provistos por CakePHP, en los cuales existen
algunos campos que necesitas conocer para almacenar la información: model, foreign_key, alias, y parent_id.

Los campos model y foreign_key de un objeto ACL te permiten enlazar directamente el objeto con el correspondiente
registro de la base de datos (si existe alguno). Por ejemplo, muchos AROs tendrán su correspondencia con registros
de Usuarios en la base de datos. Estableciendo el campo foreign_key del ARO con el ID del Usuario te permitirá
enlazar la información del ARO y del Usuario con una simple llamada find() del modelo del Usuario si las relaciones
fueron configuradas correctamente. En cambio, si lo que quieres es gestionar las operaciones de editar en un post
específico en un blog o un listado de recetas, podrías elegir enlazar un ACO a ese registro en particular.

El campo alias de un objeto ACL es sólo una etiqueta que puede ser fácilmente interpretada por un ser humano, y se
utiliza para identificar un objeto ACL que no tiene una correlación directa con algún registro de un modelo. Los alias
son muy útiles para nombrar grupos de usuarios en colecciones de ACOs.

El campo parent_id de un objeto ACL te permite completar la estructura del árbol. Debes proveer el ID del nodo padre
en el árbol para crear un nuevo hijo.

Antes de crear nuevos objetos ACL, necesitamos cargar las respectivas clases. La forma más fácil de hacer esto es
incluir el componente ACL en el array $components de tu controlador:

Plain Text View (#)


1. var $components = array('Acl');

Una vez que haz hecho esto, veamos ejemplos de cómo sería la creación de algunos objetos. El código siguiente
puede ser colocado en la acción de algún controlador:

Mientras los ejemplos se enfocan en la creación de AROs, las mismas técnicas pueden ser usadas para crear el árbol
de ACOs.

Siguiendo con la configuración de la Comunidad, creemos primero nuestro grupo de ACOs. Debido a que nuestros
grupos no tendrán registros específicos asociados a ellos, usaremos alias en la creación de los objetos ACL. Lo que
estamos haciendo aquí es desde la perspectiva de la acción de un controlador, pero puede realizarse en otro lugar.
Lo que vamos a usar es una aproximación algo artificial, pero deberías sentirte cómodo usando estas técnicas para
crear AROs y ACOs al vuelo.

Esto no debería ser algo drásticamente nuevo, sólo estamos utilizando los modelos para guardar los datos como
siempre hacemos:

Plain Text View (#)

184 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. function algunaAccion()
2. {
3. $aro = new Aro();
4.
5. //Aquí tenemos la información de nuestros grupos en un array sobre el cual iteraremos luego
6. $groups = array(
7. 0 => array(
8. 'alias' => 'guerreros'
9. ),
10. 1 => array(
11. 'alias' => 'magos'
12. ),
13. 2 => array(
14. 'alias' => 'hobbits'
15. ),
16. 3 => array(
17. 'alias' => 'visitantes'
18. ),
19. );
20.
21. //Iterar para crear los ARO de los grupos
22. foreach($groups as $data)
23. {
24. //Recuerda llamar a create() cuando estés guardando información dentro de bucles...
25. $aro->create();
26.
27. //Guardar datos
28. $aro->save($data);
29. }
30. //Aquí va otra lógica de la acción...
31. }

Una vez creados, podemos utilizar la aplicación de consola de ACL para verificar la estructura de los árboles.

$ cake acl view aro

Aro tree:
---------------------------------------------------------------
[1]guerreros

[2]magos

[3]hobbits

[4]visitantes

---------------------------------------------------------------

Supongo que no se parece mucho a un árbol en este punto, pero al menos pudimos verificar que tenemos los cuatro
nodos de primer nivel. Agreguemos algunos hijos a esos nodos agregando nuestros AROs específicos de cada
usuario dentro de esos grupos. Todo buen ciudadano de la Tierra Media tiene una cuenta en nuestro nuevo sistema,
entonces nosotros referiremos esos AROs a los registros dentro del modelo específico en la base de datos.

Cuando agregue hijos al árbol, asegúrese de utilizar el ID del nodo ACL y no un valor de foreign_key.

Plain Text View (#)

185 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. function algunaAccion()
2. {
3. $aro = new Aro();
4.
5. //Aquí tenemos nuestros registros de usuario, listos para ser relacionados con nuevos registros ARO
6. //Estos datos pueden venir de un modelo, pero en este caso estamos usando arrays estáticos
7. //con propósitos de demostración.
8.
9. $users = array(
10. 0 => array(
11. 'alias' => 'Aragorn',
12. 'parent_id' => 1,
13. 'model' => 'User',
14. 'foreign_key' => 2356,
15. ),
16. 1 => array(
17. 'alias' => 'Legolas',
18. 'parent_id' => 1,
19. 'model' => 'User',
20. 'foreign_key' => 6342,
21. ),
22. 2 => array(
23. 'alias' => 'Gimli',
24. 'parent_id' => 1,
25. 'model' => 'User',
26. 'foreign_key' => 1564,
27. ),
28. 3 => array(
29. 'alias' => 'Gandalf',
30. 'parent_id' => 2,
31. 'model' => 'User',
32. 'foreign_key' => 7419,
33. ),
34. 4 => array(
35. 'alias' => 'Frodo',
36. 'parent_id' => 3,
37. 'model' => 'User',
38. 'foreign_key' => 7451,
39. ),
40. 5 => array(
41. 'alias' => 'Bilbo',
42. 'parent_id' => 3,
43. 'model' => 'User',
44. 'foreign_key' => 5126,
45. ),
46. 6 => array(
47. 'alias' => 'Merry',
48. 'parent_id' => 3,
49. 'model' => 'User',
50. 'foreign_key' => 5144,
51. ),
52. 7 => array(
53. 'alias' => 'Pippin',
54. 'parent_id' => 3,
55. 'model' => 'User',
56. 'foreign_key' => 1211,
57. ),
58. 8 => array(
59. 'alias' => 'Gollum',
60. 'parent_id' => 4,
61. 'model' => 'User',

186 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Típicamente no usarás el alias y los campos model/foreing_key al mismo tiempo, pero aquí estamos utilizando los
dos para que la estructura sea más fácil de leer y para propósitos de demostración.

La salida de la aplicación de consola ahora debería ser un poco más interesante. Veamos:

$ cake acl view aro

Aro tree:
---------------------------------------------------------------
[1]guerreros

[5]Aragorn

[6]Legolas

[7]Gimli

[2]magos

[8]Gandalf

[3]hobbits

[9]Frodo

[10]Bilbo

[11]Merry

[12]Pippin

[4]visitantes

[13]Gollum

---------------------------------------------------------------

Ahora que ya tenemos nuestro árbol de AROs configurado apropiadamente, discutamos una posible aproximación
para la estructura del árbol de ACOs. Mientras que podemos estructurar más de una representación abstracta de
nuestros ACOs, a menudo es más práctico modelar un árbol de ACOs después de configurar los controladores y
acciones. Tenemos cindo objetos principales que queremos manejar en este escenario, y la configuración natural
para una aplicación Cake es un grupo de modelos y en segundo lugar, los controladores que los manipulan. Es en
éstos controladores donde queremos controlar el acceso a algunas acciones específicas.

Basándonos en esa idea, vamos a crear un árbol de ACOs que imite una aplicación Cake. Como tenenos cinco ACOs,
vamos a crear un árbol de ACOs que se verá algo así:

Armas
Anillo
Jamón
EsfuerzosDiplomáticos
Cervezas

Una buena característica de la implementación de ACL en Cake, es que cada ACO automáticamente contiene cuatro
propiedades relacionadas con las acciones CRUD (en inglés create, read, update, and delete). Puedes crear nodos
dentro de cada uno de esos ACOs principales, pero usando la gestión de acciones que provee Cake abarcarás las
operaciones básicas de CRUD sobre un objeto dado. Teniendo esto en mente hará que tu árbol de ACOs sea más
pequeño y fácil de mantener. Veremos cómo usadas esas propiedades cuando hablemos acerca de cómo asignar
permisos.

Como ya eres un profesional creando AROs, usa las mismas técnicas para crear este árbol de ACOs. Crea esos grupos
de nivel superior usando el modelo básico de Aco

5.1.3.3 (#Asignando-Permisos-1248) Asignando Permisos

187 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Después de crear los ACOs y los AROs, finalmente podremos asignar los permisos entre los dos grupos. Esto se
realiza utilizando el componente ACL de Cake. Sigamos con nuestro ejemplo

En este ejemplo trabajaremos en el contexto de una acción de un controlador. Tenemos que hacer esto debido a que
los permisos son manejados por el componente ACL

Plain Text View (#)


1. class AlgunController extends AppController
2. {
3. // Podrías colocar esta declaración en AppController
4. // para que sea heredada por todos los controladores
5. var $components = array('Acl');
6. }

Asignemos algunos permisos básicos utilizando el componente ACL in la acción dentro de este controlador

Plain Text View (#)


1. function index()
2. {
3. //Permitirle a los guerreros acceso total a las armas
4. //Ambos ejemplos usan la sintaxis de alias vista anteriormente
5. $this->Acl->allow('guerreros', 'Armas');
6.
7. //Aunque el Rey puede no querer que todo el mundo tenga
8. //acceso irrestricto
9. $this->Acl->deny('guerreros/Legolas', 'Armas', 'delete');
10. $this->Acl->deny('guerreros/Gimli', 'Armas', 'delete');
11.
12. die(print_r('hecho', 1));
13. }

En la primer llamada que hicimos al componente ACL permitimos que cualquier usuario dentro del grupo ARO
denominado "guerreros" tenga acceso irrestricto a cualquier arma dentro del grupo ACO denominado "Armas". Esto lo
realizamos referenciando a ambos grupos por sus alias.

¿Has notado el uso del tercer parámetro? Ahí es donde utilizamos esas acciones pre-contruidos para todos los ACOs
dentro de Cake. La opción por defecto para ese parámetro son create, read, update, y delete, pero puedes agregar
una columna en la tabla aros_acos (comenzando con el prefijo "_", por ejemplo _admin) y utilizarla junto con las otras
acciones.

La segunda llamada es un intento de realizar una asignación de permisos mucho más granular. Nosotros queremos
que Aragorn tenga acceso irrestricto, pero no queremos que los otros guerreros pertenecientes al grupo tengan la
habilidad de borrar registros de Armas. En el ejemplo utilizamos la sintaxis de alias, pero se puede usar también de la
forma model/foreign_key. El ejemplo anterior es equivalente a este:

Plain Text View (#)


1. // 6342 = Legolas
2. // 1564 = Gimli
3. $this->Acl->deny(array('model' => 'User', 'foreign_key' => 6342), 'Armas', 'delete');
4. $this->Acl->deny(array('model' => 'User', 'foreign_key' => 1564), 'Armas', 'delete');

Para acceder a un nodo utilizando la sintaxis de alias, debemos usar una cadena de caracteres delimitada por barras
('/usuarios/empleados/desarrolladores'). Para acceder a un nodo utilizando la sintaxis model/foreign_key debes
utilizar un arreglo con dos parámetros: array('model' => 'Usuario', 'foreign_key' => 8282).

La próxima sección nos ayudará a validar nuestra configuración utilizando el componente ACL para verificar los
permisos que acabamos de asignar.

5.1.3.4 (#Verificando-Permisos-El-Componente-ACL-1249) Verificando Permisos: El Componente ACL

188 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Vamos a utilizar el componente ACL para asegurarnos que ni los enanos ni los elfos pueden quitas armas de la
armería. En este punto, deberíamos ser capaces de utilizar AclComponent para verificar los permisos entre los ACOs y
AROs que hemos creado. La sintaxis básica para realizar una verificación de permisos es:

Plain Text View (#)


1. $this->Acl->check( $aro, $aco, $action = '*');

Vamos a intentarlo dentro de una acción en un controlador:

Plain Text View (#)


1. function index()
2. {
3. //Todos estos devuelven true
4. $this->Acl->check('guerreros/Aragorn', 'Armas');
5. $this->Acl->check('guerreros/Aragorn', 'Armas', 'create');
6. $this->Acl->check('guerreros/Aragorn', 'Armas', 'read');
7. $this->Acl->check('guerreros/Aragorn', 'Armas', 'update');
8. $this->Acl->check('guerreros/Aragorn', 'Armas', 'delete');
9.
10. //Recuerda que también podemos utilizar la sintaxis model/foreign_key
11. //para los AROs de nuestro usuario
12. $this->Acl->check(array('model' => 'User', 'foreign_key' => 2356), 'Armas');
13.
14. //Estos también deben devolver true:
15. $result = $this->Acl->check('guerreros/Legolas', 'Armas', 'create');
16. $result = $this->Acl->check('guerreros/Gimli', 'Armas', 'read');
17.
18. //Pero estos devuelven false:
19. $result = $this->Acl->check('guerreros/Legolas', 'Armas','delete');
20. $result = $this->Acl->check('guerreros/Gimli', 'Armas', 'delete');
21. }

El uso que le dimos aquí es solamente con propósitos de demostración, pero esperamos que puedas ver cómo la
verificación de permisos de esta forma puede ser utilizada para decidir cuándo permitir o no determinada acción,
mostrar un mensaje de error o redirigir al usuario a la pantalla de autenticación.

5.2 (#Autenticación-1250) Autenticación

Un sistema de autenticación de usuarios es una parte común de muchas aplicaciones web. En CakePHP hay muchas
formas para autenticar usuarios, cada una de estas provee diferentes opciones. La esencia de componente de
autenticación es comprobar si el usuario tiene una cuenta con el sitio. De ser así, el componente da al usuario acceso
completo a sitio.

Este componente se puede combinar con el componente ACL (access control lists) para crear niveles más complejos
de acceso al sitio. El componente ACL, por ejemplo, podría permitir acceso a un usuario a áreas publicas del sitio,
mientras que concede a otro usuario acceso a porciones administrativas protegidas del sitio.

El AuthComponent de CakePHP se puede usar para crear un sistema fácil y rápidamente. Veamos como construir un
sistema de autenticación simple.

Al igual que todos los componentes, se utiliza mediante la incorporación de 'Auth' a la lista de componentes en el
controlador:

Plain Text View (#)


1. class FooController extends AppController {
2. var $components = array('Auth');

O añadelo al AppController si todos tus controladores lo van a usar:

Plain Text View (#)


1. class AppController extends Controller {
2. var $components = array('Auth');

189 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Ahora, hay unas pocas convenciones en las que pensar cuando se usa el AuthComponent. Por defecto, el
AuthComponent espera que se tenga una tabla llamada 'users' con campos llamados 'username' y 'password'. En
algunos casos, las bases de datos no permiten usar 'password' como nombre de columna, mas tarde, veremos como
cambiar el nombre por defecto de los campos para trabajar con nuestro propio entorno.

Vamos a crear nuestra tabla 'users' usando el siguiente SQL:

Plain Text View (#)


1. CREATE TABLE users (
2. id integer auto_increment,
3. username char(50),
4. password char(50),
5. PRIMARY KEY (id)
6. );

Algo a tener en cuenta a la hora de crear una tabla para almacenar todos los datos de autenticación del usuario es
que el AuthComponent espera el valor del password almacenado esté encriptado en vez de estar almacenado en texto
plano. Asegúrese de que el campo que utilizará para almacenar la contraseña sea suficientemente largo para
almacenar el hash (40 caracteres para SHA1, por ejemplo).

Para la configuración más básica usted solo tiene que crear dos acciones en el controlador:

Plain Text View (#)


1. class UsersController extends AppController {
2. var $name = 'Users';
3. var $components = array('Auth'); //No es necesario si se declaro en el app controller
4. /**
5. * El AuthComponent proporciona la funcionalidad necesaria
6. * para el acceso (login), por lo que se puede dejar esta función en blanco.
7. */
8. function login() {
9. }
10. function logout() {
11. $this->redirect($this->Auth->logout());
12. }
13. }

Si bien usted puede dejar la función login() en blanco, necesitara crear la vista para la acción login (guardela en
app/views/users/login.ctp). Esta es la única vista del UsersController que es necesario crear, sin embargo. El
siguiente ejemplo asume que ya está familiarizado con el uso del Form helper:

Plain Text View (#)


1. <?php
2. echo $session->flash('auth');
3. echo $form->create('User', array('action' => 'login'));
4. echo $form->input('username');
5. echo $form->input('password');
6. echo $form->end('Login');
7. ?>

Esta vista crea un simple formulario de login en el cual introducir el nombre de usuario y la clave. Una vez enviado
este formulario, el AuthComponent se encargará del resto por usted. El session flash message mostrara cualquier
información generada por el AuthComponent.

Lo creas o no, ya está! Esta es la manera de implementar una increiblemente simple, base de datos de autenticación
usando el componente Auth. Sin embargo, hay mucho más que podemos hacer. Echemos un vistazo a algunos usos
más avanzados del componente.

5.2.1 (#Configurando-las-variables-del-componente-Auth-1251) Configurando las variables del componente Auth

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1251)

190 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Comparar con el texto original (/es/compare/1251/Configurando-las-variables-del-componente-Auth)

Mas info sobre traduciones (/es/view/818)

Para cambiar las opciones predeterminadas de AuthComponent tienes que crear el método beforeFilter() en el
controlador, llamar a varios métodos predefinidos, y configurar algunas variables del componente.

Para cambiar el nombre del campo que se utiliza para guardar las contraseñas, 'password', a 'secretword', por
ejemplo, haríamos lo siguiente:

Plain Text View (#)


1. class UsersController extends AppController {
2. var $components = array('Auth');
3. function beforeFilter() {
4. $this->Auth->fields = array(
5. 'username' => 'username',
6. 'password' => 'secretword'
7. );
8. }
9. }

En este caso, ¡no olvidemos que también hay que cambiar en la vista el nombre del campo!

Las variables del componente Auth también se utilizan para que los usuarios que no han entrado en el sistema
puedan acceder a determinados métodos.

Por ejemplo, si queremos que todos los usuarios puedan acceder solamente a los métodos index y view, hacemos lo
siguiente:

Plain Text View (#)


1. function beforeFilter() {
2. $this->Auth->allow('index','view');
3. }

5.2.2 (#Mostrando-Mensajes-de-Error-en-la-Autentificación-1252) Mostrando Mensajes de Error en la Autentificación

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1252)


Comparar con el texto original (/es/compare/1252/Mostrando-Mensajes-de-Error-en-la-Autentificación)

Mas info sobre traduciones (/es/view/818)

Con el objetivo de desplegar los mensajes de error que la Autentificacion muestra, necesitas añadir el siguiente
codigo en tu vista. En este caso, el mensaje aparecerá debajo de los mensajes flash regulares:

Plain Text View (#)


1. <?php
2. if ($session->check('Message.flash')) {
3. $session->flash();
4. }
5. if ($session->check('Message.auth')) {
6. $session->flash('auth');
7. }
8. ?>

5.2.3 (#Problemas-comunes-con-Auth-1253) Problemas comunes con Auth

A veces puede ser difícil diagnosticar problemas cuando encuentras comportamientos inesperados. Recordar estos
puntos te puede ayudar.

Password hashing

Al enviar información a través de un formulario, el componente Auth encripta automáticamente el contenido del

191 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

campo contraseña, si también hay datos en el campo nombre de usuario. Así que si estás intentando crear algún tipo
de página de registro de nuevo usuario, asegúrate de que el usuario rellene un campo "confirmar contraseña" que
puedas comparar. Aquí va un código de ejemplo:

Plain Text View (#)


1. <?php
2. function register() {
3. if ($this->data) {
4. if ($this->data['User']['password'] == $this->Auth->password($this->data['User']['password_confi
5. $this->User->create();
6. $this->User->save($this->data);
7. }
8. }
9. }
10. ?>

5.2.4 (#Cambiar-la-Función-Hash-1254) Cambiar la Función Hash

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1254)


Comparar con el texto original (/es/compare/1254/Cambiar-la-Función-Hash)

Mas info sobre traduciones (/es/view/818)

AuthComponent usa la clase Security para encriptar una contraseña. La clase Security usa el esquema SHA1 por
defecto. Para cambiar a otra función hash usada por el componente Auth, usa el método setHash pasándole md5, sha1
o sha256 como primer y único parámetro.

Plain Text View (#)


1. Security::setHash('md5'); // o sha1 o sha256.

La clase Security usa el valor de inicialización (salt value, que se encuentras en /app/config/core.php) para el hashing
de la contraseña.

Si quieres usar una lógica diferente para el hashing de la contraseña más allá de md5/sha1 con el valor salt de la
aplicacion, necesitará reescribir el mecanismo estandar hashPassword - podrías necesitar hacer esto si, por ejemplo,
tuvieses una base de datos existente que anteriormente usaba un esquema de hashing sin un valor de salt. Para hacer
esto, crea el metodo hashPasswords (/es/view/384/hashPasswords) en la clase que quieras que se haga a cargo del
hashing de las contraseñas (normalmente el modelo User ) y establece el atributo authenticate (/es/view
/739/authenticate) de Auth al objeto contra el que se está autenticando (normalmente es User) de este modo:

Plain Text View (#)


1. function beforeFilter() {
2. $this->Auth->authenticate = ClassRegistry::init('User');
3. ...
4. parent::beforeFilter();
5. }

Con el código anterior, el método hashPasswords() del modelo User será llamado cada vez que Cake llame a
AuthComponent::hashPasswords(). Aquí está un ejemplo del método hashPasswords, apropiado si ya tienes una tabla de
usuarios repleta de contraseñas de hash 'plain md5':

Plain Text View (#)

192 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. class User extends AppModel {


2. function hasPasswords($data) {
3. if (isset($data['User']['password'])) {
4. $data['User']['password'] = md5($data['User']['password']);
5. return $data;
6. }
7. return $data;
8. }
9. }

5.2.5 (#Métodos-de-AuthComponent-1255) Métodos de AuthComponent

5.2.5.1 (#action-1256) action

action (string $action = ':controller/:action')

Si estas usando ACOs (http://book.cakephp.org/es/view/465/Understanding-How-ACL-Works) como parte de tu estructura


ACL (http://book.cakephp.org/es/view/465/Understanding-How-ACL-Works) , puedes obtener la ruta al nodo del ACO
(http://book.cakephp.org/es/view/465/Understanding-How-ACL-Works) que está enlazado a un par controlador/acción
particular.

Plain Text View (#)


1. $acoNode = $this->Auth->action('users/delete');

Si no le pasas valores, utilizará el par controlador/acción actual (el que se está ejecutando).

5.2.5.2 (#allow-1257) allow

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1257)


Comparar con el texto original (/es/compare/1257/allow)

Mas info sobre traduciones (/es/view/818)

Si tienes acciones en tu controlador que no necesitas que se autentiquen contra ellas (como una acción de registro de
usuarios), puedes agregar métodos que debe ignorar AuthComponent. El siguiente ejemplo muestra como permitir
una acción llamada 'register'.

Plain Text View (#)


1. function beforeFilter() {
2. ...
3. $this->Auth->allow('register');
4. }

Si deseas permitir que múltiples acciones no usen autenticación, las pasas como parámetros al método allow():

Plain Text View (#)


1. function beforeFilter() {
2. ...
3. $this->Auth->allow('foo', 'bar', 'baz');
4. }

Atajo: también puedes permitir todas las acciones en un controlador usando '*'.

Plain Text View (#)


1. function beforeFilter() {
2. ...
3. $this->Auth->allow('*');
4. }

Si estás usando requestAction en tu layout o en tus elementos, deberías permitir esas acciones para poder abrir la

193 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

página de login correctamente.

El componente auth supone que tus nombres de acciones siguen las convenciones (/es/view/559/URL-
Considerations-for-Controller-Names) y usan guiones bajos.

5.2.5.3 (#deny-1258) deny

Habrá algunas veces que quieras eliminar acciones de la lista de acciones permitidas (añadidas usando
$this->Auth->allow()). He aquí un ejemplo:

Plain Text View (#)


1. function beforeFilter() {
2. $this->Auth->authorize = 'controller';
3. $this->Auth->allow('delete');
4. }
5. function isAuthorized() {
6. if ($this->Auth->user('role') != 'admin') {
7. $this->Auth->deny('delete');
8. }
9. ...
10. }

5.2.5.4 (#hashPasswords-1259) hashPasswords

hashPasswords ($data)

Este método verifica si $data contiene los campos nombre de usuario(username) y contraseña(password ), tal y como
está especificado en la variable $fields indexados por el nombre del modelo especificado en $userModel. Si el array
$data contiene el nombre de usuario y la contraseña, realiza el hash del campo contraseña en el array y devuelve el
array $data con el mismo formato. Esta función debe ser usada antes de realizar llamadas de inserción o actualización
de los datos del usuario cuando afecta al campo contraseña.

Plain Text View (#)


1. $data['User']['username'] = 'me@me.com';
2. $data['User']['password'] = 'changeme';
3. $hashedPasswords = $this->Auth->hashPasswords($data);
4. pr($hashedPasswords);
5. /* devuelve:
6. Array
7. (
8. [User] => Array
9. (
10. [username] => me@me.com
11. [password] => 8ed3b7e8ced419a679a7df93eff22fae
12. )
13. )
14. */

En el campo $hashedPasswords['User']['password'] ahora debería ser realizado el 'hash' usando el método password
del componente.

Si tu controlador usa el compoente Auth y los datos recibidos por POST contienen los campos explicados arriba,
automáticamente realizará el hash al campo contraseña usando esta función.

5.2.5.5 (#mapActions-1260) mapActions

Si estás utilizando Acl en modo CRUD, tal vez desees asignar ciertas acciones no predeterminadas a cada parte de
CRUD.

Plain Text View (#)

194 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. $this->Auth->mapActions(
2. array(
3. 'create' => array('ciertaAccion'),
4. 'read' => array('ciertaAccion', 'ciertaAccion2'),
5. 'update' => array('ciertaAccion'),
6. 'delete' => array('ciertaAccion')
7. )
8. );

5.2.5.6 (#login-1261) login

login($data = null)

Si estás haciendo algún tipo de login basada en Ajax, puedes usar este método para identificar manualmente a
alguien en el sistema. Si no pasas ningún valor para $data, automáticamente usará los datos enviados mediante POST
al controlador.

Por ejemplo, en una aplicación tal vez desees asignar a un usuario una contraseña y autoidentificarlo en el sistema
tras el registro. En un ejemplo muy simplificado:

Vista:

Plain Text View (#)


1. echo $form->create('User',array('action'=>'registrar'));
2. echo $form->input('username');
3. echo $form->end('Regístrame');

Controlador:

Plain Text View (#)


1. function registrar() {
2. if(!empty($this->data)) {
3. $this->User->create();
4. $contrasena_asignada = "ConTr4senna";
5. $this->data['User']['password'] = $contrasena_asignada;
6. if($this->User->save($this->data)) {
7. // enviar el email de registro conteniendo la contraseña al nuevo usuario
8. $this->Auth->login($this->data);
9. $this->redirect("inicio");
10. }
11. }

Una cosa a remarcar es que has de redirigir manualmente al usuario tras el login ya que no se invoca
loginRedirect().

$this->Auth->login($data) devuelve 1 tras un login exitoso, 0 en caso de fallo.

5.2.5.7 (#logout-1262) logout

Provee de una manera rápida de 'deautenticar' a alguien y redirigirlo a donde necesite ir. Este método también es útil
si deseas proporcionar un enlace 'Cerrar sesión' dentro de una sección para usuarios registrados de tu aplicación.

Ejemplo:

Plain Text View (#)


1. $this->redirect($this->Auth->logout());

5.2.5.8 (#password-1263) password

password (string $password)

Pásale una cadena de texto, y obtendrás la contraseña 'hasheada'. Esta es una funcionalidad esencial si estás creando

195 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

una pantala de registro de usuario donde los usuarios han de insertar sus contraseñas una segunda vez para
confirmarlas.

Plain Text View (#)


1. if ($this->data['User']['password'] ==
2. $this->Auth->password($this->data['User']['password2'])) {
3. // Las contraseñas concuerdan, continuar procesando
4. ...
5. } else {
6. $this->flash('Las contraseñas introducidas no concuerdan', 'users/registrar');
7. }

El componente Auth automáticamente aplicará el hash al campo contraseña (password ) si también está presente el
campo nombre de usuario (username) en los datos recibidos en la petición.

Cake añade tu cadena contraseña a un valor salt y después realiza el hash . La función de hash utilizada depende de la
seleccionada por la clase utilidad del núcleo Security (sha1 por defecto). Puedes utilizar la función
Security::setHash para cambiar el método para calcular el hash . El valor salt es el indicado en la configuración de tu
aplicación definido en tu core.php.

5.2.5.9 (#user-1264) user

user(string $key = null)

Este método proporciona información sobre el usuario actualmente identificado. La información es tomada de la
sesión. Por ejemplo:

Plain Text View (#)


1. if ($this->Auth->user('rol') == 'admin') {
2. $this->flash('Tienes acceso de administrador');
3. }

También puede ser usado para obtener todos los datos de sesión del usuario así:

Plain Text View (#)


1. $data['User'] = $this->Auth->user();

Si este método devuelve null es que el usuario no se ha identificado (logged in ).

En la vista puedes utilizar el helper Session para obtener la información del usuario actualmente autenticado:

Plain Text View (#)


1. $session->read('Auth.User'); // devuelve el registro completo del usuario
2. $session->read('Auth.User.nombre') //devuelve el valor particular de un campo

La clave de la sesión puede ser diferente dependiendo de qué modelo se ha configurado para ser utilizado por Auth.
P.e., si usas el modelo Cuenta en vez de User, entonces la clave de sesión sería Auth.Cuenta.

5.2.6 (#Atributos-de-AuthComponent-1265) Atributos de AuthComponent

Ahora hay varias variables relacionadas con Auth que también puedes utilizar. Normalmente añades esta
configuración en el método beforeFilter() de tu controlador. Si necesitas aplicar dicha configuración a todo
el sitio, deberías añadirla a beforeFilter() de AppController.

5.2.6.1 (#userModel-1266) userModel

¿No deseas utilizar un modelo User contra el que autenticar? No hay problema. Simplemente cámbialo configurando
este valor con el nombre del modelo que deseas usar.

Plain Text View (#)

196 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <?php
2. $this->Auth->userModel = 'Miembro';
3. ?>

5.2.6.2 (#fields-1267) fields

Sobreescribe los campos de usuario y contraseña por defecto usados para la autenticación.

Plain Text View (#)


1. <?php
2. $this->Auth->fields = array('username' => 'email', 'password' => 'passwd');
3. ?>

5.2.6.3 (#userScope-1268) userScope

Utiliza esto para añadir requisitos adicionales para que la autenticación sea exitosa.

Plain Text View (#)


1. <?php
2. $this->Auth->userScope = array('User.activo' => true);
3. ?>

5.2.6.4 (#loginAction-1269) loginAction

Puedes cambiar el login por defecto de /users/login para que sea cualquier acción a tu elección.

Plain Text View (#)


1. <?php
2. $this->Auth->loginAction = array('admin' => false, 'controller' => 'miembros', 'action' => 'inicio_s
3. ?>

5.2.6.5 (#loginRedirect-1270) loginRedirect

El componente AuthComponent recuerda qué par controlador/acción estabas tratando de ejecutar antes de que
pedirte que te autenticaras, almacenando el valor en Session bajo la clave Auth.redirect. Sin embargo, si este valor
de la sesión no está definido (si vienes de la página de login de un enlace externo, por ejemplo), entonces el usuario
será redirigido a la URL indicada en loginRedirect.

Ejemplo:

Plain Text View (#)


1. <?php
2. $this->Auth->loginRedirect = array('controller' => 'miembros', 'action' => 'inicio');
3. ?>

5.2.6.6 (#logoutRedirect-1271) logoutRedirect

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1271/logoutRedirect) .. Mas info
sobre traduciones (/es/view/818)

You can also specify where you want the user to go after they are logged out, with the default being the login action.

Plain Text View (#)


1. <?php
2. $this->Auth->logoutRedirect = array(Configure::read('Routing.admin') => false, 'controller' => 'memb
3. ?>

5.2.6.7 (#loginError-1272) loginError

197 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Cambia el mensaje de error por defecto que se mostrará, cuando el login no sea exitoso.

Plain Text View (#)


1. <?php
2. $this->Auth->loginError = "No, you fool! That's not the right password!";
3. ?>

5.2.6.8 (#authError-1273) authError

Cambia el mensaje de error por defecto que será mostrado, cuando intenten acceder a un objeto o a una acción a la
que no autorizada.

Plain Text View (#)


1. <?php
2. $this->Auth->authError = "Sorry, you are lacking access.";
3. ?>

5.2.6.9 (#autoRedirect-1274) autoRedirect

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1274/autoRedirect) .. Mas info
sobre traduciones (/es/view/818)

Normally, the AuthComponent will automatically redirect you as soon as it authenticates. Sometimes you want to do
some more checking before you redirect users:

Plain Text View (#)


1. <?php
2. function beforeFilter() {
3. ...
4. $this->Auth->autoRedirect = false;
5. }
6. ...
7. function login() {
8. //-- code inside this function will execute only when autoRedirect was set to false (i.e. in a befor
9. if ($this->Auth->user()) {
10. if (!empty($this->data['User']['remember_me'])) {
11. $cookie = array();
12. $cookie['username'] = $this->data['User']['username'];
13. $cookie['password'] = $this->data['User']['password'];
14. $this->Cookie->write('Auth.User', $cookie, true, '+2 weeks');
15. unset($this->data['User']['remember_me']);
16. }
17. $this->redirect($this->Auth->redirect());
18. }
19. if (empty($this->data)) {
20. $cookie = $this->Cookie->read('Auth.User');
21. if (!is_null($cookie)) {
22. if ($this->Auth->login($cookie)) {
23. // Clear auth message, just in case we use it.
24. $this->Session->delete('Message.auth');
25. $this->redirect($this->Auth->redirect());
26. }
27. }
28. }
29. }
30. ?>

The code in the login function will not execute unless you set $autoRedirect to false in a beforeFilter. The code
present in the login function will only execute after authentication was attempted. This is the best place to determine
whether or not a successful login occurred by the AuthComponent (should you desire to log the last successful login

198 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

timestamp, etc.).

With autoRedirect set to false, you can also inject additional code such as keeping track of the last successful login
timestamp

Plain Text View (#)


1. <?php
2. function login() {
3. if( !(empty($this->data)) && $this->Auth->user() ){
4. $this->User->id = $this->Auth->user('id');
5. $this->User->saveField('last_login', date('Y-m-d H:i:s') );
6. $this->redirect($this->Auth->redirect());
7. }
8. }
9. ?>

5.2.6.10 (#authorize-1275) authorize

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1275/authorize) .. Mas info
sobre traduciones (/es/view/818)

Normally, the AuthComponent will attempt to verify that the login credentials you've entered are accurate by
comparing them to what's been stored in your user model. However, there are times where you might want to do some
additional work in determining proper credentials. By setting this variable to one of several different values, you can
do different things. Here are some of the more common ones you might want to use.

Plain Text View (#)


1. <?php
2. $this->Auth->authorize = 'controller';
3. ?>

When authorize is set to 'controller', you'll need to add a method called isAuthorized() to your controller. This method
allows you to do some more authentication checks and then return either true or false.

Plain Text View (#)


1. <?php
2. function isAuthorized() {
3. if ($this->action == 'delete') {
4. if ($this->Auth->user('role') == 'admin') {
5. return true;
6. } else {
7. return false;
8. }
9. }
10. return true;
11. }
12. ?>

Remember that this method will be checked after you have already passed the basic authentication check against the
user model.

Plain Text View (#)


1. <?php
2. $this->Auth->authorize = array('model'=>'User');
3. ?>

Don't want to add anything to your controller and might be using ACO's? You can get the AuthComponent to call a
method in your user model called isAuthorized() to do the same sort of thing:

Plain Text View (#)

199 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <?php
2. class User extends AppModel {
3. ...
4. function isAuthorized($user, $controller, $action) {
5. switch ($action) {
6. case 'default':
7. return false;
8. break;
9. case 'delete':
10. if ($user['User']['role'] == 'admin') {
11. return true;
12. }
13. break;
14. }
15. }
16. }
17. ?>

Lastly, you can use authorize with actions such as below

Plain Text View (#)


1. <?php
2. $this->Auth->authorize = 'actions';
3. ?>

By using actions, Auth will make use of ACL and check with AclComponent::check(). An isAuthorized function is not
needed.

Plain Text View (#)


1. <?php
2. $this->Auth->authorize = 'crud';
3. ?>

By using crud, Auth will make use of ACL and check with AclComponent::check(). Actions should be mapped to CRUD
(see mapActions (http://book.cakephp.org/view/1260/mapActions) ).

5.2.6.11 (#sessionKey-1276) sessionKey

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1276/sessionKey) .. Mas info
sobre traduciones (/es/view/818)

Name of the session array key where the record of the current authed user is stored.

Defaults to "Auth", so if unspecified, the record is stored in "Auth.{$userModel name}".

Plain Text View (#)


1. <?php
2. $this->Auth->sessionKey = 'Authorized';
3. ?>

5.2.6.12 (#ajaxLogin-1277) ajaxLogin

Si estás haciendo solicitudes basadas en Ajax o Javascript que requieren sesiones autenticadas, establece en esta
variable el nombre del elemento vista que deseas mostrar y retornar cuando la sesión es inválida o ha expirado.

Como con cualquier parte de CakePHP, asegúrate de revisar la clase AuthComponent (http://api.cakephp.org/class
/auth-component) para mayores detalles.

5.2.6.13 (#authenticate-1278) authenticate

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1278/authenticate) .. Mas info
sobre traduciones (/es/view/818)

200 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

This variable holds a reference to the object responsible for hashing passwords if it is necessary to change/override
the default password hashing mechanism. See Changing the Encryption Type (/es/view/566/Changing-Encryption-Type)
for more info.

5.2.6.14 (#actionPath-1279) actionPath

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1279/actionPath) .. Mas info
sobre traduciones (/es/view/818)

If using action-based access control, this defines how the paths to action ACO nodes is computed. If, for example, all
controller nodes are nested under an ACO node named 'Controllers', $actionPath should be set to 'Controllers/'.

5.2.6.15 (#x5-2-6-15-flashElement-1637) 5.2.6.15 flashElement

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1637/x5-2-6-15-flashElement) ..
Mas info sobre traduciones (/es/view/818)

In case that you want to have another layout for your Authentication error message you can define with the
flashElement variable that another element will be used for display.

Plain Text View (#)


1. <?php
2. $this->Auth->flashElement = "message_error";
3. ?>

5.3 (#Cookies-1280) Cookies

El componente Cookie es una abstracción para acceder al método nativo de PHP setcookie(). También incluye una
serie de funcionalidades muy útiles para agilizar la escritura de cookies. Antes de tratar de utilizar el componente
Cookie, debe asegurarse que se encuentra habilitado en el arreglo $components: si está habilitado uno de los
elementos del arreglo debe ser 'Cookie'

5.3.1 (#Configuración-del-Controlador-1281) Configuración del Controlador

Hay una serie de variables que se configuran en el controlador, y te permiten modificar la forma en que las cookies
son creadas y gestionadas. Estas variables especiales generalmente se setean en el método beforeFilter() de tu
controlador.

Variable
por defecto descripción
Cookie
string
'CakeCookie' El nombre de la cookie.
$name
string Esta cadena es utilizada para encriptar el valor escrito en la cookie. La cadena debería ser
null
$key aleatoria y difícil de adivinar.
string El nombre de dominio habilitado para acceder a la cookie, ej. Use '.tudominio.com' para
''
$domain permitir acceso desde todos los subdominios.
El tiempo en que expirará la cookie. Los enteros son interpretados como segundos, y un
int o
valor 0 es equivalente a 'cookie de sesión', es decir, la cookie expira cuando se cierra el
string '5 Days'
navegador. Si el valor es una cadena, será interpretada con la función de PHP strtotime().
$time
Puedes configurar esto directamente dentro del método de escritura write().
La ruta del servidor donde la cookie será aplicada. Si $cookiePath está seteada a '/foo/', la
string cookie estará disponible sólo dentro del directorio /foo/ y todos los subdirectorios (como
'/'
$path por ejemplo /foo/bar/) de tu dominio. La opción por defecto es en todo el dominio. Puedes
configurar esto directamente dentro del método de escritura write().
Indica que la cookie deberá ser transmitida únicamente por una conexión segura HTTPS.
boolean
false Cuando este valor sea true, la cookie será creada sólo si existe una conexión segura. Puedes
$secure
configurar esto directamente dentro del método de escritura write()

El siguiente recorte del código de un controlador muestra cómo incluir el componente Cookie y cómo configurar las
variables necesarias para enviar una cookie llamada 'baker_id' para el dominio 'example.com' que a su vez necesita
una conexión segura, debe estar disponible para la ruta ʻ/bakers/preferencias/ʼ, y expira en una hora.

Plain Text View (#)

201 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. var $components = array('Cookie');


2. function beforeFilter() {
3. $this->Cookie->name = 'baker_id';
4. $this->Cookie->time = 3600; // o '1 hour'
5. $this->Cookie->path = '/bakers/preferencias/';
6. $this->Cookie->domain = 'example.com';
7. $this->Cookie->secure = true; //enviar sólo por una conexión segura HTTPS
8. $this->Cookie->key = 'qSI232qs*&sXOw!';
9. }

A continuación, veremos cómo utilizar los diferentes métodos del componente Cookie.

5.3.2 (#Utilizando-el-Componente-1282) Utilizando el Componente

202 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1282)


Comparar con el texto original (/es/compare/1282/Utilizando-el-Componente)

Mas info sobre traduciones (/es/view/818)

Esta sección resume los métodos del componente Cookie.

write(mixed $key, mixed $value, boolean $encrypt, mixed $expires)

El método write() es el corazón del componente, $key es la variable que se quiere guardar en la cookie y $value es el
dato para almacenar.

Plain Text View (#)


1. $this->Cookie->write('nombre','Pepito');

También puedes agrupar variables utilizando la notación de 'punto' en el parámetro $key.

Plain Text View (#)


1. $this->Cookie->write('Usuario.nombre', 'Pepito');
2. $this->Cookie->write('Usuario.rol','Lider');

Si deseas escribir más de un valor a la vez en la cookie, puedes pasar un arreglo:

Plain Text View (#)


1. $this->Cookie->write(
2. array('nombre'=>'Pepito','rol'=>'Lider')
3. );
4.

Todos los valores de las cookis son encriptados por defecto. Si desea almacenar valores en texto puro, cambie el
tecer parámetro del método write() a false.

Plain Text View (#)


1. $this->Cookie->write('nombre','Pepito',false);

El último parámetro del método es $expires: el número de segundos antes de que la cookie expire. Por convenienia,
este parámetro puede ser pasado como una cadena que entienda la función strtotime() de PHP:

Plain Text View (#)


1. //Ambas cookies expiran en una hora.
2. $this->Cookie->write('nombre','Pepito',false, 3600);
3. $this->Cookie->write('Apellido','Gonzales',false, '1 hour');

read(mixed $key)

Este método es utilizado para leer el valor de una variable almaenada en una cookie. La variable a leer debe ser
especificada en el parámetro $key.

Plain Text View (#)


1. //Muestra “Pepito”
2. echo $this->Cookie->read('name');
3. //También se puede utilizar la notación de 'punto' para leer
4. echo $this->Cookie->read('Usuario.nombre');
5. //Para obtener las variables que has agrupado utilizando
6. //la notación de 'punto' como un arreglo debes usar
7. $this->Cookie->read('Usuario');
8. //esto devuelve un arreglo similar a array('nombre' => 'Pepito', 'rol'=>'Lider')

del(mixed $key)

Borra el contenido de la variable $key almacenada en una cookie. También funciona con la notación de 'punto'.

203 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Plain Text View (#)


1. //Borrar una variable
2. $this->Cookie->del('bar')
3.
4. //Borrar la variable bar, pero no todas las contenidas en foo
5. $this->Cookie->del('foo.bar')

destroy()

Destruye la cookie actual.

5.4 (#Email-1283) Email

El componente Email es una manera simple de agregarle a tu aplicación CakePHP la funcionalidad de envío de mails,
usando los mismos conceptos de layouts, vistas, archivos .ctp, etc, formateados como texto, html, o ambos. Puede
enviar mails por medio de las funciones propias de PHP, vía servidor SMTP o en modo DEBUG en el que escribe el
mensaje en un mensaje flash de sesión. También soporta archivos adjuntados y inclusión/filtrado simple de
encabezados. Hay un montón de cosas que no hace por tí, pero te pondrá en movimiento.

5.4.1 (#Atributos-y-Variables-de-la-clase-1284) Atributos y Variables de la clase

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1284)


Comparar con el texto original (/es/compare/1284/Atributos-y-Variables-de-la-clase)

Mas info sobre traduciones (/es/view/818)

Estos son los valores que puedes configurar antes de hacer la llamada EmailComponent::send()

to dirección a la que se dirige el mensaje (string)


cc arreglo de direcciones a enviar copias del mensaje (CC)
bcc arreglo de direcciones a enviar las copias ocultas del mensaje (CCO)
replyTo dirección de respuesta(string)
from dirección remitente (string)
subject asunto del mensaje (string)
Elemento email a usar para el mensaje(ubicado en app/views/elements/email/html/ y en app/views
template
/elements/email/text/)
Layout usado por el mail (ubicado en app/views/layouts/email/html/ y en app/views/layouts/email
layout
/text/)
lineLength Longitud (en caracteres) en la que corta las líneas largas. Por defecto es 70. (integer)
sendAs Como quieres mandar el mensaje: text(texto), html(código HTML) o both(ambos).
attachments Arreglo de archivos a enviar (rutas absolutas y relativas)
delivery Como enviar el mensaje (mail, smtp [requerirá el campo smtpOptions explicado abajo] y debug)
Arreglo asociativo de opciones para el envío por SMTP. (port(puerto), host(servidor), timeout(tiempo
smtpOptions
de espera), username(nombre de usuario), password(contraseña))

Hay algunas opciones más para configurar, para mayor información consulta la documentación de CakePHP.

5.4.1.1 (#Envío-múltiple-de-emails-en-bucle-1285) Envío múltiple de emails en bucle

Si lo que quieres es enviar varios emails usando un bucle, deberás resetear los campos de mails usando el método
reset() del componente Email. Necesitarás resetearlo antes de setear nuevamente las propiedades del email.

Plain Text View (#)


1. $this->Email->reset()

5.4.1.2 (#Debugging-Emails-1635) Debugging Emails

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1635/Debugging-Emails) .. Mas

204 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

info sobre traduciones (/es/view/818)

If you do not want to actually send an email and instead want to test out the functionality, you can use the following
delivery option:

Plain Text View (#)


1. $this->Email->delivery = 'debug';

In order to view those debugging information you need to create an extra line in your view or layout file (e.g.
underneath your normal flash message in /layouts/default.ctp): Plain Text View (#)
1. <?php echo $this->Session->flash(); ?>
2. <?php echo $this->Session->flash('email'); ?>

5.4.2 (#Envío-de-un-mensaje-simple-1286) Envío de un mensaje simple

Para enviar un mensaje sin usar ningún template, sólo pasa el cuerpo del mensaje como una cadena (string) o un
arreglo de líneas al método send(). Por ejemplo:

Plain Text View (#)


1. $this->Email->from = 'Alguien <alguien@ejemplo.com>';
2. $this->Email->to = 'Alguien más <alguien.mas@ejemplo.com>';
3. $this->Email->subject = 'Prueba';
4. $this->Email->send('Hola cuerpo de mensaje!!!');

5.4.2.1 (#Configurando-el-Layout-1287) Configurando el Layout

Para usar tanto texto como html en el email necesitarás crear los archivos de layout para ellos. Tal como lo hayas
hecho para tu layout default para las vistas en un navegador, precisas establecer los layouts default para tus emails.
En la carpeta app/views/layouts/ precisas tener (como mínimo) esta estructura

Plain Text View (#)


1. email/
2. html/
3. default.ctp
4. text/
5. default.ctp

Estos son los archivos que conservan los valores por defecto para los templates de layout para tus mensajes. Un
simple ejemplo de contenido:

email/text/default.ctp Plain Text View (#)

1. <?php echo $content_for_layout; ?>

email/html/default.ctp Plain Text View (#)

1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">


2. <html>
3. <body>
4. <?php echo $content_for_layout; ?>
5. </body>
6. </html>

5.4.2.2 (#Configurar-un-elemento-Email-para-el-cuerpo-del-me-1288) Configurar un elemento Email para el cuerpo del mensaje

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1288)


Comparar con el texto original (/es/compare/1288/Configurar-un-elemento-Email-para-el-cuerpo-del-me)

Mas info sobre traduciones (/es/view/818)

En el directorio app/views/elements/email/ debes configurar carpetas para text(mails modo texto) y html(mails modo

205 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

HTML) a menos que quieras usar sólo uno de ellos. En cada una de estas carpetas debes crear templates para poder
utilizar con el contenido que le envíes a la vista ya sea usando $this->set() o usando el parámetro $contents del
método send(). Algunos ejemplos simples a continuación, usando el template simple_message.ctp

text Plain Text View (#)

1. Estimado <?php echo $User['first']. ' ' . $User['last'] ?>,


2. Gracias por su interés.

html Plain Text View (#)

1. <p>Estimado <?php echo $User['first']. ' ' . $User['last'] ?>,<br />


2. &nbsp;&nbsp;&nbsp;Gracias por su interés.</p>

5.4.2.3 (#Controlador-1289) Controlador

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1289)


Comparar con el texto original (/es/compare/1289/Controlador)

Mas info sobre traduciones (/es/view/818)

En tu controlador necesitas agregar el componente a tu array $components o agregar un array $components a tu


controlador de la forma:

Plain Text View (#)


1. <?php
2. var $components = array('Email');
3. ?>

En este ejemplo configuraremos un método privado para manejar el envío de mensajes de email a un usuario
identificado por un $id. En nuestro controlador (usemos el controlador User en este ejemplo):

Plain Text View (#)


1. <?php
2. function _sendNewUserMail($id) {
3. $User = $this->User->read(null,$id);
4. $this->Email->to = $User['User']['email'];
5. $this->Email->bcc = array('secreto@ejemplo.com');
6. $this->Email->subject = 'Bienvenido a nuestra cosa genial';
7. $this->Email->replyTo = 'support@ejemplo.com';
8. $this->Email->from = 'Cool Web App <app@ejemplo.com>';
9. $this->Email->template = 'simple_message'; // NOTAR QUE NO HAY '.ctp'
10. //Enviar como 'html', 'text' or 'both' (ambos) - (por defecto es 'text')
11. $this->Email->sendAs = 'both'; // queremos enviar un lindo email
12. //Variables de la vista
13. $this->set('User', $User);
14. //NO PASAMOS ARGUMENTOS A SEND()
15. $this->Email->send();
16. }
17. ?>

Has enviado un mensaje, podrías llamarlo desde otro método de esta forma: Plain Text View (#)
1.
2. $this->_sendNewUserMail( $this->User->id );

5.4.2.4 (#Attachments-1638) Attachments

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1638/Attachments) .. Mas info
sobre traduciones (/es/view/818)

Here's how you can send file attachments along with your message. You set an array containing the paths to the files

206 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

to attach to the attachments property of the component.

Plain Text View (#)


1. $this->Email->attachments = array(
2. TMP . 'foo.doc',
3. 'bar.doc' => TMP . 'some-temp-name'
4. );

The first file foo.doc will be attached with the same filename. For the second file we specify an alias bar.doc will be be
used for attaching instead of its actual filename some-temp-name

5.4.3 (#Enviar-un-mail-por-SMTP-1290) Enviar un mail por SMTP

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1290)


Comparar con el texto original (/es/compare/1290/Enviar-un-mail-por-SMTP)

Mas info sobre traduciones (/es/view/818)

Para enviar un mail usando servidor SMTP, los pasos a seguir son similares a los del mensaje básico. Configurar el
método de entrega (delivery ) a smtp y asignar las opciones a las propiedades del objeto de Email smtpOptions.
También puedes obtener los errores SMTP generados durante la sesión leyendo la propiedad smtpError del
componente.

Plain Text View (#)


1. /* Opciones SMTP*/
2. $this->Email->smtpOptions = array(
3. 'port'=>'25',
4. 'timeout'=>'30',
5. 'host' => 'tu.servidor.smtp',
6. 'username'=>'tu_nombre_usuario_smtp',
7. 'password'=>'tu_contraseña_smtp');
8. /* Configurar método de entrega */
9. $this->Email->delivery = 'smtp';
10. /* No le pases ningún argumento a send() */
11. $this->Email->send();
12. /* Chequeo de errores SMTP. */
13. $this->set('smtp-errors', $this->Email->smtpError);

Si tu servidor SMTP requiere autenticación, asegúrate de especificar los parámetros de nombre de usuario y
contraseña en smtpOptions como se ve en el ejemplo.

5.5 (#Request-Handling-1291) Request Handling

El componente Request Handler (manejador de la petición) es usado en CakePHP para obtener información adicional
sobre las peticiones HTTP que son realizadas a tus aplicaciones. Puedes usarlo para informar a tus controladores
sobre Ajax, como también para obtener información adicional sobre tipos de contenido que el cliente acepta y
cambiar automáticamente al layout apropiado cuando estén activadas las extensiones de ficheros.

Por defecto, RequestHandler detectará automáticamente las peticiones Ajax basadas en la cabecera HTTP-X-
Requested-With que utilizan muchas librerías javascript. Cuando se utiliza junto con Router::parseExtensions(),
RequestHandler cambiará automáticamente los ficheros de layout y vista a aquellos que coincidan con el tipo pedido.
Además, si existe un helper con el mismo nombre que la extensión pedida, se añadirá al array de helpers del
controlador. Finalmente, si son "POSTeados" datos XML a tus controladores, se parsearán en un objecto XML que se
asigna a Controller::data, y que puede entonces ser salvado como datos de modelo. Para poder hacer uso de
Request handler , debe ser incluído en tu array $components.

Plain Text View (#)

207 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <?php
2. class WidgetController extends AppController {
3.
4. var $components = array('RequestHandler');
5.
6. //resto del controlador
7. }
8. ?>

5.5.1 (#Obtaining-Request-Information-1292) Obtaining Request Information

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1292/Obtaining-Request-
Information) .. Mas info sobre traduciones (/es/view/818)

Request Handler has several methods that provide information about the client and its request.

accepts ( $type = null)

$type can be a string, or an array, or null. If a string, accepts will return true if the client accepts the content type. If
an array is specified, accepts return true if any one of the content types is accepted by the client. If null returns an
array of the content-types that the client accepts. For example:

Plain Text View (#)


1. class PostsController extends AppController {
2.
3. var $components = array('RequestHandler');
4. function beforeFilter () {
5. if ($this->RequestHandler->accepts('html')) {
6. // Execute code only if client accepts an HTML (text/html) response
7. } elseif ($this->RequestHandler->accepts('xml')) {
8. // Execute XML-only code
9. }
10. if ($this->RequestHandler->accepts(array('xml', 'rss', 'atom'))) {
11. // Executes if the client accepts any of the above: XML, RSS or Atom
12. }
13. }
14. }

Other request 'type' detection methods include:

isAjax()

Returns true if the request contains the X-Requested-Header equal to XMLHttpRequest.

isSSL()

Returns true if the current request was made over an SSL connection.

isXml()

Returns true if the current request accepts XML as a response.

isRss()

Returns true if the current request accepts RSS as a response.

isAtom()

Returns true if the current call accepts an Atom response, false otherwise.

isMobile()

Returns true if user agent string matches a mobile web browser, or if the client accepts WAP content. The supported
Mobile User Agent strings are:

iPhone

208 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

MIDP
AvantGo
BlackBerry
J2ME
Opera Mini
DoCoMo
NetFront
Nokia
PalmOS
PalmSource
portalmmm
Plucker
ReqwirelessWeb
SonyEricsson
Symbian
UP.Browser
Windows CE
Xiino

isWap()

Returns true if the client accepts WAP content.

All of the above request detection methods can be used in a similar fashion to filter functionality intended for specific
content types. For example when responding to Ajax requests, you often will want to disable browser caching, and
change the debug level. However, you want to allow caching for non-ajax requests. The following would accomplish
that:

Plain Text View (#)


1. if ($this->RequestHandler->isAjax()) {
2. Configure::write('debug', 0);
3. $this->header('Pragma: no-cache');
4. $this->header('Cache-control: no-cache');
5. $this->header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
6. }
7. //Continue Controller action

You could also disable caching with the functionally analogous Controller::disableCache

Plain Text View (#)


1. if ($this->RequestHandler->isAjax()) {
2. $this->disableCache();
3. }
4. //Continue Controller action

5.5.2 (#Request-Type-Detection-1293) Request Type Detection

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1293/Request-Type-Detection) ..
Mas info sobre traduciones (/es/view/818)

RequestHandler also provides information about what type of HTTP request has been made and allowing you to
respond to each Request Type.

isPost()

Returns true if the request is a POST request.

isPut()

Returns true if the request is a PUT request.

isGet()

Returns true if the request is a GET request.

isDelete()

209 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Returns true if the request is a DELETE request.

5.5.3 (#Obtaining-Additional-Client-Information-1294) Obtaining Additional Client Information

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1294/Obtaining-Additional-
Client-Information) .. Mas info sobre traduciones (/es/view/818)

getClientIP()

Get the remote client IP address

getReferer()

Returns the domain name from which the request originated

getAjaxVersion()

Gets Prototype version if call is Ajax, otherwise empty string. The Prototype library sets a special "Prototype version"
HTTP header.

5.5.4 (#Responding-To-Requests-1295) Responding To Requests

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1295/Responding-To-Requests) ..
Mas info sobre traduciones (/es/view/818)

In addition to request detection RequestHandler also provides easy access to altering the output and content type
mappings for your application.

setContent($name, $type = null)

$name string - The name or file extension of the Content-type ie. html, css, json, xml.
$type mixed - The mime-type(s) that the Content-type maps to.

setContent adds/sets the Content-types for the given name. Allows content-types to be mapped to friendly aliases and
or extensions. This allows RequestHandler to automatically respond to requests of each type in its startup method. If
you are using Router::parseExtension, you should use the file extension as the name of the Content-type.
Furthermore, these content types are used by prefers() and accepts().

setContent is best used in the beforeFilter() of your controllers, as this will best leverage the automagicness of
content-type aliases.

The default mappings are:

javascript text/javascript
js text/javascript
json application/json
css text/css
html text/html, */*
text text/plain
txt text/plain
csv application/vnd.ms-excel, text/plain
form application/x-www-form-urlencoded
file multipart/form-data
xhtml application/xhtml+xml, application/xhtml, text/xhtml
xhtml-mobile application/vnd.wap.xhtml+xml
xml application/xml, text/xml
rss application/rss+xml
atom application/atom+xml
amf application/x-amf
wap text/vnd.wap.wml, text/vnd.wap.wmlscript, image/vnd.wap.wbmp
wml text/vnd.wap.wml
wmlscript text/vnd.wap.wmlscript
wbmp image/vnd.wap.wbmp
pdf application/pdf
zip application/x-zip
tar application/x-tar

prefers($type = null)

210 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Determines which content-types the client prefers. If no parameter is given the most likely content type is returned. If
$type is an array the first type the client accepts will be returned. Preference os determined primarily by the file
extension parsed by Router if one has been provided. and secondly by the list of content-types in HTTP_ACCEPT.

renderAs($controller, $type)

$controller - Controller Reference


$type - friendly content type name to render content for ex. xml, rss.

Change the render mode of a controller to the specified type. Will also append the appropriate helper to the
controller's helper array if available and not already in the array.

respondAs($type, $options)

$type - Friendly content type name ex. xml, rss or a full content type like application/x-shockwave
$options - If $type is a friendly type name that has more than one content association, $index is used to select
the content type.

Sets the response header based on content-type map names. If DEBUG is greater than 1, the header is not set.

responseType()

Returns the current response type Content-type header or null if one has yet to be set.

mapType($ctype)

Maps a content-type back to an alias

5.6 (#El-Componente-Security-1296) El Componente Security

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1296)


Comparar con el texto original (/es/compare/1296/El-Componente-Security)

Mas info sobre traduciones (/es/view/818)

El componente Security provee una forma fácil de aumentar la seguridad en tu aplicación. Con el componente Security
se puede crear una intefaz para manejar autenticaciones HTTP. Se configura en el método beforeFilter() de tus
controladores, y tiene distintos parámetros para ajustar. Todas esas propiedades pueden configurarse directamente
con los métodos creados para tal fin, y que se llaman de la misma manera.

5.6.1 (#Configuración-1297) Configuración

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1297)


Comparar con el texto original (/es/compare/1297/Configuración)

Mas info sobre traduciones (/es/view/818)

$blackHoleCallback
Un callback del controlador que se encargará de manejar las peticiones que hayan sido enviadas al "agujero
negro".
$requirePost
Una lista de acciones del controlador que requieren una petición POST para ejecutarse. Un arreglo de acciones
del controlador o '*' para forzar que todas las acciones requieran POST.
$requireSecure
Lista de acciones que requieren una conexión SSL para ejecutarse. Un arreglo de acciones del controlador o '*'
para forzar que todas las acciones requieran una conexión SSL.
$requireAuth
Una lista de acciones que requieren una clave de autenticación válida. Esta clave es configurada por el
componente Security.
$requireLogin
Una lista de acciones que requieren autenticación HTTP (basic o diges). También acepta '*' indicando que todas
las acciones del controlador requieren autenticación HTTP.
$loginOptions
Opciones para la autenticación HTTP. Permite definir que tipo de autenticación utilizar, y los callbacks del

211 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

controlador para el proceso de autenticación.


$loginUsers
Un arreglo asociativo de usuarios => passords que sonusados para autenticaciones HTTP. Si estás utilizando
autenticacion digest, los passwords deben ser encryptados con el algoritmo MD5.
$allowedControllers
Una lista de controladores desde los cuales la acción del controlador actual puede recibir peticiones. También
puede utilizarse para peticiones entre controladores.
$allowedActions
Una lista de acciones desde las cuales las acciones del controlador actual pueden para recibir peticiones.
También puede utilizarse para peticiones entre controladores.
$disabledFields
Campos del formulario que se necesitan deshabilitar para una petición dada.

5.6.2 (#Métodos-1298) Métodos

5.6.2.1 (#requirePost-1299) requirePost()

Define las acciones que requieren una petición POST. Acepta cualquier número de argumentos. Puede ser llamado sin
argumentos para forzar a que todas las acciones requieran una petición POST.

5.6.2.2 (#requireSecure-1300) requireSecure()

Define las acciones que requieren una conexión SSL presente. Acepta cualquier cantidad de argumentos. Puede ser
llamado sin argumentos para forzar que todas las acciones requieran una conexión SSL.

5.6.2.3 (#requireAuth-1301) requireAuth()

Define las acciones que requieren un token válido generado por el componente Security. Acepta cualquier número de
argumentos. Puede ser llamado sin argumentos para forzar que todas las acciones requieran una autenticación válida.

5.6.2.4 (#requireLogin-1302) requireLogin()

Define las acciones que requieren una autenticación HTTP válida. Acepta cualquier número de argumentos. Puede ser
llamada sin argumentos para forzar que todas las acciones requieran una autenticación HTTP válida.

5.6.2.5 (#loginCredentials-string-type-1303) loginCredentials(string $type)

Trata de validar las credenciales para una petición de autenticación HTTP. $type es el tipo de autenticación que se
desea verificar. Puede ser 'basic', o 'digest'. Si se deja como null o vació, tratará de verificar las dos. Devuelve un
arreglo con el nombre de usuario y el password si tuvo éxtito.

5.6.2.6 (#loginRequest-array-options-1304) loginRequest(array $options)

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1304/loginRequest-array-
options) .. Mas info sobre traduciones (/es/view/818)

Generates the text for an HTTP-Authenticate request header from an array of $options.

$options generally contains a 'type', 'realm' . Type indicate which HTTP-Authenticate method to use. Realm defaults to
the current HTTP server environment.

5.6.2.7 (#parseDigestAuthData-string-digest-1305) parseDigestAuthData(string $digest)

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1305/parseDigestAuthData-
string-digest) .. Mas info sobre traduciones (/es/view/818)

Parse an HTTP digest authentication request. Returns and array of digest data as an associative array if succesful, and
null on failure.

5.6.2.8 (#generateDigestResponseHash-array-data-1306) generateDigestResponseHash(array $data)

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit
/1306/generateDigestResponseHash-array-data) .. Mas info sobre traduciones (/es/view/818)

212 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Creates a hash that to be compared with an HTTP digest-authenticated response. $data should be an array created by
SecurityComponent::parseDigestAuthData().

5.6.2.9 (#blackHole-object-controller-string-error-1307) blackHole(object $controller, string $error)

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1307/blackHole-object-
controller-string-error) .. Mas info sobre traduciones (/es/view/818)

Black-hole an invalid request with a 404 error or a custom callback. With no callback, the request will be exited. If a
controller callback is set to SecurityComponent::blackHoleCallback, it will be called and passed any error information.

5.6.3 (#Uso-1308) Uso

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1308)


Comparar con el texto original (/es/compare/1308/Uso)

Mas info sobre traduciones (/es/view/818)

EL uso del componente security generalmente se hace en el método beforeFilter() del controlador. Usted especifica las
restricciones de seguridad que desee y el componente Security las hara cumplir en el arranque.

Plain Text View (#)


1. <?php
2. class WidgetController extends AppController {
3. var $components = array('Security');
4. function beforeFilter() {
5. $this->Security->requirePost('delete');
6. }
7. }
8. ?>

En este ejemplo la accion delete solo puede ser lanzada satisfactoriamente si se recive una solicitud POST.

Plain Text View (#)


1. <?php
2. class WidgetController extends AppController {
3. var $components = array('Security');
4. function beforeFilter() {
5. if(isset($this->params[Configure::read('Routing.admin')])){
6. $this->Security->requireSecure();
7. }
8. }
9. }
10. ?>

Este ejemplo forzaría todas las acciones que tengan enrrutamiento admin a requerir peticiones seguras del SSL.

5.6.4 (#Basic-HTTP-Authentication-1309) Basic HTTP Authentication

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1309/Basic-HTTP-Authentication)
.. Mas info sobre traduciones (/es/view/818)

The SecurityComponent has some very powerful authentication features. Sometimes you may need to protect some
functionality inside your application using HTTP Basic Authentication (http://en.wikipedia.org
/wiki/Basic_access_authentication) . One common usage for HTTP Auth is protecting a REST or SOAP API.

This type of authentication is called basic for a reason. Unless you're transferring information over SSL, credentials
will be transferred in plain text.

Using the SecurityComponent for HTTP authentication is easy. The code example below includes the
SecurityComponent and adds a few lines of code inside the controller's beforeFilter method.

213 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Plain Text View (#)


1. class ApiController extends AppController {
2. var $name = 'Api';
3. var $uses = array();
4. var $components = array('Security');
5. function beforeFilter() {
6. $this->Security->loginOptions = array(
7. 'type'=>'basic',
8. 'realm'=>'MyRealm'
9. );
10. $this->Security->loginUsers = array(
11. 'john'=>'johnspassword',
12. 'jane'=>'janespassword'
13. );
14. $this->Security->requireLogin();
15. }
16.
17. function index() {
18. //protected application logic goes here...
19. }
20. }

The loginOptions property of the SecurityComponent is an associative array specifying how logins should be
handled. You only need to specify the type as basic to get going. Specify the realm if you want display a nice message
to anyone trying to login or if you have several authenticated sections (= realms) of your application you want to keep
separate.

The loginUsers property of the SecurityComponent is an associative array containing users and passwords that
should have access to this realm. The examples here use hard-coded user information, but you'll probably want to
use a model to make your authentication credentials more manageable.

Finally, requireLogin() tells SecurityComponent that this Controller requires login. As with requirePost(), above,
providing method names will protect those methods while keeping others open.

5.7 (#Sesiones-1310) Sesiones

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1310)


Comparar con el texto original (/es/compare/1310/Sesiones)

Mas info sobre traduciones (/es/view/818)

El componente Session de CakePHP provee una forma de persistir datos entre las peticiones de las páginas. Actúa
como una abstracción para acceder a las variables $_SESSION, y a su vez, agrega distintos métodos útiles
relacionados con este arreglo.

Las sesiones pueden persistirse de diferentes maneras. Por defecto se utilizan los métodos provistos por PHP; sin
embargo, existen otras opciones:

cake
Guarda los archivos de la sesión en el directorio temporal de tu aplicación tmp/sessions.
database
Guarda la información dentro de la base de datos.
php
La opción por defecto. Guarda la información como se indica en php.ini

Para cambiar el método por defecto de gestión de sesiones, debes modificar el parámetro de configuración
Session.save para reflejar la opción deseada. Si eliges 'database', también deberías descomentar el parámetro
Session.database y ejecutar el archivo SQL perteneciente a la sesión localizado en app/config

En views/elements la sesión puede ser accedida por medio del helper Session

5.7.1 (#Métodos-1311) Métodos

214 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

El componente Session es usado para interactuar con la información de la sesión. Incluye operaciones básicas de
ABM (Alta, Baja y Modificación) como también opciones para comunicarse con los usuarios.

Debe notarse que se pueden crear estructuras de arreglos en las sesiones utilizando la notación de 'punto'. De esta
forma, Usuario.email equivaldrá a:

Plain Text View (#)


1. array('Usuario' =>
2. array('email' => 'clarkKent@dailyplanet.com')
3. );

Los puntos son usados para indicar arreglos anidados.

5.7.1.1 (#write-1312) write

write($name, $value)

Guarda en la sesión una variable llamada $name con el valor $value. $name puede utilizar la notación de 'punto'. Por
ejemplo:

Plain Text View (#)


1. $this->Session->write('Persona.colorOjos', 'Verde');

Escribe el valor 'Verde' en la sesión, dentro de Persona => colorOjos.

5.7.1.2 (#setFlash-1313) setFlash

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1313)


Comparar con el texto original (/es/compare/1313/setFlash)

Mas info sobre traduciones (/es/view/818)

setFlash($message, $layout = 'default', $params = array(), $key = 'flash')

Se utiliza para guardar una variable de sesión que puede ser mostrada en la vista. $layout permite controlar qué
layout (ubicado en /app/views/layouts) se utilizará para mostrar el mensaje. Si la variable $layout queda configurada
con su valor por defecto, 'default', el mensaje se mostrará como se ve a continuación:

Plain Text View (#)


1. <div id="flashMessage" class="message"> [message] </div>

$params permite pasar variables adicionales para mostrar en el layout. $key es utilizado para modificar el índice del
arreglo $message en el arreglo de mensajes (por defecto es 'flash'). $message es el texto que se quiere cargar en la
sesión.

Los parámetros puede afectar el div que se muestre, por ejemplo pasando un parámetro 'class' en el arreglo $params,
se modificará el div resultante de utilizar el método $session->flash() en la vista.

Plain Text View (#)


1. setFlash('Mensaje de ejemplo', 'default', array('class' => 'clase_ejemplo'))

La salida de $session->flash() del ejemplo anterior será:

Plain Text View (#)


1. <div id="flashMessage" class="clase_ejemplo">Mensaje de ejemplo</div>

5.7.1.3 (#read-1314) read

215 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

read($name)

Devuelve el contenido de la variable $name dentro de la sesión. Si $name es null, se devolverá todo el contenido de
la sesión. Ej.

Plain Text View (#)


1. $verde = $this->Session->read('Persona.colorOjos');

Recupera el valor 'Verde' de la sesión.

5.7.1.4 (#check-1315) check

check($name)

Se utiliza para verificar si una variable ha sido seteada en la sesión. Devuelve true en caso afirmativo, y false si la
variable nunca fue seteada.

5.7.1.5 (#delete-1316) delete

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1316)


Comparar con el texto original (/es/compare/1316/delete)

Mas info sobre traduciones (/es/view/818)

delete($name) /*o*/ del($name)

Borra los datos de la variable $name dentro de la sesión. Ej.

Plain Text View (#)


1. $this->Session->del('Persona.colorOjos');

Nuestra información de sesión ya no tiene el valor 'Verde', ni siquiera la clave 'colorOjos'. Sin embardo, Persona
todavía existe en la sesión. Para eliminar la variable completa de la sesión se debe usar:

Plain Text View (#)


1. $this->Session->del('Persona');

5.7.1.6 (#destroy-1317) destroy

El método destroy eliminará la cookie de sesión y todos los datos almacenados en los archivos temporales del
sistema. Destruirá la sesión de PHP y creará una sesión nueva.

Plain Text View (#)


1. $this->Session->destroy()

5.7.1.7 (#error-1318) error

error()

Se utiliza para determinar el último error en una sesión.

6 (#Core-Behaviors-Comportamientos-Basicos-1319) Core Behaviors (Comportamientos Basicos)

Los comportamientos (Behaviors) agregan funcionalidad extra a tus modelos. CakePHP viene con un numero de
comportamientos incorporados tales como el Arbol (Tree) y Contenible (Containable).

6.1 (#ACL-1320) ACL

El comportamiento Acl provee una forma de integrar un modelo con tu sistema ACL. Puede crear tanto los AROs o los
ACOs transparentemente.

216 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Para usar el nuevo comportamiento, puedes añadirlo a la propiedad $actsAs de tu modelo. Cuando lo agregas al
arreglo $actsAs, se pueden elegir entre hacer la entrada actual como un ARO o un ACO. El valor por defecto es para
crear AROs.

Plain Text View (#)


1. class User extends AppModel {
2. var $actsAs = array('Acl' => array('type' => 'requester'));
3. }

Esto incluye el comportamiento de Acl en el modo ARO. Para que el comportamiento ACL sea ACO, se debe usar:

Plain Text View (#)


1. class Post extends AppModel {
2. var $actsAs = array('Acl' => array('type' => 'controlled'));
3. }

Se puede agregar el comportamiento ACL al vuelo, de la siguiente forma:

Plain Text View (#)


1. $this->Post->Behaviors->attach('Acl', array('type' => 'controlled'));

6.1.1 (#Using-the-AclBehavior-1321) Using the AclBehavior

Muchos de los comportamientos ACL funcionan transparentemente en el método afterSave() del Modelo. Sin embargo,
usarlo requiere que tu Modelo tenga el método parentNode() definido. Esto es usado por el comportamiento ACL para
determinar las relaciones padre-hijo. El método parentNode() del modelo debe retornar null, o bien, retornar una
referencia al modelo padre.

Plain Text View (#)


1. function parentNode() {
2. return null;
3. }

Si se quiere setear un nodo ACO o ARO como padre del modelo, parentNode() debe retornar el alias del nodo ACO o
ARO.

Plain Text View (#)


1. function parentNode() {
2. return 'root_node';
3. }

Un ejemplo más completo. Usando un modelo User, donde User tiene la relación belongsTo con el modelo Group.

Plain Text View (#)


1. function parentNode() {
2. if (!$this->id && empty($this->data)) {
3. return null;
4. }
5. $data = $this->data;
6. if (empty($this->data)) {
7. $data = $this->read();
8. }
9. if (!$data['User']['group_id']) {
10. return null;
11. } else {
12. $this->Group->id = $data['User']['group_id'];
13. $groupNode = $this->Group->node();
14. return array('Group' => array('id' => $groupNode[0]['Aro']['foreign_key']));
15. }
16. }

217 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

En el ejemplo de arriba el valor de retorno es un arreglo que tiene la misma estructura que el resultado de la
operación find() del modelo. Es importante setear el valor del id o la relacion parentNode fallará. El comportamiento
Acl usa esta data para construir la estructura del árbol.

6.1.2 (#node-1322) node()

El comportamiento ACL también permite rescatar el nodo ACL asociado al registro del modelo. Despues de setear
$model->id se puede utilizar $model->node() para rescatar el nodo ACL asociado.

Tambien se puede rescatar el nodo ACL de cualquier fila, pasandolo dentro de un arreglo.

Plain Text View (#)


1. $this->User->id = 1;
2. $node = $this->User->node();
3.
4. $user = array('User' => array(
5. 'id' => 1
6. ));
7. $node = $this->User->node($user);

Ambos retornaran la misma información del nodo ACL.

6.2 (#Containable-1323) Containable

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1323/Containable) .. Mas info
sobre traduciones (/es/view/818)

A new addition to the CakePHP 1.2 core is the ContainableBehavior. This model behavior allows you to filter and limit
model find operations. Using Containable will help you cut down on needless wear and tear on your database,
increasing the speed and overall performance of your application. The class will also help you search and filter your
data for your users in a clean and consistent way.

Containable allows you to streamline and simplify operations on your model bindings. It works by temporarily or
permanently altering the associations of your models. It does this by using supplied the containments to generate a
series of bindModel and unbindModel calls.

To use the new behavior, you can add it to the $actsAs property of your model:

Plain Text View (#)


1. class Post extends AppModel {
2. var $actsAs = array('Containable');
3. }

You can also attach the behavior on the fly:

Plain Text View (#)


1. $this->Post->Behaviors->attach('Containable');

# (#Using-Containable-1324) Using Containable

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1324/Using-Containable) .. Mas
info sobre traduciones (/es/view/818)

To see how Containable works, let's look at a few examples. First, we'll start off with a find() call on a model named
Post. Let's say that Post hasMany Comment, and Post hasAndBelongsToMany Tag. The amount of data fetched in a
normal find() call is rather extensive:

Plain Text View (#)


1. debug($this->Post->find('all'));

[0] => Array


(
[Post] => Array

218 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

(
[id] => 1
[title] => First article
[content] => aaa
[created] => 2008-05-18 00:00:00
)
[Comment] => Array
(
[0] => Array
(
[id] => 1
[post_id] => 1
[author] => Daniel
[email] => dan@example.com
[website] => http://example.com
[comment] => First comment
[created] => 2008-05-18 00:00:00
)
[1] => Array
(
[id] => 2
[post_id] => 1
[author] => Sam
[email] => sam@example.net
[website] => http://example.net
[comment] => Second comment
[created] => 2008-05-18 00:00:00
)
)
[Tag] => Array
(
[0] => Array
(
[id] => 1
[name] => Awesome
)
[1] => Array
(
[id] => 2
[name] => Baking
)
)
)
[1] => Array
(
[Post] => Array
(...

For some interfaces in your application, you may not need that much information from the Post model. One thing the
ContainableBehavior does is help you cut down on what find() returns.

For example, to get only the post-related information, you can do the following:

Plain Text View (#)


1. $this->Post->contain();
2. $this->Post->find('all');

You can also invoke Containable's magic from inside the find() call:

Plain Text View (#)


1. $this->Post->find('all', array('contain' => false));

219 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Having done that, you end up with something a lot more concise:

[0] => Array


(
[Post] => Array
(
[id] => 1
[title] => First article
[content] => aaa
[created] => 2008-05-18 00:00:00
)
)
[1] => Array
(
[Post] => Array
(
[id] => 2
[title] => Second article
[content] => bbb
[created] => 2008-05-19 00:00:00
)
)

This sort of help isn't new: in fact, you can do that without the ContainableBehavior doing something like this:

Plain Text View (#)


1. $this->Post->recursive = -1;
2. $this->Post->find('all');

Containable really shines when you have complex associations, and you want to pare down things that sit at the same
level. The model's $recursive property is helpful if you want to hack off an entire level of recursion, but not when you
want to pick and choose what to keep at each level. Let's see how it works by using the contain() method.

The contain method's first argument accepts the name, or an array of names, of the models to keep in the find
operation. If we wanted to fetch all posts and their related tags (without any comment information), we'd try something
like this:

Plain Text View (#)


1. $this->Post->contain('Tag');
2. $this->Post->find('all');

Again, we can use the contain key inside a find() call:

Plain Text View (#)


1. $this->Post->find('all', array('contain' => 'Tag'));

Without Containable, you'd end up needing to use the unbindModel() method of the model, multiple times if you're
paring off multiple models. Containable creates a cleaner way to accomplish this same task.

# (#Containing-deeper-associations-1325) Containing deeper associations

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1325/Containing-deeper-
associations) .. Mas info sobre traduciones (/es/view/818)

Containable also goes a step deeper: you can filter the data of the associated models. If you look at the results of the
original find() call, notice the author field in the Comment model. If you are interested in the posts and the names of
the comment authors — and nothing else — you could do something like the following:

Plain Text View (#)

220 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. $this->Post->contain('Comment.author');
2. $this->Post->find('all');
3. //or..
4. $this->Post->find('all', array('contain' => 'Comment.author'));

Here, we've told Containable to give us our post information, and just the author field of the associated Comment
model. The output of the find call might look something like this:

[0] => Array


(
[Post] => Array
(
[id] => 1
[title] => First article
[content] => aaa
[created] => 2008-05-18 00:00:00
)
[Comment] => Array
(
[0] => Array
(
[author] => Daniel
[post_id] => 1
)
[1] => Array
(
[author] => Sam
[post_id] => 1
)
)
)
[1] => Array
(...

As you can see, the Comment arrays only contain the author field (plus the post_id which is needed by CakePHP to
map the results).

You can also filter the associated Comment data by specifying a condition:

Plain Text View (#)


1. $this->Post->contain('Comment.author = "Daniel"');
2. $this->Post->find('all');
3. //or...
4. $this->Post->find('all', array('contain' => 'Comment.author = "Daniel"'));

This gives us a result that gives us posts with comments authored by Daniel:

[0] => Array


(
[Post] => Array
(
[id] => 1
[title] => First article
[content] => aaa
[created] => 2008-05-18 00:00:00
)
[Comment] => Array
(
[0] => Array
(
[id] => 1
[post_id] => 1

221 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

[author] => Daniel


[email] => dan@example.com
[website] => http://example.com
[comment] => First comment
[created] => 2008-05-18 00:00:00
)
)
)

Additional filtering can be performed by supplying the standard Model->find() (/es/view/66/models#find-449)


options:

Plain Text View (#)


1. $this->Post->find('all', array('contain' => array(
2. 'Comment' => array(
3. 'conditions' => array('Comment.author =' => "Daniel"),
4. 'order' => 'Comment.created DESC'
5. )
6. )));

Here's an example of using the ContainableBehavior when you've got deep and complex model relationships.

Let's consider the following model associations:

User->Profile
User->Account->AccountSummary
User->Post->PostAttachment->PostAttachmentHistory->HistoryNotes
User->Post->Tag

This is how we retrieve the above associations with Containable:

Plain Text View (#)


1. $this->User->find('all', array(
2. 'contain'=>array(
3. 'Profile',
4. 'Account' => array(
5. 'AccountSummary'
6. ),
7. 'Post' => array(
8. 'PostAttachment' => array(
9. 'fields' => array('id', 'name'),
10. 'PostAttachmentHistory' => array(
11. 'HistoryNotes' => array(
12. 'fields' => array('id', 'note')
13. )
14. )
15. ),
16. 'Tag' => array(
17. 'conditions' => array('Tag.name LIKE' => '%happy%')
18. )
19. )
20. )
21. ));

Keep in mind that contain key is only used once in the main model, you don't to use 'contain' again for related models

When using 'fields' and 'contain' options - be careful to include all foreign keys that your query directly or indirectly
requires. Please also note that because Containable must to be attached to all models used in containment, you may
consider attaching it to your AppModel.

6.2.1 (#Using-Containable-with-pagination-1326) Using Containable with pagination

222 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1326/Using-Containable-
with-pagination) .. Mas info sobre traduciones (/es/view/818)

By including the 'contain' parameter in the $paginate property it will apply to both the find('count') and the find('all')
done on the model

See the section Using Containable (http://book.cakephp.org/view/1324/Using-Containable) for further details.

Here's an example of how to contain associations when paginating.

Plain Text View (#)


1. $this->paginate['User'] = array(
2. 'contain' => array('Profile', 'Account'),
3. 'order' => 'User.username'
4. );
5. $users = $this->paginate('User');

# (#ContainableBehavior-options-1327) ContainableBehavior options

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1327/ContainableBehavior-
options) .. Mas info sobre traduciones (/es/view/818)

The ContainableBehavior has a number of options that can be set when the Behavior is attached to a model. The
settings allow you to fine tune the behavior of Containable and work with other behaviors more easily.

recursive (boolean, optional) set to true to allow containable to automatically determine the recursiveness level
needed to fetch specified models, and set the model recursiveness to this level. setting it to false disables this
feature. The default value is true.
notices (boolean, optional) issues E_NOTICES for bindings referenced in a containable call that are not valid.
The default value is true.
autoFields: (boolean, optional) auto-add needed fields to fetch requested bindings. The default value is true.

You can change ContainableBehavior settings at run time by reattaching the behavior as seen in Using behaviors
(/es/view/1070/Using-Behaviors)

ContainableBehavior can sometimes cause issues with other behaviors or queries that use aggregate functions and/or
GROUP BY statements. If you get invalid SQL errors due to mixing of aggregate and non-aggregate fields, try disabling
the autoFields setting.

Plain Text View (#)


1. $this->Post->Behaviors->attach('Containable', array('autoFields' => false));

6.3 (#Translate-1328) Translate

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1328)


Comparar con el texto original (/es/compare/1328/Translate)

Mas info sobre traduciones (/es/view/818)

TranslateBehavior es bastante fácil de configurar y trabaja fuera de la caja con muy poca configuración. En esta
sección, usted aprenderá cómo añadir y configurar el comportamiento (behavior) para usarlo en cualquier modelo.

6.3.1 (#Inicializando-las-tablas-de-la-Base-de-datos-i18n-1329) Inicializando las tablas de la Base de datos i18n

Puede utilizar la consola de CakePHP o puede crearlo manualmente. Se recomienda utilizar la consola para esto, por
que podrían pasar que hallan cambios de diseño en las futuras versiones de CakePHP. Si lo haces por consola,
puedes estar seguro que tiene el correcto diseño.

Plain Text View (#)


1. ./cake i18n

Seleccione [I] y se ejecuta el script e inicializa la Base de datos i18n. Se le preguntará si desea eliminar cualquiera
que exista y si desea crearla.Responde un Sí, si usted esta seguro de que no existe una tabla i18n, y responda con Sí

223 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

para crear la tabla de nuevo.

6.3.2 (#Adjuntando-el-Comportamiento-de-Traducción-a-tus--1330) Adjuntando el Comportamiento de Traducción a tus Modelos

Se debe incorporar al modelo haciendo uso de la propiedad $actsAs como en el siguiente ejemplo.

Plain Text View (#)


1. <?php
2. class Post extends AppModel {
3. var $name = 'Post';
4. var $actsAs = array(
5. 'Translate'
6. );
7. }
8. ?>

Esto no hará nada aún, pues es necesario configurar algunas opciones antes de comenzar a funcionar. Se deben
definir qué campos de el modelo actual serán rastreados en la tabla de traducciones creada en el paso anterior.

6.3.3 (#Definiendo-los-Campos-1331) Definiendo los Campos

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1331)


Comparar con el texto original (/es/compare/1331/Definiendo-los-Campos)

Mas info sobre traduciones (/es/view/818)

Se pueden establecer los campos simplemente extendiendo el valor 'Translate' con otro array, por ejemplo:

Plain Text View (#)


1. <?php
2. class Post extends AppModel {
3. var $name = 'Post';
4. var $actsAs = array(
5. 'Translate' => array(
6. 'campoUno', 'campoDos', 'campoN'
7. )
8. );
9. }
10. ?>

Luego de haber hecho esto (por ejemplo poner "nombre" como uno de los campos) ya has terminado la configuración
básica. Genial! De acuerdo con el ejemplo anterior, ahora el modelo debería verse algo así:

Plain Text View (#)


1. <?php
2. class Post extends AppModel {
3. var $name = 'Post';
4. var $actsAs = array(
5. 'Translate' => array(
6. 'nombre'
7. )
8. );
9. }
10. ?>

6.3.4 (#Conclusiones-1332) Conclusiones

Desde ahora en cada actualización/creación de un registro hará que TranslateBehavior copie el valor "nombre" en la
tabla de traducciones (por defecto: i18n) de acuerdo a la localización actual. Una localización corresponde al
identificador de una lengua

224 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

La localización actual es el valor actual de Configure::read('Config.language'). El valor de Config.language es


establecido en la Clase L10n - a no ser que ya se haya establecido. Sin embargo, TranlateBehavior te permite invalidar
esto último 'al vuelo', lo cual permite al usuario de tus páginas crear multiples versiones sin la necesidad de que este
cambie sus preferencias. Más sobre esto en la siguiente sección.

6.3.5 (#Obtener-todos-los-registros-de-traducción-para-un-1333) Obtener todos los registros de traducción para un campo determinado

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1333)


Comparar con el texto original (/es/compare/1333/Obtener-todos-los-registros-de-traducción-para-un)

Mas info sobre traduciones (/es/view/818)

Si se desea obtener todos los registros de traducción asociados al modelo actual, simplemente se extiende el arreglo
de campos en la configuracion como se muestra abajo. El nombre se puede definir sin restricciones

Plain Text View (#)


1. <?php
2. class Post extends AppModel {
3. var $name = 'Post';
4. var $actsAs = array(
5. 'Translate' => array(
6. 'name' => 'nameTranslation'
7. )
8. );
9. }
10. ?>

Con esta configuración el resultado de find() se verá similar a esto:

Plain Text View (#)

225 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. Array
2. (
3. [Post] => Array
4. (
5. [id] => 1
6. [name] => Beispiel Eintrag
7. [body] => lorem ipsum...
8. [locale] => de_de
9. )
10. [nameTranslation] => Array
11. (
12. [0] => Array
13. (
14. [id] => 1
15. [locale] => en_us
16. [model] => Post
17. [foreign_key] => 1
18. [field] => name
19. [content] => Example entry
20. )
21. [1] => Array
22. (
23. [id] => 2
24. [locale] => de_de
25. [model] => Post
26. [foreign_key] => 1
27. [field] => name
28. [content] => Beispiel Eintrag
29. )
30. )
31. )

Nota: El registro del modelo contiene un campo virtual llamado "locale", el cual indica que "locale" es usado en el
resultado.

6.3.5.1 (#Using-the-bindTranslation-method-1334) Using the bindTranslation method

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1334/Using-the-bindTranslation-
method) .. Mas info sobre traduciones (/es/view/818)

You can also retrieve all translations, only when you need them, using the bindTranslation method

bindTranslation($fields, $reset)

$fields is a named-key array of field and association name, where the key is the translatable field and the value is the
fake association name.

Plain Text View (#)


1. $this->Post->bindTranslation(array ('name' => 'nameTranslation'));
2. $this->Post->find('all', array ('recursive'=>1)); // need at least recursive 1 for this to work.

With this setup the result of your find() should look something like this:

Plain Text View (#)

226 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. Array
2. (
3. [Post] => Array
4. (
5. [id] => 1
6. [name] => Beispiel Eintrag
7. [body] => lorem ipsum...
8. [locale] => de_de
9. )
10. [nameTranslation] => Array
11. (
12. [0] => Array
13. (
14. [id] => 1
15. [locale] => en_us
16. [model] => Post
17. [foreign_key] => 1
18. [field] => name
19. [content] => Example entry
20. )
21. [1] => Array
22. (
23. [id] => 2
24. [locale] => de_de
25. [model] => Post
26. [foreign_key] => 1
27. [field] => name
28. [content] => Beispiel Eintrag
29. )
30. )
31. )

6.3.6 (#Saving-in-another-language-1335) Saving in another language

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1335/Saving-in-another-
language) .. Mas info sobre traduciones (/es/view/818)

You can force the model which is using the TranslateBehavior to save in a language other than the on detected.

To tell a model in what language the content is going to be you simply change the value of the $locale property on
the model before you save the data to the database. You can do that either in your controller or you can define it
directly in the model.

Example A: In your controller Plain Text View (#)


1. <?php
2. class PostsController extends AppController {
3. var $name = 'Posts';
4.
5. function add() {
6. if ($this->data) {
7. $this->Post->locale = 'de_de'; // we are going to save the german version
8. $this->Post->create();
9. if ($this->Post->save($this->data)) {
10. $this->redirect(array('action' => 'index'));
11. }
12. }
13. }
14. }
15. ?>

Example B: In your model Plain Text View (#)

227 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <?php
2. class Post extends AppModel {
3. var $name = 'Post';
4. var $actsAs = array(
5. 'Translate' => array(
6. 'name'
7. )
8. );
9.
10. // Option 1) just define the property directly
11. var $locale = 'en_us';
12.
13. // Option 2) create a simple method
14. function setLanguage($locale) {
15. $this->locale = $locale;
16. }
17. }
18. ?>

6.3.7 (#Multiple-Translation-Tables-1336) Multiple Translation Tables

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1336/Multiple-Translation-
Tables) .. Mas info sobre traduciones (/es/view/818)

If you expect a lot entries you probably wonder how to deal with a rapidly growing database table. There are two
properties introduced by TranslateBehavior that allow to specify which "Model" to bind as the model containing the
translations.

These are $translateModel and $translateTable.

Lets say we want to save our translations for all posts in the table "post_i18ns" instead of the default "i18n" table. To
do so you need to setup your model like this:

Plain Text View (#)


1. <?php
2. class Post extends AppModel {
3. var $name = 'Post';
4. var $actsAs = array(
5. 'Translate' => array(
6. 'name'
7. )
8. );
9.
10. // Use a different model (and table)
11. var $translateModel = 'PostI18n';
12. }
13. ?>

Important is that you have to pluralize the table. It is now a usual model and can be treated as such and thus comes
with the conventions involved. The table schema itself must be identical with the one generated by the CakePHP
console script. To make sure it fits one could just initialize a empty i18n table using the console and rename the table
afterwards.

6.3.7.1 (#Create-the-TranslateModel-1337) Create the TranslateModel

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1337/Create-the-TranslateModel)
.. Mas info sobre traduciones (/es/view/818)

For this to work you need to create the actual model file in your models folder. Reason is that there is no property to
set the displayField directly in the model using this behavior yet.

Make sure that you change the $displayField to 'field'.

228 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Plain Text View (#)


1. <?php
2. class PostI18n extends AppModel {
3. var $displayField = 'field'; // important
4. }
5. // filename: post_i18n.php
6. ?>

That's all it takes. You can also add all other model stuff here like $useTable. But for better consistency we could do
that in the model which actually uses this translation model. This is where the optional $translateTable comes into
play.

6.3.7.2 (#Changing-the-Table-1338) Changing the Table

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1338/Changing-the-Table) .. Mas
info sobre traduciones (/es/view/818)

If you want to change the name of the table you simply define $translateTable in your model, like so:

Plain Text View (#)


1. <?php
2. class Post extends AppModel {
3. var $name = 'Post';
4. var $actsAs = array(
5. 'Translate' => array(
6. 'name'
7. )
8. );
9.
10. // Use a different model
11. var $translateModel = 'PostI18n';
12.
13. // Use a different table for translateModel
14. var $translateTable = 'post_translations';
15. }
16. ?>

Please note that you can't use $translateTable alone. If you don't intend to use a custom $translateModel then leave
this property untouched. Reason is that it would break your setup and show you a "Missing Table" message for the
default I18n model which is created in runtime.

6.4 (#Arboles-Tree-1339) Arboles (Tree)

Es muy común que se desea almacenar datos jerárquicos en una tabla de base de datos. Ejemplos de estos datos
pueden ser: categorías con subcategorías ilimitadas, los datos relativos a un sistema de menús multinivel o una
representación literal de la jerarquía tal como se utiliza para almacenar objetos de control de acceso con la lógica
ACL.

Para pequeños árboles de datos, o cuando los datos son de sólo unos pocos niveles de profundidad es simple añadir
un campo parent_id a su tabla de base de datos y utilizar este para hacer un seguimiento de cual item es padre de
quien. Sin embargo, Cake Viene equipado con este paquete, pero con un comportamiento de gran alcance que le
permite utilizar los beneficios de la lógica MPTT (http://dev.mysql.com/tech-resources/articles/hierarchical-data.html)
sin preocuparse de cualquiera de los entresijos de la técnica - a menos que ud lo desee ;).

6.4.1 (#Requerimientos-1340) Requerimientos

Para poder usar la funcionalidad de árbol, la tabla de la base de datos debe tener los 3 campos listados a
continuación (enteros todos):

padre - el nombre por defecto del campo es parent_id, para almacenar el id del objeto padre
izquierda - el nombre por defecto del campo es lft, para almacenar el valor lft de la fila actual.
deracha - el nombre por defecto del campo es rght, para almacenar el valor rght de la fila actual.

229 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Si esta familiarizado con la lógina MPTT ud puede preguntarse por que el campos parent existe - simplemente es más
facil de realizar ciertas tareas si existe un enlace directo al padre almacenado en la base de datos - tales como la
búsquera de los hijos directos.

6.4.2 (#Uso-Básico-1341) Uso Básico

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1341)


Comparar con el texto original (/es/compare/1341/Uso-Básico)

Mas info sobre traduciones (/es/view/818)

El comportamiento de arbol tiene muchas cosas incluidas, pero empecemos con un simple ejemplo - crearemos una
pequeña tabla en una base de datos y le agregaremos algunos datos:

CREATE TABLE categories (


id INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT,
parent_id INTEGER(10) DEFAULT NULL,
lft INTEGER(10) DEFAULT NULL,
rght INTEGER(10) DEFAULT NULL,
name VARCHAR(255) DEFAULT '',
PRIMARY KEY (id)
);

INSERT INTO `categories` (`id`, `name`, `parent_id`, `lft`, `rght`) VALUES(1, 'Mis Categorias', NULL, 1, 30);
INSERT INTO `categories` (`id`, `name`, `parent_id`, `lft`, `rght`) VALUES(2, 'Diversion', 1, 2, 15);
INSERT INTO `categories` (`id`, `name`, `parent_id`, `lft`, `rght`) VALUES(3, 'Deportes', 2, 3, 8);
INSERT INTO `categories` (`id`, `name`, `parent_id`, `lft`, `rght`) VALUES(4, 'Surfing', 3, 4, 5);
INSERT INTO `categories` (`id`, `name`, `parent_id`, `lft`, `rght`) VALUES(5, 'Alpinismo', 3, 6, 7);
INSERT INTO `categories` (`id`, `name`, `parent_id`, `lft`, `rght`) VALUES(6, 'Amigos', 2, 9, 14);
INSERT INTO `categories` (`id`, `name`, `parent_id`, `lft`, `rght`) VALUES(7, 'Gerald', 6, 10, 11);
INSERT INTO `categories` (`id`, `name`, `parent_id`, `lft`, `rght`) VALUES(8, 'Gwendolyn', 6, 12, 13);
INSERT INTO `categories` (`id`, `name`, `parent_id`, `lft`, `rght`) VALUES(9, 'Trabajo', 1, 16, 29);
INSERT INTO `categories` (`id`, `name`, `parent_id`, `lft`, `rght`) VALUES(10, 'Reportes', 9, 17, 22);
INSERT INTO `categories` (`id`, `name`, `parent_id`, `lft`, `rght`) VALUES(11, 'Anual', 10, 18, 19);
INSERT INTO `categories` (`id`, `name`, `parent_id`, `lft`, `rght`) VALUES(12, 'Status', 10, 20, 21);
INSERT INTO `categories` (`id`, `name`, `parent_id`, `lft`, `rght`) VALUES(13, 'Viajes', 9, 23, 28);
INSERT INTO `categories` (`id`, `name`, `parent_id`, `lft`, `rght`) VALUES(14, 'Nacional', 13, 24, 25);
INSERT INTO `categories` (`id`, `name`, `parent_id`, `lft`, `rght`) VALUES(15, 'Internacional', 13, 26, 27);

Para el propósito de verificar que todo está configurado correctamente, podemos crear un metodo de testeo y obtener
los contenidos de nuestro arbol de categorias para ver como queda. Con un simple controlador:

Plain Text View (#)


1. <?php
2. class CategoriesController extends AppController {
3. var $name = 'Categories';
4.
5. function index() {
6. $this->data = $this->Category->generatetreelist(null, null, null, '&nbsp;&nbsp;&nbsp;');
7. debug ($this->data); die;
8. }
9. }
10. ?>

y un metodo aun mas simple en el modelo:

Plain Text View (#)

230 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <?php
2. // app/models/category.php
3. class Category extends AppModel {
4. var $name = 'Category';
5. var $actsAs = array('Tree');
6. }
7. ?>

Podemos verificar como se ve que nuestro arbol de categoria visitando /categories Deberias ver algo como:

Mis Categorias
Diversion
Deportes
Surfing
Alpinismo
Amigos
Gerald
Gwendolyn
Trabajo
Reportes
Anual
Status
Viajes
Nacional
Internacional

6.4.2.1 (#Agregando-datos-1342) Agregando datos

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1342)


Comparar con el texto original (/es/compare/1342/Agregando-datos)

Mas info sobre traduciones (/es/view/818)

En la seccion anterior, usamos datos pre-existentes y chequeamos que se vieran en forma jerarquica con el método
generatetreelist. Sin embargo, usualmente agregaríamos los datos de la misma forma que lo hariamos con cualquier
modelo. Por ejemplo:

Plain Text View (#)


1. // pseudo código del controlador
2. $data['Category']['parent_id'] = 3;
3. $data['Category']['name'] = 'Skating';
4. $this->Category->save($data);

Cuando se usa el comportamiento de arbol no es necesario hacer nada mas que configurar el parent_id, y el
comportamiento de arbol se encargara del resto. Si no se setea el parent_id el comportamiento de arbol lo agregara al
arbol como una entrada en el nivel superior:

Plain Text View (#)


1. // pseudo codigo controlador
2. $data = array();
3. $data['Category']['name'] = 'Otra Categoria';
4. $this->Category->save($data);

Ejecutando estos dos trozos de código alterará el árbol como sigue:

Mis Categorias
Diversion
Deportes
Surfing
Alpinismo
Skating New
Amigos

231 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Gerald
Gwendolyn
Trabajo
Reportes
Anual
Status
Viajes
Nacional
Internacional
Otra Categoria New

6.4.2.2 (#Modificando-datos-1343) Modificando datos

Modificar datos es tan transparente como agregar nuevos datos. Si modificas algo, pero no modificas el campo
parent_id - la estructura de tus datos permanecera inalterada. Por ejemplo:

Plain Text View (#)


1. // pseudo codigo de controlador
2. $this->Category->id = 5; // id de Apinismo
3. $this->Category->save(array('name' =>'Pesca'));

El codigo anterior no modifica el parent_id - incluso si el parent_id es incluido en los datos que son pasados al
método save, si el valor no ha sido cambiado, tampoco lo hace la estructura de datos. Entonces, el arbol de datos
queda:

Mis Categorias
Diversion
Deportes
Surfing
Pesca Updated
Skating
Amigos
Gerald
Gwendolyn
Trabajo
Reportes
Anual
Status
Viajes
Nacional
Internacional
Otra Categoria

Mover un dato a traves del arbol tambien es simple. Digamos que Pesca no pertenece a Deportes, sino que deberia
estar en Otra Categoria. Con el siguiente código:

Plain Text View (#)


1. // pseudo codigo de controlador
2. $this->Category->id = 5; // id of Pesca
3. $newParentId = $this->Category->field('id', array('name' => 'Otra Categoria'));
4. $this->Category->save(array('parent_id' => $newParentId));

Como es de esperar la estructura queda modificada a:

Mis Categorias
Diversion
Deportes
Surfing
Skating
Amigos
Gerald
Gwendolyn
Trabajo
Reportes
Anual

232 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Status
Viajes
Nacional
Internacional
Otra Categoria
Pesca Movido

6.4.2.3 (#Borrando-datos-1344) Borrando datos

El comportamiento de arbol provee algunas formas para manejar la eliminación de datos. Para comenzar con un
ejemplo simple, diremos que la categoria reportes ya no es necesaria. Para eliminarla y cualquier hijo que ella tenga
basta llamar a delete tal como lo harias en cualquier modelo. Por ejemplo, en el siguiente código:

Plain Text View (#)


1. // pseudo codigo de controlador
2. $this->Category->id = 10;
3. $this->Category->delete();

El arbol de categorias sería modificado como sigue:

Mis Categorias
Diversion
Deportes
Surfing
Skating
Amigos
Gerald
Gwendolyn
Trabajo
Viajes
Nacional
Internacional
Otras Categorias
Pesca

6.4.2.4 (#Haciendo-consultas-y-usando-tus-datos-1345) Haciendo consultas y usando tus datos

Usar y manipular datos jerarquicos puede ser algo complejo. Ademas de los metodos de busqueda del nucleo como
find(), con los arboles tenemos unos cuantos metodos más para su manipulacion.

Muchos metodos del comportamiento de arbol devuelven y se apoyan en el orden del campo lft. Si llamas a find() y
no ordenas por el campo lft, o llamas algun metodo de arboles entregandole un tipo de ordenamiento, quizas
obtengas resultados no deseados.

6.4.2.4.1 (#El-método-children-1346) El método children

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1346)


Comparar con el texto original (/es/compare/1346/El-método-children)

Mas info sobre traduciones (/es/view/818)

El método children toma la llave primaria (id) de una fila y retorna los hijos, por defecto en el roden en que aparecen
en el árbol. El segundo parámetro es opcional y define si se entregan o no sólo los hijos directos. Usando el ejemplo
de la sección anterior:

Plain Text View (#)


1. $allChildren = $this->Category->children(1); // un arreglo plano con 11 valores
2. // -- o bien --
3. $this->Category->id = 1;
4. $allChildren = $this->Category->children(); // un arreglo plano con 11 valores
5. // Retornar solo los hijos directos
6. $directChildren = $this->Category->children(1, true); //un arreglo plano con 2 valores

233 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Si quieres un arreglo recursivo utiliza find('threaded')

6.4.2.4.2 (#Contando-los-hijos-1347) Contando los hijos

Tal como el método children, childCount toma la llave primaria (id) y retorna cuantos hijos tiene. El segundo
parámetro es opcional y define si se contarán o no los hijos directos. Usando los datos del ejemplo anterior:

Plain Text View (#)


1. $totalChildren = $this->Category->childCount(1); // entrega 11
2. // -- o bien --
3. $this->Category->id = 1;
4. $directChildren = $this->Category->childCount(); // entrega 11
5. //Solo los hijos directos
6. $numChildren = $this->Category->childCount(1, true); // entrega 2

6.4.2.4.3 (#generatetreelist-1348) generatetreelist

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1348/generatetreelist) .. Mas
info sobre traduciones (/es/view/818)

generatetreelist ($conditions=null, $keyPath=null, $valuePath=null, $spacer= '_', $recursive=null)

This method will return data similar to find('list') (/es/view/1022/find-list) , with an indented prefix to show the
structure of your data. Below is an example of what you can expect this method to return.

$conditions - Uses the same conditional options as find().


$keyPath - Path to the field to use for the key.
$valuePath - Path to the field to use for the label.
$spacer - The string to use in front of each item to indicate depth.
$recursive - The number of levels deep to fetch associated records

All the parameters are optional, with the following defaults:

$conditions = null
$keyPath = Model's primary key
$valuePath = Model's displayField
$spacer = '_'
$recursive = Model's recursive setting

Plain Text View (#)


1. $treelist = $this->Category->generatetreelist();

Output:

array(
[1] => "My Categories",
[2] => "_Fun",
[3] => "__Sport",
[4] => "___Surfing",
[16] => "___Skating",
[6] => "__Friends",
[7] => "___Gerald",
[8] => "___Gwendolyn",
[9] => "_Work",
[13] => "__Trips",
[14] => "___National",
[15] => "___International",
[17] => "Other People's Categories",
[5] => "_Extreme fishing"
)

6.4.2.4.4 (#getparentnode-1349) getparentnode

234 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1349/getparentnode) .. Mas info
sobre traduciones (/es/view/818)

This convenience function will, as the name suggests, return the parent node for any node, or false if the node has no
parent (its the root node). For example:

Plain Text View (#)


1. $parent = $this->Category->getparentnode(2); //<- id for fun
2. // $parent contains All categories

6.4.2.4.5 (#getpath-1350) getpath

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1350/getpath) .. Mas info sobre
traduciones (/es/view/818)

getpath( $id = null, $fields = null, $recursive = null )

The 'path' when refering to hierachial data is how you get from where you are to the top. So for example the path from
the category "International" is:

My Categories
...
Work
Trips
...
International

Using the id of "International" getpath will return each of the parents in turn (starting from the top).

Plain Text View (#)


1. $parents = $this->Category->getpath(15);

// contents of $parents
array(
[0] => array('Category' => array('id' => 1, 'name' => 'My Categories', ..)),
[1] => array('Category' => array('id' => 9, 'name' => 'Work', ..)),
[2] => array('Category' => array('id' => 13, 'name' => 'Trips', ..)),
[3] => array('Category' => array('id' => 15, 'name' => 'International', ..)),
)

6.4.3 (#Uso-Avanzado-1351) Uso Avanzado

Este comportamiento de modelo no sólo trabaja en segundo plano, hay una gran variedad de métodos específicos
definidos en este comportamiento para antender todas tus necesidades de datos jerárquicos, y cualquier problema
inesperado que pueda surgir en el proceso.

6.4.3.1 (#moveDown-1352) moveDown

Utilizado para mover un único nodo hacia abajo del árbol. Debes indicar el ID del elemento a mover y un número
entero positivo de cuantas posiciones el nodo debería ser movido hacia abajo. Todos los nodos hijos del nodo a
mover también serán movidos

Un ejemplo de una acción de controlador (en un controlador llamado Categories) que mueve un nodo hacia abajo del
arbol:

Plain Text View (#)

235 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. function movedown($name = null, $delta = null) {


2. $cat = $this->Category->findByName($name);
3. if (empty($cat)) {
4. $this->Session->setFlash('No hay una categoría de nombre ' . $name);
5. $this->redirect(array('action' => 'index'), null, true);
6. }
7.
8. $this->Category->id = $cat['Category']['id'];
9.
10. if ($delta > 0) {
11. $this->Category->moveDown($this->Category->id, abs($delta));
12. } else {
13. $this->Session->setFlash('Por favor indique el número de posiciones que el nodo debe ser mo
14. }
15.
16. $this->redirect(array('action' => 'index'), null, true);
17. }

Por ejemplo, si quicieras mover la categoría "Sport" un nivel hacia abajo, deberías llamar a: /categories/movedown
/Sport/1.

6.4.3.2 (#moveUp-1353) moveUp

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1353/moveUp) .. Mas info sobre
traduciones (/es/view/818)

Used to move a single node up the tree. You need to provide the ID of the element to be moved and a positive number
of how many positions the node should be moved up. All child nodes will also be moved.

Here's an example of a controller action (in a controller named Categories) that moves a node up the tree:

Plain Text View (#)


1. function moveup($name = null, $delta = null){
2. $cat = $this->Category->findByName($name);
3. if (empty($cat)) {
4. $this->Session->setFlash('There is no category named ' . $name);
5. $this->redirect(array('action' => 'index'), null, true);
6. }
7.
8. $this->Category->id = $cat['Category']['id'];
9.
10. if ($delta > 0) {
11. $this->Category->moveup($this->Category->id, abs($delta));
12. } else {
13. $this->Session->setFlash('Please provide a number of positions the category should be moved
14. }
15.
16. $this->redirect(array('action' => 'index'), null, true);
17.
18. }

For example, if you would like to move the category "Gwendolyn" up one position you would request /categories
/moveup/Gwendolyn/1. Now the order of Friends will be Gwendolyn, Gerald.

6.4.3.3 (#removeFromTree-1354) removeFromTree

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1354/removeFromTree) .. Mas
info sobre traduciones (/es/view/818)

removeFromTree($id=null, $delete=false)

Using this method wil either delete or move a node but retain its sub-tree, which will be reparented one level higher.

236 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

It offers more control than delete() (/es/view/1316/delete) , which for a model using the tree behavior will remove the
specified node and all of its children.

Taking the following tree as a starting point:

My Categories
Fun
Sport
Surfing
Extreme knitting
Skating

Running the following code with the id for 'Sport'

Plain Text View (#)


1. $this->Node->removeFromTree($id);

The Sport node will be become a top level node:

My Categories
Fun
Surfing
Extreme knitting
Skating
Sport Moved

This demonstrates the default behavior of removeFromTree of moving the node to have no parent, and re-parenting all
children.

If however the following code snippet was used with the id for 'Sport'

Plain Text View (#)


1. $this->Node->removeFromTree($id,true);

The tree would become

My Categories
Fun
Surfing
Extreme knitting
Skating

This demonstrates the alternate use for removeFromTree, the children have been reparented and 'Sport' has been
deleted.

6.4.3.4 (#reorder-1355) reorder

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1355/reorder) .. Mas info sobre
traduciones (/es/view/818)

reorder ( array('id' => null, 'field' => $Model->displayField, 'order' => 'ASC', 'verify' => true) )

Reorders the nodes (and child nodes) of the tree according to the field and direction specified in the parameters. This
method does not change the parent of any node.

Plain Text View (#)


1. $model->reorder(array(
2. 'id' => , //id of record to use as top node for reordering, default: $Model->id
3. 'field' => , //which field to use in reordering, default: $Model->displayField
4. 'order' => , //direction to order, default: 'ASC'
5. 'verify' => //whether or not to verify the tree before reorder, default: true
6. ));

6.4.4 (#Data-Integrity-1356) Data Integrity

237 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Debido a la naturaleza de las estructuras complejas autorreferentes como los árboles y las listas enlazadas,
ocasionalmente pueden romperse debido a una llamada poco cuidadosa. Tómalo con calma, ¡no todo está perdido!
Tree Behavior contiene varias características que antes no estaban documentadas, diseñadas para recuperarse de tales
situaciones.

6.4.4.1 (#Recover-1628) Recover

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1628/Recover) .. Mas info sobre
traduciones (/es/view/818)

recover(&$model, $mode = 'parent', $missingParentAction = null)

The mode parameter is used to specify the source of info that is valid/correct. The opposite source of data will be
populated based upon that source of info. E.g. if the MPTT fields are corrupt or empty, with the $mode 'parent' the
values of the parent_id field will be used to populate the left and right fields. The missingParentAction parameter only
applies to "parent" mode and determines what to do if the parent field contains an id that is not present.

Available $mode options:

'parent' - use the existing parent_id's to update the lft and rght fields
'tree' - use the existing lft and rght fields to update parent_id

Available missingParentActions options when using mode='parent':

null - do nothing and carry on


'return' - do nothing and return
'delete' - delete the node
int - set the parent_id to this id

Plain Text View (#)


1. // Rebuild all the left and right fields based on the parent_id
2. $this->Category->recover();
3. // or
4. $this->Category->recover('parent');
5.
6. // Rebuild all the parent_id's based on the lft and rght fields
7. $this->Category->recover('tree');

6.4.4.2 (#Reorder-1629) Reorder

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1629/Reorder) .. Mas info sobre
traduciones (/es/view/818)

reorder(&$model, $options = array())

Reorders the nodes (and child nodes) of the tree according to the field and direction specified in the parameters. This
method does not change the parent of any node.

Reordering affects all nodes in the tree by default, however the following options can affect the process:

'id' - only reorder nodes below this node.


'field' - field to use for sorting, default is the displayField for the model.
'order' - 'ASC' for ascending, 'DESC' for descending sort.
'verify' - whether or not to verify the tree prior to resorting.

$options is used to pass all extra parameters, and has the following possible keys by default, all of which are
optional:

Plain Text View (#)

238 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. array(
2. 'id' => null,
3. 'field' => $model->displayField,
4. 'order' => 'ASC',
5. 'verify' => true
6. )

6.4.4.3 (#Verify-1630) Verify

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1630/Verify) .. Mas info sobre
traduciones (/es/view/818)

verify(&$model)

Returns true if the tree is valid otherwise an array of errors, with fields for type, incorrect index and message.

Each record in the output array is an array of the form (type, id, message)

type is either 'index' or 'node'


'id' is the id of the erroneous node.
'message' depends on the error

Plain Text View (#)


1. $this->Categories->verify();

Example output:

Array
(
[0] => Array
(
[0] => node
[1] => 3
[2] => left and right values identical
)
[1] => Array
(
[0] => node
[1] => 2
[2] => The parent node 999 doesn't exist
)
[10] => Array
(
[0] => index
[1] => 123
[2] => missing
)
[99] => Array
(
[0] => node
[1] => 163
[2] => left greater than right
)

7 (#Ayudantes-del-Core-1357) Ayudantes del Core

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1357)


Comparar con el texto original (/es/compare/1357/Ayudantes-del-Core)

239 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Mas info sobre traduciones (/es/view/818)

Los Ayudantes o Helpers son clases a modo de componentes para la capa de presentación de tu aplicación. Contienen
lógica de presentación que puede ser compartida por muchas vistas, elementos y layouts.

Esta sección describe cada uno de los Helpers incluidos en CakePHP como Form, Html, JavaScript y RSS.

Lee la sección Helpers (/es/view/98/helpers) para aprender más acerca de los helpers y cómo puedes crear los tuyos
propios.

7.1 (#AJAX-1358) AJAX

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1358)


Comparar con el texto original (/es/compare/1358/AJAX)

Mas info sobre traduciones (/es/view/818)

El AjaxHelper utilizas las populares librerías Prototype y script.aculo.us para operaciones Ajax y efectos en el lado del
cliente. Para utilizar el AjaxHelper has de tener la versión actual de las librerías de JavaScript de www.prototypejs.org
(http://www.prototypejs.org) y http://script.aculo.us (http://script.aculo.us/) situadas en /app/webroot/js. Además has de
incluir las librerías Prototype y script.aculo.us en los layouts o vistas que requieran las funcionalidades de
AjaxHelper.

Para poder cargar las librerías Prototype y script.aculo.us necesitarás incluir los helpers Ajax y Javascript en tu
controlador:

Plain Text View (#)


1. class WidgetsController extends AppController {
2. var $name = 'Widgets';
3. var $helpers = array('Html','Ajax','Javascript');
4. }

Una vez que hayas incluido el helper de javascript en tu controlador, puedes utilizar el método link() de $javascript
para incluir las liberías Prototype y script.aculo.us en la vista:

Plain Text View (#)


1. echo $javascript->link('prototype');
2. echo $javascript->link('scriptaculous');

Ahora ya puedes puedes utilizar el helper Ajax en tu vista:

Plain Text View (#)


1. $ajax->loquesea();

Si se incluye el componente RequestHandler (/es/view/174/request-handling) en el controlador, CakePHP


automáticamente aplicará el layout Ajax cuando se realize una petición de una acción mediante AJAX.

Plain Text View (#)


1. class WidgetsController extends AppController {
2. var $name = 'Widgets';
3. var $helpers = array('Html','Ajax','Javascript');
4. var $components = array( 'RequestHandler' );
5. }

7.1.1 (#AjaxHelper-Options-1359) AjaxHelper Options

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1359)


Comparar con el texto original (/es/compare/1359/AjaxHelper-Options)

Mas info sobre traduciones (/es/view/818)

240 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

La mayoría de los métodos del AjaxHelper permiten suministrar un arreglo de opciones ($options). Puedes usar este
arreglo para configurar el comportamiento del AjaxHelper. Antes de cubrir los métodos específicos del helper,
veamos las diferentes opciones disponibles a través de este arreglo. Esta sección será de utilidad como referencia
mientras inicias el uso de los métodos del AjaxHelper.

7.1.1.1 (#General-Options-1360) General Options

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1360)


Comparar con el texto original (/es/compare/1360/General-Options)

Mas info sobre traduciones (/es/view/818)

$options['url']
La url del controlador/acción que se quiere llamar.
$options['update']
El id del elemento DOM a ser actualizado con el contenido que retorne.
$options['frequency']
El número de segundos entre intervalos de observación.
$options['type']
Indica si la petición se realiza de forma síncrona ó asíncrona (por omisión).

7.1.1.2 (#Opciones-de-retrollamadas-Callback-Options-1361) Opciones de retrollamadas (Callback Options)

Las opciones de Callbacks te permiten llamar a las funciones de JavaScript en puntos específicos en el proceso de
solicitud (request). Si estás buscando insertar un poco de lógica antes, después, o durante tus operaciones de
AjaxHelper, usa estas Callbacks para estableces las cosas.

$options keys Description

$options['condition'] El fragmento de código JavaScriptque necesita evaluar a true antes de que la solicitud se inicie.

$options['before'] Se ejecuta antes de que una solicitud sea efectuada. Un uso común de esta es permitir la
visibilidad de un indicador de progreso.

$options['confirm'] Texto a mostrar en un cuadro de confirmación de JavaScript antes de proceder.

$options['loading'] Código de la Callback que se ejecutará mientras que los datos se recuperan desde el servidor.

$options['after'] JavaScript llamado inmediatamente después de que se ejecuta una solicitud; se dispare antes de
que se ejecute la callback $options['loading'].

$options['loaded'] Código de la Callback a ser ejecutado cuando un documento remoto es recivido por el cliente.

$options['interactive']Llamada cuando un usuario puede interactuar con el documento remoto, a pesar de que no ha
terminado de cargar.

$options['complete'] Callback JavaScript a ser ejecutada cuando se completa un XMLHttpRequest.

7.1.2 (#Métodos-1362) Métodos

7.1.2.1 (#link-1363) link

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1363)


Comparar con el texto original (/es/compare/1363/link)

Mas info sobre traduciones (/es/view/818)

241 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

link(string $title, string $href, array $options, string $confirm, boolean $escapeTitle)

Devuelve un enlace a una acción remota definida por $options['url'] o $href que se llama en background utilizando
XMLHttpRequest cuando se hace clic en el enlace. El resultado de esa petición puede ser insertada en un objeto DOM
cuya identificación se puede especificar con $options['update'].

Si $options['url'] esta en blanco href es utilizado en su lugar

Ejemplo:

Plain Text View (#)


1. <div id="post">
2. </div>
3. <?php echo $ajax->link(
4. 'View Post',
5. array( 'controller' => 'posts', 'action' => 'view', 1 ),
6. array( 'update' => 'post' )
7. );
8. ?>

Por defecto, estas solicitudes son procesadas asincrónicamente mientras se utilizan diferentes callbacks

Ejemplo:

Plain Text View (#)


1. <div id="post">
2. </div>
3. <?php echo $ajax->link(
4. 'View Post',
5. array( 'controller' => 'posts', 'action' => 'post', 1 ),
6. array( 'update' => 'post', 'complete' => 'alert( "Hello World" )' )
7. );
8. ?>

Para usa procesamiento sincrónico especificar $options['type'] = 'synchronous'.

Para automatizar que el layout utilizado sea ajax incluir el componente RequestHandler en el controlador

Por defecto el contenido del elemento es reemplazado. Para cambiar este comportamiento especificar
$options['position']

Ejemplo:

Plain Text View (#)


1. <div id="post">
2. </div>
3. <?php echo $ajax->link(
4. 'View Post',
5. array( 'controller' => 'posts', 'action' => 'view', 1),
6. array( 'update' => 'post', 'position' => 'top' )
7. );
8. ?>

$confirm puede ser usado para llamar un JavaScript confirm() message antes de que la petición se efectúe. Permite al
usuario prever la ejecución.

Ejemplo:

Plain Text View (#)

242 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <div id="post">
2. </div>
3. <?php echo $ajax->link(
4. 'Delete Post',
5. array( 'controller' => 'posts', 'action' => 'delete', 1 ),
6. array( 'update' => 'post' ),
7. 'Do you want to delete this post?'
8. );
9. ?>

7.1.2.2 (#remoteFunction-1364) remoteFunction

remoteFunction(array $options);

Esta funcion crea el codigo JavaScript necesario para hacer una llamada remota. Es usado principalmente como un
helper(ayudante) para los enlaces(link). Esto no se utiliza muy a menudo a menos que usted necesite generar algunos
codigos personalizados.

The $options for this function are the same as for the link method

Example:

Plain Text View (#)


1. <div id="post">
2. </div>
3. <script type="text/javascript">
4. <?php echo $ajax->remoteFunction(
5. array(
6. 'url' => array( 'controller' => 'posts', 'action' => 'view', 1 ),
7. 'update' => 'post'
8. )
9. ); ?>
10. </script>

It can also be assigned to HTML Event Attributes:

Plain Text View (#)


1. <?php
2. $remoteFunction = $ajax->remoteFunction(
3. array(
4. 'url' => array( 'controller' => 'posts', 'action' => 'view', 1 ),
5. 'update' => 'post' )
6. );
7. ?>
8. <div id="post" onmouseover="<?php echo $remoteFunction; ?>" >
9. Mouse Over This
10. </div>

If $options['update'] is not passed, the browser will ignore the server response.

7.1.2.3 (#remoteTimer-1365) remoteTimer

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1365/remoteTimer) .. Mas info
sobre traduciones (/es/view/818)

remoteTimer(array $options)

Periodically calls the action at $options['url'], every $options['frequency'] seconds. Usually used to update a
specific div (specified by $options['update']) with the result of the remote call. Callbacks can be used.

remoteTimer is the same as the remoteFunction except for the extra $options['frequency']

243 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Example:

Plain Text View (#)


1. <div id="post">
2. </div>
3. <?php
4. echo $ajax->remoteTimer(
5. array(
6. 'url' => array( 'controller' => 'posts', 'action' => 'view', 1 ),
7. 'update' => 'post', 'complete' => 'alert( "request completed" )',
8. 'position' => 'bottom', 'frequency' => 5
9. )
10. );
11. ?>

The default $options['frequency'] is 10 seconds

7.1.2.4 (#form-1366) form

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1366/form) .. Mas info sobre
traduciones (/es/view/818)

form(string $action, string $type, array $options)

Returns a form tag that submits to $action using XMLHttpRequest instead of a normal HTTP request via $type ('post' or
'get'). Otherwise, form submission will behave exactly like normal: data submitted is available at $this->data inside
your controllers. If $options['update'] is specified, it will be updated with the resulting document. Callbacks can be
used.

The options array should include the model name e.g. Plain Text View (#)
1. $ajax->form('edit','post',array('model'=>'User','update'=>'UserInfoDiv'));

Alternatively, if you need to cross post to another controller from your form: Plain Text View (#)
1. $ajax->form(array('type' => 'post',
2. 'options' => array(
3. 'model'=>'User',
4. 'update'=>'UserInfoDiv',
5. 'url' => array(
6. 'controller' => 'comments',
7. 'action' => 'edit'
8. )
9. )
10. ));

You should not use the $ajax->form() and $ajax->submit() in the same form. If you want the form validation to work
properly use the $ajax->submit() method as shown below.

7.1.2.5 (#submit-1367) submit

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1367/submit) .. Mas info sobre
traduciones (/es/view/818)

submit(string $title, array $options)

Returns a submit button that submits the form to $options['url'] and updates the div specified in
$options['update']

Plain Text View (#)

244 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <div id='testdiv'>
2. <?php
3. echo $form->create('User');
4. echo $form->input('email');
5. echo $form->input('name');
6. echo $ajax->submit('Submit', array('url'=> array('controller'=>'users', 'action'=>'add'), 'update' => 't
7. echo $form->end();
8. ?>
9. </div>

Use the $ajax->submit() method if you want form validation to work properly. i.e. You want the messages you specify
in your validation rules to show up correctly.

7.1.2.6 (#observeField-1368) observeField

observeField(string $fieldId, array $options)

Observa el campo con el id DOM especificado por $field_id (cada $options['frequency'] segundos ) y realiza un
XMLHttpRequest si su contenido ha cambiado.

Plain Text View (#)


1. <?php echo $form->create( 'Post' ); ?>
2. <?php $titles = array( 1 => 'Tom', 2 => 'Dick', 3 => 'Harry' ); ?>
3. <?php echo $form->input( 'title', array( 'options' => $titles ) ) ?>
4. </form>
5. <?php
6. echo $ajax->observeField( 'PostTitle',
7. array(
8. 'url' => array( 'action' => 'edit' ),
9. 'frequency' => 0.2,
10. )
11. );
12. ?>

observeField utiliza las mismas opciones que link

El campo a enviar puede ser asignado utilizando $options['with']. Por defecto este contiene
Form.Element.serialize('$fieldId'). Los datos enviados están disponibles en $this->data de tu controlador. Los
Callbacks pueden ser utilizados con esta función.

Para enviar un formulario completo cuando el contenido cambie utilice $options['with'] = Form.serialize( $('Form
ID') )

7.1.2.7 (#observeForm-1369) observeForm

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1369/observeForm) .. Mas info
sobre traduciones (/es/view/818)

observeForm(string $form_id, array $options)

Similar to observeField(), but operates on an entire form identified by the DOM id $form_id. The supplied $options are
the same as observeField(), except the default value of the $options['with'] option evaluates to the serialized (request
string) value of the form.

7.1.2.8 (#autoComplete-1370) autoComplete

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1370/autoComplete) .. Mas info
sobre traduciones (/es/view/818)

autoComplete(string $fieldId, string $url, array $options)

Renders a text field with $fieldId with autocomplete. The remote action at $url should return a suitable list of
autocomplete terms. Often an unordered list is used for this. First, you need to set up a controller action that fetches

245 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

and organizes the data you'll need for your list, based on user input:

Plain Text View (#)


1. function autoComplete() {
2. //Partial strings will come from the autocomplete field as
3. //$this->data['Post']['subject']
4. $this->set('posts', $this->Post->find('all', array(
5. 'conditions' => array(
6. 'Post.subject LIKE' => $this->data['Post']['subject'].'%'
7. ),
8. 'fields' => array('subject')
9. )));
10. $this->layout = 'ajax';
11. }

Next, create app/views/posts/auto_complete.ctp that uses that data and creates an unordered list in (X)HTML:

Plain Text View (#)


1. <ul>
2. <?php foreach($posts as $post): ?>
3. <li><?php echo $post['Post']['subject']; ?></li>
4. <?php endforeach; ?>
5. </ul>

Finally, utilize autoComplete() in a view to create your auto-completing form field:

Plain Text View (#)


1. <?php echo $form->create('User', array('url' => '/users/index')); ?>
2. <?php echo $ajax->autoComplete('Post.subject', '/posts/autoComplete')?>
3. <?php echo $form->end('View Post')?>

Once you've got the autoComplete() call working correctly, use CSS to style the auto-complete suggestion box. You
might end up using something similar to the following:

div.auto_complete {
position :absolute;
width :250px;
background-color :white;
border :1px solid #888;
margin :0px;
padding :0px;
}
li.selected { background-color: #ffb; }

7.1.2.9 (#isAjax-1371) isAjax

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1371/isAjax) .. Mas info sobre
traduciones (/es/view/818)

isAjax()

Allows you to check if the current request is a Prototype Ajax request inside a view. Returns a boolean. Can be used
for presentational logic to show/hide blocks of content.

7.1.2.10 (#drag-drop-1372) drag & drop

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1372/drag-drop) .. Mas info
sobre traduciones (/es/view/818)

drag(string $id, array $options)

Makes a Draggable element out of the DOM element specified by $id. For more information on the parameters accepted

246 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

in $options see http://github.com/madrobby/scriptaculous/wikis/draggable (http://github.com/madrobby


/scriptaculous/wikis/draggable) .

Common options might include:

$options keys Description


Sets whether the element should only be draggable by an embedded handle. The value must be
an element reference or element id or a string referencing a CSS class value. The first
$options['handle']
child/grandchild/etc. element found within the element that has this CSS class value will be
used as the handle.
If set to true, the element returns to its original position when the drags ends. Revert can also
$options['revert']
be an arbitrary function reference, called when the drag ends.
$options['constraint'] Constrains the drag to either 'horizontal' or 'vertical', leave blank for no constraints.

drop(string $id, array $options)

Makes the DOM element specified by $id able to accept dropped elements. Additional parameters can be specified with
$options. For more information see http://github.com/madrobby/scriptaculous/wikis/droppables (http://github.com
/madrobby/scriptaculous/wikis/droppables) .

Common options might include:

$options keys Description


Set to a string or javascript array of strings describing CSS classes that the droppable
$options['accept']
element will accept. The drop element will only accept elements of the specified CSS classes.
The droppable element will only accept the dragged element if it is contained in the given
$options['containment']
elements (element ids). Can be a string or a javascript array of id references.
If set to 'horizontal' or 'vertical', the droppable element will only react to a draggable element
$options['overlap']
if it is overlapping the droparea by more than 50% in the given axis.
A javascript call back that is called when the dragged element is dropped on the droppable
$options['onDrop']
element.

dropRemote(string $id, array $options)

Makes a drop target that creates an XMLHttpRequest when a draggable element is dropped on it. The $options array
for this function are the same as those specified for drop() and link().

7.1.2.11 (#slider-1373) slider

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1373/slider) .. Mas info sobre
traduciones (/es/view/818)

slider(string $id, string $track_id, array $options)

Creates a directional slider control. For more information see http://wiki.github.com/madrobby/scriptaculous/slider


(http://wiki.github.com/madrobby/scriptaculous/slider) .

Common options might include:

$options keys Description

$options['axis'] Sets the direction the slider will move in. 'horizontal' or 'vertical'. Defaults to horizontal

$options['handleImage'] The id of the image that represents the handle. This is used to swap out the image src with
disabled image src when the slider is enabled. Used in conjunction with handleDisabled.

$options['increment'] Sets the relationship of pixels to values. Setting to 1 will make each pixel adjust the slider
value by one.

$options['handleDisabled']The id of the image that represents the disabled handle. This is used to change the image
src when the slider is disabled. Used in conjunction handleImage.

247 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

$options['change'] JavaScript callback fired when the slider has finished moving, or has its value changed. The
$options['onChange'] callback function receives the slider's current value as a parameter.

$options['slide'] JavaScript callback that is called whenever the slider is moved by dragging. It receives the
$options['onSlide'] slider's current value as a parameter.

7.1.2.12 (#editor-1374) editor

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1374/editor) .. Mas info sobre
traduciones (/es/view/818)

editor(string $id, string $url, array $options)

Creates an in-place editor at DOM id. The supplied $url should be an action that is responsible for saving element
data. For more information and demos see http://github.com/madrobby/scriptaculous/wikis/ajax-inplaceeditor
(http://github.com/madrobby/scriptaculous/wikis/ajax-inplaceeditor) .

Common options might include:

$options keys Description

$options['collection'] Activate the 'collection' mode of in-place editing. $options['collection'] takes an array
which is turned into options for the select. To learn more about collection see
http://github.com/madrobby/scriptaculous/wikis/ajax-inplacecollectioneditor
(http://github.com/madrobby/scriptaculous/wikis/ajax-inplacecollectioneditor) .

$options['callback'] A function to execute before the request is sent to the server. This can be used to
format the information sent to the server. The signature is function(form, value)

$options['okText'] Text of the submit button in edit mode

$options['cancelText'] The text of the link that cancels editing

$options['savingText'] The text shown while the text is sent to the server

$options['formId']

$options['externalControl']

$options['rows'] The row height of the input field

$options['cols'] The number of columns the text area should span

$options['size'] Synonym for ʻcolsʼ when using single-line

$options['highlightcolor'] The highlight color

$options['highlightendcolor']The color which the highlight fades to

$options['savingClassName']

$options['formClassName']

248 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

$options['loadingText']

$options['loadTextURL']

Example

Plain Text View (#)


1. <div id="in_place_editor_id">Text To Edit</div>
2. <?php
3. echo $ajax->editor(
4. "in_place_editor_id",
5. array(
6. 'controller' => 'Posts',
7. 'action' => 'update_title',
8. $id
9. ),
10. array()
11. );
12. ?>

7.1.2.13 (#sortable-1375) sortable

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1375/sortable) .. Mas info sobre
traduciones (/es/view/818)

sortable(string $id, array $options)

Makes a list or group of floated objects contained by $id sortable. The options array supports a number of
parameters. To find out more about sortable see http://wiki.github.com/madrobby/scriptaculous/sortable
(http://wiki.github.com/madrobby/scriptaculous/sortable) .

Common options might include:

$options keys Description

$options['tag'] Indicates what kind of child elements of the container will be made sortable. Defaults to 'li'.

$options['only'] Allows for further filtering of child elements. Accepts a CSS class.

$options['overlap'] Either 'vertical' or 'horizontal'. Defaults to vertical.

$options['constraint'] Restrict the movement of the draggable elements. accepts 'horizontal' or 'vertical'. Defaults to
vertical.

$options['handle'] Makes the created Draggables use handles, see the handle option on Draggables.

$options['onUpdate'] Called when the drag ends and the Sortable's order is changed in any way. When dragging from
one Sortable to another, the callback is called once on each Sortable.

$options['hoverclass']Give the created droppable a hoverclass.

$options['ghosting'] If set to true, dragged elements of the sortable will be cloned and appear as a ghost, instead of
directly manipulating the original element.

7.2 (#Cache-1376) Cache

El helper Cache permite almacenar temporalmente (caching) layouts y vistas completas, ahorrando tiempo en

249 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

descargar y retornar algunos datos. El caching de vistas en CakePHP almacena temporalmente los layouts y vistas
utilizando el motor de almacenamiento seleccionado. Es importante notar que el helper de Cache opera de manera
diferente a otros helpers. No tiene metodos que se puedan llamar directamente. En vez de eso, una vista es marcada
con tags, que permiten decirle cuales bloques no deben ser cacheados.

Cuando una URL es requerida, CakePHP verifica si aquel requerimiento esta cacheado.Si lo está, el resto del proceso
es saltado. Cualquier bloque no cacheado se procesa normalmente y la vista es entregada. Esto crea grandes ahorros
en tiempos de proceso para cada requerimiento para una URL cacheada, asi tambien menos código es ejecutado. Si
CakePHP no encuentra una vista cacheada, o el cache ha expirado para la URL requerida, se continúa normalmente
con el requerimiento.

7.2.1 (#Generalidades-en-Caching-1377) Generalidades en Caching

El caching tiene como intención ser un medio de almacenamiento temporal que reduce la carga del servidor. Por
ejemplo podrías almacenar el resultado de una consulta que requiere mucho tiempo de modo de no realizarla
nuevamente en cada actualización de la página.

El Caching no debe utilizarze nunca para almacenar datos en forma permanente. Solo debes cachear elementos que
puedan ser eventualmente regenerados si es necesario.

7.2.2 (#Motores-de-Cache-en-Cake-1378) Motores de Cache en Cake

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1378)


Comparar con el texto original (/es/compare/1378/Motores-de-Cache-en-Cake)

Mas info sobre traduciones (/es/view/818)

Lo nuevo en la version 1.2 de CakePHP son varios motores de cache. El helper de cache interactua transparentemente
con estos motores, permitiendo almacenar vistas en multiples formas sin preocuparse de las caracteristicas
especificas del medio de almacenamiento. La elección del motor de cache es controlada a traves del archivo
app/config/core.php config. Muchas opciones para cada motor de cache son listados en el archivo de configuracion
core.php, mas detalles acerca de cada motor se puede encontrar en la seccion de Caching.

El File Engine es el motor por defecto en CakePHP. Escribe archivos planos en el sistema de archivos y
File
cuenta con numerosos parámetros, pero funciona bien con los valores por defecto.
EL motor APC implementa el método Alternative PHP Cache (http://php.net/apc) . Asi como XCache, este
APC
motor almacena codigo ya compilado de PHP.
El motor XCache opera en forma similar al APC, pero implementanto el método XCache
XCache
(http://xcache.lighttpd.net/) . Requiere la autenticacion de usuarios para funcionar apropiadamente.
El motor Memcache funciona utilizando un servidor de almacenamiento en memoria, lo que permite crear
Memcache objetos cache en la memoria del sistema. Mas informacion acerca de este método puede ser encontrada en
php.net (http://www.php.net/memcache) y memcached (http://www.danga.com/memcached/)

7.2.3 (#Configuracion-del-Cache-Helper-1379) Configuracion del Cache Helper

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1379)


Comparar con el texto original (/es/compare/1379/Configuracion-del-Cache-Helper)

Mas info sobre traduciones (/es/view/818)

El caching de vistas y el helper de cache tienen varioes elementos de configuración importantes. Estos se detallan más
abajo.

Para usar el cache helper en cualquier vista o controlador, debes primero configurar Configure::Cache.check a true en
la linea 80 de core.php. Si no se configura a true, entonces el cache no sera verificado o creado.

7.2.4 (#Caching-en-los-Controllers-1380) Caching en los Controllers

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1380)


Comparar con el texto original (/es/compare/1380/Caching-en-los-Controllers)

250 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Mas info sobre traduciones (/es/view/818)

Cualquier controlador que utilice la funcionalidad de caching necesita incluir el CacheHelper en el arreglo $helpers.

Plain Text View (#)


1. var $helpers = array('Cache');

Necesitas ademas indicar cuales acciones necesitan caching, y cuanto tiempo durará cacheada cada acción. Esto se
hace a traves de la variable $cacheAction en tus controladores. $cacheAction debería ser configurada como un
arreglo el cual contiene las acciones a ser cacheadas y la duracion en segundos que deben permanecer en tal
condicion. EL tiempo puede expresarse en formato strtotime(). (ie. "1 hour", o "3 minutes").

Usando como ejemplo ArticlesController, que recibe un gran tráfico que necesita cachearse.

Por ejemplo, cachear los articulos visitados frecuentemente por diversos periodos de tiempo

Plain Text View (#)


1. var $cacheAction = array(
2. 'view/23/' => 21600,
3. 'view/48/' => 36000,
4. 'view/52' => 48000
5. );

Hacer caching de una acción completa en este caso un listado de articulos

Plain Text View (#)


1. var $cacheAction = array(
2. 'archives/' => '60000'
3. );

Cachear todas las acciones del controlador usando un formato amigable strtotime() para indicar el tiempo de cacheo.

Plain Text View (#)


1. var $cacheAction = "1 hour";

7.2.5 (#Marking-Non-Cached-Content-in-Views-1381) Marking Non-Cached Content in Views

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1381/Marking-Non-Cached-
Content-in-Views) .. Mas info sobre traduciones (/es/view/818)

There will be times when you don't want an entire view cached. For example, certain parts of the page may look
different whether a user is currently logged in or browsing your site as a guest.

To indicate blocks of content that are not to be cached, wrap them in <cake:nocache> </cake:nocache> like so:

Plain Text View (#)


1. <cake:nocache>
2. <?php if ($session->check('User.name')) : ?>
3. Welcome, <?php echo $session->read('User.name')?>.
4. <?php else: ?>
5. <?php echo $html->link('Login', 'users/login')?>
6. <?php endif; ?>
7. </cake:nocache>

It should be noted that once an action is cached, the controller method for the action will not be called - otherwise
what would be the point of caching the page. Therefore, it is not possible to wrap <cake:nocache> </cake:nocache>
around variables which are set from the controller as they will be null .

7.2.6 (#Clearing-the-Cache-1382) Clearing the Cache

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1382/Clearing-the-Cache) .. Mas
info sobre traduciones (/es/view/818)

251 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

It is important to remember that the Cake will clear a cached view if a model used in the cached view is modified. For
example, if a cached view uses data from the Post model, and there has been an INSERT, UPDATE, or DELETE query
made to a Post, the cache for that view is cleared, and new content is generated on the next request.

If you need to manually clear the cache, you can do so by calling Cache::clear(). This will clear all cached data,
excluding cached view files. If you need to clear the cached view files, use clearCache().

7.3 (#Formularios-1383) Formularios

El FormHelper es una nueva adición a CakePHP. La mayor parte del trabajo de creación de formularios recae sobre el
uso de esta nueva clase, en lugar de los (ahora obsoletos) métodos del HtmlHelper. El FormHelper se centra en la
creación de formularios rápidamente, de esta manera agiliza la validación, el precargado y el diseño de la interfaz. El
FormHelper es bastante flexible - este hará casi todo automáticamente por usted, o si lo desea puede usar métodos
específicos para hacer solo lo que necesite.

7.3.1 (#Creando-Formularios-1384) Creando Formularios

El primer método que necesitarás para poder aprovecha el FormHelper es create(). Este método se encarga de
escribir la etiqueta de apertura del formulario.

create(string $modelo = null, array $opciones = array())

Todos los parámetros son opcionales. Si create() es llamado sin parámetros, asume que estás construyendo un
formulario que será enviado al controlador actual, ya sea vía la acción add() o edit(). El método por omisión para el
envío es POST. El elemento form es regresado con un ID DOM. El ID es generado usando el nombre del modelo y el
nombre de la acción del controlador en formato CamelCased. Si fuera a llamar create() dentro de una vista de
UsersController, vería algo como lo siguiente en la vista

Plain Text View (#)


1. <form id="UserAddForm" method="post" action="/users/add">

Puedes también pasar false para el parámetro $modelo. Esto pondrá los datos de tu formulario en el array:
$this->data (en lugar de ponerlos en en sub-array: $this->data['Model']). Esto puede ser muy útil para formularios
cortos que quizá no representen nada en tu base de datos.

The create() method allows us to customize much more using the parameters, however. First, you can specify a
model name. By specifying a model for a form, you are creating that form's context. All fields are assumed to belong to
this model (unless otherwise specified), and all models referenced are assumed to be associated with it. If you do not
specify a model, then it assumes you are using the default model for the current controller.

Plain Text View (#)


1. <?php echo $form->create('Recipe'); ?>
2.
3. //Output:
4. <form id="RecipeAddForm" method="post" action="/recipes/add">

This will POST the form data to the add() action of RecipesController. However, you can also use the same logic to
create an edit form. The FormHelper uses the $this->data property to automatically detect whether to create an add or
edit form. If $this->data contains an array element named after the form's model, and that array contains a non-empty
value of the model's primary key, then the FormHelper will create an edit form for that record. For example, if we
browse to http://site.com/recipes/edit/5, we might get the following:

Plain Text View (#)

252 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. // controllers/recipes_controller.php:
2. <?php
3. function edit($id = null) {
4. if (empty($this->data)) {
5. $this->data = $this->Recipe->findById($id);
6. } else {
7. // Save logic goes here
8. }
9. }
10. ?>
11.
12. // views/recipes/edit.ctp:
13. // Since $this->data['Recipe']['id'] = 5, we should get an edit form
14. <?php echo $form->create('Recipe'); ?>
15.
16. //Output:
17. <form id="RecipeEditForm" method="post" action="/recipes/edit/5">
18. <input type="hidden" name="_method" value="PUT" />

Since this is an edit form, a hidden input field is generated to override the default HTTP method.

The $options array is where most of the form configuration happens. This special array can contain a number of
different key-value pairs that affect the way the form tag is generated.

7.3.1.1 (#options-type-1385) $options[ʻtypeʼ]

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1385/options-type) .. Mas info
sobre traduciones (/es/view/818)

This key is used to specify the type of form to be created. Valid values include ʻpostʼ, ʻgetʼ, ʻfileʼ, ʻputʼ and ʻdeleteʼ.

Supplying either ʻpostʼ or ʻgetʼ changes the form submission method accordingly.

Plain Text View (#)


1. <?php echo $form->create('User', array('type' => 'get')); ?>
2.
3. //Output:
4. <form id="UserAddForm" method="get" action="/users/add">

Specifying ʻfileʼ changes the form submission method to ʻpostʼ, and includes an enctype of “multipart/form-data” on
the form tag. This is to be used if there are any file elements inside the form. The absence of the proper enctype
attribute will cause the file uploads not to function.

Plain Text View (#)


1. <?php echo $form->create('User', array('type' => 'file')); ?>
2.
3. //Output:
4. <form id="UserAddForm" enctype="multipart/form-data" method="post" action="/users/add">

When using ʻputʼ or ʻdeleteʼ, your form will be functionally equivalent to a 'post' form, but when submitted, the HTTP
request method will be overridden with 'PUT' or 'DELETE', respectively. This allows CakePHP to emulate proper REST
support in web browsers.

7.3.1.2 (#options-action-1386) $options[ʻactionʼ]

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1386/options-action) .. Mas info
sobre traduciones (/es/view/818)

The action key allows you to point the form to a specific action in your current controller. For example, if youʼd like to
point the form to the login() action of the current controller, you would supply an $options array like the following:

Plain Text View (#)

253 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <?php echo $form->create('User', array('action' => 'login')); ?>


2.
3. //Output:
4. <form id="UserLoginForm" method="post" action="/users/login">
5. </form>

7.3.1.3 (#options-url-1387) $options[ʻurlʼ]

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1387/options-url) .. Mas info
sobre traduciones (/es/view/818)

If the desired form action isnʼt in the current controller, you can specify a URL for the form action using the ʻurlʼ key
of the $options array. The supplied URL can be relative to your CakePHP application, or can point to an external
domain.

Plain Text View (#)


1. <?php echo $form->create(null, array('url' => '/recipes/add')); ?>
2. // or
3. <?php echo $form->create(null, array('url' => array('controller' => 'recipes', 'action' => 'add'))); ?>
4.
5. //Output:
6. <form method="post" action="/recipes/add">
7.
8. <?php echo $form->create(null, array(
9. 'url' => 'http://www.google.com/search',
10. 'type' => 'get'
11. )); ?>
12.
13. //Output:
14. <form method="get" action="http://www.google.com/search">

Also check HtmlHelper::url (http://book.cakephp.org/view/1448/url) method for more examples of different types of urls.

7.3.1.4 (#options-default-1388) $options[ʻdefaultʼ]

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1388/options-default) .. Mas info
sobre traduciones (/es/view/818)

If ʻdefaultʼ has been set to boolean false, the formʼs submit action is changed so that pressing the submit button does
not submit the form. If the form is meant to be submitted via AJAX, setting ʻdefaultʼ to false suppresses the formʼs
default behavior so you can grab the data and submit it via AJAX instead.

7.3.1.5 (#x7-3-1-5-options-inputDefaults-1639) 7.3.1.5 $options['inputDefaults']

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1639/x7-3-1-5-options-
inputDefaults) .. Mas info sobre traduciones (/es/view/818)

You can declare a set of default options for input() with the inputDefaults key to customize your default input
creation.

Plain Text View (#)


1. echo $this->Form->create('User', array(
2. 'inputDefaults' => array(
3. 'label' => false,
4. 'div' => false
5. )
6. ));

All inputs created from that point forward would inherit the options declared in inputDefaults. You can override the
defaultOptions by declaring the option in the input() call.

254 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Plain Text View (#)


1. echo $this->Form->input('password'); // No div, no label
2. echo $this->Form->input('username', array('label' => 'Username')); // has a label element

7.3.2 (#Closing-the-Form-1389) Closing the Form

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1389)


Comparar con el texto original (/es/compare/1389/Closing-the-Form)

Mas info sobre traduciones (/es/view/818)

El FormHelper tambien incluye un método end() que completa el código del formulario. A menudo, el método end()
solo escribe la etiqueta de cierre del formulario, pero el usar end() también hace que el FormHelper inserte los
elementos hidden necesarios en el formulario para los métodos que dependen de este.

Plain Text View (#)


1. <?php echo $form->create(); ?>
2.
3. <!-- Form elements go here -->
4.
5. <?php echo $form->end(); ?>

Si una cadena es colocada como primer parámetro del end(), el FormHelper agregará un boton submit llamado de esa
manera además de la etiqueta de cierre del formulario.

Plain Text View (#)


1. <?php echo $form->end('Finish'); ?>
2.
3. Output:
4.
5. <div class="submit">
6. <input type="submit" value="Finish" />
7. </div>
8. </form>

7.3.3 (#Automagic-Form-Elements-1390) Automagic Form Elements

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1390/Automagic-Form-Elements)
.. Mas info sobre traduciones (/es/view/818)

First, letʼs look at some of the more automatic form creation methods in the FormHelper. The main method weʼll look
at is input(). This method will automatically inspect the model field it has been supplied in order to create an
appropriate input for that field.

input(string $fieldName, array $options = array())


Column Type Resulting Form Field
string (char, varchar, etc.) text
boolean, tinyint(1) checkbox
text textarea
text, with name of password, passwd, or psword password
date day, month, and year selects
datetime, timestamp day, month, year, hour, minute, and meridian selects
time hour, minute, and meridian selects

For example, letʼs assume that my User model includes fields for a username (varchar), password (varchar), approved
(datetime) and quote (text). I can use the input() method of the FormHelper to create appropriate inputs for all of these
form fields.

Plain Text View (#)

255 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <?php echo $form->create(); ?>


2.
3. <?php
4. echo $form->input('username'); //text
5. echo $form->input('password'); //password
6. echo $form->input('approved'); //day, month, year, hour, minute, meridian
7. echo $form->input('quote'); //textarea
8. ?>
9.
10. <?php echo $form->end('Add'); ?>

A more extensive example showing some options for a date field:

Plain Text View (#)


1. echo $form->input('birth_dt', array( 'label' => 'Date of birth'
2. , 'dateFormat' => 'DMY'
3. , 'minYear' => date('Y') - 70
4. , 'maxYear' => date('Y') - 18 ));

Besides the specific input options found below you can specify any html attribute (for instance onfocus). For more
information on $options and $htmlAttributes see HTML Helper (/es/view/1434/HTML) .

And to round off, here's an example for creating a hasAndBelongsToMany select. Assume that User
hasAndBelongsToMany Group. In your controller, set a camelCase plural variable (group -> groups in this case, or
ExtraFunkyModel -> extraFunkyModels) with the select options. In the controller action you would put the following:

Plain Text View (#)


1. $this->set('groups', $this->User->Group->find('list'));

And in the view a multiple select can be expected with this simple code:

Plain Text View (#)


1. echo $form->input('Group');

If you want to create a select field while using a belongsTo- or hasOne-Relation, you can add the following to your
Users-controller (assuming your User belongsTo Group):

Plain Text View (#)


1. $this->set('groups', $this->User->Group->find('list'));

Afterwards, add the following to your form-view:

Plain Text View (#)


1. echo $form->input('group_id');

If your model name consists of two or more words, e.g., "UserGroup", when passing the data using set() you should
name your data in a pluralised and camelCased format as follows:

Plain Text View (#)


1. $this->set('userGroups', $this->UserGroup->find('list'));
2. // or
3. $this->set('reallyInappropriateModelNames', $this->ReallyInappropriateModelName->find('list'));

7.3.3.1 (#Field-naming-convention-1391) Field naming convention

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1391/Field-naming-convention) ..
Mas info sobre traduciones (/es/view/818)

The Form helper is pretty smart. Whenever you specify a field name with the form helper methods, it'll automatically
use the current model name to build an input with a format like the following:

Plain Text View (#)

256 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <input type="text" id="ModelnameFieldname" name="data[Modelname][fieldname]">

You can manually specify the model name by passing in Modelname.fieldname as the first parameter.

Plain Text View (#)


1. echo $form->input('Modelname.fieldname');

If you need to specify multiple fields using the same field name, thus creating an array that can be saved in one shot
with saveAll(), use the following convention:

Plain Text View (#)


1. <?php
2. echo $form->input('Modelname.0.fieldname');
3. echo $form->input('Modelname.1.fieldname');
4. ?>
5.
6. <input type="text" id="Modelname0Fieldname" name="data[Modelname][0][fieldname]">
7. <input type="text" id="Modelname1Fieldname" name="data[Modelname][1][fieldname]">

7.3.3.2 (#options-type-1392) $options[ʻtypeʼ]

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1392/options-type) .. Mas info
sobre traduciones (/es/view/818)

You can force the type of an input (and override model introspection) by specifying a type. In addition to the field
types found in the table above (/es/view/1390/Automagic-Form-Elements) , you can also create ʻfileʼ, and ʻpasswordʼ
inputs.

Plain Text View (#)


1. <?php echo $form->input('field', array('type' => 'file')); ?>
2.
3. Output:
4.
5. <div class="input">
6. <label for="UserField">Field</label>
7. <input type="file" name="data[User][field]" value="" id="UserField" />
8. </div>

7.3.3.3 (#options-before-options-between-options-separator-a-1393) $options[ʻbeforeʼ], $options[ʻbetweenʼ], $options[ʻseparatorʼ] and $options[ʻafterʼ]

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1393/options-before-options-
between-options-separator-a) .. Mas info sobre traduciones (/es/view/818)

Use these keys if you need to inject some markup inside the output of the input() method.

Plain Text View (#)


1. <?php echo $form->input('field', array(
2. 'before' => '--before--',
3. 'after' => '--after--',
4. 'between' => '--between---'
5. ));?>
6.
7. Output:
8.
9. <div class="input">
10. --before--
11. <label for="UserField">Field</label>
12. --between---
13. <input name="data[User][field]" type="text" value="" id="UserField" />
14. --after--
15. </div>

257 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

For radio type input the 'separator' attribute can be used to inject markup to separate each input/label pair.

Plain Text View (#)


1. <?php echo $form->input('field', array(
2. 'before' => '--before--',
3. 'after' => '--after--',
4. 'between' => '--between---',
5. 'separator' => '--separator--',
6. 'options' => array('1', '2')
7. ));?>
8.
9. Output:
10.
11. <div class="input">
12. --before--
13. <input name="data[User][field]" type="radio" value="1" id="UserField1" />
14. <label for="UserField1">1</label>
15. --separator--
16. <input name="data[User][field]" type="radio" value="2" id="UserField2" />
17. <label for="UserField2">2</label>
18. --between---
19. --after--
20. </div>

For date and datetime type elements the 'separator' attribute can be used to change the string between select
elements. Defaults to '-'.

7.3.3.4 (#options-options-1394) $options[ʻoptionsʼ]

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1394/options-options) .. Mas
info sobre traduciones (/es/view/818)

This key allows you to manually specify options for a select input, or for a radio group. Unless the ʻtypeʼ is specified
as ʻradioʼ, the FormHelper will assume that the target output is a select input.

Plain Text View (#)


1. <?php echo $form->input('field', array('options' => array(1,2,3,4,5))); ?>

Output:

<div class="input">
<label for="UserField">Field</label>
<select name="data[User][field]" id="UserField">
<option value="0">1</option>
<option value="1">2</option>
<option value="2">3</option>
<option value="3">4</option>
<option value="4">5</option>
</select>
</div>

Options can also be supplied as key-value pairs.

Plain Text View (#)


1. <?php echo $form->input('field', array('options' => array(
2. 'Value 1'=>'Label 1',
3. 'Value 2'=>'Label 2',
4. 'Value 3'=>'Label 3'
5. ))); ?>

Output:

258 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

<div class="input">
<label for="UserField">Field</label>
<select name="data[User][field]" id="UserField">
<option value="Value 1">Label 1</option>
<option value="Value 2">Label 2</option>
<option value="Value 3">Label 3</option>
</select>
</div>

If you would like to generate a select with optgroups, just pass data in hierarchical format. Works on multiple
checkboxes and radio buttons too, but instead of optgroups wraps elements in fieldsets.

Plain Text View (#)


1. <?php echo $form->input('field', array('options' => array(
2. 'Label1' => array(
3. 'Value 1'=>'Label 1',
4. 'Value 2'=>'Label 2'
5. ),
6. 'Label2' => array(
7. 'Value 3'=>'Label 3'
8. )
9. ))); ?>

Output:

<div class="input">
<label for="UserField">Field</label>
<select name="data[User][field]" id="UserField">
<optgroup label="Label1">
<option value="Value 1">Label 1</option>
<option value="Value 2">Label 2</option>
</optgroup>
<optgroup label="Label2">
<option value="Value 3">Label 3</option>
</optgroup>
</select>
</div>

7.3.3.5 (#options-multiple-1395) $options[ʻmultipleʼ]

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1395)


Comparar con el texto original (/es/compare/1395/options-multiple)

Mas info sobre traduciones (/es/view/818)

Si ʻmultipleʼ es puesto a true para una entrada de tipo select, el select admitirá multiples selecciones.
Alternativamente, poniendo ʻmultipleʼ igual a ʻcheckboxʼ la salida será una lista de checkboxes relacionados.

Plain Text View (#)


1. $form->input('Modelo.campo', array( 'type' => 'select', 'multiple' => true ));
2. $form->input('Modelo.campo', array( 'type' => 'select', 'multiple' => 'checkbox' ));

7.3.3.6 (#options-maxLength-1396) $options[ʻmaxLengthʼ]

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1396/options-maxLength) .. Mas
info sobre traduciones (/es/view/818)

Defines the maximum number of characters allowed in a text input.

7.3.3.7 (#options-div-1397) $options[ʻdivʼ]

259 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1397/options-div) .. Mas info
sobre traduciones (/es/view/818)

Use this option to set attributes of the input's containing div. Using a string value will set the div's class name. An
array will set the div's attributes to those specified by the array's keys/values. Alternatively, you can set this key to
false to disable the output of the div.

Setting the class name:

Plain Text View (#)


1. echo $form->input('User.name', array('div' => 'class_name'));

Output:

<div class="class_name">
<label for="UserName">Name</label>
<input name="data[User][name]" type="text" value="" id="UserName" />
</div>

Setting multiple attributes:

Plain Text View (#)


1. echo $form->input('User.name', array('div' => array('id' => 'mainDiv', 'title' => 'Div Title', 'styl

Output:

<div class="input text" id="mainDiv" title="Div Title" style="display:block">


<label for="UserName">Name</label>
<input name="data[User][name]" type="text" value="" id="UserName" />
</div>

Disabling div output:

Plain Text View (#)


1. <?php echo $form->input('User.name', array('div' => false));?>

Output:

<label for="UserName">Name</label>
<input name="data[User][name]" type="text" value="" id="UserName" />

7.3.3.8 (#options-label-1398) $options[ʻlabelʼ]

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1398/options-label) .. Mas info
sobre traduciones (/es/view/818)

Set this key to the string you would like to be displayed within the label that usually accompanies the input.

Plain Text View (#)


1. <?php echo $form->input( 'User.name', array( 'label' => 'The User Alias' ) );?>

Output:

<div class="input">
<label for="UserName">The User Alias</label>
<input name="data[User][name]" type="text" value="" id="UserName" />
</div>

Alternatively, set this key to false to disable the output of the label.

Plain Text View (#)


1. <?php echo $form->input( 'User.name', array( 'label' => false ) ); ?>

Output:

260 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

<div class="input">
<input name="data[User][name]" type="text" value="" id="UserName" />
</div>

Set this to an array to provide additional options for the label element. If you do this, you can use a text key in the
array to customize the label text.

Plain Text View (#)


1. <?php echo $form->input( 'User.name', array( 'label' => array('class' => 'thingy', 'text' => 'The User A

Output:

<div class="input">
<label for="UserName" class="thingy">The User Alias</label>
<input name="data[User][name]" type="text" value="" id="UserName" />
</div>

7.3.3.9 (#options-legend-1399) $options['legend']

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1399/options-legend) .. Mas info
sobre traduciones (/es/view/818)

Some inputs like radio buttons will be automatically wrapped in a fieldset with a legend title derived from the fields
name. The title can be overridden with this option. Setting this option to false will completely eliminate the fieldset.

7.3.3.10 (#options-id-1400) $options[ʻidʼ]

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1400/options-id) .. Mas info
sobre traduciones (/es/view/818)

Set this key to force the value of the DOM id for the input.

7.3.3.11 (#options-error-1401) $options['error']

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1401/options-error) .. Mas info
sobre traduciones (/es/view/818)

Using this key allows you to override the default model error messages and can be used, for example, to set i18n
messages. It has a number of suboptions which control the wrapping element, wrapping element class name, and
whether HTML in the error message will be escaped.

To disable error message output set the error key to false.

Plain Text View (#)


1. $form->input('Model.field', array('error' => false));

To modify the wrapping element type and its class, use the following format:

Plain Text View (#)


1. $form->input('Model.field', array('error' => array('wrap' => 'span', 'class' => 'bzzz')));

To prevent HTML being automatically escaped in the error message output, set the escape suboption to false:

Plain Text View (#)


1. $form->input('Model.field', array('error' => array('escape' => false)));

To override the model error messages use an associate array with the keyname of the validation rule:

Plain Text View (#)


1. $form->input('Model.field', array('error' => array('tooShort' => __('This is not long enough', true) )))

As seen above you can set the error message for each validation rule you have in your models. In addition you can
provide i18n messages for your forms.

261 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

7.3.3.12 (#options-default-1402) $options['default']

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1402/options-default) .. Mas info
sobre traduciones (/es/view/818)

Used to set a default value for the input field. The value is used if the data passed to the form does not contain a value
for the field (or if no data is passed at all).

Example usage:

Plain Text View (#)


1. <?php
2. echo $form->input('ingredient', array('default'=>'Sugar'));
3. ?>

Example with select field (Size "Medium" will be selected as default):

Plain Text View (#)


1. <?php
2. $sizes = array('s'=>'Small', 'm'=>'Medium', 'l'=>'Large');
3. echo $form->input('size', array('options'=>$sizes, 'default'=>'m'));
4. ?>

You cannot use default to check a checkbox - instead you might set the value in $this->data in your controller,
$form->data in your view, or set the input option checked to true.

Date and datetime fields' default values can be set by using the 'selected' key.

7.3.3.13 (#options-selected-1403) $options[ʻselectedʼ]

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1403/options-selected) .. Mas
info sobre traduciones (/es/view/818)

Used in combination with a select-type input (i.e. For types select, date, time, datetime). Set ʻselectedʼ to the value of
the item you wish to be selected by default when the input is rendered.

Plain Text View (#)


1. echo $form->input('close_time', array('type' => 'time', 'selected' => '13:30:00'));

The selected key for date and datetime inputs may also be a UNIX timestamp.

7.3.3.14 (#options-rows-options-cols-1404) $options[ʻrowsʼ], $options[ʻcolsʼ]

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1404/options-rows-options-cols)
.. Mas info sobre traduciones (/es/view/818)

These two keys specify the number of rows and columns in a textarea input.

Plain Text View (#)


1. echo $form->input('textarea', array('rows' => '5', 'cols' => '5'));

Output:

Plain Text View (#)


1. <div class="input text">
2. <label for="FormTextarea">Textarea</label>
3. <textarea name="data[Form][textarea]" cols="5" rows="5" id="FormTextarea" >
4. </textarea>
5. </div>

7.3.3.15 (#options-empty-1405) $options[ʻemptyʼ]

262 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1405/options-empty) .. Mas info
sobre traduciones (/es/view/818)

If set to true, forces the input to remain empty.

When passed to a select list, this creates a blank option with an empty value in your drop down list. If you want to
have a empty value with text displayed instead of just a blank option, pass in a string to empty.

Plain Text View (#)


1. <?php echo $form->input('field', array('options' => array(1,2,3,4,5), 'empty' => '(choose one)')); ?>

Output:

<div class="input">
<label for="UserField">Field</label>
<select name="data[User][field]" id="UserField">
<option value="">(choose one)</option>
<option value="0">1</option>
<option value="1">2</option>
<option value="2">3</option>
<option value="3">4</option>
<option value="4">5</option>
</select>
</div>

If you need to set the default value in a password field to blank, use 'value' => '' instead.

Options can also supplied as key-value pairs.

7.3.3.16 (#options-timeFormat-1406) $options[ʻtimeFormatʼ]

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1406/options-timeFormat) .. Mas
info sobre traduciones (/es/view/818)

Used to specify the format of the select inputs for a time-related set of inputs. Valid values include ʻ12ʼ, ʻ24ʼ, and
ʻnoneʼ.

7.3.3.17 (#options-dateFormat-1407) $options[ʻdateFormatʼ]

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1407/options-dateFormat) .. Mas
info sobre traduciones (/es/view/818)

Used to specify the format of the select inputs for a date-related set of inputs. Valid values include ʻDMYʼ, ʻMDYʼ,
ʻYMDʼ, and ʻNONEʼ.

7.3.3.18 (#options-minYear-options-maxYear-1408) $options['minYear'], $options['maxYear']

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1408/options-minYear-options-
maxYear) .. Mas info sobre traduciones (/es/view/818)

Used in combination with a date/datetime input. Defines the lower and/or upper end of values shown in the years
select field.

7.3.3.19 (#options-interval-1409) $options['interval']

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1409/options-interval) .. Mas
info sobre traduciones (/es/view/818)

This option specifies the number of minutes between each option in the minutes select box.

Plain Text View (#)


1. <?php echo $form->input('Model.time', array('type' => 'time', 'interval' => 15)); ?>

Would create 4 options in the minute select. One for each 15 minutes.

263 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

7.3.3.20 (#options-class-1410) $options['class']

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1410/options-class) .. Mas info
sobre traduciones (/es/view/818)

You can set the classname for an input field using $options['class']

Plain Text View (#)


1. echo $form->input('title', array('class' => 'custom-class'));

7.3.4 (#File-Fields-1411) File Fields

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1411/File-Fields) .. Mas info
sobre traduciones (/es/view/818)

To add a file upload field to a form, you must first make sure that the form enctype is set to "multipart/form-data", so
start off with a create function such as the following.

Plain Text View (#)


1. echo $form->create('Document', array('enctype' => 'multipart/form-data') );
2. // OR
3. echo $form->create('Document', array('type' => 'file'));

Next add either of the two lines to your form view file.

Plain Text View (#)


1. echo $form->input('Document.submittedfile', array('between'=>'<br />','type'=>'file'));
2. // or
3. echo $form->file('Document.submittedfile');

Due to the limitations of HTML itself, it is not possible to put default values into input fields of type 'file'. Each time the
form is displayed, the value inside will be empty.

Upon submission, file fields provide an expanded data array to the script receiving the form data.

For the example above, the values in the submitted data array would be organized as follows, if the CakePHP was
installed on a Windows server. 'tmp_name' will have a different path in a Unix environment.

Plain Text View (#)


1. $this->data['Document']['submittedfile'] = array(
2. 'name' => conference_schedule.pdf
3. 'type' => application/pdf
4. 'tmp_name' => C:/WINDOWS/TEMP/php1EE.tmp
5. 'error' => 0
6. 'size' => 41737
7. );

This array is generated by PHP itself, so for more detail on the way PHP handles data passed via file fields read the
PHP manual section on file uploads (http://php.net/features.file-upload) .

7.3.4.1 (#Validating-Uploads-1412) Validating Uploads

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1412/Validating-Uploads) .. Mas
info sobre traduciones (/es/view/818)

Below is an example validation method you could define in your model to validate whether a file has been successfully
uploaded.

Plain Text View (#)

264 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. // Based on comment 8 from: http://bakery.cakephp.org/articles/view/improved-advance-validation-with-par


2. function isUploadedFile($params){
3. $val = array_shift($params);
4. if ((isset($val['error']) && $val['error'] == 0) ||
5. (!empty( $val['tmp_name']) && $val['tmp_name'] != 'none')) {
6. return is_uploaded_file($val['tmp_name']);
7. }
8. return false;
9. }

7.3.5 (#Form-Element-Specific-Methods-1413) Form Element-Specific Methods

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1413/Form-Element-Specific-
Methods) .. Mas info sobre traduciones (/es/view/818)

The rest of the methods available in the FormHelper are for creating specific form elements. Many of these methods
also make use of a special $options parameter. In this case, however, $options is used primarily to specify HTML tag
attributes (such as the value or DOM id of an element in the form).

Plain Text View (#)


1. <?php echo $form->text('username', array('class' => 'users')); ?>

Will output:

<input name="data[User][username]" type="text" class="users" id="UserUsername" />

7.3.5.1 (#checkbox-1414) checkbox

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1414/checkbox) .. Mas info
sobre traduciones (/es/view/818)

checkbox(string $fieldName, array $options)

Creates a checkbox form element. This method also generates an associated hidden form input to force the
submission of data for the specified field.

Plain Text View (#)


1. <?php echo $form->checkbox('done'); ?>

Will output:

<input type="hidden" name="data[User][done]" value="0" id="UserDone_" />


<input type="checkbox" name="data[User][done]" value="1" id="UserDone" />

7.3.5.2 (#button-1415) button

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1415/button) .. Mas info sobre
traduciones (/es/view/818)

button(string $title, array $options = array())

Creates an HTML button with the specified title and a default type of "button". Setting $options['type'] will output one
of the three possible button types:

1. submit: Same as the $form->submit method - (the default).


2. reset: Creates a form reset button.
3. button: Creates a standard push button.

Plain Text View (#)

265 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <?php
2. echo $form->button('A Button');
3. echo $form->button('Another Button', array('type'=>'button'));
4. echo $form->button('Reset the Form', array('type'=>'reset'));
5. echo $form->button('Submit Form', array('type'=>'submit'));
6. ?>

Will output:

<button type="submit">A Button</button>


<button type="button">Another Button</button>
<button type="reset">Reset the Form</button>
<button type="submit">Submit Form</button>

The button input type allows for a special $option attribute called 'escape' which accepts a bool and determines
whether to HTML entity encode the $title of the button. Defaults to false.

Plain Text View (#)


1. <?php
2. echo $form->button('Submit Form', array('type'=>'submit','escape'=>true));
3. ?>

7.3.5.3 (#year-1416) year

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1416/year) .. Mas info sobre
traduciones (/es/view/818)

year(string $fieldName, int $minYear, int $maxYear, mixed $selected, array $attributes, boolean $showEmpty)

Creates a select element populated with the years from $minYear to $maxYear, with the $selected year selected by
default. HTML attributes may be supplied in $attributes. If $showEmpty is false, the select will not include an empty
option.

Plain Text View (#)


1. <?php
2. echo $form->year('purchased',2000,date('Y'));
3. ?>

Will output:

<select name="data[User][purchased][year]" id="UserPurchasedYear">


<option value=""></option>
<option value="2009">2009</option>
<option value="2008">2008</option>
<option value="2007">2007</option>
<option value="2006">2006</option>
<option value="2005">2005</option>
<option value="2004">2004</option>
<option value="2003">2003</option>

<option value="2002">2002</option>
<option value="2001">2001</option>
<option value="2000">2000</option>
</select>

7.3.5.4 (#month-1417) month

266 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1417/month) .. Mas info sobre
traduciones (/es/view/818)

month(string $fieldName, mixed $selected, array $attributes, boolean $showEmpty)

Creates a select element populated with month names.

Plain Text View (#)


1. <?php
2. echo $form->month('mob');
3. ?>

Will output:

<select name="data[User][mob][month]" id="UserMobMonth">


<option value=""></option>
<option value="01">January</option>
<option value="02">February</option>
<option value="03">March</option>
<option value="04">April</option>
<option value="05">May</option>
<option value="06">June</option>
<option value="07">July</option>
<option value="08">August</option>
<option value="09">September</option>
<option value="10">October</option>
<option value="11">November</option>
<option value="12">December</option>
</select>

You can pass in your own array of months to be used by setting the 'monthNames' attribute, or have months displayed
as numbers by passing false. (Note: the default months are internationalized and can be translated using localization.)

Plain Text View (#)


1. <?php
2. echo $form->month('mob', null, array('monthNames' => false));
3. ?>

7.3.5.5 (#dateTime-1418) dateTime

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1418/dateTime) .. Mas info
sobre traduciones (/es/view/818)

dateTime($fieldName, $dateFormat = 'DMY', $timeFormat = '12', $selected = null, $attributes = array())

Creates a set of select inputs for date and time. Valid values for $dateformat are ʻDMYʼ, ʻMDYʼ, ʻYMDʼ or ʻNONEʼ. Valid
values for $timeFormat are ʻ12ʼ, ʻ24ʼ, and null.

You can specify not to display empty values by setting "array('empty' => false)" in the attributes parameter. You also
can pre-select the current datetime by setting $selected = null and $attributes = array("empty" => false).

7.3.5.6 (#day-1419) day

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1419/day) .. Mas info sobre
traduciones (/es/view/818)

day(string $fieldName, mixed $selected, array $attributes, boolean $showEmpty)

Creates a select element populated with the (numerical) days of the month.

To create an empty option with prompt text of your choosing (e.g. the first option is 'Day'), you can supply the text as
the final parameter as follows:

Plain Text View (#)

267 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <?php
2. echo $form->day('created');
3. ?>

Will output:

<select name="data[User][created][day]" id="UserCreatedDay">


<option value=""></option>
<option value="01">1</option>
<option value="02">2</option>
<option value="03">3</option>
...
<option value="31">31</option>
</select>

7.3.5.7 (#hour-1420) hour

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1420/hour) .. Mas info sobre
traduciones (/es/view/818)

hour(string $fieldName, boolean $format24Hours, mixed $selected, array $attributes, boolean $showEmpty)

Creates a select element populated with the hours of the day.

7.3.5.8 (#minute-1421) minute

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1421/minute) .. Mas info sobre
traduciones (/es/view/818)

minute(string $fieldName, mixed $selected, array $attributes, boolean $showEmpty)

Creates a select element populated with the minutes of the hour.

7.3.5.9 (#meridian-1422) meridian

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1422/meridian) .. Mas info
sobre traduciones (/es/view/818)

meridian(string $fieldName, mixed $selected, array $attributes, boolean $showEmpty)

Creates a select element populated with ʻamʼ and ʻpmʼ.

7.3.5.10 (#error-1423) error

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1423/error) .. Mas info sobre
traduciones (/es/view/818)

error(string $fieldName, mixed $text, array $options)

Shows a validation error message, specified by $text, for the given field, in the event that a validation error has
occurred.

Options:

'escape' bool Whether or not to html escape the contents of the error.
'wrap' mixed Whether or not the error message should be wrapped in a div. If a string, will be used as the HTML
tag to use.
'class' string The classname for the error message

7.3.5.11 (#file-1424) file

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1424/file) .. Mas info sobre
traduciones (/es/view/818)

file(string $fieldName, array $options)

268 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Creates a file input.

Plain Text View (#)


1. <?php
2. echo $form->create('User',array('type'=>'file'));
3. echo $form->file('avatar');
4. ?>

Will output:

<form enctype="multipart/form-data" method="post" action="/users/add">


<input name="data[User][avatar]" value="" id="UserAvatar" type="file">

When using $form->file(), remember to set the form encoding-type, by setting the type option to 'file' in
$form->create()

7.3.5.12 (#hidden-1425) hidden

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1425/hidden) .. Mas info sobre
traduciones (/es/view/818)

hidden(string $fieldName, array $options)

Creates a hidden form input. Example:

Plain Text View (#)


1. <?php
2. echo $form->hidden('id');
3. ?>

Will output:

<input name="data[User][id]" value="10" id="UserId" type="hidden">

7.3.5.13 (#isFieldError-1426) isFieldError

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1426/isFieldError) .. Mas info
sobre traduciones (/es/view/818)

isFieldError(string $fieldName)

Returns true if the supplied $fieldName has an active validation error.

Plain Text View (#)


1. <?php
2. if ($form->isFieldError('gender')){
3. echo $form->error('gender');
4. }
5. ?>

When using $form->input(), errors are rendered by default.

7.3.5.14 (#label-1427) label

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1427/label) .. Mas info sobre
traduciones (/es/view/818)

label(string $fieldName, string $text, array $attributes)

Creates a label tag, populated with $text.

Plain Text View (#)

269 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <?php
2. echo $form->label('status');
3. ?>

Will output:

<label for="UserStatus">Status</label>

7.3.5.15 (#password-1428) password

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1428/password) .. Mas info
sobre traduciones (/es/view/818)

password(string $fieldName, array $options)

Creates a password field.

Plain Text View (#)


1. <?php
2. echo $form->password('password');
3. ?>

Will output:

<input name="data[User][password]" value="" id="UserPassword" type="password">

7.3.5.16 (#radio-1429) radio

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1429/radio) .. Mas info sobre
traduciones (/es/view/818)

radio(string $fieldName, array $options, array $attributes)

Creates a radio button input. Use $attributes['value'] to set which value should be selected default.

Use $attributes['separator'] to specify HTML in between radio buttons (e.g. <br />).

Radio elements are wrapped with a label and fieldset by default. Set $attributes['legend'] to false to remove them.

Plain Text View (#)


1. <?php
2. $options=array('M'=>'Male','F'=>'Female');
3. $attributes=array('legend'=>false);
4. echo $form->radio('gender',$options,$attributes);
5. ?>

Will output:

<input name="data[User][gender]" id="UserGender_" value="" type="hidden">


<input name="data[User][gender]" id="UserGenderM" value="M" type="radio">
<label for="UserGenderM">Male</label>
<input name="data[User][gender]" id="UserGenderF" value="F" type="radio">
<label for="UserGenderF">Female</label>

If for some reason you don't want the hidden input, setting $attributes['value'] to a selected value or boolean false
will do just that.

7.3.5.17 (#select-1430) select

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1430/select) .. Mas info sobre
traduciones (/es/view/818)

select(string $fieldName, array $options, mixed $selected, array $attributes)

270 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Creates a select element, populated with the items in $options, with the option specified by $selected shown as
selected by default. If you wish to display your own default option, add your string value to the 'empty' key in the
$attributes variable, or set it to false to turn off the default empty option

Plain Text View (#)


1. <?php
2. $options=array('M'=>'Male', 'F'=>'Female');
3. echo $form->select('gender', $options)
4. ?>

Will output:

<select name="data[User][gender]" id="UserGender">


<option value=""></option>
<option value="M">Male</option>
<option value="F">Female</option>
</select>

The select input type allows for a special $option attribute called 'escape' which accepts a bool and determines
whether to HTML entity encode the contents of the select options. Defaults to true.

Plain Text View (#)


1. <?php
2. $options=array('M'=>'Male', 'F'=>'Female');
3. echo $form->select('gender', $options, null, array('escape'=>false));
4. ?>

7.3.5.18 (#submit-1431) submit

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1431/submit) .. Mas info sobre
traduciones (/es/view/818)

submit(string $caption, array $options)

Creates a submit button with caption $caption. If the supplied $caption is a URL to an image (it contains a ʻ.ʼ
character), the submit button will be rendered as an image.

It is enclosed between div tags by default; you can avoid this by declaring $options['div'] = false.

Plain Text View (#)


1. <?php
2. echo $form->submit();
3. ?>

Will output:

<div class="submit"><input value="Submit" type="submit"></div>

You can also pass a relative or absolute url to an image for the caption parameter instead of caption text.

Plain Text View (#)


1. <?php
2. echo $form->submit('ok.png');
3. ?>

Will output:

<div class="submit"><input type="image" src="/img/ok.png"></div>

7.3.5.19 (#text-1432) text

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1432/text) .. Mas info sobre
traduciones (/es/view/818)

271 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

text(string $fieldName, array $options)

Creates a text input field.

Plain Text View (#)


1. <?php
2. echo $form->text('first_name');
3. ?>

Will output:

<input name="data[User][first_name]" value="" id="UserFirstName" type="text">

7.3.5.20 (#textarea-1433) textarea

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1433/textarea) .. Mas info sobre
traduciones (/es/view/818)

textarea(string $fieldName, array $options)

Creates a textarea input field.

Plain Text View (#)


1. <?php
2. echo $form->textarea('notes');
3. ?>

Will output:

<textarea name="data[User][notes]" id="UserNotes"></textarea>

The textarea input type allows for the $options attribute of 'escape' which determines whether or not the contents of
the textarea should be escaped. Defaults to true.

Plain Text View (#)


1. <?php
2. echo $form->textarea('notes',array('escape'=>false);
3. // OR....
4. echo $form->input('notes',array('type'=>'textarea','escape'=>false);
5. ?>

7.3.6 (#x1-3-improvements-1616) 1.3 improvements

272 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1616/x1-3-improvements) .. Mas
info sobre traduciones (/es/view/818)

The FormHelper is one of the most frequently used classes in CakePHP, and has had several improvements made to it.

Entity depth limitations

In 1.2 there was a hard limit of 5 nested keys. This posed significant limitations on form input creation in some
contexts. In 1.3 you can now create infinitely nested form element keys. Validation errors and value reading for
arbitrary depths has also been added.

Model introspection

Support for adding 'required' classes, and properties like maxlength to hasMany and other associations has been
improved. In the past only 1 model and a limited set of associations would be introspected. In 1.3 models are
introspected as needed, providing validation and additional information such as maxlength.

Default options for input()

In the past if you needed to use 'div' => false, or 'label' => false you would need to set those options on each
and every call to input(). Instead in 1.3 you can declare a set of default options for input() with the inputDefaults
key.

Plain Text View (#)


1. echo $this->Form->create('User', array(
2. 'inputDefaults' => array(
3. 'label' => false,
4. 'div' => false
5. )
6. ));

All inputs created from that point forward would inherit the options declared in inputDefaults. You can override the
defaultOptions by declaring the option in the input() call.

Plain Text View (#)


1. echo $this->Form->input('password'); // No div, no label
2. echo $this->Form->input('username', array('label' => 'Username')); // has a label element

Omit attributes

You can now set any attribute key to null or false in an options/attributes array to omit that attribute from a particular
html tag.

Plain Text View (#)


1. echo $this->Form->input('username', array(
2. 'div' => array('class' => false)
3. )); // Omits the 'class' attribute added by default to div tag

Accept-charset

Forms now get an accept-charset set automatically, it will match the value of App.encoding, it can be overridden or
removed using the 'encoding' option when calling create().

Plain Text View (#)


1. // To remove the accept-charset attribute.
2. echo $this->Form->create('User', array('encoding' => null));

Removed parameters

Many methods such as select, year, month, day, hour, minute, meridian and datetime took a $showEmpty parameter,
these have all been removed and rolled into the $attributes parameter using the 'empty' key.

Default url

The default url for forms either was add or edit depending on whether or not a primary key was detected in the data

273 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

array. In 1.3 the default url will be the current action, making the forms submit to the action you are currently on.

Disabling hidden inputs for radio and checkbox

The automatically generated hidden inputs for radio and checkbox inputs can be disabled by setting the
'hiddenField' option to false.

button()

button() now creates button elements, these elements by default do not have html entity encoding enabled. You can
enable html escaping using the escape option. The former features of FormHelper::button have been moved to
FormHelper::submit.

submit()

Due to changes in button(), submit() can now generate reset, and other types of input buttons. Use the type option to
change the default type of button generated. In addition to creating all types of buttons, submit() has before and
after options that behave exactly like their counterparts in input().

$options['format']

The HTML generated by the form helper is now more flexible than ever before. The $options parameter to
Form::input() now supports an array of strings describing the template you would like said element to follow. It's just
been recently added to SCM, and has a few bugs for non PHP 5.3 users, but should be quite useful for all. The
supported array keys are array('before', 'input', 'between', 'label', 'after', 'error').

7.4 (#HTML-1434) HTML

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1434)


Comparar con el texto original (/es/compare/1434/HTML)

Mas info sobre traduciones (/es/view/818)

El rol del HtmlHelper de CakePHP es hacer los tags referentes a HTML y sus opciones simples, rápidas, y más
resistentes al cambio. Usando este ayudante pondremos más luz sobre tu aplicación, y más flexibilidad en cuanto a
donde se encuentre en relación al dominio principal.

El rol del HtmlHelper ha cambiado significativamente desde CakePHP 1.1. Los metodos relacionados a Form ya no se
usan y han sido movidos al nuevo FormHelper. Si tu estas buscando ayuda para los formularios HTML, Revisa lo
nuevo de FormHelper.

Antes de dar un vistaso a los metodos de HtmlHelper, vas a necesitar conocimientos sobre configuración y usos en
las situaciones que te puede ayudar esta clase. En primer lugar, en un esfuerzo para aliviar a aquellos que gustan de
usar las etiquetas cortas (<?= ?>) o muchas llamadas a echo() en el codigo de sus vistas todos los metodos del
HtmlHelper son pasados por el metodo output(). Si tu deseas activar automáticamente la salida para generar HTML con
el ayudante simplemente implementa output() en tu AppHelper.

Plain Text View (#)


1. function output($cadena) {
2. echo $cadena;
3. }

Haciendo esto no necesitarás agregar llamadas a echo en el codigo de tus vistas.

Muchos metodos HtmlHelper incluyen parametros $htmlAttributes, esto te permite hilvanar cualquier atributo extra en
tus tags. Aquí hay algunos ejemplos de como se usan los parámetros $htmlAttributes

Plain Text View (#)


1. Atributos Deseados: <tag class="algunaClase" />
2. Arreglo de Parametros: array('class'=>'algunaClase')
3.
4. Atributos Deseados: <tag name="foo" value="bar" />
5. Arreglo de Parametros: array('name' => 'foo', 'value' => 'bar')

274 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

El HtmlHelper está disponible en todas las vistas de forma predeterminada. Si usted está recibiendo un error que le
informa que no está ahí, es por lo general debido a su nombre que esta faltando y puede configurarlo manualmente
en la variable $helpers del controlador.

7.4.1 (#Inserting-Well-Formatted-elements-1435) Inserting Well-Formatted elements

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1435/Inserting-Well-Formatted-
elements) .. Mas info sobre traduciones (/es/view/818)

The most important task the HtmlHelper accomplishes is creating well formed markup. Don't be afraid to use it often -
you can cache views in CakePHP in order to save some CPU cycles when views are being rendered and delivered. This
section will cover some of the methods of the HtmlHelper and how to use them.

7.4.1.1 (#charset-1436) charset

charset(string $charset=null)

Usada para crear metadatos que especificarán la codificación de los caracteres del documento. El valor por defecto es
UTF-8.

Plain Text View (#)


1. <?php echo $html->charset(); ?>

Generará como salida:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

O sino tambien:

Plain Text View (#)


1. <?php echo $html->charset('ISO-8859-1'); ?>

Generará como salida:

<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />

7.4.1.2 (#css-1437) css

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1437)


Comparar con el texto original (/es/compare/1437/css)

Mas info sobre traduciones (/es/view/818)

css(mixed $path, string $rel = null, array $htmlAttributes = array(), boolean $inline = true)

Crea un enlace a una o más hojas de estilos CSS. Si $inline está en false, los tags de enlace son agregados en la
variable $scripts_for_layout, la cual puedes imprimir dentro del tag head del documento.

Este método de inclusión de CSS asume que el archivo CSS especificado esté en el directorio /app/webroot/css.

Plain Text View (#)


1. <?php echo $html->css('forms'); ?>

Hará la salida:

<link rel="stylesheet" type="text/css" href="/es/css/forms.css" />

El primer parámetro puede ser un arreglo para incluir varios archivos.

Plain Text View (#)


1. <?php echo $html->css(array('forms','tables','menu')); ?>

Hará la salida:

275 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

<link rel="stylesheet" type="text/css" href="/es/css/forms.css" />


<link rel="stylesheet" type="text/css" href="/es/css/tables.css" />
<link rel="stylesheet" type="text/css" href="/es/css/menu.css" />

7.4.1.3 (#meta-1438) meta

meta(string $type, string $url = null, array $attributes = array(), boolean $inline = true)

Este método es útil para vincular a los recursos externos como los feeds RSS / Atom y favicons. Como CSS (), puede
especificar si desea o no que esta etiqueta a aparezca en la línea o en la etiqueta de la cabecera con el cuarto
parámetro.

Si establece el atributo "type" usando el parámetro $htmlAttributes, CakePHP contiene algunos atajos:

type valor traducido


html text/html
rss application/rss+xml
atom application/atom+xml
icon image/x-icon
Plain Text View (#)
1. <?php echo $html->meta(
2. 'favicon.ico',
3. '/favicon.ico',
4. array('type' => 'icon')
5. );?> //Salida (saltos de linea añadidos) </p>
6. <link
7. href="http://example.com/favicon.ico"
8. title="favicon.ico" type="image/x-icon"
9. rel="alternate"
10. />
11.
12. <?php echo $html->meta(
13. 'Comments',
14. '/comments/index.rss',
15. array('type' => 'rss'));
16. ?>
17.
18. //Salida (saltos de linea añadidos)
19. <link
20. href="http://example.com/comments/index.rss"
21. title="Comments"
22. type="application/rss+xml"
23. rel="alternate"
24. />

Este método también puede utilizarse para agregar las etiquetas "meta" para las palabras claves y las descripciones.
Ejemplo:

Plain Text View (#)


1. <?php echo $html->meta(
2. 'keywords',
3. 'ingrese las palabas claves aquí'
4. );?>
5. //Salida <meta name="keywords" content="ingrese las palabas claves aquí"/>
6. //
7. <?php echo $html->meta(
8. 'description',
9. 'ingrese alguna descripcion meta aquí'
10. );?>
11. //Salida <meta name="description" content="ingrese alguna descripcion meta aquí"/>

276 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Si deseas añadir una etiqueta meta personalizada en el primer parámetro se debe establecer una matriz. Para una
salida de la etiqueta "robots noindex" debe utilizar el siguiente código:

Plain Text View (#)


1. echo $html->meta(array('name' => 'robots', 'content' => 'noindex'));

7.4.1.4 (#docType-1439) docType

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1439/docType) .. Mas info sobre
traduciones (/es/view/818)

docType(string $type = 'xhtml-strict')

Returns a (X)HTML doctype tag. Supply the doctype according to the following table:

type translated value


html text/html
html4-strict HTML4 Strict
html4-trans HTML4 Transitional
html4-frame HTML4 Frameset
xhtml-strict XHTML1 Strict
xhtml-trans XHTML1 Transitional
xhtml-frame XHTML1 Frameset
xhtml11 XHTML 1.1
Plain Text View (#)
1. <?php echo $html->docType(); ?>
2. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.
3. <?php echo $html->docType('html4-trans'); ?>
4. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

7.4.1.5 (#style-1440) style

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1440/style) .. Mas info sobre
traduciones (/es/view/818)

style(array $data, boolean $oneline = true)

Builds CSS style definitions based on the keys and values of the array passed to the method. Especially handy if your
CSS file is dynamic.

Plain Text View (#)


1. <?php echo $html->style(array(
2. 'background' => '#633',
3. 'border-bottom' => '1px solid #000',
4. 'padding' => '10px'
5. )); ?>

Will output:

background:#633; border-bottom:1px solid #000; padding:10px;

7.4.1.6 (#image-1441) image

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1441)


Comparar con el texto original (/es/compare/1441/image)

Mas info sobre traduciones (/es/view/818)

image(string $path, array $htmlAttributes = array())

277 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Crea una etiqueta de imagen, la ruta especificada será relativa a /app/webroot/img/.

Plain Text View (#)


1. <?php echo $html->image('cake_logo.png', array('alt' => 'CakePHP'))?>

Mostrará:

<img src="/img/cake_logo.png" alt="CakePHP" />

Si desea crear un link asociado a la imagen especifique el link de destino usando la opción url option en
$htmlAttributes.

Plain Text View (#)


1. <?php echo $html->image("recipes/6.jpg", array(
2. "alt" => "Bizcochos",
3. 'url' => array('controller' => 'recipes', 'action' => 'view', 6)
4. )); ?>

Mostrará:

<a href="/es/recipes/view/6">
<img src="/img/recipes/6.jpg" alt="Bizcochos" />
</a>

7.4.1.7 (#link-1442) link

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1442/link) .. Mas info sobre
traduciones (/es/view/818)

link(string $title, mixed $url = null, array $options = array(), string $confirmMessage = false)

General purpose method for creating HTML links. Use $options to specify attributes for the element and whether or
not the $title should be escaped.

Plain Text View (#)


1. <?php echo $html->link('Enter', '/pages/home', array('class'=>'button','target'=>'_blank')); ?>

Will output:

<a href="/es/pages/home" class="button" target="_blank">Enter</a>

Specify $confirmMessage to display a javascript confirm() dialog.

Plain Text View (#)


1. <?php echo $html->link(
2. 'Delete',
3. array('controller'=>'recipes', 'action'=>'delete', 6),
4. array(),
5. "Are you sure you wish to delete this recipe?"
6. );?>

Will output:

<a href="/es/recipes/delete/6" onclick="return confirm('Are you sure you wish to delete this recipe?');">Delete

Query strings can also be created with link().

Plain Text View (#)

278 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <?php echo $html->link('View image', array(


2. 'controller' => 'images',
3. 'action' => 'view',
4. 1,
5. '?' => array( 'height' => 400, 'width' => 500))
6. );

Will output:

<a href="/es/images/view/1?height=400&width=500">View image</a>

HTML special characters in $title will be converted to HTML entities. To disable this conversion, set the escape
option to false in the $options array.

Plain Text View (#)


1. <?php
2. echo $html->link(
3. $html->image("recipes/6.jpg", array("alt" => "Brownies")),
4. "recipes/view/6",
5. array('escape'=>false)
6. );
7. ?>

Will output:

<a href="/es/recipes/view/6">
<img src="/img/recipes/6.jpg" alt="Brownies" />
</a>

Also check HtmlHelper::url (http://book.cakephp.org/view/1448/url) method for more examples of different types of urls.

7.4.1.8 (#tag-1443) tag

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1443/tag) .. Mas info sobre
traduciones (/es/view/818)

tag(string $tag, string $text, array $htmlAttributes)

Returns text wrapped in a specified tag. If no text is specified then only the opening <tag> is returned.

Plain Text View (#)


1. <?php echo $html->tag('span', 'Hello World.', array('class' => 'welcome'));?>
2.
3. //Output
4. <span class="welcome">Hello World</span>
5.
6. //No text specified.
7. <?php echo $html->tag('span', null, array('class' => 'welcome'));?>
8.
9. //Output
10. <span class="welcome">

7.4.1.9 (#div-1444) div

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1444/div) .. Mas info sobre
traduciones (/es/view/818)

div(string $class, string $text, array $options)

Used for creating div-wrapped sections of markup. The first parameter specifies a CSS class, and the second is used to

279 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

supply the text to be wrapped by div tags. If the last parameter has been set to true, $text will be printed
HTML-escaped.

If no text is specified, only an opening div tag is returned.

Plain Text View (#)


1. <?php echo $html->div('error', 'Please enter your credit card number.');?>
2.
3. //Output
4. <div class="error">Please enter your credit card number.</div>

7.4.1.10 (#para-1445) para

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1445/para) .. Mas info sobre
traduciones (/es/view/818)

para(string $class, string $text, array $htmlAttributes, boolean $escape = false)

Returns a text wrapped in a CSS-classed <p> tag. If no text is supplied, only a starting <p> tag is returned.

Plain Text View (#)


1. <?php echo $html->para(null, 'Hello World.');?>
2.
3. //Output
4. <p>Hello World.</p>

7.4.1.11 (#script-1589) script

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1589/script) .. Mas info sobre
traduciones (/es/view/818)

script(mixed $url, mixed $options)

Creates link(s) to a javascript file. If key inline is set to false in $options, the link tags are added to the
$scripts_for_layout variable which you can print inside the head tag of the document.

Include a script file into the page. $options['inline'] controls whether or not a script should be returned inline or
added to $scripts_for_layout. $options['once'] controls, whether or not you want to include this script once per
request or more than once.

You can also use $options to set additional properties to the generated script tag. If an array of script tags is used,
the attributes will be applied to all of the generated script tags.

This method of javascript file inclusion assumes that the javascript file specified resides inside the /app/webroot/js
directory.

Plain Text View (#)


1. <?php echo $html->script('scripts'); ?>

Will output:

<script type="text/javascript" href="/es/js/scripts.js"></script>

You can link to files with absolute paths as well to link files that are not in app/webroot/js

Plain Text View (#)


1. <?php echo $html->script('/otherdir/script_file'); ?>

The first parameter can be an array to include multiple files.

Plain Text View (#)


1. <?php echo $html->script(array('jquery','wysiwyg','scripts')); ?>

280 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Will output:

<script type="text/javascript" href="/es/js/jquery.js"></script>


<script type="text/javascript" href="/es/js/wysiwyg.js"></script>
<script type="text/javascript" href="/es/js/scripts.js"></script>

7.4.1.12 (#scriptBlock-1604) scriptBlock

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1604/scriptBlock) .. Mas info
sobre traduciones (/es/view/818)

scriptBlock($code, $options = array())

Generate a code block containing $code set $options['inline'] to false to have the script block appear in
$scripts_for_layout. Also new is the ability to add attributes to script tags. $html->scriptBlock('stuff',
array('defer' => true)); will create a script tag with defer="defer" attribute.

7.4.1.13 (#scriptStart-1605) scriptStart

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1605/scriptStart) .. Mas info
sobre traduciones (/es/view/818)

scriptStart($options = array())

Begin a buffering code block. This code block will capture all output between scriptStart() and scriptEnd() and
create an script tag. Options are the same as scriptBlock()

7.4.1.14 (#scriptEnd-1606) scriptEnd

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1606/scriptEnd) .. Mas info
sobre traduciones (/es/view/818)

scriptEnd()

End a buffering script block, returns the generated script element or null if the script block was opened with inline =
false.

An example of using scriptStart() and scriptEnd() would be:

Plain Text View (#)


1. $html->scriptStart(array('inline' => false));
2. echo $js->alert('I am in the javascript');
3. $html->scriptEnd();

7.4.1.15 (#tableHeaders-1446) tableHeaders

tableHeaders(array $names, array $trOptions = null, array $thOptions = null)

Crea una fila de encabezados de tabla para ser usados dentro de la etiqueta <table>.

Plain Text View (#)

281 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <?php echo $html->tableHeaders(array('Fecha','Nombre','Activo'));?>


2.
3. //Salida
4. <tr>
5. <th>Fecha</th>
6. <th>Nombre</th>
7. <th>Activo</th>
8. </tr>
9.
10. <?php echo $html->tableHeaders(
11. array('Fecha','Nombre','Activo'),
12. array('class' => 'estado'),
13. array('class' => 'tabla_productos')
14. );?>
15.
16. //Salida
17. <tr class="estado">
18. <th class="tabla_productos">Fecha</th>
19. <th class="tabla_productos">Nombre</th>
20. <th class="tabla_productos">Activo</th>
21. </tr>

7.4.1.16 (#tableCells-1447) tableCells

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1447/tableCells) .. Mas info
sobre traduciones (/es/view/818)

tableCells(array $data, array $oddTrOptions = null, array $evenTrOptions = null, $useCount = false,
$continueOddEven = true)

Creates table cells, in rows, assigning <tr> attributes differently for odd- and even-numbered rows. Wrap a single
table cell within an array() for specific <td>-attributes.

Plain Text View (#)

282 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <?php echo $html->tableCells(array(


2. array('Jul 7th, 2007', 'Best Brownies', 'Yes'),
3. array('Jun 21st, 2007', 'Smart Cookies', 'Yes'),
4. array('Aug 1st, 2006', 'Anti-Java Cake', 'No'),
5. ));
6. ?>
7.
8. //Output
9. <tr><td>Jul 7th, 2007</td><td>Best Brownies</td><td>Yes</td></tr>
10. <tr><td>Jun 21st, 2007</td><td>Smart Cookies</td><td>Yes</td></tr>
11. <tr><td>Aug 1st, 2006</td><td>Anti-Java Cake</td><td>No</td></tr>
12.
13. <?php echo $html->tableCells(array(
14. array('Jul 7th, 2007', array('Best Brownies', array('class'=>'highlight')) , 'Yes'),
15. array('Jun 21st, 2007', 'Smart Cookies', 'Yes'),
16. array('Aug 1st, 2006', 'Anti-Java Cake', array('No', array('id'=>'special'))),
17. ));
18. ?>
19.
20. //Output
21. <tr><td>Jul 7th, 2007</td><td class="highlight">Best Brownies</td><td>Yes</td></tr>
22. <tr><td>Jun 21st, 2007</td><td>Smart Cookies</td><td>Yes</td></tr>
23. <tr><td>Aug 1st, 2006</td><td>Anti-Java Cake</td><td id="special">No</td></tr>
24.
25. <?php echo $html->tableCells(
26. array(
27. array('Red', 'Apple'),
28. array('Orange', 'Orange'),
29. array('Yellow', 'Banana'),
30. ),
31. array('class' => 'darker')
32. );
33. ?>
34.
35. //Output
36. <tr class="darker"><td>Red</td><td>Apple</td></tr>
37. <tr><td>Orange</td><td>Orange</td></tr>
38. <tr class="darker"><td>Yellow</td><td>Banana</td></tr>

7.4.1.17 (#url-1448) url

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1448)


Comparar con el texto original (/es/compare/1448/url)

Mas info sobre traduciones (/es/view/818)

url(mixed $url = NULL, boolean $full = false)

Devuelve un URL que apunta a alguna combinación de controlador y acción. Si $url está vacío devuelve el valor de
REQUEST_URI, en caso contrario genera el URL para la combinación de controlador y acción. Si $full es true, se
antepondrá el URL base del sitio al resultado.

Plain Text View (#)

283 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <?php echo $html->url(array(


2. "controller" => "posts",
3. "action" => "view",
4. "bar"));?>
5.
6. // Salida
7. /posts/view/bar

Enseguida más ejemplos de uso:

URL con parámetros nombrados (named parameters)

Plain Text View (#)


1. <?php echo $html->url(array(
2. "controller" => "posts",
3. "action" => "view",
4. "foo" => "bar"));
5. ?>
6.
7. // Salida
8. /posts/view/foo:bar

URL con extensión

Plain Text View (#)


1. <?php echo $html->url(array(
2. "controller" => "posts",
3. "action" => "list",
4. "ext" => "rss"));
5. ?>
6.
7. // Salida
8. /posts/list.rss

URL (empezando con '/') con el URL completo del sitio agregado al inicio.

Plain Text View (#)


1. <?php echo $html->url('/posts', true); ?>
2.
3. //Salida
4. http://www.example.com/posts

URL con parámetros GET y ancla nombrada (named anchor)

Plain Text View (#)


1. <?php echo $html->url(array(
2. "controller" => "posts",
3. "action" => "buscar",
4. "?" => array("foo" => "bar"),
5. "#" => "primero"));
6. ?>
7.
8. //Salida
9. /posts/buscar?foo=bar#primero

Por mas info ver el Router::url (http://api.cakephp.org/class/router#method-Routerurl) en el API.

284 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

7.4.2 (#Changing-the-tags-output-by-HtmlHelper-1449) Changing the tags output by HtmlHelper

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1449/Changing-the-tags-output-
by-HtmlHelper) .. Mas info sobre traduciones (/es/view/818)

The built in tag sets for HtmlHelper are XHTML compliant, however if you need to generate HTML for HTML4 you will
need to create and load a new tags config file containing the tags you'd like to use. To change the tags used create
app/config/tags.php containing:

Plain Text View (#)


1. $tags = array(
2. 'metalink' => '<link href="%s"%s >',
3. 'input' => '<input name="%s" %s >',
4. //...
5. );

You can then load this tag set by calling $html->loadConfig('tags');

7.5 (#Js-1592) Js

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1592/Js) .. Mas info sobre
traduciones (/es/view/818)

Since the beginning CakePHP's support for Javascript has been with Prototype/Scriptaculous. While we still think these
are an excellent Javascript library, the community has been asking for support for other libraries. Rather than drop
Prototype in favour of another Javascript library. We created an Adapter based helper, and included 3 of the most
requested libraries. Prototype/Scriptaculous, Mootools/Mootools-more, and jQuery/jQuery UI. And while the API is
not as expansive as the previous AjaxHelper we feel that the adapter based solution allows for a more extensible
solution giving developers the power and flexibility they need to address their specific application needs.

Javascript Engines form the backbone of the new JsHelper. A Javascript engine translates an abstract Javascript element
into concrete Javascript code specific to the Javascript library being used. In addition they create an extensible system
for others to use.

7.5.1 (#Using-a-specific-Javascript-engine-1594) Using a specific Javascript engine

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1594/Using-a-specific-
Javascript-engine) .. Mas info sobre traduciones (/es/view/818)

First of all download your preferred javascript library and place it in app/webroot/js

Then you must include the library in your page. To include it in all pages, add this line to the <head> section of
app/views/layouts/default.ctp (copy this file from cake/libs/view/layouts/default.ctp if you have not created your
own).

Plain Text View (#)


1. echo $this->Html->script('jquery'); // Include jQuery library

Replace jquery with the name of your library file (.js will be added to the name).

By default scripts are cached, and you must explicitly print out the cache. To do this at the end of each page, include
this line just before the ending </body> tag

Plain Text View (#)


1. echo $js->writeBuffer(); // Write cached scripts

You must include the library in your page and print the cache for the helper to function.

Javascript engine selection is declared when you include the helper in your controller.

Plain Text View (#)


1. var $helpers = array('Js' => array('Jquery'));

The above would use the Jquery Engine in the instances of JsHelper in your views. If you do not declare a specific

285 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

engine, the jQuery engine will be used as the default. As mentioned before, there are three engines implemented in the
core, but we encourage the community to expand the library compatibility.

7.5.1.1 (#Using-jQuery-with-other-libraries-1643) Using jQuery with other libraries

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1643/Using-jQuery-with-other-
libraries) .. Mas info sobre traduciones (/es/view/818)

The jQuery library, and virtually all of its plugins are constrained within the jQuery namespace. As a general rule,
"global" objects are stored inside the jQuery namespace as well, so you shouldn't get a clash between jQuery and any
other library (like Prototype, MooTools, or YUI).

That said, there is one caveat: By default, jQuery uses "$" as a shortcut for "jQuery"

To override the "$" shortcut, use the jQueryObject variable.

Plain Text View (#)


1. $js->JqueryEngine->jQueryObject = '$j';
2. print $html->scriptBlock('var $j = jQuery.noConflict();',
3. array('inline' => false)); //Tell jQuery to go into noconflict mode

7.5.2 (#Creating-a-Javascript-Engine-1595) Creating a Javascript Engine

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1595/Creating-a-Javascript-
Engine) .. Mas info sobre traduciones (/es/view/818)

Javascript engine helpers follow normal helper conventions, with a few additional restrictions. They must have the
Engine suffix. DojoHelper is not good, DojoEngineHelper is correct. Furthermore, they should extend
JsBaseEngineHelper in order to leverage the most of the new API.

7.5.3 (#Javascript-engine-usage-1596) Javascript engine usage

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1596/Javascript-engine-usage) ..
Mas info sobre traduciones (/es/view/818)

The JsHelper provides a few methods, and acts as a facade for the the Engine helper. You should not directly access
the Engine helper except in rare occasions. Using the facade features of the JsHelper allows you to leverage the
buffering and method chaining features built-in; (method chaining only works in PHP5).

The JsHelper by default buffers almost all script code generated, allowing you to collect scripts throughout the view,
elements and layout, and output it in one place. Outputting buffered scripts is done with $js->writeBuffer(); this will
return the buffer contents in a script tag. You can disable buffering wholesale with the $bufferScripts property or
setting buffer => false in methods taking $options.

Since most methods in Javascript begin with a selection of elements in the DOM, $js->get() returns a $this, allowing
you to chain the methods using the selection. Method chaining allows you to write shorter, more expressive code. It
should be noted that method chaining Will not work in PHP4

Plain Text View (#)


1. $js->get('#foo')->event('click', $eventCode);

Is an example of method chaining. Method chaining is not possible in PHP4 and the above sample would be written
like

Plain Text View (#)


1. $js->get('#foo');
2. $js->event('click', $eventCode);

# (#Common-options-1597) Common options

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1597/Common-options) .. Mas
info sobre traduciones (/es/view/818)

In attempts to simplify development where Js libraries can change, a common set of options is supported by JsHelper,

286 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

these common options will be mapped out to the library specific options internally. If you are not planning on
switching Javascript libraries, each library also supports all of its native callbacks and options.

# (#Callback-wrapping-1598) Callback wrapping

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1598/Callback-wrapping) .. Mas
info sobre traduciones (/es/view/818)

By default all callback options are wrapped with the an anonymous function with the correct arguments. You can
disable this behavior by supplying the wrapCallbacks = false in your options array.

# (#Working-with-buffered-scripts-1599) Working with buffered scripts

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1599/Working-with-buffered-
scripts) .. Mas info sobre traduciones (/es/view/818)

One drawback to previous implementation of 'Ajax' type features was the scattering of script tags throughout your
document, and the inability to buffer scripts added by elements in the layout. The new JsHelper if used correctly
avoids both of those issues. It is recommended that you place $js->writeBuffer() at the bottom of your layout file
above the </body> tag. This will allow all scripts generated in layout elements to be output in one place. It should be
noted that buffered scripts are handled separately from included script files.

writeBuffer($options = array())

Writes all Javascript generated so far to a code block or caches them to a file and returns a linked script.

Options

inline - Set to true to have scripts output as a script block inline if cache is also true, a script link tag will be
generated. (default true)
cache - Set to true to have scripts cached to a file and linked in (default false)
clear - Set to false to prevent script cache from being cleared (default true)
onDomReady - wrap cached scripts in domready event (default true)
safe - if an inline block is generated should it be wrapped in <![CDATA[ ... ]]> (default true)

Creating a cache file with writeBuffer() requires that webroot/js be world writable and allows a browser to cache
generated script resources for any page.

buffer($content)

Add $content to the internal script buffer.

getBuffer($clear = true)

Get the contents of the current buffer. Pass in false to not clear the buffer at the same time.

7.5.4 (#Methods-1593) Methods

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1593/Methods) .. Mas info sobre
traduciones (/es/view/818)

The core Javascript Engines provide the same feature set across all libraries, there is also a subset of common options
that are translated into library specific options. This is done to provide end developers with as unified an API as
possible. The following list of methods are supported by all the Engines included in the CakePHP core. Whenever you
see separate lists for Options and Event Options both sets of parameters are supplied in the $options array for the
method.

object($data, $options = array())

Converts values into JSON. There are a few differences between this method and JavascriptHelper::object(). Most
notably there is no affordance for stringKeys or q options found in the JavascriptHelper. Furthermore $js->object();
cannot make script tags.

Options:

prefix - String prepended to the returned data.


postfix - String appended to the returned data.

287 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Example Use:

Plain Text View (#)


1. $json = $js->object($data);

sortable($options = array())

Sortable generates a javascript snippet to make a set of elements (usually a list) drag and drop sortable.

The normalized options are:

Options

containment - Container for move action


handle - Selector to handle element. Only this element will start sort action.
revert - Whether or not to use an effect to move sortable into final position.
opacity - Opacity of the placeholder
distance - Distance a sortable must be dragged before sorting starts.

Event Options

start - Event fired when sorting starts


sort - Event fired during sorting
complete - Event fired when sorting completes.

Other options are supported by each Javascript library, and you should check the documentation for your javascript
library for more detailed information on its options and parameters.

Example use:

Plain Text View (#)


1. $js->get('#my-list');
2. $js->sortable(array(
3. 'distance' => 5,
4. 'containment' => 'parent',
5. 'start' => 'onStart',
6. 'complete' => 'onStop',
7. 'sort' => 'onSort',
8. 'wrapCallbacks' => false
9. ));

Assuming you were using the jQuery engine, you would get the following code in your generated Javascript block:

Plain Text View (#)


1. $("#myList").sortable({containment:"parent", distance:5, sort:onSort, start:onStart, stop:onStop});

request($url, $options = array())

Generate a javascript snippet to create an XmlHttpRequest or 'AJAX' request.

Event Options

complete - Callback to fire on complete.


success - Callback to fire on success.
before - Callback to fire on request initialization.
error - Callback to fire on request failure.

Options

method - The method to make the request with defaults to GET in more libraries
async - Whether or not you want an asynchronous request.
data - Additional data to send.
update - Dom id to update with the content of the request.
type - Data type for response. 'json' and 'html' are supported. Default is html for most libraries.

288 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

evalScripts - Whether or not <script> tags should be eval'ed.


dataExpression - Should the data key be treated as a callback. Useful for supplying $options['data'] as
another Javascript expression.

Example use

Plain Text View (#)


1. $js->event('click',
2. $js->request(array(
3. 'action' => 'foo', param1), array(
4. 'async' => true,
5. 'update' => '#element')));

get($selector)

Set the internal 'selection' to a CSS selector. The active selection is used in subsequent operations until a new
selection is made.

Plain Text View (#)


1. $js->get('#element');

The JsHelper now will reference all other element based methods on the selection of #element. To change the active
selection, call get() again with a new element.

drag($options = array())

Make an element draggable.

Options

handle - selector to the handle element.


snapGrid - The pixel grid that movement snaps to, an array(x, y)
container - The element that acts as a bounding box for the draggable element.

Event Options

start - Event fired when the drag starts


drag - Event fired on every step of the drag
stop - Event fired when dragging stops (mouse release)

Example use

Plain Text View (#)


1. $js->get('#element');
2. $js->drag(array(
3. 'container' => '#content',
4. 'start' => 'onStart',
5. 'drag' => 'onDrag',
6. 'stop' => 'onStop',
7. 'snapGrid' => array(10, 10),
8. 'wrapCallbacks' => false
9. ));

If you were using the jQuery engine the following code would be added to the buffer.

Plain Text View (#)


1. $("#element").draggable({containment:"#content", drag:onDrag, grid:[10,10], start:onStart, stop:onStop})

drop($options = array())

Make an element accept draggable elements and act as a dropzone for dragged elements.

Options

289 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

accept - Selector for elements this droppable will accept.


hoverclass - Class to add to droppable when a draggable is over.

Event Options

drop - Event fired when an element is dropped into the drop zone.
hover - Event fired when a drag enters a drop zone.
leave - Event fired when a drag is removed from a drop zone without being dropped.

Example use

Plain Text View (#)


1. $js->get('#element');
2. $js->drop(array(
3. 'accept' => '.items',
4. 'hover' => 'onHover',
5. 'leave' => 'onExit',
6. 'drop' => 'onDrop',
7. 'wrapCallbacks' => false
8. ));

If you were using the jQuery engine the following code would be added to the buffer:

Plain Text View (#)


1. <code class=
2. "php">$("#element").droppable({accept:".items", drop:onDrop, out:onExit, over:onHover});</code>

''Note'' about MootoolsEngine::drop

Droppables in Mootools function differently from other libraries. Droppables are implemented as an extension of
Drag. So in addtion to making a get() selection for the droppable element. You must also provide a selector rule to the
draggable element. Furthermore, Mootools droppables inherit all options from Drag.

slider()

Create snippet of Javascript that converts an element into a slider ui widget. See your libraries implementation for
additional usage and features.

Options

handle - The id of the element used in sliding.


direction - The direction of the slider either 'vertical' or 'horizontal'
min - The min value for the slider.
max - The max value for the slider.
step - The number of steps or ticks the slider will have.
value - The initial offset of the slider.

Events

change - Fired when the slider's value is updated


complete - Fired when the user stops sliding the handle

Example use

Plain Text View (#)

290 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. $js->get('#element');
2. $js->slider(array(
3. 'complete' => 'onComplete',
4. 'change' => 'onChange',
5. 'min' => 0,
6. 'max' => 10,
7. 'value' => 2,
8. 'direction' => 'vertical',
9. 'wrapCallbacks' => false
10. ));

If you were using the jQuery engine the following code would be added to the buffer:

Plain Text View (#)


1. $("#element").slider({change:onChange, max:10, min:0, orientation:"vertical", stop:onComplete, value:2})

effect($name, $options = array())

Creates a basic effect. By default this method is not buffered and returns its result.

Supported effect names

The following effects are supported by all JsEngines

show - reveal an element.


hide - hide an element.
fadeIn - Fade in an element.
fadeOut - Fade out an element.
slideIn - Slide an element in.
slideOut - Slide an element out.

Options

speed - Speed at which the animation should occur. Accepted values are 'slow', 'fast'. Not all effects use the
speed option.

Example use

If you were using the jQuery engine.

Plain Text View (#)


1. $js->get('#element');
2. $result = $js->effect('fadeIn');
3. //$result contains $("#foo").fadeIn();

event($type, $content, $options = array())

Bind an event to the current selection. $type can be any of the normal DOM events or a custom event type if your
library supports them. $content should contain the function body for the callback. Callbacks will be wrapped with
function (event) { ... } unless disabled with the $options.

Options

wrap - Whether you want the callback wrapped in an anonymous function. (defaults to true)
stop - Whether you want the event to stopped. (defaults to true)

Example use

Plain Text View (#)


1. $js->get('#some-link');
2. $js->event('click', $js->alert('hey you!'));

If you were using the jQuery library you would get the following Javascript code.

Plain Text View (#)

291 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. $('#some-link').bind('click', function (event) {


2. alert('hey you!');
3. return false;
4. });

You can remove the return false; by passing setting the stop option to false.

Plain Text View (#)


1. $js->get('#some-link');
2. $js->event('click', $js->alert('hey you!'), array('stop' => false));

If you were using the jQuery library you would the following Javascript code would be added to the buffer. Note that
the default browser event is not cancelled.

Plain Text View (#)


1. $('#some-link').bind('click', function (event) {
2. alert('hey you!');
3. });

domReady($callback)

Creates the special 'DOM ready' event. writeBuffer() automatically wraps the buffered scripts in a domReady method.

each($callback)

Create a snippet that iterates over the currently selected elements, and inserts $callback.

Example

Plain Text View (#)


1. $js->get('div.message');
2. $js->each('$(this).css({color: "red"});');

Using the jQuery engine would create the following Javascript

Plain Text View (#)


1. $('div.message').each(function () { $(this).css({color: "red"});});

alert($message)

Create a javascript snippet containing an alert() snippet. By default, alert does not buffer, and returns the script
snippet.

Plain Text View (#)


1. $alert = $js->alert('Hey there');

confirm($message)

Create a javascript snippet containing a confirm() snippet. By default, confirm does not buffer, and returns the script
snippet.

Plain Text View (#)


1. $alert = $js->confirm('Are you sure?');

prompt($message, $default)

Create a javascript snippet containing a prompt() snippet. By default, prompt does not buffer, and returns the script
snippet.

Plain Text View (#)


1. $prompt = $js->prompt('What is your favorite color?', 'blue');

submit()

292 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Create a submit input button that enables XmlHttpRequest submitted forms. Options can include
both those for FormHelper::submit() and JsBaseEngine::request(), JsBaseEngine::event();

Forms submitting with this method, cannot send files. Files do not transfer over XmlHttpRequest
and require an iframe, or other more specialized setups that are beyond the scope of this helper.

Options

confirm - Confirm message displayed before sending the request. Using confirm, does not replace any before
callback methods in the generated XmlHttpRequest.
buffer - Disable the buffering and return a script tag in addition to the link.
wrapCallbacks - Set to false to disable automatic callback wrapping.

Example use

Plain Text View (#)


1. echo $js->submit('Save', array('update' => '#content'));

Will create a submit button with an attached onclick event. The click event will be buffered by default.

Plain Text View (#)


1. echo $js->submit('Save', array('update' => '#content', 'div' => false, 'type' => 'json', 'async' => fals

Shows how you can combine options that both FormHelper::submit() and Js::request() when using submit.

link($title, $url = null, $options = array())

Create an html anchor element that has a click event bound to it. Options can include both those for HtmlHelper::link()
and JsBaseEngine::request(), JsBaseEngine::event(); $htmlAttributes is used to specify additional options that are
supposed to be appended to the generated anchor element. If an option is not part of the standard attributes or
$htmlAttributes it will be passed to request() as an option. If an id is not supplied, a randomly generated one will be
created for each link generated.

Options

confirm - Generate a confirm() dialog before sending the event.


id - use a custom id.
htmlAttributes - additional non-standard htmlAttributes. Standard attributes are class, id, rel, title, escape,
onblur and onfocus.
buffer - Disable the buffering and return a script tag in addition to the link.

Example use

Plain Text View (#)


1. echo $js->link('Page 2', array('page' => 2), array('update' => '#content'));

Will create a link pointing to /page:2 and updating #content with the response.

You can use the htmlAttributes option to add in additional custom attributes.

Plain Text View (#)


1. echo $js->link('Page 2', array('page' => 2), array(
2. 'update' =&gt; '#content',
3. 'htmlAttributes' =&gt; array('other' =&gt; 'value')
4. ));
5. //Creates the following html
6. <a href="/es/posts/index/page:2" other="value">Page 2</a>

serializeForm($options = array())

Serialize the form attached to $selector. Pass true for $isForm if the current selection is a form element. Converts the
form or the form element attached to the current selection into a string/json object (depending on the library
implementation) for use with XHR operations.

293 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Options

isForm - is the current selection a form, or an input? (defaults to false)


inline - is the rendered statement going to be used inside another JS statement? (defaults to false)

Setting inline == false allows you to remove the trailing ;. This is useful when you need to serialize a form element as
part of another Javascript operation, or use the serialize method in an Object literal.

redirect($url)

Redirect the page to $url using window.location.

value($value)

Converts a PHP-native variable of any type to a JSON-equivalent representation. Escapes any string values into JSON
compatible strings. UTF-8 characters will be escaped.

7.5.5 (#Ajax-Pagination-1600) Ajax Pagination

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1600/Ajax-Pagination) .. Mas
info sobre traduciones (/es/view/818)

Much like Ajax Pagination in 1.2, you can use the JsHelper to handle the creation of Ajax pagination links instead of
plain HTML links.

# (#Making-Ajax-Links-1601) Making Ajax Links

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1601/Making-Ajax-Links) .. Mas
info sobre traduciones (/es/view/818)

Before you can create ajax links you must include the Javascript library that matches the adapter you are using with
JsHelper. By default the JsHelper uses jQuery. So in your layout include jQuery (or whichever library you are using)

Plain Text View (#)


1. echo $this->Html->script('jquery');

Similar to 1.2 you need to tell the PaginatorHelper that you want to make Javascript enhanced links instead of plain
HTML ones. To do so you use options()

Plain Text View (#)


1. $this->Paginator->options(array(
2. 'update' => '#content',
3. 'evalScripts' => true
4. ));

The PaginatorHelper now knows to make javascript enhanced links, and that those links should update the #content
element. Of course this element must exist, and often times you want to wrap $content_for_layout with a div matching
the id used for the update option. You also should set evalScripts to true if you are using the Mootools or Prototype
adapters, without evalScripts these libraries will not be able to chain requests together. The indicator option is not
supported by JsHelper and will be ignored.

You then create all the links as needed for your pagination features. Since the JsHelper automatically buffers all
generated script content to reduce the number of <script> tags in your source code you must call write the buffer
out. At the bottom of your view file. Be sure to include:

Plain Text View (#)


1. echo $this->Js->writeBuffer();

If you omit this you will not be able to chain ajax pagination links. When you write the buffer, it is also cleared, so
you don't have worry about the same Javascript being output twice.

# (#Adding-effects-and-transitions-1602) Adding effects and transitions

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1602/Adding-effects-

294 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

and-transitions) .. Mas info sobre traduciones (/es/view/818)

Since indicator is no longer supported, you must add any indicator effects yourself.

Plain Text View (#)


1. <html>
2. <head>
3. <?php echo $this->Html->script('jquery'); ?>
4. //more stuff here.
5. </head>
6. <body>
7. <div id="content">
8. <?php echo $content_for_layout; ?>
9. </div>
10. <?php echo $this->Html->image('indicator.gif', array('id' => 'busy-indicator')); ?>
11. </body>
12. </html>

Remember to place the indicator.gif file inside app/webroot/img folder. You may see a situation where the
indicator.gif displays immediately upon the page load. You need to put in this css #busy-indicator { display:none;
} in your main css file.

With the above layout, we've included an indicator image file, that will display a busy indicator animation that we will
show and hide with the JsHelper. To do that we need to update our options() function.

Plain Text View (#)


1. $this->Paginator->options(array(
2. 'update' => '#content',
3. 'evalScripts' => true,
4. 'before' => $this->Js->get('#busy-indicator')->effect('fadeIn', array('buffer' => false)),
5. 'complete' => $this->Js->get('#busy-indicator')->effect('fadeOut', array('buffer' => false)),
6. ));

This will show/hide the busy-indicator element before and after the #content div is updated. Although indicator has
been removed, the new features offered by JsHelper allow for more control and more complex effects to be created.

7.6 (#Javascript-1450) Javascript

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1450)


Comparar con el texto original (/es/compare/1450/Javascript)

Mas info sobre traduciones (/es/view/818)

EL ayudante Javascript es usado para en la creación de etiquetas y bloques de código javascript bien formados.
Existen varios métodos algunos de los cuales están diseñados para trabajar con el framework Javascript Prototype
(http://www.prototypejs.org) .

7.6.1 (#Methods-1451) Methods

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1451/Methods) .. Mas info sobre
traduciones (/es/view/818)

codeBlock($script, $options = array('allowCache'=>true,'safe'=>true,'inline'=>true), $safe)

string $script - The JavaScript to be wrapped in SCRIPT tags


array $options - Set of options:
allowCache: boolean, designates whether this block is cacheable using the current cache settings.
safe: boolean, whether this block should be wrapped in CDATA tags. Defaults to helper's object
configuration.
inline: whether the block should be printed inline, or written to cached for later output (i.e.
$scripts_for_layout).
boolean $safe - DEPRECATED. Use $options['safe'] instead

295 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

codeBlock returns a formatted script element containing $script. But can also return null if Javascript helper is set to
cache events. See JavascriptHelper::cacheEvents(). And can write in $scripts_for_layout if you set $options['inline'] to
false.

blockEnd()

Ends a block of cached Javascript. Can return either a end script tag, or empties the buffer, adding the contents to the
cachedEvents array. Its return value depends on the cache settings. See JavascriptHelper::cacheEvents()

link($url, $inline = true)

mixed $url - String URL to JavaScript file, or an array of URLs.


boolean $inline If true, the <script> tag will be printed inline, otherwise it will be printed in
$scripts_for_layout

Creates a javascript link to a single or many javascript files. Can output inline or in $scripts_for_layout.

If the filename is prefixed with "/", the path will be relative to the base path of your application. Otherwise, the path
will be relative to your JavaScript path, usually webroot/js.

escapeString($string)

string $script - String that needs to get escaped.

Escape a string to be JavaScript friendly. Allowing it to safely be used in javascript blocks.

The characters that are escaped are:

"\r\n" => '\n'


"\r" => '\n'
"\n" => '\n'
'"' => '\"'
"'" => "\\'"

event($object, $event, $observer, $useCapture)

string $object - DOM Object to be observed.


string $event - type of event to observe ie 'click', 'over'.
string $observer - Javascript function to call when event occurs.
array $options - Set options: useCapture, allowCache, safe
boolean $options['useCapture'] - Whether to fire the event in the capture or bubble phase of event
handling. Defaults false
boolean $options['allowCache'] - See JavascriptHelper::cacheEvents()
boolean $options['safe'] - Indicates whether <script /> blocks should be written 'safely,' i.e. wrapped in
CDATA blocks

Attach a javascript event handler specified by $event to an element DOM element specified by $object. Object does not
have to be an ID reference it can refer to any valid javascript object or CSS selectors. If a CSS selector is used the event
handler is cached and should be retrieved with JavascriptHelper::getCache(). This method requires the Prototype
library.

cacheEvents($file, $all)

boolean $file - If true, code will be written to a file


boolean $all - If true, all code written with JavascriptHelper will be sent to a file

Allows you to control how the JavaScript Helper caches event code generated by event(). If $all is set to true, all code
generated by the helper is cached and can be retrieved with getCache() or written to file or page output with
writeCache().

getCache($clear)

boolean $clear - If set to true the cached javascript is cleared. Defaults to true.

Gets (and clears) the current JavaScript event cache

writeEvents($inline)

boolean $inline - If true, returns JavaScript event code. Otherwise it is added to the output of

296 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

$scripts_for_layout in the layout.

Returns cached javascript code. If $file was set to true with cacheEvents(), code is cached to a file and a script link to
the cached events file is returned. If inline is true, the event code is returned inline. Else it is added to the
$scripts_for_layout for the page.

includeScript($script)

string $script - File name of script to include.

Includes the named $script. If $script is left blank the helper will include every script in your app/webroot/js
directory. Includes the contents of each file inline. To create a script tag with an src attribute use link().

object($data, $options)

array $data - Data to be converted


array $options - Set of options: block, prefix, postfix, stringKeys, quoteKeys, q
boolean $options['block'] - Wraps return value in a <script /> block if true. Defaults to false.
string $options['prefix'] - Prepends the string to the returned data.
string $options['postfix'] - Appends the string to the returned data.
array $options['stringKeys'] - A list of array keys to be treated as a string.
boolean $options['quoteKeys'] - If false, treats $stringKey as a list of keys *not* to be quoted. Defaults to
true.
string $options['q'] - The type of quote to use.

Generates a JavaScript object in JavaScript Object Notation (JSON) from $data array.

7.7 (#Number-1452) Number

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1452/Number) .. Mas info sobre
traduciones (/es/view/818)

The NumberHelper contains convenience methods that enable display numbers in common formats in your views.
These methods include ways to format currency, percentages, data sizes, format numbers to specific precisions and
also to give you more flexibility with formating numbers.

All of these functions return the formated number; They do not automatically echo the output into the view.

7.7.1 (#currency-1453) currency

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1453/currency) .. Mas info sobre
traduciones (/es/view/818)

currency(mixed $number, string $currency= 'USD', $options = array())

This method is used to display a number in common currency formats (EUR,GBP,USD). Usage in a view looks like:

Plain Text View (#)


1. <?php echo $number->currency($number,$currency); ?>

The first parameter, $number, should be a floating point number that represents the amount of money you are
expressing. The second parameter is used to choose a predefined currency formatting scheme:

$currency 1234.56, formatted by currency type


EUR € 1.236,33
GBP £ 1,236.33
USD $ 1,236.33

The third parameter is an array of options for further defining the output. The following options are available:

Option Description
before The currency symbol to place before whole numbers ie. '$'
The currency symbol to place after decimal numbers ie. 'c'. Set to boolean false to use no decimal symbol.
after
eg. 0.35 => $0.35.
zero The text to use for zero values, can be a string or a number. ie. 0, 'Free!'

297 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Option Description
places Number of decimal places to use. ie. 2
thousands Thousands separator ie. ','
decimals Decimal separator symbol ie. '.'
negative Symbol for negative numbers. If equal to '()', the number will be wrapped with ( and )
escape Should the output be htmlentity escaped? Defaults to true

If a non-recognized $currency value is supplied, it is prepended to a USD formatted number. For example:

Plain Text View (#)


1. <?php echo $number->currency('1234.56', 'FOO'); ?>
2.
3. //Outputs:
4. FOO 1,234.56

7.7.2 (#precision-1454) precision

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1454/precision) .. Mas info
sobre traduciones (/es/view/818)

precision (mixed $number, int $precision = 3)

This method displays a number with the specified amount of precision (decimal places). It will round in order to
maintain the level of precision defined.

Plain Text View (#)


1. <?php echo $number->precision(456.91873645, 2 ); ?>
2.
3. //Outputs:
4. 456.92

7.7.3 (#toPercentage-1455) toPercentage

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1455/toPercentage) .. Mas info
sobre traduciones (/es/view/818)

toPercentage(mixed $number, int $precision = 2)

Like precision(), this method formats a number according to the supplied precision (where numbers are rounded to
meet the given precision). This method also expresses the number as a percentage and prepends the output with a
percent sign.

Plain Text View (#)


1. <?php echo $number->toPercentage(45.691873645); ?>
2.
3. //Outputs:
4. 45.69%

7.7.4 (#toReadableSize-1456) toReadableSize

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1456/toReadableSize) .. Mas info
sobre traduciones (/es/view/818)

toReadableSize(string $data_size)

This method formats data sizes in human readable forms. It provides a shortcut way to convert bytes to KB, MB, GB,
and TB. The size is displayed with a two-digit precision level, according to the size of data supplied (i.e. higher sizes
are expressed in larger terms):

Plain Text View (#)

298 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. echo $number->toReadableSize(0); // 0 Bytes


2. echo $number->toReadableSize(1024); // 1 KB
3. echo $number->toReadableSize(1321205.76); // 1.26 MB
4. echo $number->toReadableSize(5368709120); // 5.00 GB

7.7.5 (#format-1457) format

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1457/format) .. Mas info sobre
traduciones (/es/view/818)

format (mixed $number, mixed $options=false)

This method gives you much more control over the formatting of numbers for use in your views (and is used as the
main method by most of the other NumberHelper methods). Using this method might looks like:

Plain Text View (#)


1. $number->format($number, $options);

The $number parameter is the number that you are planning on formatting for output. With no $options supplied, the
number 1236.334 would output as 1,236. Note that the default precision is zero decimal places.

The $options parameter is where the real magic for this method resides.

If you pass an integer then this becomes the amount of precision or places for the function.
If you pass an associated array, you can use the following keys:
places (integer): the amount of desired precision
before (string): to be put before the outputted number
escape (boolean): if you want the value in before to be escaped
decimals (string): used to delimit the decimal places in a number
thousands (string): used to mark off thousand, millions, … places

Plain Text View (#)


1. echo $number->format('123456.7890', array(
2. 'places' => 2,
3. 'before' => '¥ ',
4. 'escape' => false,
5. 'decimals' => '.',
6. 'thousands' => ','
7. ));
8. // output '¥ 123,456.79'

7.8 (#Paginator-1458) Paginator

El Paginator helper, se usa para imprimir los controles de los números de página y de los links siguiente y previo.

Ve también Tareas comunes con CakePHP - Paginacion (/es/view/164/pagination) para más información.

7.8.1 (#Métodos-1459) Métodos

options($options = array())

options() : Opciones por defecto de la paginación para los links. Si se suministra un string, éste se usa como el
id del elemento DOM a updatear. Vea #options para la lista de las llaves posibles.

options() configura todas las opciones para el Paginator Helper. Las opciones soportadas son:

format

Formato del contador. Los formatos soportados son 'range' y 'pages' y custon (personalizado) que es el por defecto.
En el modo por defecto el string proporcionado es parseado y los tokens son reemplazados por sus verdaderos
valores. Los tokens disponibles son:

%page% - la página actual.


%pages% - número total de páginas.
%current% - número actual de registros mostrados.

299 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

%count% - número total de registros en el conjunto resultado.


%start% - numero del primer registro mostrado.
%end% - numero del ultimo registro mostrado.

Ahora que sabes los tokens disponibles, puedes usar el método counter() para mostrar todos tipo de información
retornada en los resultados, por ejemplo:

Plain Text View (#)


1. echo $paginator->counter(array(
2. 'format' => 'Pagina %page% de %pages%,
3. mostrando %current% registros de un total de %count%,
4. comenzando en el registro %start%, terminando en el %end%'
5. ));

separator

El separador entre la pagina actual y el numero de paginas. El valor por defecto es ' of '. Esto se usa en conjunto con
formato = 'pages'

url

La url de la accion de paginación. url tiene algunas sub opciones también

sort - la llave por la cual los registros estan ordenados


direction - la dirección en la cual se ordena. Valor por defecto 'ASC'
page - el número de página a mostrar

model

El nombre del modelo que esta siendo paginado.

escape

Define si el campo de título de los links debería ser sin HTML. Valor por defecto true.

update

El id del elemento DOM a updatear con los resultados de una llamada AJAX.. Si no esta especificada, se crearán links
regulares.

indicator

El id del elemento DOM que será mostrado como indicador de descarga o trabajo en curso mientras se ejecuta la
llamada AJAX.

link($title, $url = array(), $options = array())

string $title - El título del link.


mixed $url Url para la acción. Ver Router::url()
array $options Opciones para el link. ver options() para la lista de llaves.

Crea un link regular o AJAX con los parametros de paginación.

Plain Text View (#)


1. echo $paginator->link('Ordenados por título en pagina 5',
2. array('sort' => 'title', 'page' => 5, 'direction' => 'desc'));

Si se creó en la vista en /posts/index Debería crear un link apuntando a '/posts/index/page:5/sort:title


/direction:desc'

7.9 (#RSS-1460) RSS

El helper RSS hace que generar XML para un RSS feed sea muy fácil.

7.9.1 (#Creando-un-RSS-feed-con-el-RssHelper-1461) Creando un RSS feed con el RssHelper

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

300 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Ver que ha cambiado (/es/nodes/redirect_to_revision/1461)


Comparar con el texto original (/es/compare/1461/Creando-un-RSS-feed-con-el-RssHelper)

Mas info sobre traduciones (/es/view/818)

Este ejemplo asume que tu tienes creados un controlador de Posts y un modelo de Post y que quieres hacer una vista
alternativa para RSS.

Crear una version xml/rss de posts/index es algo muy fácil con CakePHP 1.2. Despues de unos simples pasos puedes
añadir la extension .rss a post/index haciendo tu URL posts/index.rss. Antes de adelantarnos tratando de conseguir
que nuestro servicio web quede listo, debemos hacer algunas pequeñas cosas. Primero debemos activar
parseExtensions, esto se hace en app/config/routes.php

Plain Text View (#)


1. Router::parseExtensions('rss');

En segundo lugar una buena idea es agregar RequestHandler al arreglo de componentes $components de
PostsController. Esto permitirá que ocurra mucha automagia. En la llamanda anterior hemos activado la extension
.rss. Cuando usamos Router::parseExtensions() podemos pasar tantos argumentos o extensiones como queramos.
Esto activará cada 'extension/content-type' para el uso de nuestra aplicación. Ahora, cuando la dirección
posts/index.rss sea requerida obtendrás una versión xml de posts/index. Sin embargo, lo primero que necesitamos
es hacer que los archivos de vista que crearán nuestro rss/xml feed.

7.9.1.1 (#Código-para-el-Controlador-1462) Código para el Controlador

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1462)


Comparar con el texto original (/es/compare/1462/Código-para-el-Controlador)

Mas info sobre traduciones (/es/view/818)

Antes de crear nuestra version RSS de posts/index necesitamos poner algunas cosas en orden. Es tentador poner el
canal de metadatos en la accion del controlador y pasarlo a nuestas vistas usando la función Controller::set() pero es
es inapropiado. Esta información también ir a la vista. Pero eso vendrá después, por ahora si tienes alguna lógica
diferente para los datos usados en el RSS feed y los datos que se usan en la vista html puedes usar el método
RequestHandler::isRss(), de otra forma tu controlador puede quedar igual.

Plain Text View (#)


1. // Modificar la accion del controlador de Posts que corresponde
2. // a la cual entrega el rss feed, que en nuestro caso
3. // es la accion index
4. public function index(){
5. if( $this->RequestHandler->isRss() ){
6. $posts = $this->Post->find('all', array('limit' => 20, 'order' => 'Post.created DESC'));
7. $this->set(compact('posts'));
8. } else {
9. // esta no es una llamada Rss, entonces entregamos
10. // usamos los datos para la salida html
11. $this->paginate['Post'] = array('order' = 'Post.created DESC', 'limit' => 10);
12.
13. $posts = $this->paginate();
14. $this->set(compact('posts'));
15. }
16. }

Con todas las variables de vista configuradas necesitamos crear un layout rss.

7.9.1.1.1 (#Layout-RSS-1463) Layout RSS

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1463)


Comparar con el texto original (/es/compare/1463/Layout-RSS)

301 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Mas info sobre traduciones (/es/view/818)

Un layout RSS es muy simple, escribe lo siguiente en app/view/layouts/rss/default.ctp:

Plain Text View (#)


1. echo $rss->header();
2. if (!isset($documentData)) {
3. $documentData = array();
4. }
5. if (!isset($channelData)) {
6. $channelData = array();
7. }
8. if (!isset($channelData['title'])) {
9. $channelData['title'] = $title_for_layout;
10. }
11. $channel = $rss->channel(array(), $channelData, $content_for_layout);
12. echo $rss->document($documentData,$channel);

No parece ser la gran cosa, sin embargo gracias al poder del RssHelper hara un monton de cosas por nosotros. No
hemos configrado $documentData o $channelData en nuestro controlador, sin embargo, en CakePHP 1.2 tus vistas
pueden pasar variables de vuelta al layout. En este momento nuestro arreglo $channelData entrará en acción para
configurar todos los metadatos para nuestro feed.

Lo siguiente es el archivo de vista de posts/index. Así como necesitamos un layout, necesitamos crear el directorio
views/posts/rss/ y crear un nuevo index.ctp dentro. El contenido de ese archivo está mas abajo.

7.9.1.1.2 (#La-vista-1464) La vista

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1464)


Comparar con el texto original (/es/compare/1464/La-vista)

Mas info sobre traduciones (/es/view/818)

Nuestra vista comienza por configurar las variables $documentData y $channelData para el layout, estos contienen
todos los metadatos para nuestro RSS feed. Esto se hace utilizando el método View::set() el cual es análogo al método
Controller::set(). Acá estamos pasando los metadatos del canal de vuelta al layout.

Plain Text View (#)


1. $this->set('documentData', array(
2. 'xmlns:dc' => 'http://purl.org/dc/elements/1.1/'));
3. $this->set('channelData', array(
4. 'title' => __("Artículos más leídos", true),
5. 'link' => $html->url('/', true),
6. 'description' => __("Artículos más recientes.", true),
7. 'language' => 'en-us'));

La segunda parte de la vista genera los elementos para los registros del feed. Esto se consigue haciendo un ciclo a
los datos entregados a la vista ($items) y usando el método RssHelper::item(). El otro método que puedes usar es,
RssHelper::items() el cual toma una llamada y un arreglo de items para el feed. (El metodo usado para las llamadas
siempre a se ha llamado transformRss()). Hay un punto débil en este método, que es que no puedes usar ningún
método de otro helper para preparar los datos dentro del metodo de la llamada, porque el ámbito dentro de la
llamada no incluye nada que no se haya entregado desde afuera, lo que no da acceso al TimeHelper o cualquier otro
que necesitemos. El metodo RssHelper::item() transforma el arreglo asociativo en un elemento para cada par llave-
valor.

Plain Text View (#)

302 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. foreach ($entries as $entry) {


2. $postTime = strtotime($entry['Entry']['created']);
3.
4. $entryLink = array(
5. 'controller' => 'entries',
6. 'action' => 'view',
7. 'year' => date('Y', $postTime),
8. 'month' => date('m', $postTime),
9. 'day' => date('d', $postTime),
10. $entry['Entry']['slug']);
11. // deberías importar Sanitize
12. App::import('Sanitize');
13. // Acá es donde se limpia el cuerpo del texto para la salida como la descripción
14. // de los items rss, esto necesita tener solo texto para asegurarnos de que valide el feed
15. $bodyText = preg_replace('=\(.*?)\=is', '', $entry['Entry']['body']);
16. $bodyText = $text->stripLinks($bodyText);
17. $bodyText = Sanitize::stripAll($bodyText);
18. $bodyText = $text->truncate($bodyText, 400, '...', true, true);
19.
20. echo $rss->item(array(), array(
21. 'title' => $entry['Entry']['title'],
22. 'link' => $entryLink,
23. 'guid' => array('url' => $entryLink, 'isPermaLink' => 'true'),
24. 'description' => $bodyText,
25. 'dc:creator' => $entry['Entry']['author'],
26. 'pubDate' => $entry['Entry']['created']));
27. }

Puedes ver que podemos usar el loop para preparar los datos para ser transformados en elementos XML. Es
importante filtrar cuaquier caracter que no sea de texto plano, especialmente si estas usando un editor de html para el
cuerpo de tu blog. En el codigo anterior usamos el método TextHelper::stripLinks() y algunos pocos métodos de la
clase Sanitize, pero recomendamos escribir un helper especializado para dejar el texto realmente limpio. Una vez que
hemos configurado los datos para el feed, podemos usar el método RssHelper::item() para crear el XML del formato
RSS. Una vez que hayas hecho todo esto, puedes probar tu RSS dirigiéndote a la direccion /entries/index.rss y verás
tu nuevo feed. Siempre es importante que valides tu RSS feed antes de ponerlo en produccion. Esto se puede hacer
visitando algunos sitios como FeedValidator o el sitio de w3c en http://validator.w3.org/feed/.

7.10 (#Sesión-1465) Sesión

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1465)


Comparar con el texto original (/es/compare/1465/Sesión)

Mas info sobre traduciones (/es/view/818)

Como contraparte natural al Componente Session, el Helper Session refleja la mayoría de las funcionalidades de los
componentes y las hace disponible a las vistas. El Helper de Sesión se agrega automáticamente a tu vista, no es
necesario agregarlo en el arreglo $helpers en el controlador.

La mayor diferencia entre el Helper y el Componente de Sesión es que el Helper no puede escribir en la sesión.

Al igual que en el Componente de Sesión, los datos son escritos y leídos usando estructuras de arreglos separadas
por puntos.

Plain Text View (#)


1. array('User' =>
2. array('username' => 'super@ejemplo.com')
3. );

Dada la estructura de arreglo previa, el nodo sería accesado por User.username, con el punto indicando el arreglo
enlazado. Esta notación es usada por todos los métodos del Helper de Sesión siempre que se utilice $key.

303 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

7.10.1 (#Methods-1466) Methods

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1466/Methods) .. Mas info sobre
traduciones (/es/view/818)

read($key) Read from the Session. Returns a string or array depending on the contents of the session.
id() Returns the current session ID.
check($key) Check to see if a key is in the Session. Returns a boolean on the key's existence.
This will return the contents of the $_SESSION.Message. It is used in conjunction with the Session
flash($key)
Component's setFlash() method.
error() Returns the last error in the session if one exists.

7.10.2 (#flash-1467) flash

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1467/flash) .. Mas info sobre
traduciones (/es/view/818)

The flash method uses the default key set by setFlash(). You can also retrieve specific keys in the session. For
example, the Auth component sets all of its Session messages under the 'auth' key

Plain Text View (#)


1. // Controller code
2. $this->Session->setFlash('My Message');
3. // In view
4. echo $session->flash();
5. // outputs "<div id='flashMessage' class='message'>My Message</div>"
6. // output the AuthComponent Session message, if set.
7. echo $session->flash('auth');

# (#Using-Flash-for-Success-and-Failure-1468) Using Flash for Success and Failure

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1468/Using-Flash-for-Success-
and-Failure) .. Mas info sobre traduciones (/es/view/818)

In some web sites, particularly administration backoffice web applications it is often expected that the result of an
operation requested by the user has associated feedback as to whether the operation succeeded or not. This is a
classic usage for the flash mechanism since we only want to show the user the result once and not keep the message.

One way to achieve this is to use Session->flash() with the layout parameter. With the layout parameter we can be in
control of the resultant html for the message.

In the controller you might typically have code:

Plain Text View (#)


1. if ($user_was_deleted) {
2. $this->Session->setFlash('The user was deleted successfully.', 'flash_success');
3. } else {
4. $this->Session->setFlash('The user could not be deleted.', 'flash_failure');
5. }

The flash_success and flash_failure parameter represents an element file to place in the root app/views/elements
folder, e.g. app/views/elements/flash_success.ctp, app/views/elements/flash_failure.ctp

Inside the flash_success element file would be something like this:

Plain Text View (#)


1. <div class="flash flash_success">
2. <?php echo $message ?>
3. </div>

The final step is in your main view file where the result is to be displayed to add simply

304 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Plain Text View (#)


1. <?php echo $session->flash(); ?>

And of course you can then add to your CSS a selector for div.flash, div.flash_success and div.flash_failure

7.11 (#Text-1469) Text

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1469/Text) .. Mas info sobre
traduciones (/es/view/818)

The TextHelper contains methods to make text more usable and friendly in your views. It aids in enabling links,
formatting urls, creating excerpts of text around chosen words or phrases, highlighting key words in blocks of text,
and to gracefully truncating long stretches of text.

# (#autoLinkEmails-1618) autoLinkEmails

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1618/autoLinkEmails) .. Mas info
sobre traduciones (/es/view/818)

autoLinkEmails(string $text, array $htmlOptions=array())

Adds links to the well-formed email addresses in $text, according to any options defined in $htmlOptions (see
HtmlHelper::link() (/es/view/1442) ).

Plain Text View (#)


1. $my_text = 'For more information regarding our world-famous pastries and desserts, contact info@example.
2. $linked_text = $text->autoLinkEmails($my_text);

Output:

For more information regarding our world-famous pastries and desserts,


contact <a href="mailto:info@example.com">info@example.com</a>

# (#autoLinkUrls-1619) autoLinkUrls

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1619/autoLinkUrls) .. Mas info
sobre traduciones (/es/view/818)

autoLinkUrls(string $text, array $htmlOptions=array())

Same as in autoLinkEmails(), only this method searches for strings that start with https, http, ftp, or nntp and links
them appropriately.

# (#autoLink-1620) autoLink

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1620/autoLink) .. Mas info sobre
traduciones (/es/view/818)

autoLink(string $text, array $htmlOptions=array())

Performs the functionality in both autoLinkUrls() and autoLinkEmails() on the supplied $text. All URLs and emails
are linked appropriately given the supplied $htmlOptions.

# (#excerpt-1621) excerpt

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1621/excerpt) .. Mas info sobre
traduciones (/es/view/818)

excerpt(string $haystack, string $needle, int $radius=100, string $ending="...")

Extracts an excerpt from $haystack surrounding the $needle with a number of characters on each side determined by
$radius, and suffixed with $ending. This method is especially handy for search results. The query string or keywords
can be shown within the resulting document.

Plain Text View (#)

305 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. echo $text->excerpt($last_paragraph, 'method', 50);

Output:

mined by $radius, and suffixed with $ending. This method is especially handy for
search results. The query...

# (#highlight-1622) highlight

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1622/highlight) .. Mas info sobre
traduciones (/es/view/818)

highlight(string $haystack, string $needle, $highlighter='<span class="highlight">\1</span>')

Highlights $needle in $haystack using the $highlighter string specified.

Plain Text View (#)


1. echo $text->highlight($last_sentence, 'using');

Output:

Highlights $needle in $haystack <span class="highlight">using</span>


the $highlighter string specified.

# (#stripLinks-1623) stripLinks

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1623/stripLinks) .. Mas info
sobre traduciones (/es/view/818)

stripLinks($text)

Strips the supplied $text of any HTML links.

# (#toList-1624) toList

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1624/toList) .. Mas info sobre
traduciones (/es/view/818)

toList(array $list, $and='and')

Creates a comma-separated list where the last two items are joined with ʻandʼ.

Plain Text View (#)


1. echo $text->toList($colors);

Output:

red, orange, yellow, green, blue, indigo and violet

# (#truncate-1625) truncate

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1625/truncate) .. Mas info sobre
traduciones (/es/view/818)

truncate(string $text, int $length=100, array $options)

Cuts a string to the $length and adds a suffix with 'ending' if the text is longer than $length. If 'exact' is passed as
false, the truncation will occur after the next word ending. If 'html' is passed as true, html tags will be respected
and will not be cut off.

$options is used to pass all extra parameters, and has the following possible keys by default, all of which are
optional:

Plain Text View (#)

306 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. array(
2. 'ending' => '...',
3. 'exact' => true,
4. 'html' => false
5. )

Plain Text View (#)


1. echo $text->truncate(
2. 'The killer crept forward and tripped on the rug.',
3. 22,
4. array(
5. 'ending' => '...',
6. 'exact' => false
7. )
8. );

Output:

The killer crept...

# (#trim-1626) trim

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1626/trim) .. Mas info sobre
traduciones (/es/view/818)

trim()

An alias for truncate.

7.12 (#Tiempo-1470) Tiempo

El ayudante de tiempo (Time Helper), como su nombre lo indica, te ayuda a ahorrar tiempo. Permite que se haga un
procesamiento rápido de la información relacionada con el tiempo. Este ayudante tiene dos tareas principales que
puede realizar

1. ¡Puede dar formato a textos de tiempo


2. Puede probar el tiempo (pero no pude doblarlo, lo sentimos).

7.12.1 (#Formatting-1471) Formatting

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1471)


Comparar con el texto original (/es/compare/1471/Formatting)

Mas info sobre traduciones (/es/view/818)

fromString( $date_string )

fromString toma una cadena de texto y la convierte en un objeto de tiempo. Si la cadena suministrada es un número,
la convertirá a un entero, siendo este el número de segundos que han transcurrido desde el Epoch de Unix (1 de
Enero 1970 00:00:00 GMT). Pasarle un texto "20081231" creará un resultado indeseado ya que tratará de convertirlo
a segundos, lo que resultará en este caso "Vier, Ago 21 1970, 06:07"

toQuarter( $date_string, $range = false )

toQuarter devolverá 1, 2, 3 o 4 dependiendo de en qué trimestre del año la fecha se encuantra. Si el $range es true,
devolverá un arreglo con dos elementos con las fechas de inicio y fin en el formato "2008-03-31"

toUnix( $date_string )

toUnix es un sinónimo para fromString.

toAtom( $date_string )

toAtom devuelve una texto de tiempo en el formato Atom "2008-01-12T00:00:00Z"

307 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

toRSS( $date_string )

toRSS devuelve un texto de tiempo en el formato RSS "Sat, 12 Jan 2008 00:00:00 -0500"

nice( $date_string = null )

nice toma una texto de tiempo y lo devuelve en el formato "Tue, Jan 1st 2008, 19:25".

niceShort( $date_string = null )

niceShort toma un texto de tiempo y lo devuelve en el formato "Jan 1st 2008, 19:25". Si la fecha es el día actual el
formato será "Hoy, 19:25". Si la fecha ayer, devolverá en el formato "Ayer, 19:25".

daysAsSql( $begin, $end, $field_name )

daysAsSql devuelve una cadena de texto en el formato "($campo >= '2008-01-21 00:00:00') AND ($campo <=
'2008-01-25 23:59:59')".

dayAsSql( $date_string, $field_name )

dayAsSql crea una cadena de texto en el mismo formato que daysAsSql, pero solo necesita un único objeto de tiempo

timeAgoInWords( $date_string, $options = array(), $backwards = null )

timeAgoInWords toma una cadena de texto que representa uan fecha y lo convierte a un formato amigable como
"Hace 3 semanas, 3 días". Pasarle true en $backwards hará que se declare el tiempo en el futuro, lo que devolverá el
formato "el 31/12/08".

Opción Descripción
format un formato de fechas; por defecto "on 31/12/08"
determina el el punto de corte en el que no uará más palabras y usará el formato de fechas en su lugar, por
end
defecto "+1 month"

relativeTime( $date_string, $format = 'j/n/y' )

relativeTime es un básicamente un sinónimo para timeAgoInWords.

gmt( $date_string = null )

gmt devolverá la fecha como un entero fijado al tiempo medio de Greenwich (GMT).

format( $format = 'd-m-Y', $date_string)

format es un sinónimo para la función date de php.

Función Formato
nice Mar, Enero 1 2008, 19:25
Enero 1 2008, 19:25
niceShort Hoy, 19:25
Ayer, 19:25
daysAsSql ($campo >= '2008-01-21 00:00:00') AND ($campo <= '2008-01-25 23:59:59')
dayAsSql ($campo >= '2008-01-21 00:00:00') AND ($campo <= '2008-01-21 23:59:59')
el 21/01/08
timeAgoInWords Hace 3 mese, 3 semanas, 2 días
relativeTime Hace 7 minutos
Hace 2 segundos
gmt 1200787200

7.12.2 (#Testing-Time-1472) Testing Time

isToday (es Hoy)


isThisWeek (es esta Semana)
isThisMonth (es este MEs)
isThisYear (es este Año)
wasYesterday (fue Ayer)

308 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

isTomorrow (es Mañana)


wasWithinLast (sucedió dentro del rango de tiempo)

Todas las funciones anteriores devuelve true o false al pasarle una cadena de texto que represente una fecha.
wasWithinLast toma el parámetro adicional $time_interval (intervalo de tiempo):

$time->wasWithinLast( $time_interval, $date_string )

wasWithinLast toma un intervalo de tiempo que es un texto en el formato "3 months" y acepta un intervalo de tiempo
en segundos, minutos, horas, días, semanas, meses, años. Si un intervalo de tiempo no es reconocido (por ejemplo
se tipeó erróneamente), se usará por defecto días

7.13 (#XML-1473) XML

El helper XML simplifica la salida de documentos XML.

7.13.1 (#serialize-1474) serialize

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1474)


Comparar con el texto original (/es/compare/1474/serialize)

Mas info sobre traduciones (/es/view/818)

El método serialize toma un arreglo y crea una cadena XML de los datos. Esto es usado comúnmente para serializar
datos de modelos.

Plain Text View (#)


1. <?php
2. echo $xml->serialize($data);
3. // El formato será similar a:
4. // <model_name id="1" field_name="content" />
5. ?>

El método serialize actua como un atajo para instanciar la clase XML incorporada en CakePHP, y usar el método
toString de la misma. Si necesitas más control sobre la serialización, quizás quieras invocar la clase XML
directamente.

7.13.2 (#elem-1475) elem

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1475)


Comparar con el texto original (/es/compare/1475/elem)

Mas info sobre traduciones (/es/view/818)

El método elem permite construir una cadena-nodo XML con atributos y también contenido interno.

string elem (string $name, $attrib = array(), mixed $content = null, $endTag = true)

Plain Text View (#)


1. echo $xml->elem('count', array('namespace' => 'myNameSpace'), 'contenido');
2. // genera: <myNameSpace:count>contenido</count>

Si quieres empaquetar tu nodo de texto con CDATA, el tercer argumento debería ser un arreglo con dos llaves: 'cdata'
y 'value'

Plain Text View (#)


1. echo $xml->elem('count', null, array('cdata'=>true,'value'=>'contenido');
2. // genera: <count><![CDATA[contenido]]></count>

7.13.3 (#header-1476) header

309 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

El método header() se usa para escribir la declaración de XML.

Plain Text View (#)


1. <?php
2. echo $xml->header();
3. // genera: <?xml version="1.0" encoding="UTF-8" ?>
4. ?>

Puedes entregar el número de la versión y tipo de codificación como parámetros del metodo header.

Plain Text View (#)


1. <?php
2. echo $xml->header(array('version'=>'1.1'));
3. // genera: <?xml version="1.1" encoding="UTF-8" ?>
4. ?>

8 (#Librerias-de-utilidades-del-núcleo-1477) Librerias de utilidades del núcleo

CakePHP incluye librerías de utilidades de propósito general que se pueden invocar desde cualquier lugar de la
aplicación. Por ejemplo, Set y HttpSocket.

8.1 (#App-1644) App

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1644/App) .. Mas info sobre
traduciones (/es/view/818)

App is a very small utility library. It only contains the import method. But, with the import method, you can
accomplish a lot.

Plain Text View (#)


1. // examples
2. App::Import('Core','File');
3. App::Import('Model','Post');
4. App::import('Vendor', 'geshi');
5. App::import('Vendor', 'flickr/flickr');
6. App::import('Vendor', 'SomeName', array('file' => 'some.name.php'));
7. App::import('Vendor', 'WellNamed', array('file' => 'services'.DS.'well.named.php'));

You can read more about it in the book (http://book.cakephp.org/view/936/Importing-Controllers-Models-Components-


Behaviors-) or the API documentation (http://api13.cakephp.org/class/app#method-Appimport)

8.2 (#Inflector-1478) Inflector

La clase Inflector toma una cadena y puede manipularla produciendo variaciones en las palabras tales como
pluralizacion y notacion de CaMeLlo, siendo accedida normalmente de forma estática. Ejemplo:
Inflector::pluralize('ejemplo') retorna "ejemplos".

8.2.1 (#Class-methods-1479) Class methods

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1479/Class-methods) .. Mas info
sobre traduciones (/es/view/818)

Input Output
pluralize Apple, Orange, Person, Man Apples, Oranges, People, Men
singularize Apples, Oranges, People, Men Apple, Orange, Person, Man
camelize Apple_pie, some_thing, people_person ApplePie, SomeThing, PeoplePerson
It should be noted that underscore will only convert camelCase formatted words. Words that contains
underscore spaces will be lower-cased, but will not contain an underscore.
applePie, someThing apple_pie, some_thing
humanize apple_pie, some_thing, people_person Apple Pie, Some Thing, People Person

310 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

tableize Apple, UserProfileSetting, Person apples, user_profile_settings, people


classify apples, user_profile_settings, people Apple, UserProfileSetting, Person
variable apples, user_result, people_people apples, userResult, peoplePeople
Slug converts special characters into latin versions and converting unmatched characters and spaces to
slug underscores. The slug method expects UTF-8 encoding.
apple purée apple_puree

8.3 (#Cadenas-String-1480) Cadenas (String)

La clase String incluye métodos para crear y manipular cadenas cómodamente. Estos métodos se acceden
normalmente de forma estática; por ejemplo: String::uuid().

8.3.1 (#uuid-1481) uuid

El método uuid se utiliza para generar identificadores únicos de acuerdo a la especificación RFC 4122
(http://www.ietf.org/rfc/rfc4122.txt) . El uuid es una cadena de 128 bits con el formato 485fc381-
e790-47a3-9794-1337c0a8fe68.

Plain Text View (#)


1. String::uuid(); // 485fc381-e790-47a3-9794-1337c0a8fe68

8.3.2 (#tokenize-1482) tokenize

string tokenize ($data, $separator = ',', $leftBound = '(', $rightBound = ')')

Divide una cadena en subcadenas (tokens), ignorando cualquier instancia de $separator que aparece entre
$leftBound y $rightBound.

8.3.3 (#insert-1483) insert

string insert ($string, $data, $options = array())

El método insert se utiliza para sustituir las claves de una plantilla (basada en una cadena de caracteres) por los
valores de una matriz asociativa.

Plain Text View (#)


1. String::insert('Mi nombre es :nombre y tengo :edad años de edad.', array('nombre' => 'Bob', 'edad' => '6
2. // genera: "Mi nombre es Bob y tengo 65 años de edad."

8.3.4 (#cleanInsert-1484) cleanInsert

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1484)


Comparar con el texto original (/es/compare/1484/cleanInsert)

Mas info sobre traduciones (/es/view/818)

string cleanInsert ($string, $options = array())

Limpia la cadena String::insert de acuerdo a las opciones de la matriz $options, en función de la clave 'clean' de
$options. El método que se utiliza por defecto es texto, pero también está disponible html. El objetivo de esta función
es sustituir, alrededor de los marcadores, los espacios en blanco y las marcas innecesarias que no sustituye
Set::insert.

8.4 (#Xml-1485) Xml

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1485)


Comparar con el texto original (/es/compare/1485/Xml)

Mas info sobre traduciones (/es/view/818)

311 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Con la clase Xml podemos generar y analizar cómodamente fragmentos y documentos XML. Esta solución, íntegra en
PHP, sólo necesita que la extensión Xml/Expat esté instalada.

8.4.1 (#Análisis-Xml-1486) Análisis Xml

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1486)


Comparar con el texto original (/es/compare/1486/Análisis-Xml)

Mas info sobre traduciones (/es/view/818)

Para analizar un documento con la clase Xml, necesitamos una cadena con el Xml que queremos analizar.

Plain Text View (#)


1. $input = '<' . '?xml version="1.0" encoding="UTF-8" ?' . '>
2. <container>
3. <element id="first-el">
4. <name>My element</name>
5. <size>20</size>
6. </element>
7. <element>
8. <name>Your element</name>
9. <size>30</size>
10. </element>
11. </container>';
12. $xml = new Xml($input);

Esto crea un objeto de tipo documento Xml. A partir de este momento, el objeto se puede leer, manipular, y convertir
en una cadena de caracteres. .

Con el ejemplo anterior podemos hacer lo siguiente:

Plain Text View (#)


1. echo $xml->children[0]->children[0]->name;
2. // outputs 'element'
3. echo $xml->children[0]->children[0]->children[0]->children[0]->value;
4. // outputs 'My Element'
5. echo $xml->children[0]->child('element')->attributes['id'];
6. //outputs 'first-el'

8.5 (#Set-1487) Set

Gestionar correctamente las matrices puede ser una herramienta muy útil, poderosa y puede ayudar a construir un
código más optimizado y elegante. Para esto, CakePHP ofrece un conjunto muy útil de utilidades estáticas en la clase
Set.

Se puede llamar a la clase Set de CakePHP desde cualquier modelo o controlador, del mismo modo que se llama a
Inflector. Por ejemplo, Set::combine().

8.5.1 (#Set-compatible-Path-syntax-1488) Set-compatible Path syntax

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1488/Set-compatible-
Path-syntax) .. Mas info sobre traduciones (/es/view/818)

The Path syntax is used by (for example) sort, and is used to define a path.

Usage example (using Set::sort()):

Plain Text View (#)

312 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. $a = array(
2. 0 => array('Person' => array('name' => 'Jeff')),
3. 1 => array('Shirt' => array('color' => 'black'))
4. );
5. $result = Set::sort($a, '{n}.Person.name', 'asc');
6. /* $result now looks like:
7. Array
8. (
9. [0] => Array
10. (
11. [Shirt] => Array
12. (
13. [color] => black
14. )
15. )
16. [1] => Array
17. (
18. [Person] => Array
19. (
20. [name] => Jeff
21. )
22. )
23. )
24. */

As you can see in the example above, some things are wrapped in {}'s, others not. In the table below, you can see
which options are available.

Expression Definition
{n} Represents a numeric key
{s} Represents a string
Foo Any string (without enclosing brackets) is treated like a string literal.
{[a-z]+} Any string enclosed in brackets (besides {n} and {s}) is interpreted as a regular expression.
This section needs to be expanded.

8.5.2 (#insert-1489) insert

array Set::insert ($list, $path, $data = null)

Inserta $data en un arreglo segun es definido en $path.

Plain Text View (#)

313 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. $a = array(
2. 'pages' => array('name' => 'page')
3. );
4. $result = Set::insert($a, 'files', array('name' => 'files'));
5. /* $result ahora queda como:
6. Array
7. (
8. [pages] => Array
9. (
10. [name] => page
11. )
12. [files] => Array
13. (
14. [name] => files
15. )
16. )
17. */
18. $a = array(
19. 'pages' => array('name' => 'page')
20. );
21. $result = Set::insert($a, 'pages.name', array());
22. /* $result ahora queda:
23. Array
24. (
25. [pages] => Array
26. (
27. [name] => Array
28. (
29. )
30. )
31. )
32. */
33. $a = array(
34. 'pages' => array(
35. 0 => array('name' => 'main'),
36. 1 => array('name' => 'about')
37. )
38. );
39. $result = Set::insert($a, 'pages.1.vars', array('title' => 'page title'));
40. /* $result ahora queda como:
41. Array
42. (
43. [pages] => Array
44. (
45. [0] => Array
46. (
47. [name] => main
48. )
49. [1] => Array
50. (
51. [name] => about
52. [vars] => Array
53. (
54. [title] => page title
55. )
56. )
57. )
58. )
59. */

314 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

8.5.3 (#sort-1490) sort

array Set::sort ($data, $path, $dir)

Ordena un arreglo según cualquier valor, determinado por una ruta compatible con Set.

Plain Text View (#)

315 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. $a = array(
2. 0 => array('Person' => array('name' => 'Jeff')),
3. 1 => array('Shirt' => array('color' => 'black'))
4. );
5. $result = Set::sort($a, '{n}.Person.name', 'asc');
6. /* $result ahora queda:
7. Array
8. (
9. [0] => Array
10. (
11. [Shirt] => Array
12. (
13. [color] => black
14. )
15. )
16. [1] => Array
17. (
18. [Person] => Array
19. (
20. [name] => Jeff
21. )
22. )
23. )
24. */
25. $result = Set::sort($a, '{n}.Shirt', 'asc');
26. /* $result ahora queda:
27. Array
28. (
29. [0] => Array
30. (
31. [Person] => Array
32. (
33. [name] => Jeff
34. )
35. )
36. [1] => Array
37. (
38. [Shirt] => Array
39. (
40. [color] => black
41. )
42. )
43. )
44. */
45. $result = Set::sort($a, '{n}', 'desc');
46. /* $result ahora queda:
47. Array
48. (
49. [0] => Array
50. (
51. [Shirt] => Array
52. (
53. [color] => black
54. )
55. )
56. [1] => Array
57. (
58. [Person] => Array
59. (
60. [name] => Jeff
61. )

316 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

8.5.4 (#reverse-1491) reverse

array Set::reverse ($object)

Set::reverse es básicamente el opuesto de Set::map. Convierte un objeto en un arreglo. Si $object no es un objeto,


reverse simplemente retornará $object.

Plain Text View (#)

317 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. $result = Set::reverse(null);
2. // Null
3. $result = Set::reverse(false);
4. // false
5. $a = array(
6. 'Post' => array('id'=> 1, 'title' => 'First Post'),
7. 'Comment' => array(
8. array('id'=> 1, 'title' => 'First Comment'),
9. array('id'=> 2, 'title' => 'Second Comment')
10. ),
11. 'Tag' => array(
12. array('id'=> 1, 'title' => 'First Tag'),
13. array('id'=> 2, 'title' => 'Second Tag')
14. ),
15. );
16. $map = Set::map($a); // Convierte $a en un objeto de clase
17. /* $map ahora queda como:
18. stdClass Object
19. (
20. [_name_] => Post
21. [id] => 1
22. [title] => First Post
23. [Comment] => Array
24. (
25. [0] => stdClass Object
26. (
27. [id] => 1
28. [title] => First Comment
29. )
30. [1] => stdClass Object
31. (
32. [id] => 2
33. [title] => Second Comment
34. )
35. )
36. [Tag] => Array
37. (
38. [0] => stdClass Object
39. (
40. [id] => 1
41. [title] => First Tag
42. )
43. [1] => stdClass Object
44. (
45. [id] => 2
46. [title] => Second Tag
47. )
48. )
49. )
50. */
51. $result = Set::reverse($map);
52. /* $result ahora queda como:
53. Array
54. (
55. [Post] => Array
56. (
57. [id] => 1
58. [title] => First Post
59. [Comment] => Array
60. (
61. [0] => Array

318 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

8.5.5 (#combine-1492) combine

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1492)


Comparar con el texto original (/es/compare/1492/combine)

Mas info sobre traduciones (/es/view/818)

array Set::combine ($data, $path1 = null, $path2 = null, $groupPath = null)

Crea un arreglo asociativo usando un $path1 como la ruta para construir las llaves, y opcionalmente $path2 como la
ruta para obtener los valores. Si $path2 no es especificado, todos los valores serán inicializados como null (lo cual
es útil para Set::merge). Opcionalmente se pueden agrupar los valores obtenidos según la ruta especificada en
$groupPath.

Plain Text View (#)

319 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. $result = Set::combine(array(), '{n}.User.id', '{n}.User.Data');


2. // $result == array();
3. $result = Set::combine('', '{n}.User.id', '{n}.User.Data');
4. // $result == array();
5. $a = array(
6. array('User' => array('id' => 2, 'group_id' => 1,
7. 'Data' => array('user' => 'mariano.iglesias','name' => 'Mariano Iglesias'))),
8. array('User' => array('id' => 14, 'group_id' => 2,
9. 'Data' => array('user' => 'phpnut', 'name' => 'Larry E. Masters'))),
10. array('User' => array('id' => 25, 'group_id' => 1,
11. 'Data' => array('user' => 'gwoo','name' => 'The Gwoo'))));
12. $result = Set::combine($a, '{n}.User.id');
13. /* $result ahora queda como:
14. Array
15. (
16. [2] =>
17. [14] =>
18. [25] =>
19. )
20. */
21. $result = Set::combine($a, '{n}.User.id', '{n}.User.non-existant');
22. /* $result ahora queda como:
23. Array
24. (
25. [2] =>
26. [14] =>
27. [25] =>
28. )
29. */
30. $result = Set::combine($a, '{n}.User.id', '{n}.User.Data');
31. /* $result ahora queda como:
32. Array
33. (
34. [2] => Array
35. (
36. [user] => mariano.iglesias
37. [name] => Mariano Iglesias
38. )
39. [14] => Array
40. (
41. [user] => phpnut
42. [name] => Larry E. Masters
43. )
44. [25] => Array
45. (
46. [user] => gwoo
47. [name] => The Gwoo
48. )
49. )
50. */
51. $result = Set::combine($a, '{n}.User.id', '{n}.User.Data.name');
52. /* $result ahora queda como:
53. Array
54. (
55. [2] => Mariano Iglesias
56. [14] => Larry E. Masters
57. [25] => The Gwoo
58. )
59. */
60. $result = Set::combine($a, '{n}.User.id', '{n}.User.Data', '{n}.User.group_id');
61. /* $result ahora queda como:

320 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

8.5.6 (#normalize-1493) normalize

array Set::normalize ($list, $assoc = true, $sep = ',', $trim = true)

Normaliza un string o arreglo lista.

Plain Text View (#)

321 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. $a = array('Tree', 'CounterCache',
2. 'Upload' => array(
3. 'folder' => 'products',
4. 'fields' => array('image_1_id', 'image_2_id', 'image_3_id', 'image_4_id', 'image_5_id')));
5. $b = array('Cacheable' => array('enabled' => false),
6. 'Limit',
7. 'Bindable',
8. 'Validator',
9. 'Transactional');
10. $result = Set::normalize($a);
11. /* $result ahora queda como:
12. Array
13. (
14. [Tree] =>
15. [CounterCache] =>
16. [Upload] => Array
17. (
18. [folder] => products
19. [fields] => Array
20. (
21. [0] => image_1_id
22. [1] => image_2_id
23. [2] => image_3_id
24. [3] => image_4_id
25. [4] => image_5_id
26. )
27. )
28. )
29. */
30. $result = Set::normalize($b);
31. /* $result ahora queda como:
32. Array
33. (
34. [Cacheable] => Array
35. (
36. [enabled] =>
37. )
38. [Limit] =>
39. [Bindable] =>
40. [Validator] =>
41. [Transactional] =>
42. )
43. */
44. $result = Set::merge($a, $b); // Ahora mezclamos ambos y luego normalizamos
45. /* $result ahora queda como:
46. Array
47. (
48. [0] => Tree
49. [1] => CounterCache
50. [Upload] => Array
51. (
52. [folder] => products
53. [fields] => Array
54. (
55. [0] => image_1_id
56. [1] => image_2_id
57. [2] => image_3_id
58. [3] => image_4_id
59. [4] => image_5_id
60. )
61. )

322 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

8.5.7 (#countDim-1494) countDim

integer Set::countDim ($array = null, $all = false, $count = 0)

Cuenta las dimensiones de un arreglo. Si $all está seteado como falso (su valor por defecto) sólo se considerarán las
dimensiones del primer elemento en el arreglo.

Plain Text View (#)


1. $data = array('one', '2', 'three');
2. $result = Set::countDim($data);
3. // $result == 1
4. $data = array('1' => '1.1', '2', '3');
5. $result = Set::countDim($data);
6. // $result == 1
7. $data = array('1' => array('1.1' => '1.1.1'), '2', '3' => array('3.1' => '3.1.1'));
8. $result = Set::countDim($data);
9. // $result == 2
10. $data = array('1' => '1.1', '2', '3' => array('3.1' => '3.1.1'));
11. $result = Set::countDim($data);
12. // $result == 1
13. $data = array('1' => '1.1', '2', '3' => array('3.1' => '3.1.1'));
14. $result = Set::countDim($data, true);
15. // $result == 2
16. $data = array('1' => array('1.1' => '1.1.1'), '2', '3' => array('3.1' => array('3.1.1' => '3.1.1.1')));
17. $result = Set::countDim($data);
18. // $result == 2
19. $data = array('1' => array('1.1' => '1.1.1'), '2', '3' => array('3.1' => array('3.1.1' => '3.1.1.1')));
20. $result = Set::countDim($data, true);
21. // $result == 3
22. $data = array('1' => array('1.1' => '1.1.1'), array('2' => array('2.1' => array('2.1.1' => '2.1.1.1')))
23. $result = Set::countDim($data, true);
24. // $result == 4
25. $data = array('1' => array('1.1' => '1.1.1'), array('2' => array('2.1' => array('2.1.1' => array('2.1.1
26. $result = Set::countDim($data, true);
27. // $result == 5
28. $data = array('1' => array('1.1' => '1.1.1'), array('2' => array('2.1' => array('2.1.1' => array('2.1.1
29. $result = Set::countDim($data, true);
30. // $result == 5
31. $set = array('1' => array('1.1' => '1.1.1'), array('2' => array('2.1' => array('2.1.1' => array('2.1.1.
32. $result = Set::countDim($set, false, 0);
33. // $result == 2
34. $result = Set::countDim($set, true);
35. // $result == 5
36.

8.5.8 (#diff-1496) diff

array Set::diff ($val1, $val2 = null)

Calcula la diferencia entre un Set y un arreglo, dos Sets, o dos arreglos

Plain Text View (#)

323 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. $a = array(
2. 0 => array('name' => 'main'),
3. 1 => array('name' => 'about')
4. );
5. $b = array(
6. 0 => array('name' => 'main'),
7. 1 => array('name' => 'about'),
8. 2 => array('name' => 'contact')
9. );
10. $result = Set::diff($a, $b);
11. /* $result ahora queda:
12. Array
13. (
14. [2] => Array
15. (
16. [name] => contact
17. )
18. )
19. */
20. $result = Set::diff($a, array());
21. /* $result ahora queda:
22. Array
23. (
24. [0] => Array
25. (
26. [name] => main
27. )
28. [1] => Array
29. (
30. [name] => about
31. )
32. )
33. */
34. $result = Set::diff(array(), $b);
35. /* $result ahora queda:
36. Array
37. (
38. [0] => Array
39. (
40. [name] => main
41. )
42. [1] => Array
43. (
44. [name] => about
45. )
46. [2] => Array
47. (
48. [name] => contact
49. )
50. )
51. */
52. $b = array(
53. 0 => array('name' => 'me'),
54. 1 => array('name' => 'about')
55. );
56. $result = Set::diff($a, $b);
57. /* $result ahora queda:
58. Array
59. (
60. [0] => Array
61. (

324 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

8.5.9 (#check-1497) check

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1497)


Comparar con el texto original (/es/compare/1497/check)

Mas info sobre traduciones (/es/view/818)

boolean Set::check ($data, $path = null)

Verifica si una ruta particular está seteada en un arreglo

Plain Text View (#)


1. $set = array(
2. 'My Index 1' => array('First' => 'The first item')
3. );
4. $result = Set::check($set, 'My Index 1.First');
5. // $result == True
6. $result = Set::check($set, 'My Index 1');
7. // $result == True
8. $result = Set::check($set, array());
9. // $result == array('My Index 1' => array('First' => 'The first item'))
10. $set = array(
11. 'My Index 1' => array('First' =>
12. array('Second' =>
13. array('Third' =>
14. array('Fourth' => 'Heavy. Nesting.'))))
15. );
16. $result = Set::check($set, 'My Index 1.First.Second');
17. // $result == True
18. $result = Set::check($set, 'My Index 1.First.Second.Third');
19. // $result == True
20. $result = Set::check($set, 'My Index 1.First.Second.Third.Fourth');
21. // $result == True
22. $result = Set::check($set, 'My Index 1.First.Seconds.Third.Fourth');
23. // $result == False

8.5.10 (#remove-1498) remove

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1498)


Comparar con el texto original (/es/compare/1498/remove)

Mas info sobre traduciones (/es/view/818)

boolean Set::remove ($list, $path = null)

Elimina un elemento de un Set o arreglo según sea definido en una ruta en la variable $path.

Plain Text View (#)

325 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. $a = array(
2. 'pages' => array('name' => 'page'),
3. 'files' => array('name' => 'files')
4. );
5. $result = Set::remove($a, 'files', array('name' => 'files'));
6. /* $result ahora queda como:
7. Array
8. (
9. [pages] => Array
10. (
11. [name] => page
12. )
13. )
14. */

8.5.11 (#classicExtract-1499) classicExtract

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1499)


Comparar con el texto original (/es/compare/1499/classicExtract)

Mas info sobre traduciones (/es/view/818)

array Set::classicExtract ($data, $path = null)

Obtiene un valor desde un arreglo u objeto que está contenido en una ruta entregada usando una sintáxis de ruta de
arreglo, es decir:

"{n}.Person.{[a-z]+}" - Donde "{n}" representa una llave numérica, "Person" representa una cadena literal
"{[a-z]+}" (es decir, cualquier string literal encerrado en llaves junto a {n} y {s}) es interpretado como una
expresión regular.

Ejemplo 1 Plain Text View (#)


1. $a = array(
2. array('Article' => array('id' => 1, 'title' => 'Article 1')),
3. array('Article' => array('id' => 2, 'title' => 'Article 2')),
4. array('Article' => array('id' => 3, 'title' => 'Article 3')));
5. $result = Set::extract($a, '{n}.Article.id');
6. /* $result ahora queda:
7. Array
8. (
9. [0] => 1
10. [1] => 2
11. [2] => 3
12. )
13. */
14. $result = Set::extract($a, '{n}.Article.title');
15. /* $result ahora queda:
16. Array
17. (
18. [0] => Article 1
19. [1] => Article 2
20. [2] => Article 3
21. )
22. */
23. $result = Set::extract($a, '1.Article.title');
24. // $result == "Article 2"
25. $result = Set::extract($a, '3.Article.title');
26. // $result == null

Ejemplo 2 Plain Text View (#)

326 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. $a = array(
2. 0 => array('pages' => array('name' => 'page')),
3. 1 => array('fruites'=> array('name' => 'fruit')),
4. 'test' => array(array('name' => 'jippi')),
5. 'dot.test' => array(array('name' => 'jippi'))
6. );
7. $result = Set::extract($a, '{n}.{s}.name');
8. /* $result ahora queda como:
9. Array
10. (
11. [0] => Array
12. (
13. [0] => page
14. )
15. [1] => Array
16. (
17. [0] => fruit
18. )
19. )
20. */
21. $result = Set::extract($a, '{s}.{n}.name');
22. /* $result ahora queda como:
23. Array
24. (
25. [0] => Array
26. (
27. [0] => jippi
28. )
29. [1] => Array
30. (
31. [0] => jippi
32. )
33. )
34. */
35. $result = Set::extract($a,'{\w+}.{\w+}.name');
36. /* $result ahora queda como:
37. Array
38. (
39. [0] => Array
40. (
41. [pages] => page
42. )
43. [1] => Array
44. (
45. [fruites] => fruit
46. )
47. [test] => Array
48. (
49. [0] => jippi
50. )
51. [dot.test] => Array
52. (
53. [0] => jippi
54. )
55. )
56. */
57. $result = Set::extract($a,'{\d+}.{\w+}.name');
58. /* $result ahora queda como:
59. Array
60. (
61. [0] => Array

327 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

8.5.12 (#matches-1500) matches

boolean Set::matches ($conditions, $data=array(), $i = null, $length=null)

Set::matches puede ser usado para ver su un item o una ruta calza con ciertas condiciones.

Plain Text View (#)


1. $a = array(
2. array('Article' => array('id' => 1, 'title' => 'Article 1')),
3. array('Article' => array('id' => 2, 'title' => 'Article 2')),
4. array('Article' => array('id' => 3, 'title' => 'Article 3')));
5. $res=Set::matches(array('id>2'), $a[1]['Article']);
6. // returns false
7. $res=Set::matches(array('id>=2'), $a[1]['Article']);
8. // returns true
9. $res=Set::matches(array('id>=3'), $a[1]['Article']);
10. // returns false
11. $res=Set::matches(array('id<=2'), $a[1]['Article']);
12. // returns true
13. $res=Set::matches(array('id<2'), $a[1]['Article']);
14. // returns false
15. $res=Set::matches(array('id>1'), $a[1]['Article']);
16. // returns true
17. $res=Set::matches(array('id>1', 'id<3', 'id!=0'), $a[1]['Article']);
18. // returns true
19. $res=Set::matches(array('3'), null, 3);
20. // returns true
21. $res=Set::matches(array('5'), null, 5);
22. // returns true
23. $res=Set::matches(array('id'), $a[1]['Article']);
24. // returns true
25. $res=Set::matches(array('id', 'title'), $a[1]['Article']);
26. // returns true
27. $res=Set::matches(array('non-existant'), $a[1]['Article']);
28. // returns false
29. $res=Set::matches('/Article[id=2]', $a);
30. // returns true
31. $res=Set::matches('/Article[id=4]', $a);
32. // returns false
33. $res=Set::matches(array(), $a);
34. // returns true

8.5.13 (#extract-1501) extract

array Set::extract ($path, $data=null, $options=array())

Set::extract utiliza la sintáxis básica XPath 2.0 para retornar subconjuntos de la data resultante de un find(). Esta
función permite extraer datos rápidamente sin tener que hacer un ciclo a través de un arreglos multidimensionales o
de estructuras de árbol.

Si $path es un arreglo o $data es vacío la llamada se redirigirá a la función Set::classicExtract.

Plain Text View (#)


1. // Uso común:
2. $users = $this->User->find("all");
3. $results = Set::extract('/User/id', $users);
4. // results retorna:
5. // array(1,2,3,4,5,...);

Los seleccionadores implementados actualmente son:

328 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Seleccionador Descripción
/User/id Similar al clásico {n}.User.id
/User[2]/name Selecciona el nombre del segundo User
/User[id<2] Selecciona todos los Users con un id < 2
/User[id>2][<5] Selecciona todos los Users con un id > 2 pero < 5
/Post/Comment[author_name=john] Selecciona los nombres de todos los Posts que tienen al menos un
/../name comentario escrito por john
/Posts[title] Selecciona todos los Post que tienen la llave 'title'
/Comment/.[1] Selecciona el contenido del primer comentario
/Comment/.[:last] Selecciona el último comentario
/Comment/.[:first] Selecciona el primer comentario
Selecciona todos los comentarios que tienen un texto que calce con la
/Comment[text=/cakephp/i]
expresión regular (regex) /cakephp/i
/Comment/@* Selecciona todos los nombres clave de todos los comentarios

Actualmente, solo las rutas absolutas con un solo '/' están soportadas. Por favor reporte cualquier bug que encuentre
en ellas, y también las sugerencias para futuras funcionalidades son bien recibidas.

Para aprender más acerca de Set::extract refiérase a la función testExtract() en /cake/tests/cases/libs/set.test.php.

8.5.14 (#format-1502) format

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1502/format) .. Mas info sobre
traduciones (/es/view/818)

array Set::format ($data, $format, $keys)

Returns a series of values extracted from an array, formatted in a format string.

Plain Text View (#)

329 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. $data = array(
2. array('Person' => array('first_name' => 'Nate', 'last_name' => 'Abele', 'city' => 'Boston', 'state'
3. array('Person' => array('first_name' => 'Larry', 'last_name' => 'Masters', 'city' => 'Boondock', 'st
4. array('Person' => array('first_name' => 'Garrett', 'last_name' => 'Woodworth', 'city' => 'Venice Bea
5. $res = Set::format($data, '{1}, {0}', array('{n}.Person.first_name', '{n}.Person.last_name'));
6. /*
7. Array
8. (
9. [0] => Abele, Nate
10. [1] => Masters, Larry
11. [2] => Woodworth, Garrett
12. )
13. */
14. $res = Set::format($data, '{0}, {1}', array('{n}.Person.city', '{n}.Person.state'));
15. /*
16. Array
17. (
18. [0] => Boston, MA
19. [1] => Boondock, TN
20. [2] => Venice Beach, CA
21. )
22. */
23. $res = Set::format($data, '{{0}, {1}}', array('{n}.Person.city', '{n}.Person.state'));
24. /*
25. Array
26. (
27. [0] => {Boston, MA}
28. [1] => {Boondock, TN}
29. [2] => {Venice Beach, CA}
30. )
31. */
32. $res = Set::format($data, '{%2$d, %1$s}', array('{n}.Person.something', '{n}.Person.something'));
33. /*
34. Array
35. (
36. [0] => {42, 42}
37. [1] => {0, {0}}
38. [2] => {0, {1}}
39. )
40. */
41. $res = Set::format($data, '%2$d, %1$s', array('{n}.Person.first_name', '{n}.Person.something'));
42. /*
43. Array
44. (
45. [0] => 42, Nate
46. [1] => 0, Larry
47. [2] => 0, Garrett
48. )
49. */
50. $res = Set::format($data, '%1$s, %2$d', array('{n}.Person.first_name', '{n}.Person.something'));
51. /*
52. Array
53. (
54. [0] => Nate, 42
55. [1] => Larry, 0
56. [2] => Garrett, 0
57. )
58. */

8.5.15 (#enum-1503) enum

330 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1503/enum) .. Mas info sobre
traduciones (/es/view/818)

string Set::enum ($select, $list=null)

The enum method works well when using html select elements. It returns a value from an array list if the key exists.

If a comma separated $list is passed arrays are numeric with the key of the first being 0 $list = 'no, yes' would
translate to $list = array(0 => 'no', 1 => 'yes');

If an array is used, keys can be strings example: array('no' => 0, 'yes' => 1);

$list defaults to 0 = no 1 = yes if param is not passed

Plain Text View (#)


1. $res = Set::enum(1, 'one, two');
2. // $res is 'two'
3. $res = Set::enum('no', array('no' => 0, 'yes' => 1));
4. // $res is 0
5. $res = Set::enum('first', array('first' => 'one', 'second' => 'two'));
6. // $res is 'one'

8.5.16 (#numeric-1504) numeric

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1504/numeric) .. Mas info sobre
traduciones (/es/view/818)

boolean Set::numeric ($array=null)

Checks to see if all the values in the array are numeric

Plain Text View (#)

331 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. $data = array('one');
2. $res = Set::numeric(array_keys($data));
3.
4. // $res is true
5.
6. $data = array(1 => 'one');
7. $res = Set::numeric($data);
8. // $res is false
9.
10. $data = array('one');
11. $res = Set::numeric($data);
12.
13. // $res is false
14.
15. $data = array('one' => 'two');
16. $res = Set::numeric($data);
17.
18. // $res is false
19.
20. $data = array('one' => 1);
21. $res = Set::numeric($data);
22.
23. // $res is true
24.
25. $data = array(0);
26. $res = Set::numeric($data);
27.
28. // $res is true
29.
30. $data = array('one', 'two', 'three', 'four', 'five');
31. $res = Set::numeric(array_keys($data));
32.
33. // $res is true
34.
35. $data = array(1 => 'one', 2 => 'two', 3 => 'three', 4 => 'four', 5 => 'five');
36. $res = Set::numeric(array_keys($data));
37.
38. // $res is true
39.
40. $data = array('1' => 'one', 2 => 'two', 3 => 'three', 4 => 'four', 5 => 'five');
41. $res = Set::numeric(array_keys($data));
42.
43. // $res is true
44.
45. $data = array('one', 2 => 'two', 3 => 'three', 4 => 'four', 'a' => 'five');
46. $res = Set::numeric(array_keys($data));
47.
48. // $res is false

8.5.17 (#map-1505) map

332 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1505/map) .. Mas info sobre
traduciones (/es/view/818)

object Set::map ($class = 'stdClass', $tmp = 'stdClass')

This method Maps the contents of the Set object to an object hierarchy while maintaining numeric keys as arrays of
objects.

Basically, the map function turns array items into initialized class objects. By default it turns an array into a stdClass
Object, however you can map values into any type of class. Example: Set::map($array_of_values, 'nameOfYourClass');

Plain Text View (#)

333 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. $data = array(
2. array(
3. "IndexedPage" => array(
4. "id" => 1,
5. "url" => 'http://blah.com/',
6. 'hash' => '68a9f053b19526d08e36c6a9ad150737933816a5',
7. 'get_vars' => '',
8. 'redirect' => '',
9. 'created' => "1195055503",
10. 'updated' => "1195055503",
11. )
12. ),
13. array(
14. "IndexedPage" => array(
15. "id" => 2,
16. "url" => 'http://blah.com/',
17. 'hash' => '68a9f053b19526d08e36c6a9ad150737933816a5',
18. 'get_vars' => '',
19. 'redirect' => '',
20. 'created' => "1195055503",
21. 'updated' => "1195055503",
22. ),
23. )
24. );
25. $mapped = Set::map($data);
26. /* $mapped now looks like:
27. Array
28. (
29. [0] => stdClass Object
30. (
31. [_name_] => IndexedPage
32. [id] => 1
33. [url] => http://blah.com/
34. [hash] => 68a9f053b19526d08e36c6a9ad150737933816a5
35. [get_vars] =>
36. [redirect] =>
37. [created] => 1195055503
38. [updated] => 1195055503
39. )
40. [1] => stdClass Object
41. (
42. [_name_] => IndexedPage
43. [id] => 2
44. [url] => http://blah.com/
45. [hash] => 68a9f053b19526d08e36c6a9ad150737933816a5
46. [get_vars] =>
47. [redirect] =>
48. [created] => 1195055503
49. [updated] => 1195055503
50. )
51. )
52. */

Using Set::map() with a custom class for second parameter:

Plain Text View (#)

334 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. class MyClass {
2. function sayHi() {
3. echo 'Hi!';
4. }
5. }
6. $mapped = Set::map($data, 'MyClass');
7. //Now you can access all the properties as in the example above,
8. //but also you can call MyClass's methods
9. $mapped->[0]->sayHi();

8.5.18 (#pushDiff-1506) pushDiff

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1506/pushDiff) .. Mas info sobre
traduciones (/es/view/818)

array Set::pushDiff ($array1, $array2)

This function merges two arrays and pushes the differences in array2 to the bottom of the resultant array.

Example 1 Plain Text View (#)


1. $array1 = array('ModelOne' => array('id'=>1001, 'field_one'=>'a1.m1.f1', 'field_two'=>'a1.m1.f2'));
2. $array2 = array('ModelOne' => array('id'=>1003, 'field_one'=>'a3.m1.f1', 'field_two'=>'a3.m1.f2', 'field
3. $res = Set::pushDiff($array1, $array2);
4. /* $res now looks like:
5. Array
6. (
7. [ModelOne] => Array
8. (
9. [id] => 1001
10. [field_one] => a1.m1.f1
11. [field_two] => a1.m1.f2
12. [field_three] => a3.m1.f3
13. )
14. )
15. */

Example 2 Plain Text View (#)


1. $array1 = array("a"=>"b", 1 => 20938, "c"=>"string");
2. $array2 = array("b"=>"b", 3 => 238, "c"=>"string", array("extra_field"));
3. $res = Set::pushDiff($array1, $array2);
4. /* $res now looks like:
5. Array
6. (
7. [a] => b
8. [1] => 20938
9. [c] => string
10. [b] => b
11. [3] => 238
12. [4] => Array
13. (
14. [0] => extra_field
15. )
16. )
17. */

8.5.19 (#filter-1507) filter

array Set::filter ($var, $isArray=null)

Filtra los elementos vacíos de una ruta de arreglo, excluyendo el cero '0'.

335 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Plain Text View (#)


1. $res = Set::filter(array('0', false, true, 0, array('una cosa', 'Te digo', 'es asi', false)));
2. /* $res now looks like:
3. Array (
4. [0] => 0
5. [2] => 1
6. [3] => 0
7. [4] => Array
8. (
9. [0] => una cosa
10. [1] => Te digo
11. [2] => es asi
12. [3] =>
13. )
14. )
15. */

8.5.20 (#merge-1508) merge

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1508)


Comparar con el texto original (/es/compare/1508/merge)

Mas info sobre traduciones (/es/view/818)

array Set::merge ($arr1, $arr2=null)

Esta función se puede considerar como un híbrido entre las funciones array_merge y arraymerge_recursive, ambas de
PHP. La diferencia esta en que si un arreglo de llaves contiene otro arreglo entonces la función se comporta
recursivamente, a diferencia de array_merge, pero no lo hace si las llaves que contienen strings, a diferencia de
array_merge_recursive. Verifica el test de unidad para mas información.

Esta función trabaja sobre un numero ilimitado de argumentos y hace un casting como arreglos a los argumentos que
no lo sean.

Plain Text View (#)

336 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. $arry1 = array(
2. array(
3. 'id' => '48c2570e-dfa8-4c32-a35e-0d71cbdd56cb',
4. 'name' => 'mysql raleigh-workshop-08 < 2008-09-05.sql ',
5. 'description' => 'Importing an sql dump'
6. ),
7. array(
8. 'id' => '48c257a8-cf7c-4af2-ac2f-114ecbdd56cb',
9. 'name' => 'pbpaste | grep -i Impago | pbcopy',
10. 'description' => 'Eliminar las lineas que dicen "Impago".',
11. )
12. );
13. $arry2 = 4;
14. $arry3 = array(0=>"Arreglo de prueba", "gatos"=>"perros");
15. $res = Set::merge($arry1, $arry2, $arry3);
16. /* $res ahora queda como:
17. Array
18. (
19. [0] => Array
20. (
21. [id] => 48c2570e-dfa8-4c32-a35e-0d71cbdd56cb
22. [name] => mysql raleigh-workshop-08 < 2008-09-05.sql
23. [description] => Importing an sql dump
24. )
25. [1] => Array
26. (
27. [id] => 48c257a8-cf7c-4af2-ac2f-114ecbdd56cb
28. [name] => pbpaste | grep -i Impago | pbcopy
29. [description] => Eliminar las lineas que dicen "Impago".
30. )
31. [2] => 4
32. [3] => Arreglo de prueba
33. [gatos] => perros
34. )
35. */

8.5.21 (#contains-1509) contains

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1509/contains) .. Mas info sobre
traduciones (/es/view/818)

boolean Set::contains ($val1, $val2 = null)

Determines if one Set or array contains the exact keys and values of another.

Plain Text View (#)

337 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. $a = array(
2. 0 => array('name' => 'main'),
3. 1 => array('name' => 'about')
4. );
5. $b = array(
6. 0 => array('name' => 'main'),
7. 1 => array('name' => 'about'),
8. 2 => array('name' => 'contact'),
9. 'a' => 'b'
10. );
11. $result = Set::contains($a, $a);
12. // True
13. $result = Set::contains($a, $b);
14. // False
15. $result = Set::contains($b, $a);
16. // True

8.6 (#Security-1510) Security

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1510/Security) .. Mas info sobre
traduciones (/es/view/818)

The security library (http://api.cakephp.org/class/security) handles basic security measures such as providing methods
for hashing and encrypting data.

8.7 (#Cache-1511) Cache

La clase Cache en CakePHP provee una interfaz generica con varios metodos de cache. Es posible tener varias
configuraciones y motores en el archivo app/config/core.php

8.7.1 (#Cache-read-1512) Cache::read()

Cache::read($key, $config = null)

El método Cache::read() se utiliza para leer el valor guardado en el cache con el nombre $key de la configuración
$config. Si $config es null se utiliza el configuración por defecto. Cache::read() retornará el valor almacenado si es
un cache valido o false si el cache expiró o no existe. Los contenidos del cache podrían evaluarse como false, así
que asegúrate de usar el operador de comparación estricta === o !==.

Por ejemplo:

Plain Text View (#)


1. $cloud = Cache::read('cloud');
2. if ($cloud !== false) {
3. return $cloud;
4. }
5. // generate cloud data
6. // ...
7. // store data in cache
8. Cache::write('cloud', $cloud);
9. return $cloud;

8.7.2 (#Cache-write-1513) Cache::write()

Cache::write($key, $value, $config = null);

Cache::write() escribirá un valor $value en el Cache. Puedes leer o borrar ese valor más adelante refiriéndote a él por
$key. Puedes especificar opcionalmente una configuración para guardar el cache. Si no se especifica $config se usará
la configuración por defecto. Cache::write() puede almacenar cualquier tipo de objeto y es ideal para guardar
resultados de búsquedas de modelos.

Plain Text View (#)

338 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. if (($posts = Cache::read('posts')) === false) {


2. $posts = $this->Post->find('all');
3. Cache::write('posts', $posts);
4. }

Usa Cache::write() y Cache::read() para reducir con facilidad la cantidad de viajes a la base de datos para recuperar
registros.

8.7.3 (#Cache-delete-1514) Cache::delete()

Cache::delete($key, $config = null)

Cache::delete() te permitirá eliminar completamente cualquier objeto que tengas guardado en el Cache.

8.7.4 (#Cache-config-1515) Cache::config()

Cache::config() se usa para crear configuraciones de Cache adicionales. Estas configuraciones a mayores pueden
tener diferente duración, motores, rutas, o prefijos de los que tiene tu configuración por defecto. Usar
configuraciones múltiples te puede ayudar a reducir la cantidad de veces que necesitas usar Cache::set() así como
centralizar todos tus ajustes de Cache.

Debes especificar qué motor usar. No se pone por defecto a File.

Plain Text View (#)


1. Cache::config('short', array(
2. 'engine' => 'File',
3. 'duration'=> '+1 hours',
4. 'path' => CACHE,
5. 'prefix' => 'cake_short_'
6. ));
7. // long
8. Cache::config('long', array(
9. 'engine' => 'File',
10. 'duration'=> '+1 week',
11. 'probability'=> 100,
12. 'path' => CACHE . 'long' . DS,
13. ));

Añadiendo el código anterior en tu app/config/core.php tendrás dos configuraciones de Cache adicionales. El


nombre de estas configuraciones 'short' o 'long' se usa como parámetro $config para Cache::write() y
Cache::read().

8.7.5 (#Cache-set-1516) Cache::set()

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1516)


Comparar con el texto original (/es/compare/1516/Cache-set)

Mas info sobre traduciones (/es/view/818)

Cache::set() te permite puentear temporalmente los ajustes de configuración de Cache para una operación
(normalmente read o write). Si usas Cache::set() para cambiar los ajustes para una escritura, deberías usar
Cache::set() antes de leer los datos más tarde. Si no haces eso, se usará la configuración por defecto cuando se lea
la clave de la cache.

Plain Text View (#)


1. Cache::set(array('duration' => '+30 days'));
2. Cache::write('results', $data);
3. // Later on
4. Cache::set(array('duration' => '+30 days'));
5. $results = Cache::read('results');

339 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Si usar repetidamente Cache::set() quizás deberías crear una nueva configuración de Cache (/es/view/772/Cache-
config) . Esto eliminará la necesidad de llamar a Cache::set().

8.8 (#HttpSocket-1517) HttpSocket

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1517/HttpSocket) .. Mas info
sobre traduciones (/es/view/818)

CakePHP includes an HttpSocket class which can be used easily for making requests, such as those to web services.

8.8.1 (#get-1518) get

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1518/get) .. Mas info sobre
traduciones (/es/view/818)

The get method makes a simple HTTP GET request returning the results.

string get($uri, $query, $request)

$uri is the web address where the request is being made; $query is any query string parameters, either in string form:
"param1=foo&param2=bar" or as a keyed array: array('param1' => 'foo', 'param2' => 'bar').

Plain Text View (#)


1. App::import('Core', 'HttpSocket');
2. $HttpSocket = new HttpSocket();
3. $results = $HttpSocket->get('http://www.google.com/search', 'q=cakephp');
4. //returns html for Google's search results for the query "cakephp"

8.8.2 (#post-1519) post

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1519/post) .. Mas info sobre
traduciones (/es/view/818)

The post method makes a simple HTTP POST request returning the results.

string function post ($uri, $data, $request)

The parameters for the post method are almost the same as the get method, $uri is the web address where the request
is being made; $query is the data to be posted, either in string form: "param1=foo&param2=bar" or as a keyed array:
array('param1' => 'foo', 'param2' => 'bar').

Plain Text View (#)


1. App::import('Core', 'HttpSocket');
2. $HttpSocket = new HttpSocket();
3. $results = $HttpSocket->post('www.somesite.com/add', array('name' => 'test', 'type' => 'user'));
4. //$results contains what is returned from the post.

8.8.3 (#request-1520) request

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1520/request) .. Mas info sobre
traduciones (/es/view/818)

The base request method, which is called from all the wrappers (get, post, put, delete). Returns the results of the
request.

string function request($request)

$request is a keyed array of various options. Here is the format and default settings:

Plain Text View (#)

340 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. var $request = array(


2. 'method' => 'GET',
3. 'uri' => array(
4. 'scheme' => 'http',
5. 'host' => null,
6. 'port' => 80,
7. 'user' => null,
8. 'pass' => null,
9. 'path' => null,
10. 'query' => null,
11. 'fragment' => null
12. ),
13. 'auth' => array(
14. 'method' => 'Basic',
15. 'user' => null,
16. 'pass' => null
17. ),
18. 'version' => '1.1',
19. 'body' => '',
20. 'line' => null,
21. 'header' => array(
22. 'Connection' => 'close',
23. 'User-Agent' => 'CakePHP'
24. ),
25. 'raw' => null,
26. 'cookies' => array()
27. );

9 (#Aplicaciones-de-Consola-Principales-1521) Aplicaciones de Consola Principales

CakePHP viene con muchas aplicaciones de consola por defecto. Algunas de ellas se utilizan en combinacion con
algunas de las funcionalidades de Cake, (ejemplo ACL o i18n), y otras son de uso general para ayudarte a producir
más rápido

Esta sección explica cómo usar las aplicaciones de consola que vienen empaquetadas con CakePHP

Antes de que sigas con esta sección, tal vez quisieras ver La consola de CakePHP (/es/view/108/the-cakephp-console) .
La configuración de la consola no está cubierta por este capítulo, así que si nunca la has usado anteriormente, echale
un vistazo.

9.1 (#Generación-de-Código-con-Bake-1522) Generación de Código con Bake

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1522)


Comparar con el texto original (/es/compare/1522/Generación-de-Código-con-Bake)

Mas info sobre traduciones (/es/view/818)

Ya has aprendido sobre scaffolding en CakePHP: una forma simple de armar una aplicación con sólo una base de
datos y algunas clases básicas. La consola Bake es otro esfuerzo para tener CakePHP corriendo rápido. La consola
Bake puede crear cualquiera de los ingredientes básicos de CakePHP: modelos, vistas y controladores. Y no estamos
hablando sólo de clases estructurales: Bake puede crear una aplicación completamente funcional en sólo unos
minutos. De hecho, Bake es el paso natural que toman las aplicaciones una vez que han pasado por la etapa de
scaffolding

Para utilizar Bake necesitar ejecutar el script localizado en el directorio /cake/console/

$ cd ./cake/console/
$ cake bake

Dependiendo de tu configuración, podrías necesitar darle permisos de ejecución al script bash o llamarlo
usando./cake bake. La consola de Cake corre usando PHP CLI (command line interface). Si tienes algún problema con
el script, asegúrate de que tienes PHP CLI instalado y que además tienes los módulos necesarios habilitados(Ej:

341 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

MySQL).

Cuando utilices Bake por primera vez, te pedirá que crees un archivo de configuración para la base de datos, si
todavía no creaste uno.

Una vez que hayas configurado la base de datos, cuando ejecutes Bake te presentará estas opciones:

---------------------------------------------------------------
App : app
Path: /ruta/al/proyecto
---------------------------------------------------------------
Interactive Bake Shell
---------------------------------------------------------------
[D]atabase Configuration
[M]odel
[V]iew
[C]ontroller
[P]roject
[Q]uit
What would you like to Bake? (D/M/V/C/P/Q)
>

Alternativamente, puedes ejecutar cualquiera de estos comandos directamente de la línea de comandos:

$ cake bake db_config


$ cake bake model
$ cake bake view
$ cake bake controller
$ cake bake project

9.1.1 (#Bake-improvements-in-1-3-1611) Bake improvements in 1.3

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1611/Bake-improvements-
in-1-3) .. Mas info sobre traduciones (/es/view/818)

For 1.3 bake has had a significant overhaul, and a number of features and enhancements have been built in.

Two new tasks (FixtureTask and TestTask) are accessible from the main bake menu
A third task (TemplateTask) has been added for use in your shells.
All the different bake tasks now allow you to use connections other than default for baking. Using the
-connection parameter.
Plugin support has been greatly improved. You can use either -plugin PluginName or Plugin.class.
Questions have been clarified, and made easier to understand.
Multiple validations on models has been added.
Self Associated models using parent_id are now detected. For example if your model is named Thread, a
ParentThread and ChildThread association will be created.
Fixtures and Tests can be baked separately.
Baked Tests include as many fixtures as they know about, including plugin detection (plugin detection does not
work on PHP4).

So with the laundry list of features, we'll take some time to look at some of the new commands, new parameters and
updated features.

New FixtureTask, TestTask and TemplateTask.

Fixture and test baking were a bit of a pain in the past. You could only generate tests when baking the classes, and
fixtures could only be generated when baking models. This made adding tests to your applications later or even
regenerating fixtures with new schemas a bit painful. For 1.3 we've separated out Fixture and Test making them
separate tasks. This allows you to re-run them and regenerate tests and fixtures at any point in your development
process.

In addition to being rebuildable at any time, baked tests are now attempt to find as many fixtures as possible. In the
past getting into testing often involved fighting through numerous 'Missing Table' errors. With more advanced fixture
detection we hope to make testing easier and more accessible.

Test cases also generate skeleton test methods for every non-inherited public method in your classes. Saving you one

342 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

extra step.

TemplateTask is a behind the scenes task, and it handles file generation from templates. In previous versions of
CakePHP baked views were template based, but all other code was not. With 1.3 almost all the content in the files
generated by bake are controlled by templates and the TemplateTask.

The FixtureTask not only generates fixtures with dummy data, but using the interactive options or the -records
option you can enable fixture generation using live data.

New bake command

New commands have been added to make baking easier and faster. Controller, Model, View baking all feature an all
subcommand, that builds everything at once and makes speedy rebuilds easy.

Plain Text View (#)


1. cake bake model all

Would bake all the models for an application in one shot. Similarly cake bake controller all would bake all
controllers and cake bake view all would generate all view files. Parameters on the ControllerTask have changed as
well. cake bake controller scaffold is now cake bake controller public. ViewTask has had an -admin flag added,
using -admin will allow you to bake views for actions that begin with Routing.admin

As mentioned before cake bake fixture and cake bake test are new, and have several subcommands each. cake bake
fixture all will regenerate all the basic fixtures for your application. The -count parameter allows you to set the
number of fake records that are created. By running fixture task interactively you can generate fixtures using the data
in your live tables. You can use cake bake test <type> <class> to create test cases for already created objects in your
app. Type should be one of the standard CakePHP types ('component', 'controller', 'model', 'helper', 'behavior') but
doesn't have to be. Class should be an existing object of the chosen type.

Templates Galore

New in bake for 1.3 is the addition of more templates. In 1.2 baked views used templates that could be changed to
modify the view files bake generated. In 1.3 templates are used to generate all output from bake. There are separate
templates for controllers, controller action sets, fixtures, models, test cases, and the view files from 1.2. As well as
more templates, you can also have multiple template sets or, bake themes. Bake themes can be provided in your app,
or as part of plugins. An example plugin path for bake theme would be app/plugins/bake_theme/vendors/shells
/templates/dark_red/. An app bake theme called blue_bunny would be placed in app/vendors/shells/templates
/blue_bunny. You can look at cake/console/templates/default/ to see what directories and files are required of a bake
theme. However, like view files, if your bake theme doesn't implement a template, other installed themes will be
checked until the correct template is found.

Additional plugin support.

New in 1.3 are additional ways to specify plugin names when using bake. In addition to cake bake plugin Todo
controller Posts, there are two new forms. cake bake controller Todo.Posts and cake bake controller Posts
-plugin Todo. The plugin parameter can be while using interactive bake as well. cake bake controller -plugin Todo,
for example will allow you to use interactive bake to add controllers to your Todo plugin. Additional / multiple plugin
paths are supported as well. In the past bake required your plugin to be in app/plugins. In 1.3 bake will find which of
the pluginPaths the named plugin is located on, and add the files there.

9.2 (#Gestión-del-Esquema-de-la-BBDD-y-Migraciones-1523) Gestión del Esquema de la BBDD y Migraciones

El SchemaShell proporciona la funcionalidad para crear un esquema de objetos, volcados del esquema sql, así como
crear y restaurar instantáneas de base de datos.

9.2.1 (#Generando-y-Usando-Archivos-de-Esquemas-1524) Generando y Usando Archivos de Esquemas

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1524)


Comparar con el texto original (/es/compare/1524/Generando-y-Usando-Archivos-de-Esquemas)

Mas info sobre traduciones (/es/view/818)

Un archivo de esquema permite transportar fácilmente el esquema de la base de datos, sin importar en qué motor se
vaya a implementar. Puedes generar un archivo de esquema de la base de datos usando:

343 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

$ cake schema generate

Esto generará un archivo llamado schema.php en tu directorio app/config/sql.

La aplicación SchemaShell procesará sólo las tablas para las cuales existe un modelo definido. Para forzar a que cree
un esquema de todas las tablas, debes añadir la opción -f en la línea de comandos.

Para reconstruir el esquema de la base de datos a partir de un archivo schema.php generado anteriormente, debes
ejecutar:

$ cake schema run create

Esto borrará y volverá a crear todas las tablas basándose en el contenido del archivo schema.php.

Los archivos de esquema pueden ser usado para genera volcados de SQL. Para generar un archivo SQL que contenga
las sencencias CREATE TABLE ejecuta:

$ cake schema dump volcado.sql

Donde volcado.sql es el nombre que deseas ponerle al volcado. Si omites este nombre, el volcado será mostrado por
pantalla sin ser escrito en ningún archivo.

9.2.2 (#Migrations-with-CakePHP-schema-shell-1525) Migrations with CakePHP schema shell

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1525/Migrations-with-CakePHP-
schema-shell) .. Mas info sobre traduciones (/es/view/818)

Migrations allow for versioning of your database schema, so that as you develop features you have an easy and
database agnostic way to distribute database changes. Migrations are achieved through either SCM controlled schema
files or schema snapshots. Versioning a schema file with the schema shell is quite easy. If you already have a schema
file created running

$ cake schema generate

Will bring up the following choices:

Generating Schema...
Schema file exists.
[O]verwrite
[S]napshot
[Q]uit
Would you like to do? (o/s/q)

Choosing [s] (snapshot) will create an incremented schema.php. So if you have schema.php, it will create
schema_2.php and so on. You can then restore to any of these schema files at any time by running:

$ cake schema update -s 2

Where 2 is the snapshot number you wish to run. The schema shell will prompt you to confirm you wish to perform
the ALTER statements that represent the difference between the existing database the currently executing schema file.

You can perform a dry run by adding a -dry to your command.

9.3 (#Modificando-el-HTML-producido-por-defecto-del-scri-1526) Modificando el HTML producido por defecto del script


bake

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1526)


Comparar con el texto original (/es/compare/1526/Modificando-el-HTML-producido-por-defecto-del-scri)

Mas info sobre traduciones (/es/view/818)

Si deseas modificar el HTML producido por el comando "bake", sigue los siguientes pasos:

1. Dirígete a: cake/console/libs/templates/views
2. Existen cuatro archivos ahí
3. Cópialos en: app/vendors/shells/templates/views

344 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

4. Haz los cambios a la salida HTML para controlar la forma en que "bake" construye las vistas.

10 (#Ejemplo-de-Aplicación-1527) Ejemplo de Aplicación

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1527)


Comparar con el texto original (/es/compare/1527/Ejemplo-de-Aplicación)

Mas info sobre traduciones (/es/view/818)

En esta sección podrás ver cómo se unen todas las piezas en una aplicación de CakePHP típica.

Alternativamente, puedes visitar CakeForge (http://cakeforge.org/) y The Bakery (http://bakery.cakephp.org/) para


encontrar aplicaciones existentes y otros componentes.

10.1 (#Blog-1528) Blog

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1528)


Comparar con el texto original (/es/compare/1528/Blog)

Mas info sobre traduciones (/es/view/818)

Bienvenidos a CakePHP! Probablemente estás viendo este tutorial porque deseas aprender más acerca de cómo
funciona Cake. Es nuestro deseo incrementar la productividad y hacer la programación más agradable: esperamos que
notes esto a medida que vayas avanzando con el tutorial.

Este tutorial te guiará para que puedas crear un blog simple. Obtendremos e instalaremos Cake, creando la base de
datos y configurándola, y creando luego la lógica necesaria para mostrar, añadir, editar y borrar posts del blog.

Esto es lo que necesitas:

1. Un servidor web. Aquí asumiremos que estás usando Apache, aunque las instrucciones para utilizar otros
servidores deberían ser similares. Tal vez necesitemos jugar un poco con la configuración del servidor, pero la
mayoría de pueden obtener y poner en marcha Cake sin modificar la configuración para nada.

2. Un servidor de base de datos. Nosotros utilizaremos MySQL es este tutorial. Deberás saber lo suficiente de SQL
como para crear una base de datos: Cake se encarga del resto a partir de ahí.

3. Conocimiento básico de PHP. Cuanto más programación orientada a objetos hayas hecho, mejor, pero no
tengas miedo si eres un fan de la programación procedural.

4. Finalmente, necesitarás un conocimiento básico del patrón MVC. Puedes darle un vistazo al capítulo
"Comenzando con CakePHP", en la sección: Entendiendo Modelo-Vista-Controlador (/es/view/10/Entendiendo-
Modelo-Vista-Controlador) . No te preocupes, es menos de una página.

Comencemos!

10.1.1 (#Obteniendo-Cake-1529) Obteniendo Cake

345 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1529)


Comparar con el texto original (/es/compare/1529/Obteniendo-Cake)

Mas info sobre traduciones (/es/view/818)

Primero debemos conseguir una copia reciente de CakePHP.

Para esto debes visitar la sección del proyecto CakePHP en Cakeforge http://cakeforge.org/projects/cakephp/
(http://cakeforge.org/projects/cakephp/) y descargar la versión estable. Para este tutorial vamos a usar la 1.2.x.x

También puedes obtener una copia mediante svn en https://svn.cakephp.org/repo/trunk/cake/1.2.x.x/


(https://svn.cakephp.org/repo/trunk/cake/1.2.x.x/)

Sin importar cómo hayas conseguido Cake, deber colocar los archivos en el directorio raíz del servidor
(DocumentRoot). Una vez terminado, los directorios deberían lucir algo así:

Plain Text View (#)


1. /ruta_al_directorio_raiz
2. /app
3. /cake
4. /docs
5. /vendors
6. .htaccess
7. index.php

Este es un buen momento para aprender un poco más acerca de cómo Cake utiliza la estructura de directorios: puedes
verlo en el capítulo "Principios básicos de CakePHP", sección : Estructura de archivos de CakePHP (/es/view
/19/Estructura-de-archivos-de-CakePHP) .

10.1.2 (#Creando-la-Base-de-Datos-del-Blog-1530) Creando la Base de Datos del Blog

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1530)


Comparar con el texto original (/es/compare/1530/Creando-la-Base-de-Datos-del-Blog)

Mas info sobre traduciones (/es/view/818)

A continuación debemos crear la base de datos en la que se basará nuestro blog. Lo primero que haremos será crear
una tabla para almacenar nuestros posts. También insertaremos algunos posts para poder utilizarlos de testeo.
Ejecuta el siguiente código SQL en tu base de datos:

Plain Text View (#)


1. /* Primero, crear la tabla para los posts: */
2. CREATE TABLE posts (
3. id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
4. title VARCHAR(50),
5. body TEXT,
6. created DATETIME DEFAULT NULL,
7. modified DATETIME DEFAULT NULL
8. );
9. /* Luego insertar algunos posts de ejemplo: */
10. INSERT INTO posts (title,body,created)
11. VALUES ('El título', 'Este es el cuerpo del post.', NOW());
12. INSERT INTO posts (title,body,created)
13. VALUES ('Un título otra vez', 'Y el cuerpo del post a continuación.', NOW());
14. INSERT INTO posts (title,body,created)
15. VALUES ('Título ataca de nuevo', 'Esto es realmente exitante! No.', NOW());

La elección de los nombres de la tabla y las columnas no es arbitrario. Si sigues las convenciones de Cake
relacionadas a la base de datos, y las convenciones relacionadas a los nombres de las clases (puedes consultar

346 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

ambas en "Convenciones de CakePHP" (/es/view/22/Convenciones-de-CakePHP) ), tendrás la posibilidad de aprovechar


muchas ventajas y evitar la configuración. Cake es lo suficientemente flexible como para acomodarse inclusive al peor
esquema de base de datos de aplicaciones antiguas, sin embargo, si utilizas las convenciones ahorrarás mucho
tiempo de desarrollo.

Puedes ver las "Convenciones de CakePHP" (/es/view/22/Convenciones-de-CakePHP) para más información, pero es
suficiente con decir que al llamar a la tabla 'posts' automáticamente estará asociada con el modelo Post, y al tener los
campos 'modified' y 'created', éstos serán manejados automáticamente por Cake.

10.1.3 (#Configuración-de-la-Base-de-Datos-en-Cake-1531) Configuración de la Base de Datos en Cake

Vamos a decirle a Cake dónde está nuestra base de datos y cómo conectarse a ella. Para muchos, esta será la primera
y última vez que configuren algo.

Una copia del archivo de configuración de la base de datos se encuentra en /app/config/database.php.default. Haz
una copia en el mismo directorio, pero nombrándola database.php.

El archivo de configuración debería ser fácil de seguir: sólo debes reemplazar los valores en el arreglo $default con
la información que se corresponda a tu configuración. Un ejemplo completo deberíe verse como el siguiente:

Plain Text View (#)


1. var $default = array(
2. 'driver' => 'mysql',
3. 'persistent' => 'false',
4. 'host' => 'localhost',
5. 'port' => '',
6. 'login' => 'usuario_de_la_BD',
7. 'password' => 'c4k3-rUl3Z',
8. 'database' => 'tutorial_blog',
9. 'schema' => '',
10. 'prefix' => '',
11. 'encoding' => ''
12. );

Una vez que hayas guardado el nuevo database.php, deberías poder abrir el navegador en la página de inicio de Cake
y ver que puede conectarse a la base de datos sin problemas.

10.1.4 (#Configuración-Opcional-1532) Configuración Opcional

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1532)


Comparar con el texto original (/es/compare/1532/Configuración-Opcional)

Mas info sobre traduciones (/es/view/818)

Hay dos ítems más que pueden ser configurados. La mayoría de los desarrolladores realiza estos pasos, pero para
este tutorial no son necesarios. El primero es definir una cadena (o "salt") para darle más seguridad a los hash. El
segundo ítem es darle acceso de escritura a Cake, a su directorio tmp.

La cadena de seguridad (o "salt") es usada para generar hashes. Puedes cambiarla editando el archivo /app/config
/core.php. No importan tanto cuál es el nuevo valor del salt, siempre y cuando no sea fácil de adivinar.

Plain Text View (#)


1. <?php
2. /**
3. * Una cadena aleatoria usada en los métodos de hashing de seguridad.
4. */
5. Configure::write('Security.salt', 'pl345e-P45s_7h3*S@l7!');
6. ?>

La segunda tarea es darle al servidor web permisos de escritura sobre el directorio app/tmp. La mejor forma de hacer
esto es encontrar con qué nombre de usuario está corriendo el servidor (<?php echo `whoami`; ?>) y cambiar el

347 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

propietario de app/tmp a ese usuario. El comando a ejecutar (en sistemas *nix) puede lucir similar a esto:

Plain Text View (#)


1. $ chown -R www-data app/tmp

Si por alguna razón CakePHP no puede escribir en ese directorio, podrás ver un aviso cuando te encuentres
navegando la aplicación en modo debug.

10.1.5 (#Una-aclaración-para-mod_rewrite-1533) Una aclaración para mod_rewrite

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1533)


Comparar con el texto original (/es/compare/1533/Una-aclaración-para-mod_rewrite)

Mas info sobre traduciones (/es/view/818)

Es muy probable que los usuarios novatos tengan problemas con mod_rewrite, así que haremos una mención aquí. Si
la página de bienvenida de CakePHP se ve un poco rara (sin imágenes o estilos CSS), probablemente no tengas
funcionando el módulo mod_rewrite en tu sistema. Algunos consejos para que hacerlo funcionar:

1. Asegúrate que la sobreescritura (override) esté permitida (allowed ): en tu httpd.conf, deberías tener una
sección en la que se definen los permisos sobre cada Directorio en tu servidor. Asegúrate que AllowOverride
esté puesto en All para el Directorio correcto. Por razones de seguridad y de performance, no setees
AllowOverride en All dentro de <Directory />. A su vez, busca el bloque <Directory> que haga referencia al
directorio de tu sitio web..

2. Asegúrate que estás editando el httpd.conf correcto en vez de un httpd.conf específico de usuario o sitio web.

3. Por una u otra razón, puedes haber conseguido una copia de CakePHP sin los archivos .htaccess necesarios.
Esto a veces sucede porque algunos sistemas operativos tratan a los archivos cuyo nombre comienza con '.'
como ocultos, y no los copia. Asegúrate que tu copia de CakePHP proviene de la sección de descargas del sitio
o desde nuestro repositorio SVN.

4. Asegúrate que Apache esté cargando mod_rewrite correctamente! Deberías ver algo como LoadModule
rewrite_module libexec/httpd/mod_rewrite.so o (en Apache 1.3) AddModule mod_rewrite.c en tu httpd.conf.

Si no quieres o no puedes hacer funcionar mod_rewrite (o algún otro módulo compatible), necesitarás usar las 'pretty'
URLs proporcionadas por CakePHP. En /app/config/core.php, descomenta la línea que diga algo como:

Plain Text View (#)


1. Configure::write('App.baseUrl', env('SCRIPT_NAME'));

Also remove these .htaccess files:

Plain Text View (#)


1. /.htaccess
2. /app/.htaccess
3. /app/webroot/.htaccess
4.

Esto hará que tus URLs se vean de la forma www.example.com/index.php/controllername/actionname/param en vez de


www.example.com/controllername/actionname/param.

10.1.5.1 (#URL-Rewrites-on-IIS7-Windows-hosts-1636) URL Rewrites on IIS7 (Windows hosts)

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1636/URL-Rewrites-on-IIS7-
Windows-hosts) .. Mas info sobre traduciones (/es/view/818)

IIS7 does not natively support .htaccess files. While there are add-ons that can add this support, you can also import
htaccess rules into IIS to use CakePHP's native rewrites. To do this, follow these steps:

1. Use Microsoft's Web Platform Installer to install the URL Rewrite Module 2.0.
2. Create a new file in your CakePHP folder, called web.config

348 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

3. Using Notepad or another XML-safe editor, copy the following code into your new web.config file...

Plain Text View (#)


1. <?xml version="1.0" encoding="UTF-8"?>
2. <configuration>
3. <system.webServer>
4. <rewrite>
5. <rules>
6. <rule name="Imported Rule 1" stopProcessing="true">
7. <match url="^(.*)$" ignoreCase="false" />
8. <conditions logicalGrouping="MatchAll">
9. <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
10. <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
11. </conditions>
12. <action type="Rewrite" url="index.php?url={R:1}" appendQueryString="true" />
13. </rule>
14. <rule name="Imported Rule 2" stopProcessing="true">
15. <match url="^$" ignoreCase="false" />
16. <action type="Rewrite" url="/" />
17. </rule>
18. <rule name="Imported Rule 3" stopProcessing="true">
19. <match url="(.*)" ignoreCase="false" />
20. <action type="Rewrite" url="/{R:1}" />
21. </rule>
22. <rule name="Imported Rule 4" stopProcessing="true">
23. <match url="^(.*)$" ignoreCase="false" />
24. <conditions logicalGrouping="MatchAll">
25. <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
26. <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
27. </conditions>
28. <action type="Rewrite" url="index.php?url={R:1}" appendQueryString="true" />
29. </rule>
30. </rules>
31. </rewrite>
32. </system.webServer>
33. </configuration>

It is also possible to use the Import functionality in IIS's URL Rewrite module to import rules directly from CakePHP's
.htaccess files in root, /app/, and /app/webroot/ - although some editing within IIS may be necessary to get these to
work. When Importing the rules this way, IIS will automatically create your web.config file for you.

Once the web.config file is created with the correct IIS-friendly rewrite rules, CakePHP's links, css, js, and rerouting
should work correctly.

10.1.6 (#Crear-un-modelo-Post-1534) Crear un modelo Post

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1534)


Comparar con el texto original (/es/compare/1534/Crear-un-modelo-Post)

Mas info sobre traduciones (/es/view/818)

La clase Model es el pan y manteca de las aplicaciones CakePHP. Creando un modelo CakePHP que interactúe con
nuestra base de datos, tendremos la base para poder hacer luego nuestras acciones de vista, agregar, editar, y
eliminar.

Los archivos de clases de modelo de CakePHP van en la carpeta /app/models, y el archivo que crearemos lo
grabaremos en /app/models/post.php. El archivo completo debería verse así:

Plain Text View (#)

349 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <?php
2. class Post extends AppModel {
3. var $name = 'Post';
4. }
5. ?>

La convención en la nomenclatura es muy importante en CakePHP. Nombrando nuestro modelo como Post, CakePHP
puede automáticamente inferir que este modelo será usado en el controlador PostsController , y será atado a la tabla
de la base de datos llamada posts.

CakePHP dinámicamente creará un objeto de modelo por ti, si no puede encontrar el archivo correspondiente en
/app/models. Esto también dice que si nombras incorrectamente tu archivo (i.e. Post.php or posts.php) CakePHP no
reconocerá ninguna de tus configuraciones y usará las opciones por defecto.

Siempre es una buena idea agregar la variable $name, y suele ahorrarnos problemas con los nombres de las clases en
PHP4.

Para más información sobre modelos, como prefijos de tabla, callbacks, y validación, revisar el capítulo Models
(/es/view/66/) del Manual.

10.1.7 (#Crear-un-controlador-para-Post-1535) Crear un controlador para Post

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1535)


Comparar con el texto original (/es/compare/1535/Crear-un-controlador-para-Post)

Mas info sobre traduciones (/es/view/818)

A continuación, crearemos un controlador para nuestros posts. El controlador es donde existe toda la lógica del
negocio para la interacción con los posts. En pocas palabras, es el lugar en el que juegas con los modelos y realizas
el trabajo con los posts. Ubicaremos este nuevo controlador en un archivo llamado posts_controller.php dentro del
directorio /app/controllers. Así es como debe verse un controlador básico:

Plain Text View (#)


1. <?php
2. class PostsController extends AppController {
3. var $name = 'Posts';
4. }
5. ?>

Ahora, agreguemos una acción a nuestro controlador. Las acciones a menudo representan una función o una
interfase en una aplicación. Por ejemplo, cuando los usuarios ingresan www.example.com/posts/index (que es lo
mismo que www.example.com/posts/), esperan ver un listado de posts. El código para esa acción se vería como esto:

Plain Text View (#)


1. <?php
2. class PostsController extends AppController {
3. var $name = 'Posts';
4. function index() {
5. $this->set('posts', $this->Post->find('all'));
6. }
7. }
8. ?>

Déjenme explicar un poquito la acción. Definiendo la función index() en nuestro PostsController, los usuarios
pueden ahora acceder a la lógica ubicada en www.example.com/posts/index. De forma similar, si definimos una
función llamada foobar(), los usuarios podrían acceder a ella en www.example.com/posts/foobar.

Puede tentarte querer nombrar a tus controladores y acciones de cierta forma para obtener cierto URL. Resiste la
tentación. Sigue las convenciones de CakePHP (nombres en plural para los controladores, etc.) y crea nombres
legibles y entendibles para las acciones. Puedes mapear luego URLs a tu código usando "routes".

La única instrucción en la acción usa set() para pasar datos desde el controlador a la vista (que crearemos a

350 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

continuación). La línea iguala la variable de vista llamada 'posts' al valor retornado por el método del modelo Post
find('all'). Nuestro modelo Post está disponible automáticamente en $this->Post porque hemos seguido la
convención de nombres de Cake.

Para aprender más sobre los controladores de Cake, chequea el capítulo "Desarrollando con CakePHP": "Controllers"
(/es/view/49/) .

10.1.8 (#Creando-las-Vistas-Views-de-los-Post-1536) Creando las Vistas(Views) de los Post

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1536)


Comparar con el texto original (/es/compare/1536/Creando-las-Vistas-Views-de-los-Post)

Mas info sobre traduciones (/es/view/818)

Ahora que tenemos los datos que fluyen a nuestro modelo y la lógica de nuestra aplicación y el flujo definido por
nuestro controlador, vamos a crear una vista (view) para la acción “index” que hemos creado anteriormente.

Cake view(vistas) son solo fragmentos de presentaciones-sabrosas que se adaptan dentro de las aplicaciones
diseñadas. Para la mayoría de las aplicaciones estaremos mezclando HTML con PHP, pero puede terminar usando
XML, CSV, o incluso de datos binarios.

Los Diseños (Layouts) de presentación son el código que se envuelve alrededor de las vista (views), y pueden ser
definidas y modificadas, pero por ahora, vamos a usar el valor por defecto.

¿Recuerda que en la última sección la forma en que asigno la variable "posts" a de la vista fue usando método set()?
La forma que transmite datos a la vista sería algo como esto:

// print_r($posts) output:

Array
(
[0] => Array
(
[Post] => Array
(
[id] => 1
[title] => The title
[body] => This is the post body.
[created] => 2008-02-13 18:34:55
[modified] =>
)
)
[1] => Array
(
[Post] => Array
(
[id] => 2
[title] => A title once again
[body] => And the post body follows.
[created] => 2008-02-13 18:34:56
[modified] =>
)
)
[2] => Array
(
[Post] => Array
(
[id] => 3
[title] => Title strikes back
[body] => This is really exciting! Not.
[created] => 2008-02-13 18:34:57
[modified] =>

351 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

)
)
)

Los archivos de las Cakeʼs views (vistas de cake) se almacenan en /app/views dentro de una carpeta con el nombre del
controlador que corresponden (tendremos que crear una carpeta llamada "posts" en este caso). Para dar formato a los
datos de los posts en un cuadro lindo, el código de nuestra vista podría ser algo como esto:

Plain Text View (#)


1. <!-- Archivo: /app/views/posts/index.ctp -->
2. <h1>Blog posts</h1>
3. <table>
4. <tr>
5. <th>Id</th>
6. <th>Title</th>
7. <th>Created</th>
8. </tr>
9. <!-- Aqui se hace el ciclo que recorre nuestros arreglo $posts , imprimiendo la información de cada
10. <?php foreach ($posts as $post): ?>
11. <tr>
12. <td><?php echo $post['Post']['id']; ?></td>
13. <td>
14. <?php echo $html->link($post['Post']['title'],
15. "/posts/view/".$post['Post']['id']); ?>
16. </td>
17. <td><?php echo $post['Post']['created']; ?></td>
18. </tr>
19. <?php endforeach; ?>
20.
21. </table>

Creemos que esto debería ser algo sencillo.

Usted puede haber notado el uso de un objeto llamado $html. Esta es una instancia de la clase CakePHP HtmlHelper.
CakePHP viene con un conjunto de "view helpers" (vistas de ayuda) que hacen cosas como la vinculación, la forma de
salida, manejo JavaScript y Ajax. Puede obtener más información sobre cómo utilizarlas en el capítulo "Built-in
Helpers" (/es/view/181/) , pero lo que es importante señalar aquí es que el método link() generará un vínculo HTML
con un título determinado (el primer parámetro) y la URL (la segunda parámetro).

Al especificar las URL en Cake, sólo tiene que dar una ruta relativa de la base de la aplicación, y cake llena en el resto.
Es así, que las URL se suelen quedar de la forma de /controlador/acción/parametro1/parametro2 (/controller/action
/param1/param2).

En este punto, usted debería ser capaz de escribir en el navegador http://www.example.com/posts/index. Usted debe
observar en la vista, el formato correcto con el título y la lista de los posts.

Si le sucedió que hizo click en uno de los enlaces que hemos creado en esta vista (que vinculan el título de un post a
una URL /posts/view/some_id), probablemente ha sido informado por CakePHP que la acción aún no ha sido definida.
Si no recibió el informe, es que algo ha ido mal, o que realmente ya la a definido, en cuyo caso es muy astuto. De lo
contrario, la vamos a crear ahora en el PostsController:

Plain Text View (#)

352 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <?php
2. class PostsController extends AppController {
3. var $name = 'Posts';
4. function index() {
5. $this->set('posts', $this->Post->find('all'));
6. }
7. function view($id = null) {
8. $this->Post->id = $id;
9. $this->set('post', $this->Post->read());
10. }
11. }
12. ?>

La llamada set() les debe lucir familiar. Informamos de que estamos usando read() en lugar de find('all') porque
realmente solo queremos la información de un único post.

Tenga en cuenta que la acción de nuestra vista toma un parámetro: la ID del post que nos gustaría ver. Este parámetro
se entrega a la acción a través de la URL solicitada. Si un usuario solicita /posts/view/3, entonces el valor '3' es
pasado como $id.

Ahora vamos a crear la vista para las “view” de nuestra nueva acción y lo colocaremos en /app/views/posts/view.ctp.

Plain Text View (#)


1. <!-- archivo: /app/views/posts/view.ctp -->
2. <h1><?php echo $post['Post']['title']?></h1>
3. <p><small>Created: <?php echo $post['Post']['created']?></small></p>
4. <p><?php echo $post['Post']['body']?></p>

Verifique que esto esta funcionando en los vínculos de /posts/index o manualmente solicitando un post accediendo
a /posts/view/1.

10.1.9 (#Agregando-Posts-1537) Agregando Posts

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1537)


Comparar con el texto original (/es/compare/1537/Agregando-Posts)

Mas info sobre traduciones (/es/view/818)

Leer y mostrar de la base de datos nuestros postʼs es un gran comienzo, pero debe habilitarse para agregar nuevos
postʼs.

En primer lugar, empezar por crear la acción add() controlador PostsController:

Plain Text View (#)

353 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <?php
2. class PostsController extends AppController {
3. var $name = 'Posts';
4. function index() {
5. $this->set('posts', $this->Post->find('all'));
6. }
7. function view($id) {
8. $this->Post->id = $id;
9. $this->set('post', $this->Post->read());
10. }
11. function add() {
12. if (!empty($this->data)) {
13. if ($this->Post->save($this->data)) {
14. $this->Session->setFlash('Your post has been saved.');
15. $this->redirect(array('action' => 'index'));
16. }
17. }
18. }
19. }
20. ?>

Lo que esta acción add() hace es lo siguiente: si los datos del formulario presentado no están vacíos, trate de guardar
los datos utilizando el modelo Post. Si por alguna razón, no guarda, simplemente hacer que se quede en la vista. Esto
nos da la oportunidad de mostrar los errores de validación de usuario u otras advertencias.

Cuando un usuario utiliza un formulario de datos POST en su aplicación, esta información está disponible en
$this->data. Usted puede usar las funciones pr() o debug para imprimir, si quieres ver como luce esto.

Usamos la función del componente Session setFlash() (/es/view/400/setFlash) para adjuntar un mensaje a una
variable de sesión que se mostrará en la página después de la redirección. En el diseño tenemos $session->flash()
(/es/view/568/flash) , que muestra el mensaje y borra la variable de sesión correspondiente. La función redirect
(/es/view/425/redirect) del controlador redirige a otra dirección URL. El parámetro array('action'=>'index) se
traduce en la URL /posts es decir, la acción index del controlador posts. Puede referirse a Router::url
(http://api.cakephp.org/class/router#method-Routerurl) en función de la API para ver los formatos en los que se puede
especificar una dirección URL para diversas funciones de cake.

Llamando al método save() haremos comprobación de errores de validación y abortar el guardado si algo ocurre.
Hablaremos de cómo se manejan los errores en las siguientes secciones.

10.1.10 (#Validación-de-Datos-1538) Validación de Datos

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1538)


Comparar con el texto original (/es/compare/1538/Validación-de-Datos)

Mas info sobre traduciones (/es/view/818)

Cake lleva un largo camino recogiendo la monotonía de la validación de formularios de entrada. Todo el mundo odia
a la codificación de sus infinitos formularios y rutinas de validación. CakePHP hace que sea más fácil y más rápido.

Para aprovechar las características de la validación, tendrás que utilizar FormHelper de Cake en tus vistas. El
FormHelper está disponible por defecto en todas las vista en $form.

Esta es nuestra Vista Agregar(add view):

Plain Text View (#)

354 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. <!-- File: /app/views/posts/add.ctp -->


2.
3. <h1>Add Post</h1>
4. <?php
5. echo $form->create('Post');
6. echo $form->input('title');
7. echo $form->input('body', array('rows' => '3'));
8. echo $form->end('Save Post');
9. ?>

Aquí, nosotros usamos el FormHelper para generar la etiqueta de apertura de un formulario HTML. Aquí está el
código HTML que genera $form->create() :

Plain Text View (#)


1. <form id="PostAddForm" method="post" action="/posts/add">

Si create() es llamado sin suministrarle parámetros, este supone que está construyendo un formulario que
suministra datos a la acción add() (o a la acción edit() cuando el parámetro id esta incluído en los datos del
formulario ($form->data)), a través del metodo POST.

El método $form->input() es utilizado para crear elementos de formulario del mismo nombre. El primer parámetro le
dice a CakePHP a que campo corresponden, y el segundo parámetro le permite especificar una amplia gama de
opciones - en este caso, el número de filas para el textarea. Hay un poco de introspección y automátizacion aquí:
input() es la salida de diferentes elementos basados en el modelo del campo especificado.

El $form->end() genera una llamada al botón de enviar y termina el formulario. Si una cadena se suministra como el
primer parámetro a end(), FormHelper producirá un botón de enviar con ese nombre seguido del cierre de la etiqueta.
Una vez más, consulte el Chapter "Built-in Helpers" (/es/view/181/) para conocer más acerca de los helpers.

Ahora vamos a volver y actualizar nuestro /app/views/posts/index.ctp para incluir un nuevo enlace "Añadir entrada".
Antes de el <table>, añada la siguiente línea:

Plain Text View (#)


1. <?php echo $html->link('Add Post',array('controller' => 'posts', 'action' => 'add'))?>

Puede estar preguntarse: ¿cómo le digo a mi CakePHP sobre los requisitos de validación? Reglas de validación se
definen en el modelo. Vamos a mirar hacia atrás en nuestro modelo y después haremos algunos ajustes:

Plain Text View (#)


1. <?php
2. class Post extends AppModel
3. {
4. var $name = 'Post';
5. var $validate = array(
6. 'title' => array(
7. 'rule' => 'notEmpty'
8. ),
9. 'body' => array(
10. 'rule' => 'notEmpty'
11. )
12. );
13. }
14. ?>

El arreglo $validate le dice a CakePHP cómo validar sus datos cuando se llama el método save() . Aquí, he
especificado que tanto el campos cuerpo y el título no deben estar vacía. El motor de validación de CakePHP es fuerte,
con una serie de normas pre-construidas (números de tarjetas de crédito, direcciones de correo electrónico, etc) y la
flexibilidad para añadir sus propias reglas de validación. Para obtener más información sobre esta configuración,
consulte el Capítulo Validación de Datos (/es/view/125/data-validation) .

Ahora que tiene las reglas de validación en su lugar, utilice la aplicación para tratar de añadir un post con un título o
el cuerpo vacío para ver cómo funciona. Como hemos utilizado el método input() del componente FormHelper para

355 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

crear elementos de nuestro formulario, nuestros mensajes de error de validación se mostrará automáticamente.

10.1.11 (#Borrando-Posts-1539) Borrando Posts

A continuación, vamos a crear un medio para que los usuarios eliminen postʼs. Comenzaremos con la acción
delete() en el PostsController:

Plain Text View (#)


1. function delete($id) {
2. $this->Post->delete($id);
3. $this->Session->setFlash('The post with id: '.$id.' has been deleted.');
4. $this->redirect(array('action'=>'index'));
5. }

Esta lógica es eliminar el post por $ id, y utiliza $this->Session->setFlash() para mostrar al usuario un mensaje de
confirmación después de la reorientación a /posts.

Porque estamos sólo ejecutando una lógica y redireccionando, esta acción no tiene ninguna vista. Es posible que
desee actualizar su vista de índice (index) con vínculos que permitan a los usuarios eliminar posts, entonces:

Plain Text View (#)


1. /app/views/posts/index.ctp
2. <h1>Blog posts</h1>
3. <p><?php echo $html->link('Add Post', array('action' => 'add')); ?></p>
4. <table>
5. <tr>
6. <th>Id</th>
7. <th>Title</th>
8. <th>Actions</th>
9. <th>Created</th>
10. </tr>
11. <!-- Aquí esta el ciclo que muestra $posts a través de nuestro arreglo, imprimiendo la información de l
12. <?php foreach ($posts as $post): ?>
13. <tr>
14. <td><?php echo $post['Post']['id']; ?></td>
15. <td>
16. <?php echo $html->link($post['Post']['title'], array('action' => 'view', 'id' => $post['Post'][
17. </td>
18. <td>
19. <?php echo $html->link('Delete', array('action' => 'delete', post['Post']['id']), null, 'Are yo
20. </td>
21. <td><?php echo $post['Post']['created']; ?></td>
22. </tr>
23. <?php endforeach; ?>
24.
25. </table>

El código de esta vista también utiliza HtmlHelper para que pregunte al usuario con un diálogo de confirmación
JavaScript de antes de intentar borrar un post.

10.1.12 (#Editando-Posts-1540) Editando Posts

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1540)


Comparar con el texto original (/es/compare/1540/Editando-Posts)

Mas info sobre traduciones (/es/view/818)

Editando Post: ¡aquí vamos! Eres un CakePHP pro por ahora, por lo que deberías haber adoptado un patrón. Hacer la
acción, luego la vista. Aquí esta la acción edit() del PostsController que se vería como:

356 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Plain Text View (#)


1. function edit($id = null) {
2. $this->Post->id = $id;
3. if (empty($this->data)) {
4. $this->data = $this->Post->read();
5. } else {
6. if ($this->Post->save($this->data)) {
7. $this->Session->setFlash('Your post has been updated.');
8. $this->redirect(array('action' => 'index'));
9. }
10. }
11. }

Esta acción primero chequea los datos del formulario para enviarlos. Si no fue enviado, este busca el post y se lo
pasa a la vista. Si algunos datos se han enviado, intenta guardar los datos utilizando el modelo Post (o los rechazará
y mostrara al usuario los errores de validación).

La vista de edición puede tener un aspecto parecido a este:

Plain Text View (#)


1. /app/views/posts/edit.ctp
2.
3. <h1>Edit Post</h1>
4. <?php
5. echo $form->create('Post', array('action' => 'edit'));
6. echo $form->input('title');
7. echo $form->input('body', array('rows' => '3'));
8. echo $form->input('id', array('type'=>'hidden'));
9. echo $form->end('Save Post');
10. ?>

Esta vista muestra el formulario de edición (con los valores de publicados), junto con los mensajes de errores de
validación necesarios.

Cabe destacar aquí: que CakePHP asumirá que usted está editando un registro si el campo 'id' está presente en el
arreglo de datos. Si 'id' no está presente (mirar hacia atrás en nuestra opinión de añadir), Cake asumirá que usted está
añadiendo un nuevo registro para llamar a save()

Ahora puede actualizar su vista de indice, con enlaces para ir a editar posts específicos:

Plain Text View (#)

357 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. /app/views/posts/index.ctp (edit links added)


2.
3. <h1>Blog posts</h1>
4. <p><?php echo $html->link("Add Post", array('action'=>'add')); ?>
5. <table>
6. <tr>
7. <th>Id</th>
8. <th>Title</th>
9. <th>Action</th>
10. <th>Created</th>
11. </tr>
12. <!-- Aqui se hace el ciclo que recorre nuestros arreglo $posts , imprimiendo la información de cada pos
13. <?php foreach ($posts as $post): ?>
14. <tr>
15. <td><?php echo $post['Post']['id']; ?></td>
16. <td>
17. <?php echo $html->link($post['Post']['title'],array('action'=>'view', 'id'=>$post['Post']['
18. </td>
19. <td>
20. <?php echo $html->link(
21. 'Delete',
22. array('action'=>'delete', 'id'=>$post['Post']['id']),
23. null,
24. 'Are you sure?'
25. )?>
26. <?php echo $html->link('Edit', array('action'=>'edit', 'id'=>$post['Post']['id']));?>
27. </td>
28. <td><?php echo $post['Post']['created']; ?></td>
29. </tr>
30. <?php endforeach; ?>
31.
32. </table>

10.1.13 (#Rutas-1541) Rutas

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1541)


Comparar con el texto original (/es/compare/1541/Rutas)

Mas info sobre traduciones (/es/view/818)

Para algunos, el enrutamiento por defecto de CakePHP funciona lo suficientemente bien. Los desarrolladores que son
sensibles a la facilidad de uso y compatibilidad del motor de búsqueda general aprecian la forma en que CakePHP URL
mapea acciones específicas. Así que vamos a hacer un cambio rápido a las rutas en este tutorial.

Para obtener más información sobre las técnicas avanzadas de enrutamiento, consulte "Configuración de Rutas"
(/es/view/46/) .

Por defecto, CakePHP responde a una petición de la raíz de su sitio (es decir, http://www.example.com) con su
PagesController, haciendo una vista llamada "home". En lugar de ello, vamos a sustituir esto con nuestros
PostsController mediante la creación de una regla de enrutamiento.

El enrutamiento de Cake se encuentra en /app/config/routes.php. Usted querrá comentar o eliminar la línea que
define la ruta raíz predeterminada. El aspecto que presenta es:

Plain Text View (#)


1. Router::connect ('/', array('controller'=>'pages', 'action'=>'display', 'home'));

Esta línea conecta a la URL "/" con la página de inicio por defecto de CakePHP. Queremos que esto se conecte con
nuestro propio controlador, por lo que añadiremos una línea que tiene que ver asi:

Plain Text View (#)

358 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. Router::connect ('/', array('controller'=>'posts', 'action'=>'index'));

Esto debe conectar a los usuarios que solicitan '/' a la acción índex() de nuestra pronto-a-ser-creado PostsController.

CakePHP también hace uso de "enrutamiento inverso" - si con la citada ruta que definió array('controller'=>'posts',
'action'=>'index') pasa a una función que espera un arreglo, la url resultante utilizada es '/'. Es, por tanto, una
buena idea utilizar siempre los arreglos (arrays) de urls como rutas, esto significa definir a dónde va una url, y
también se asegura de que los enlaces llevan al mismo sitio.

10.1.14 (#Conclusión-1542) Conclusión

Creado aplicaciones de esta manera ganará paz, honor, amor, y dinero, incluso más allá de sus fantasías más
salvajes. Simple, ¿no? Tenga en cuenta que este tutorial es muy básico. CakePHP tiene muchas más características que
ofrecer, y es flexible en formas que no se quiso cubrir aquí para simplificar. Utilice el resto de este manual como una
guía para la construcción de aplicaciones con más ricas-características.

Ahora que ha creado la base de una aplicación Cake está listo para algo real. Comience su propio proyecto, lea el
resto del Manual (/es/) y API (http://api.cakephp.org) .

Si necesita ayuda, vengan a vernos en el #cakephp. Bienvenido a CakePHP!

10.2 (#Simple-Acl-controlled-Application-1543) Simple Acl controlled Application

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1543)


Comparar con el texto original (/es/compare/1543/Simple-Acl-controlled-Application)

Mas info sobre traduciones (/es/view/818)

Bienvenido a CakePHP, si eres nuevo con CakePHP revisa primero el tutorial del Blog. Si ya lo has visto, y ya leiste
acerca del uso de bake, y estás necesitando configurar un sistema Auth y Acl para el ingreso y autenticación de tus
usuarios, entonces este es el tutorial para ti.

Como ya mencionamos anteriormente este tutorial asume que ya tienes experiencia con CakePHP, y que estás
familiarizado con todos los conceptos del MVC que constituyen el núcleo. También te sientes cómodo con el uso de
la consola y el script bake. Si no conoces lo anterior, primero aprende todas estos elementos y luego vuelve. Este
tutorial será mucho más facil de seguir y tendra más sentido para ti. En este tutorial usaremos AuthComponent
(/es/view/172/Authentication) y AclComponent (/es/view/171/Access-Control-Lists) . Si no sabes lo que son, revisa sus
páginas en el manual antes de proceder.

Que necesitas?

1. Un servidor web. Asumiremos que usas Apache, pero las instrucciones son similares en caso de otro servidor.
Quizas debamos jugar un poco con la configuración del servidor, pero muchos consiguen utilizar CakePHP sin
tener que configurar nada.
2. Un servidor de bases de datos. Usaremos mySQL en este tutorial. Necesitarás conocer suficiente SQL para crear
la base de datos: CakePHP tomará las riendas de aquí en adelante.
3. Conocimiento PHP básico. Mientras mas programación orientada a objeto que hayas hecho mejor: pero si eres
fanático de la programación procedural no tienes nada que temer.

10.2.1 (#Preparando-nuestra-aplicación-1544) Preparando nuestra aplicación

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1544)


Comparar con el texto original (/es/compare/1544/Preparando-nuestra-aplicación)

Mas info sobre traduciones (/es/view/818)

Primero, consigamos una copia fresca de CakePHP.

Para descargarla, visita la página de CakePHP en Cakeforge: http://cakeforge.org/projects/cakephp/ y descarga la


última versión estable. Para este tutorial necesitaras la version 1.2.x.x

También puedes hacer checkout/export desde el trunk en: https://svn.cakephp.org/repo/trunk/cake/1.2.x.x/

Una vez que tengas la copia de Cake, configuraremos el archivo database.php, y cambiemos ademas el valor de

359 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Security.salt en el archivo app/config/core.php. Desde acá construiremos un esquema de base de datos simple para
nuestra aplicación. Ejecuta el siguiente código SQL en tu base de datos.

CREATE TABLE users (


id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(255) NOT NULL UNIQUE,
password CHAR(40) NOT NULL,
group_id INT(11) NOT NULL,
created DATETIME,
modified DATETIME
);

CREATE TABLE groups (


id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
created DATETIME,
modified DATETIME
);

CREATE TABLE posts (


id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
user_id INT(11) NOT NULL,
title VARCHAR(255) NOT NULL,
body TEXT,
created DATETIME,
modified DATETIME
);

CREATE TABLE widgets (


id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
part_no VARCHAR(12),
quantity INT(11)
);

Estas serán las tablas que usaremos para construir el resto de la aplicación. Una vez que tengamos la estructura en la
base de datos ya podemos comenzar a hornear. Usa cake bake (/es/view/113/Code-Generation-with-Bake) para crear
rapidamente tus modelos, controladores y vistas.

Evite el uso de Scaffold(andamios) aquí. La generación de la ACOS se verán seriamente afectados si hornear los
controladores con la función de Scaffold.

Mientras hornees tus modelos Cake automagicamente detectara las asociaciones entre tus modelos (o relaciones entre
las tablas). Dejemos que Cake entregue las asociaciones hasMany y belongsTo apropiadas. Si te pregunta por elegir
hasOne o hasMany, en general necesitarás una relación hasMany (solo) para este tutorial.

Dejaremos admin routing fuera por ahora, este tema ya es bastante complejo sin ellos. Asegurate además de NO
agregar ninguno de los dos componentes a ningún controlador mientras estes horneándolo. Haremos eso tan pronto
podamos. Ahora debieras tener modelos, controladores y vistas para tus tablas users (usuarios), groups (grupos),
posts (artículos) y widgets.

En modo actions (acciones), esto autenticará nuestros ARO que son los groups y users, con los objetos ACO -
controladores & acciones.

10.2.2 (#Preparándose-para-agregar-Autentificación-Auth-1545) Preparándose para agregar Autentificación (Auth)

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1545)


Comparar con el texto original (/es/compare/1545/Preparándose-para-agregar-Autentificación-Auth)

Mas info sobre traduciones (/es/view/818)

360 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Ahora tenemos un funcionamiento de aplicación CRUD. Bake debe tener todas las configuraciones de las relaciones
que necesitamos, si no es así debemos añadirlas ahora. Hay algunas otras piezas que añadiremos antes de que
podamos agregar los componentes de autenticación y acl. En primer lugar añadir las acciones login(inicio sesión) y
logout(salir sesión) en el controlador UsersController.

Plain Text View (#)


1. function login() {
2. //Autentificación Magica
3. }
4.
5. function logout() {
6. //limpio por ahora.
7. }

No es necesario preocuparse por agregar cualquier hash de contraseñas, debido a que AuthComponent lo hará por
nosotros automáticamente al crear/editar los usuarios, y cuando se inicia sesión, una vez configurado correctamente.
Además, si usted agrega un hash de las contraseñas manualmente AuthComponent no podrá iniciar sesión en absoluto.
Pues los hash no coincidiran.

A continuación tenemos que hacer algunas modificaciones a AppController. Si usted no tiene el controlador
/app/app_controller.php, créelo. Tenga en cuenta que esto va en /app/ y no /app/controllers/. Dado que queremos
que todo el sitio este con el control de autentificación y ACL, vamos a ponerlos en AppController.

Plain Text View (#)


1. class AppController extends Controller {
2. var $components = array('Acl', 'Auth');
3. function beforeFilter() {
4. //Configure AuthComponent
5. $this->Auth->authorize = 'actions';
6. $this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
7. $this->Auth->logoutRedirect = array('controller' => 'users', 'action' => 'login');
8. $this->Auth->loginRedirect = array('controller' => 'posts', 'action' => 'add');
9. }
10. }

Antes de configurar la ACL en todo tendrá que añadir algunos usuarios y grupos. Con AuthComponent en uso no
podremos acceder a ninguna de nuestras acciones, ya que no se ha iniciado sesión. Ahora vamos a añadir algunas
excepciones de manera que AuthComponent nos permitirá crear algunos grupos y usuarios. Por lo tanto en
GroupsController y UsersController añadiremos lo siguiente.

Plain Text View (#)


1. function beforeFilter() {
2. parent::beforeFilter();
3. $this->Auth->allowedActions = array('*');
4. }

Estas declaraciones son para decirle a AuthComponent que permita el acceso del público a todas las acciones. Esto es
sólo temporal y se eliminará una vez que tengamos unos usuarios y grupos en nuestra base de datos. No agregue los
usuarios o grupos, no todavía.

10.2.3 (#Inicializar-las-tablas-Acl-en-la-BD -1546) Inicializar las tablas Acl en la BD

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1546)


Comparar con el texto original (/es/compare/1546/Inicializar-las-tablas-Acl-en-la-BD)

Mas info sobre traduciones (/es/view/818)

Antes de que creemos nuestros users o groups querremos conectarlos con el Acl. Sin embargo, en este punto aun no
tenemos ninguna tabla Acl y si tratamos de ver cualquier página en este momento, obtendremos un error de tabla no
encontrada. Para eliminar estos errores necesitamos ejecutar un archivo de esquema. En una consola ejecuta el

361 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

siguiente codigo: cake schema run create DbAcl. Este esquema te preguntara acerca de eliminar y crear estas tablas.
Acepta la eliminación y creación de éstas tablas.

Recuerda especificar la ruta de tu directorio app si estás fuera de ella.

1. En tu directorio de aplicación app:

$ /path/to/cake/console/cake schema run create DbAcl

2. Fuera de tu directorio de aplicación app:

$ /path/to/cake/console/cake -app /path/to/app/dir schema run create DbAcl

Con los controladores listos para la entrada de datos y con las tablas Acl inicializadas estamos listos para empezar
cierto?... no del todo, aún necesitamos un poco de trabajo en los modelos de users y groups. Llamémoslo, hacerlos
automágicamente ligados a Acl.

10.2.4 (#Act-as-a-Requester-Solicitante-1547) Act as a Requester (Solicitante)

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1547)


Comparar con el texto original (/es/compare/1547/Act-as-a-Requester-Solicitante)

Mas info sobre traduciones (/es/view/818)

Para que Auth y Acl funcionen apropiadamente necesitamos asociar a nuestros modelos users y groups con registros
en las tablas Acl. Para hacer esto usaremos el AclBehavior. El AclBehavior permite la conexión automágica entre los
modelos y las tablas Acl. Su uso requiere la implementación de parentNode() en tu modelo. En nuestro modelo User
agregaremos lo siguiente:

Plain Text View (#)


1. var $name = 'User';
2. var $belongsTo = array('Group');
3. var $actsAs = array('Acl' => array('requester'));
4.
5. function parentNode() {
6. if (!$this->id && empty($this->data)) {
7. return null;
8. }
9. $data = $this->data;
10. if (empty($this->data)) {
11. $data = $this->read();
12. }
13. if (!$data['User']['group_id']) {
14. return null;
15. } else {
16. return array('Group' => array('id' => $data['User']['group_id']));
17. }
18. }

Entonces en nuestro modelo Group agrega lo siguiente:

Plain Text View (#)


1. var $actsAs = array('Acl' => array('requester'));
2.
3. function parentNode() {
4. return null;
5. }

Lo que hace esto es unir los modelos Group y User al Acl, y decirle a CakePHP que cada vez que crees un User o Group
agregues una entrada en la tabla aros. Esto hace la administración de Acl muy fácil ya que tus AROs se ligan
transparentemente a tus tablas de users y groups. De esta forma, cada vez que se crea o elimina un usuario la tabla de

362 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Aro se actualiza.

Nuestros controladores y modelos ahora están preparados para agregar algunos datos iniciales, y nuestros modelos
Group y User estan unidos a la tabla Acl. Ahora agregaremos unos groups y users usando los formularios que
creamos con bake. Yo creé en este caso los siguientes grupos:

administrators
managers
users

Tambien creé un user en cada group de tal forma de tener un user por cada grupo de acceso diferente para probarlos
luego. Escribe todo facil de recordar, sobre todos los passwords. Si haces un SELECT * FROM aros; desde la consola
de mysql obtendrás algo como:

+----+-----------+-------+-------------+-------+------+------+
| id | parent_id | model | foreign_key | alias | lft | rght |
+----+-----------+-------+-------------+-------+------+------+
| 1 | NULL | Group | 1 | NULL | 1 | 4 |
| 2 | NULL | Group | 2 | NULL | 5 | 8 |
| 3 | NULL | Group | 3 | NULL | 9 | 12 |
| 4 | 1 | User | 1 | NULL | 2 | 3 |
| 5 | 2 | User | 2 | NULL | 6 | 7 |
| 6 | 3 | User | 3 | NULL | 10 | 11 |
+----+-----------+-------+-------------+-------+------+------+
6 rows in set (0.00 sec)

Esto nos muestra que tenemos tres groups y 3 users. Los users estan anidados dentro de los grupos., lo que
significa que podemos fijar permisos mediante grupos o por usuarios.

Cuando modificamos un user, debes actualizar manualmente los ARo. Este codigo debería ser ejecutado cada vez que
actualices la información del usuario:

Plain Text View (#)


1. // Verificar si sus permisos de grupo han cambiado
2. $oldgroupid = $this->User->field('group_id');
3. if ($oldgroupid !== $this->data['User']['group_id']) {
4. $aro =& $this->Acl->Aro;
5. $user = $aro->findByForeignKeyAndModel($this->data['User']['id'], 'User');
6. $group = $aro->findByForeignKeyAndModel($this->data['User']['group_id'], 'Group');
7.
8. // Guardar en la tabla ARO
9. $aro->id = $user['Aro']['id'];
10. $aro->save(array('parent_id' => $group['Aro']['id']));
11. }

10.2.5 (#Creando-ACOs-1548) Creando ACOs

Ahora que ya tenemos nuestros users y groups (aros), podemos empezar a ingresar nuestros controladores en el Acl
y fijar los permisos para cada grupo de usuarios, además, habilitar el login y logout.

Nuestros AROs son automaticamente creados cuando nuevos usuarios y grupos son creados. ¿Que hay de
autogenerar los ACOs desde nuestros controladores y sus acciones?. Desafortunadamente no hay una manera mágica
de hacer esto. Las clases del núcleo ofrecen unas pocas formas de crear ACOs manualmente. Se pueden crear ACOs a
través de la consola o usando el AclComponent. Desde la consola esto se ve así:

cake acl create aco root controllers

Mientras que desde el AclComponent se ve asi:

Plain Text View (#)


1. $this->Acl->Aco->create(array('parent_id' => null, 'alias' => 'controllers'));
2. $this->Acl->Aco->save();

Ambos ejemplos crear nuestra 'raiz' (root) o ACO de nivel superior, el cual se llama 'controllers'. El propósito de este

363 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

nodo raiz es hacer fácil permitir/denegar (allow/deny) acceso en el ámbito global de la aplicación y permitir el uso
del Acl para propósitos no relacionados con los controladores/acciones tales como verificar permisos de registro del
modelo. Así como usaremos una raíz global para los ACO necesitaremos hacer una pequeña modificación a la
configuración de nuestro AuthComponent. AuthComponent necesita saber de la existencia de este nodo raíz, de tal forma
que cuando hacemos que ACL lo verifique, pueda usar la ruta correcta al nodo cuando busque un(a)
controlador/accion. En AppController agrega el siguiente código a beforeFilter:

Plain Text View (#)


1. $this->Auth->actionPath = 'controllers/';

10.2.6 (#Una-herramienta-automática-para-crear-ACOs-1549) Una herramienta automática para crear ACOs

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1549)


Comparar con el texto original (/es/compare/1549/Una-herramienta-automática-para-crear-ACOs)

Mas info sobre traduciones (/es/view/818)

Tal como se mencionó anteriormente, no hay una forma pre-construida para insertar y conectar nuestros
controladores y sus funciones dentro del Acl. Sin embargo, todos odiamos hacer tareas repetitivas como tipear lo que
tal vez sean cientos de acciones en una aplicación grande. He escrito una función automática para construir mi tabla
de Aco's. Esta función mirará en cada controlador de la aplicación. Añadirá cualquier metodo no privativo, ni propio
del Controller. Puedes agregar y ejecutar esto en tu AppController o cualquier otro controlador con ese propósito,
solo asegurate de eliminarlo antes de poner la aplicación en producción.

Plain Text View (#)

364 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. /**
2. * Reconstruye el Acl basado en los controladores actuales de la aplicación.
3. *
4. * @return void
5. */
6. function buildAcl() {
7. $log = array();
8.
9. $aco =& $this->Acl->Aco;
10. $root = $aco->node('controllers');
11. if (!$root) {
12. $aco->create(array('parent_id' => null, 'model' => null, 'alias' => 'controllers'));
13. $root = $aco->save();
14. $root['Aco']['id'] = $aco->id;
15. $log[] = 'Creado el nodo Aco para los controladores';
16. } else {
17. $root = $root[0];
18. }
19.
20. App::import('Core', 'File');
21. $Controllers = Configure::listObjects('controller');
22. $appIndex = array_search('App', $Controllers);
23. if ($appIndex !== false ) {
24. unset($Controllers[$appIndex]);
25. }
26. $baseMethods = get_class_methods('Controller');
27. $baseMethods[] = 'buildAcl';
28.
29. // miramos en cada controlador en app/controllers
30. foreach ($Controllers as $ctrlName) {
31. App::import('Controller', $ctrlName);
32. $ctrlclass = $ctrlName . 'Controller';
33. $methods = get_class_methods($ctrlclass);
34.
35. //buscar / crear nodo de controlador
36. $controllerNode = $aco->node('controllers/'.$ctrlName);
37. if (!$controllerNode) {
38. $aco->create(array('parent_id' => $root['Aco']['id'], 'model' => null, 'alias' => $ctrl
39. $controllerNode = $aco->save();
40. $controllerNode['Aco']['id'] = $aco->id;
41. $log[] = 'Creado el nodo Aco del controlador '.$ctrlName;
42. } else {
43. $controllerNode = $controllerNode[0];
44. }
45.
46. //Limpieza de los metodos, para eliminar aquellos en el controlador
47. //y en las acciones privadas
48. foreach ($methods as $k => $method) {
49. if (strpos($method, '_', 0) === 0) {
50. unset($methods[$k]);
51. continue;
52. }
53. if (in_array($method, $baseMethods)) {
54. unset($methods[$k]);
55. continue;
56. }
57. $methodNode = $aco->node('controllers/'.$ctrlName.'/'.$method);
58. if (!$methodNode) {
59. $aco->create(array('parent_id' => $controllerNode['Aco']['id'], 'model' => null, 'a
60. $methodNode = $aco->save();
61. $log[] = 'Creado el nodo Aco para '. $method;

365 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Quizás quieras mantener esta función cerca cuando añadas nuevos ACO's para todos los controladores & acciones
que tiene tu aplicación cada vez que la ejecutes. Sin embargo, no remueve los nodos de las acciones que ya no
existen, esto implica tener que limpiar a mano la tabla ACO. Ahora que todo lo más complejo está hecho, necesitamos
ahora configurar los permisos, y eliminar el código que deshabilitó el AuthComponent anteriormente.

Ahora, que ya está funcionando, quizás notes que tienes problemas accesando cualquier plugin que quizás estabas
ocupando. El truco para automatizar el controlador de ACO's para los plugins, es que necesita un App::import que
siga la convencion de nombre de plugins, que es PluginNombre.PluginControllerNombre.

Entonces lo que necesitamos es una función que nos entregará una lista de los nombres de los controladores de los
plugins, y que los importe en la misma forma que lo hicimos arriba para los controladores normales. La función de
abajo hará exactamente eso:

Plain Text View (#)

366 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. /**
2. * Obtener los nombres de los controladores de plugins
3. *
4. * Esta funcion entrega un arreglo con los nombres de los controladores
5. * de los plugins y además se asegura que los controladores están disponibles
6. * para nosotros, de modo de obtener los nombres de los metodos al hacer un
7. * App:import para cada uno de los plugins.
8. *
9. * @return arreglo con los nombres de los plugins.
10. *
11. */
12. function _get_plugin_controller_names(){
13. App::import('Core', 'File', 'Folder');
14. $paths = Configure::getInstance();
15. $folder =& new Folder();
16. // Cambiamos al directorio de plugins
17. $folder->cd(APP.'plugins');
18. // Obtener la lista de los archivos que terminan con
19. // controller.php
20. $files = $folder->findRecursive('.*_controller\.php');
21. // Obtener la lista de plugins
22. $Plugins = Configure::listObjects('plugin');
23. // Ciclo a través de los controladores que encontramos en el
24. // directorio de plugins
25. foreach($files as $f => $fileName)
26. {
27. // Obtener el nombre de archivo base
28. $file = basename($fileName);
29. // Obtener el nombre del controlador
30. $file = Inflector::camelize(substr($file, 0, strlen($file)-strlen('_controller.php')));
31. // Ciclo a través de los plugins
32. foreach($Plugins as $pluginName){
33. if (preg_match('/^'.$pluginName.'/', $file)){
34. // Primero nos deshacemos del AppController del plugin
35. // Hacemos esto porque nunca lo llamamos directamente
36. if (preg_match('/^'.$pluginName.'App/', $file)){
37. unset($files[$f]);
38. } else {
39. if (!App::import('Controller', $pluginName.'.'.$file))
40. {
41. debug('Error importando el archivo '.$file.' para el plugin '.$
42. }
43. // Ahora le agregamos el nombre del plugin al inicio
44. // Esto lo necesitamos para poder obtener los nombres
45. // de los métodos
46. $files[$f] = $file;
47. }
48. break;
49. }
50. }
51. }
52. return $files;
53. }

Tu puedes modificar el código original para incluir los controladores de plugins al mezclarlos con la lista que
obtuviste (ubicarlo antes del ciclo foreach):

Plain Text View (#)


1. $Plugins = $this->_get_plugin_controller_names();
2. $Controllers = array_merge($Controllers, $Plugins);

367 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

10.2.7 (#Configurando-los-permisos-1550) Configurando los permisos

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1550)


Comparar con el texto original (/es/compare/1550/Configurando-los-permisos)

Mas info sobre traduciones (/es/view/818)

Crear los permisos al igual que crear los ACO's no tiene una solucion mágica, en este caso no proveeremos una forma
automática. Para permitir a los ARO's acceder a los ACO's desde la consola, usamos:

cake acl grant $aroAlias $acoAlias [create|read|update|delete|'*']

* Necesita estar entre comillas simples ('*')

Para permitir acceso a través del AclComponent haz lo siguiente:

Plain Text View (#)


1. $this->Acl->allow($aroAlias, $acoAlias);

Ahora añadiremos algunas sentencias para permitir y denegar el acceso. Agrega lo siguiente a tu función temporal en
tu UsersController e ingresa a la dirección adecuada en tu navegador para ejecutarla. Si haces un SELECT * FROM
aros_acos deberías ver toda un montón de unos y ceros. Una vez que hayas confirmado los permisos, elimina la
función.

Plain Text View (#)


1. function initDB() {
2. $group =& $this->User->Group;
3. //Permite a los administradores hacer todo
4. $group->id = 1;
5. $this->Acl->allow($group, 'controllers');
6. //permite a los editores postear y accesar los widgets
7. $group->id = 2;
8. $this->Acl->deny($group, 'controllers');
9. $this->Acl->allow($group, 'controllers/Posts');
10. $this->Acl->allow($group, 'controllers/Widgets');
11.
12. //permite a los usuarios añadir y editar posts y widgets
13. $group->id = 3;
14. $this->Acl->deny($group, 'controllers');
15. $this->Acl->allow($group, 'controllers/Posts/add');
16. $this->Acl->allow($group, 'controllers/Posts/edit');
17. $this->Acl->allow($group, 'controllers/Widgets/add');
18. $this->Acl->allow($group, 'controllers/Widgets/edit');
19. }

Ahora hemos seteado algunas reglas básicas de acceso. Hemos permitido a los administradores accesar a todas las
funciones. Los editores pueden accesar a todas las funcionalidades de los posts y los widgets. En cambio los
usuarios solo pueden accesar aquellas funciones que permiten agregar y editar posts y widgets.

Debemos obtener una referencia del modelo Group y modificar su id para poder especificar el ARO que queremos, esto
es debido a la forma en que trabaja el AclBehavior. El AclBehavior no configura el campo alias en la tabla aros, por lo
que debemos usar una referencia a un objeto ARO que necesitemos.

Quizás hayas notado que deliberadamente deje fuera index y view fuera de mis permisos ACL. Haremos que los
metodos index y view sean de acceso público en el controlador PostsController y en el WidgetsController. Esto
permite a los usuarios no autorizados para ver estas paginas, haciendolas públicas. Sin embargo, en cualquier
momento puedes eliminar estas acciones desde AuthComponent::allowedActions y los permisos de estas dos
funciones volverán a su configuración original del Acl.

Ahora queremos eliminar las referencias al Auth->allowedActions en los controladores de users y groups. Entonces
agregamos el siguiente código en los controladores de posts y widgets:

368 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Plain Text View (#)


1. function beforeFilter() {
2. parent::beforeFilter();
3. $this->Auth->allowedActions = array('index', 'view');
4. }

Esto elimina el "interruptor de apagado" que colocamos anteriormente el los controladores de groups y users, y
otorga acceso público a las acciones index y view en aquellos controladores. En AppController::beforeFilter()
agrega lo siguiente:

Plain Text View (#)


1. $this->Auth->allowedActions = array('display');

Esto hace que la acción 'display' sea pública. Esto mantendrá publica nuestra acción PagesController::display(). Esto
es importante pues a menudo ésta es la accion accesada por defecto del routing de la aplicación.

10.2.8 (#Logueo-de-Usuarios-1551) Logueo de Usuarios

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1551)


Comparar con el texto original (/es/compare/1551/Logueo-de-Usuarios)

Mas info sobre traduciones (/es/view/818)

Nuestra aplicación ya esta bajo control de acceso, y cualquier intento de ver alguna página sin acceso público será
redirigida a la página de login. Sin embargo, necesitamos crear una vista de login antes de que alguien pueda
loguerase. Agrega el siguiente código a app/views/users/login.ctp si es que aún no lo has hecho.

Plain Text View (#)


1. <h2>Login</h2>
2. <?php
3. echo $form->create('User', array('url' => array('controller' => 'users', 'action' =>'login')));
4. echo $form->input('User.username');
5. echo $form->input('User.password');
6. echo $form->end('Login');
7. ?>

Tal vez quieras agregar un flash() para los mensajes del componente Auth en tu layout. Copia el layout por defecto
que se encuentra en cake/libs/views/layouts/default.ctp - a la carpeta de layouts de tu aplicación si es que aún no
lo has hecho. En app/views/layouts/default.ctp agrega:

Plain Text View (#)


1. $session->flash('auth');

Ahora deberias poder loguerte y todo deberá funcionar automágicamente. Cuando el acceso sea denegado el mensaje
apropiado del Auth será desplegado si es que has agragado $session->flash('auth')

10.2.9 (#Logout-deslogueo-1552) Logout (deslogueo)

Ahora al logout. Hace un momento dejamos esta función en blanco, ahora es el momento de llenarla. En
UsersController::logout() añade lo siguiente:

Plain Text View (#)


1. $this->Session->setFlash('Adios y nos vemos.');
2. $this->redirect($this->Auth->logout());

Esto establece el mensaje flash y saca al usuario de la aplicación usando el método logout del componente Auth. Este
método basicamente elimina la llave de la sesión del usuario y devuelve la url que puede ser usada en el
redireccionamiento. Si es que hay otros datos en la sesión que necesiten ser eliminados se debe agregar ese código
acá.

369 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

10.2.10 (#Todo-hecho-1553) Todo hecho

En este momento ya deberías tener una aplicación controlada por los componentes Auth y Acl. Los permisos de
usuarios se hicieron al nivel de grupo, pero pueden ser configurados a nivel de usuarios en cualquier momento.
También puedes configurar los permisos a nivel global y también por controladores y acciones. Además, tienes a tu
disposición un código reusable para facilmente expandir tu tabla de ACO a medida que tu aplicación crece.

11 (#Apendices-1554) Apendices

El texto original ha cambiado despues que la traduccion. Por favor ayundanos a reslover este differencia. Puedes:

Ver que ha cambiado (/es/nodes/redirect_to_revision/1554)


Comparar con el texto original (/es/compare/1554/Apendices)

Mas info sobre traduciones (/es/view/818)

Notas adicionales sobre el desarrollo con CakePHP

11.1 (#Migrando-desde-CakePHP-1-2-a-1-3-1561) Migrando desde CakePHP 1.2 a 1.3

Esta guía resume muchos de los cambios necesarios al migrar desde CakePHP 1.2 al 1.3. Cada sección contiene
información relevante acerca de las modificaciones hechas a los métodos existentes así como los métodos que han
sido eliminados/renombrados.

Reemplazos de archivos de aplicación (importante)

webroot/index.php: Debe ser reemplazado debido a cambios en el proceso de bootstrapping .


config/core.php: Han sido añadidas configuraciones adicionales requeridas por PHP 5.3.
webroot/test.php: Reemplace este archivo si desea correr pruebas unitarias (unit tests ).

# (#Removed-Constants-1562) Removed Constants

Las siguientes constantes han sido eliminadas de CakePHP. Si su aplicación depende de una de ellas, debe definirla
previamente en app/config/bootstrap.php

CIPHER_SEED - Reemplazada por la variable de la clase Configure Security.cipherSeed que debe ser cambiada
en app/config/core.php
PEAR
INFLECTIONS
VALID_NOT_EMPTY
VALID_EMAIL
VALID_NUMBER
VALID_YEAR

# (#Configuration-and-application-bootstrapping-1568) Configuration and application bootstrapping

Bootstrapping Additional Paths.

In your app/config/bootstrap.php you may have variables like $pluginPaths or $controllerPaths.


There is a new way to add those paths. As of 1.3 RC1 the $pluginPaths variables will no longer work. You must use
App::build() to modify paths.

Plain Text View (#)

370 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. App::build(array(
2. 'plugins' => array('/full/path/to/plugins/', '/next/full/path/to/plugins/'),
3. 'models' => array('/full/path/to/models/', '/next/full/path/to/models/'),
4. 'views' => array('/full/path/to/views/', '/next/full/path/to/views/'),
5. 'controllers' => array('/full/path/to/controllers/', '/next/full/path/to/controllers/'),
6. 'datasources' => array('/full/path/to/datasources/', '/next/full/path/to/datasources/'),
7. 'behaviors' => array('/full/path/to/behaviors/', '/next/full/path/to/behaviors/'),
8. 'components' => array('/full/path/to/components/', '/next/full/path/to/components/'),
9. 'helpers' => array('/full/path/to/helpers/', '/next/full/path/to/helpers/'),
10. 'vendors' => array('/full/path/to/vendors/', '/next/full/path/to/vendors/'),
11. 'shells' => array('/full/path/to/shells/', '/next/full/path/to/shells/'),
12. 'locales' => array('/full/path/to/locale/', '/next/full/path/to/locale/')
13. ));

Also changed is the order in which bootstrapping occurs. In the past app/config/core.php was loaded after
app/config/bootstrap.php. This caused any App::import() in an application bootstrap to be un-cached and
considerably slower than a cached include. In 1.3 core.php is loaded and the core cache configs are created before
bootstrap.php is loaded.

Loading custom inflections

inflections.php ha sido removido, se trataba de un archivo innecesario, y las características relacionadas fueron
reprogramadas en un método para incrementar su flexibilidad. Ahora utilice Inflector::rules() para cargar las
inflexiones personalizadas.

Plain Text View (#)


1. Inflector::rules('singular', array(
2. 'rules' => array('/^(bil)er$/i' => '\1', '/^(inflec|contribu)tors$/i' => '\1ta'),
3. 'uninflected' => array('singulars'),
4. 'irregular' => array('spins' => 'spinor')
5. ));

Will merge the supplied rules into the infection sets, with the added rules taking precedence over the core rules.

# (#File-renames-and-internal-changes-1563) File renames and internal changes

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1563/File-renames-and-internal-
changes) .. Mas info sobre traduciones (/es/view/818)

Library Renames

Core libraries of libs/session.php, libs/socket.php, libs/model/schema.php and libs/model/behavior.php have been


renamed so that there is a better mapping between filenames and main classes contained within (as well as dealing
with some name-spacing issues):

session.php ⇒ cake_session.php

App::import('Core', 'Session') ⇒ App::import('Core', 'CakeSession')

socket.php ⇒ cake_socket.php

App::import('Core', 'Socket') ⇒ App::import('Core', 'CakeSocket')

schema.php ⇒ cake_schema.php

App::import('Model', 'Schema') ⇒ App::import('Model', 'CakeSchema')

behavior.php ⇒ model_behavior.php

App::import('Core', 'Behavior') ⇒ App::import('Core', 'ModelBehavior')

In most cases, the above renaming will not affect userland code.

Inheritance from Object

371 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

The following classes no longer extend Object:

Router
Set
Inflector
Cache
CacheEngine

If you were using Object methods from these classes, you will need to not use those methods.

11.1.1 (#Controller-Components-1564) Controller & Components

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1564/Controller-Components) ..
Mas info sobre traduciones (/es/view/818)

Controller

Controller::set() no longer changes variables from $var_name to $varName. Variables always appear in the
view exactly as you set them.

Controller::set('title', $var) no longer sets $title_for_layout when rendering the layout.


$title_for_layout is still populated by default. But if you want to customize it, use
$this->set('title_for_layout', $var).

Controller::$pageTitle has been removed. Use $this->set('title_for_layout', $var); instead.

Controller has two new methods startupProcess and shutdownProcess. These methods are responsible for
handling the controller startup and shutdown processes.

Component

Component::triggerCallback has been added. It is a generic hook into the component callback process. It
supplants Component::startup(), Component::shutdown() and Component::beforeRender() as the preferred way
to trigger callbacks.

CookieComponent

del is deprecated use delete

AclComponent + DbAcl

Node reference checks done with paths are now less greedy and will no longer consume intermediary nodes when
doing searches. In the past given the structure:

Plain Text View (#)


1. ROOT/
2. Users/
3. Users/
4. edit

The path ROOT/Users would match the last Users node instead of the first. In 1.3, if you were expecting to get the last
node you would need to use the path ROOT/Users/Users

RequestHandlerComponent

getReferrer is deprecated use getReferer

SessionComponent & SessionHelper

del is deprecated use delete

SessionComponent::setFlash() second param used to be used for setting the layout and accordingly rendered a layout
file. This has been modifed to use an element. If you specified custom session flash layouts in your applications you
will need to make the following changes.

1. Move the required layout files into app/views/elements


2. Rename the $content_for_layout variable to $message

372 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

3. Make sure you have echo $session->flash(); in your layout

SessionComponent and SessionHelper are not automatically loaded.

Both SessionComponent and SessionHelper are no longer automatically included without you asking for them.
SessionHelper and SessionComponent now act like every other component and must be declared like any other
helper/component. You should update AppController::$components and AppController::$helpers to include these
classes to retain existing behavior.

Plain Text View (#)


1. var $components = array('Session', 'Auth', ...);
2. var $helpers = array('Session', 'Html', 'Form' ...);

These change were done to make CakePHP more explicit and declarative in what classes you the application developer
want to use. In the past there was no way to avoid loading the Session classes without modifying core files. Which is
something we want you to be able to avoid. In addition Session classes were the only magical component and helper.
This change helps unify and normalize behavior amongst all classes.

# (#Library-Classes-1565) Library Classes

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1565/Library-Classes) .. Mas
info sobre traduciones (/es/view/818)

CakeSession

del is deprecated use delete

SessionComponent

SessionComponent::setFlash() now uses an element instead of a layout as its second parameter. Be sure to
move any flash layouts from app/views/layouts to app/views/elements and change instances of
$content_for_layout to $message.

Folder

mkdir is deprecated use create


mv is deprecated use move
ls is deprecated use read
cp is deprecated use copy
rm is deprecated use delete

Set

isEqual is deprecated. Use == or ===.

String

getInstance is deprecated, call String methods statically.

Router

Routing.admin is deprecated. It provided an inconsistent behavior with other prefix style routes in that it was treated
differently. Instead you should use Routing.prefixes. Prefix routes in 1.3 do not require additional routes to be
declared manually. All prefix routes will be generated automatically. To update simply change your core.php.

Plain Text View (#)


1. //from:
2. Configure::write('Routing.admin', 'admin');
3. //to:
4. Configure::write('Routing.prefixes', array('admin'));

See the New features guide for more information on using prefix routes. A small change has also been done to
routing params. Routed params should now only consist of alphanumeric chars, - and _ or /[A-Z0-9-_+]+/.

Plain Text View (#)

373 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. Router::connect('/:$%@#param/:action/*', array(...)); // BAD


2. Router::connect('/:can/:anybody/:see/:m-3/*', array(...)); //Acceptable

For 1.3 the internals of the Router were heavily refactored to increase performance and reduce code clutter. The side
effect of this is two seldom used features were removed, as they were problematic and buggy even with the existing
code base. First path segments using full regular expressions was removed. You can no longer create routes like

Plain Text View (#)


1. Router::connect('/([0-9]+)-p-(.*)/', array('controller' => 'products', 'action' => 'show'));

These routes complicated route compilation and impossible to reverse route. If you need routes like this, it is
recommended that you use route parameters with capture patterns. Next mid-route greedy star support has been
removed. It was previously possible to use a greedy star in the middle of a route.

Plain Text View (#)


1. Router::connect(
2. '/pages/*/:event',
3. array('controller' => 'pages', 'action' => 'display'),
4. array('event' => '[a-z0-9_-]+')
5. );

This is no longer supported as mid-route greedy stars behaved erratically, and complicated route compiling. Outside
of these two edge-case features and the above changes the router behaves exactly as it did in 1.2

Also, people using the 'id' key in array-form URLs will notice that Router::url() now treats this as a named parameter. If
you previously used this approach for passing the ID parameter to actions, you will need to rewrite all your
$html->link() and $this->redirect() calls to reflect this change.

Plain Text View (#)


1. // old format:
2. $url = array('controller' => 'posts', 'action' => 'view', 'id' => $id);
3. // use cases:
4. Router::url($url);
5. $html->link($url);
6. $this->redirect($url);
7. // 1.2 result:
8. /posts/view/123
9. // 1.3 result:
10. /posts/view/id:123
11. // correct format:
12. $url = array('controller' => 'posts', 'action' => 'view', $id);

Dispatcher

Dispatcher is no longer capable of setting a controller's layout/viewPath with request parameters. Control of these
properties should be handled by the Controller, not the Dispatcher. This feature was also undocumented, and
untested.

Debugger

Debugger::checkSessionKey() has been renamed to Debugger::checkSecurityKeys()


Calling Debugger::output("text") no longer works. Use Debugger::output("txt").

Object

Object::$_log has been removed. CakeLog::write is now called statically. See New Logging features (/view
/1194/Logging) for more information on changes made to logging.

Sanitize

Sanitize::html() now actually always returns escaped strings. In the past using the $remove parameter would
skip entity encoding, returning possibly dangerous content.
Sanitize::clean() now has a remove_html option. This will trigger the strip_tags feature of Sanitize::html(),
and must be used in conjunction with the encode parameter.

374 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Configure and App

Configure::listObjects() replaced by App::objects()


Configure::corePaths() replaced by App::core()
Configure::buildPaths() replaced by App::build()
Configure no longer manages paths.
Configure::write('modelPaths', array...) replaced by App::build(array('models' => array...))
Configure::read('modelPaths') replaced by App::path('models')
There is no longer a debug = 3. The controller dumps generated by this setting often caused memory
consumption issues making it an impractical and unusable setting. The $cakeDebug variable has also been
removed from View::renderLayout You should remove this variable reference to avoid errors.
Configure::load() can now load configuration files from plugins. Use Configure::load('plugin.file'); to
load configuration files from plugins. Any configuration files in your application that use . in the name should
be updated to use _

Cache

In addition to being able to load CacheEngines from app/libs or plugins, Cache underwent some refactoring for
CakePHP1.3. These refactorings focused around reducing the number and frequency of method calls. The end result
was a significant performance improvement with only a few minor API changes which are detailed below.

The changes in Cache removed the singletons used for each Engine type, and instead an engine instance is made for
each unique key created with Cache::config(). Since engines are not singletons anymore, Cache::engine() was not
needed and was removed. In addition Cache::isInitialized() now checks cache configuration names , not cache
engine names . You can still use Cache::set() or Cache::engine() to modify cache configurations. Also checkout the
New features guide (/es/view/1572/New-features-in-CakePHP-1-3) for more information on the additional methods
added to Cache.

It should be noted that using an app/libs or plugin cache engine for the default cache config can cause performance
issues as the import that loads these classes will always be uncached. It is recommended that you either use one of
the core cache engines for your default configuration, or manually include the cache engine class before configuring
it. Furthermore any non-core cache engine configurations should be done in app/config/bootstrap.php for the same
reasons detailed above.

11.1.2 (#Model-Databases-and-Datasources-1567) Model Databases and Datasources

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1567/Model-Databases-
and-Datasources) .. Mas info sobre traduciones (/es/view/818)

Model

Model::del() and Model::remove() have been removed in favor of Model::delete(), which is now the canonical
delete method.
Model::findAll, findCount, findNeighbours, removed.
Dynamic calling of setTablePrefix() has been removed. tableprefix should be with the $tablePrefix property,
and any other custom construction behavior should be done in an overridden Model::__construct().
DboSource::query() now throws warnings for un-handled model methods, instead of trying to run them as
queries. This means, people starting transactions improperly via the $this->Model->begin() syntax will need to
update their code so that it accesses the model's DataSource object directly.
Missing validation methods will now trigger errors in development mode.
Missing behaviors will now trigger a cakeError.
Model::find(first) will no longer use the id property for default conditions if no conditions are supplied and
id is not empty. Instead no conditions will be used
For Model::saveAll() the default value for option 'validate' is now 'first' instead of true

Datasources

DataSource::exists() has been refactored to be more consistent with non-database backed datasources.
Previously, if you set var $useTable = false; var $useDbConfig = 'custom';, it was impossible for
Model::exists() to return anything but false. This prevented custom datasources from using create() or
update() correctly without some ugly hacks. If you have custom datasources that implement create(), update(),
and read() (since Model::exists() will make a call to Model::find('count'), which is passed to
DataSource::read()), make sure to re-run your unit tests on 1.3.

Databases

375 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Most database configurations no longer support the 'connect' key (which has been deprecated since pre-1.2). Instead,
set 'persistent' => true or false to determine whether or not a persistent database connection should be used

SQL log dumping

A commonly asked question is how can one disable or remove the SQL log dump at the bottom of the page?. In
previous versions the HTML SQL log generation was buried inside DboSource. For 1.3 there is a new core element
called sql_dump. DboSource no longer automatically outputs SQL logs. If you want to output SQL logs in 1.3, do the
following:

Plain Text View (#)


1. <?php echo $this->element('sql_dump'); ?>

You can place this element anywhere in your layout or view. The sql_dump element will only generate output when
Configure::read('debug') is equal to 2. You can of course customize or override this element in your app by creating
app/views/elements/sql_dump.ctp.

# (#View-and-Helpers-1566) View and Helpers

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1566/View-and-Helpers) .. Mas
info sobre traduciones (/es/view/818)

View

View::renderElement removed. Use View::element() instead.


Automagic support for .thtml view file extension has been removed either declare $this->ext = 'thtml'; in
your controllers, or rename your views to use .ctp
View::set('title', $var) no longer sets $title_for_layout when rendering the layout. $title_for_layout is
still populated by default. But if you want to customize it, use $this->set('title_for_layout', $var).
View::$pageTitle has been removed. Use $this->set('title_for_layout', $var); instead.
The $cakeDebug layout variable associated with debug = 3 has been removed. Remove it from your layouts as it
will cause errors. Also see the notes related to SQL log dumping and Configure for more information.

All core helpers no longer use Helper::output(). The method was inconsistently used and caused output issues with
many of FormHelper's methods. If you previously overrode AppHelper::output() to force helpers to auto-echo you
will need to update your view files to manually echo helper output.

TextHelper

TextHelper::trim() is deprecated, used truncate() instead.


TextHelper::highlight() no longer has:
an $highlighter parameter. Use $options['format'] instead.
an $considerHtmlparameter. Use $options['html'] instead.
TextHelper::truncate() no longer has:
an $ending parameter. Use $options['ending'] instead.
an $exact parameter. Use $options['exact'] instead.
an $considerHtmlparameter. Use $options['html'] instead.

PaginatorHelper

PaginatorHelper has had a number of enhancements applied to make styling easier.


prev(), next(), first() and last()

The disabled state of these methods now defaults to <span> tags instead of <div> tags.

passedArgs are now auto merged with url options in paginator.

sort(), prev(), next() now add additional class names to the generated html. prev() adds a class of prev. next()
adds a class of next. sort() will add the direction currently being sorted, either asc or desc.

FormHelper

FormHelper::dateTime() no longer has a $showEmpty parameter. Use $attributes['empty'] instead.


FormHelper::year() no longer has a $showEmpty parameter. Use $attributes['empty'] instead.
FormHelper::month() no longer has a $showEmpty parameter. Use $attributes['empty'] instead.

376 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

FormHelper::day() no longer has a $showEmpty parameter. Use $attributes['empty'] instead.


FormHelper::minute() no longer has a $showEmpty parameter. Use $attributes['empty'] instead.
FormHelper::meridian() no longer has a $showEmpty parameter. Use $attributes['empty'] instead.
FormHelper::select() no longer has a $showEmpty parameter. Use $attributes['empty'] instead.
Default urls generated by form helper no longer contain 'id' parameter. This makes default urls more consistent
with documented userland routes. Also enables reverse routing to work in a more intuitive fashion with default
FormHelper urls.
FormHelper::submit() Can now create other types of inputs other than type=submit. Use the type option to
control the type of input generated.
FormHelper::button() Now creates <button> elements instead of reset or clear inputs. If you want to generate
those types of inputs use FormHelper::submit() with a 'type' => 'reset' option for example.
FormHelper::secure() and FormHelper::create() no longer create hidden fieldset elements. Instead they create
hidden div elements. This improves validation with HTML4.

Also be sure to check the Form helper improvements (/view/1616/x1-3-improvements) for additional changes and new
features in the FormHelper.

HtmlHelper

HtmlHelper::meta() no longer has an $inline parameter. It has been merged with the $options array.
HtmlHelper::link() no longer has an $escapeTitle parameter. Use $options['escape'] instead.
HtmlHelper::para() no longer has an $escape parameter. Use $options['escape'] instead.
HtmlHelper::div() no longer has an $escape parameter. Use $options['escape'] instead.
HtmlHelper::tag() no longer has an $escape parameter. Use $options['escape'] instead.
HtmlHelper::css() no longer has an $inline parameter. Use $options['inline'] instead.

SessionHelper

flash() no longer auto echos. You must add an echo $session->flash(); to your session->flash() calls. flash()
was the only helper method that auto outputted, and was changed to create consistency in helper methods.

CacheHelper

CacheHelper's interactions with Controller::$cacheAction has changed slightly. In the past if you used an array for
$cacheAction you were required to use the routed url as the keys, this caused caching to break whenever routes were
changed. You also could set different cache durations for different passed argument values, but not different named
parameters or query string parameters. Both of these limitations/inconsistencies have been removed. You now use the
controller's action names as the keys for $cacheAction. This makes configuring $cacheAction easier as its no longer
coupled to the routing, and allows cacheAction to work with all custom routing. If you need to have custom cache
durations for specific argument sets you will need to detect and update cacheAction in your controller.

TimeHelper

TimeHelper has been refactored to make it more i18n friendly. Internally almost all calls to date() have been replaced
by strftime(). The new method TimeHelper::i18nFormat() has been added and will take localization data from a LC_TIME
locale definition file in app/locale following the POSIX standard. These are the changes made in the TimeHelper API:

TimeHelper::format() can now take a time string as first parameter and a format string as the second one, the
format must be using the strftime() style. When called with this parameter order it will try to automatically
convert the date format into the preferred one for the current locale. It will also take parameters as in 1.2.x
version to be backwards compatible, but in this case format string must be compatible with date().
TimeHelper::i18nFormat() has been added

Deprecated Helpers

Both the JavascriptHelper and the AjaxHelper are deprecated, and the JsHelper + HtmlHelper should be used in their
place.

You should replace

$javascript->link() with $html->script()


$javascript->codeBlock() with $html->scriptBlock() or $html->scriptStart() and $html->scriptEnd()
depending on your usage.

# (#Console-and-shells-1570) Console and shells

377 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1570/Console-and-shells) .. Mas
info sobre traduciones (/es/view/818)

Shell

Shell::getAdmin() has been moved up to ProjectTask::getAdmin()

Schema shell

cake schema run create has been renamed to cake schema create
cake schema run update has been renamed to cake schema update

Console Error Handling

The shell dispatcher has been modified to exit with a 1 status code if the method called on the shell explicitly returns
false. Returning anything else results in a 0 status code. Before the value returned from the method was used directly
as the status code for exiting the shell.

Shell methods which are returning 1 to indicate an error should be updated to return false instead.

Shell::error() has been modified to exit with status code 1 after printing the error message which now uses a
slightly different formatting.

Plain Text View (#)


1. $this->error('Invalid Foo', 'Please provide bar.');
2. // outputs:
3. Error: Invalid Foo
4. Please provide bar.
5. // exits with status code 1

ShellDispatcher::stderr() has been modified to not prepend Error: to the message anymore. It's signature is now
similar to Shell::stdout().

ShellDispatcher::shiftArgs()

The method has been modified to return the shifted argument. Before if no arguments were available the method was
returning false, it now returns null. Before if arguments were available the method was returning true, it now returns
the shifted argument instead.

11.1.3 (#Vendors-Test-Suite-schema-1571) Vendors, Test Suite & schema

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1571/Vendors-Test-Suite-
schema) .. Mas info sobre traduciones (/es/view/818)

vendors/css, vendors/js, and vendors/img

Support for these three directories, both in app/vendors as well as plugin/vendors has been removed. They have been
replaced with plugin and theme webroot directories.

Test Suite and Unit Tests

Group tests should now extend TestSuite instead of the deprecated GroupTest class. If your Group tests do not run,
you will need to update the base class.

Vendor, plugin and theme assets

Vendor asset serving has been removed in 1.3 in favour of plugin and theme webroot directories.

Schema files used with the SchemaShell have been moved to app/config/schema instead of app/config/sql Although
config/sql will continue to work in 1.3, it will not in future versions, it is recommend that the new path is used.

11.2 (#Nuevas-características-en-CakePHP-1-3-1572) Nuevas características en CakePHP 1.3

CakePHP 1.3 introdujo varias características nuevas. Esta guía intenta resumir los cambios y vincular a la
documentación expandida donde sea necesario.

# (#Componentes-1573) Componentes

378 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

SecurityComponent

Los métodos requireXX como requireGet y requirePost ahora aceptan un único array como argumento además de una
colección de cadenas de texto.

Plain Text View (#)


1. $this->Security->requirePost(array('edit', 'update'));

Configuración de componentes

La configuración para todos los componentes del núcleo puede ser definida desde el array $components. De la misma
forma que los comportamientos, se pueden declarar parametros de configuración cuando se declara el componente.

Plain Text View (#)


1. var $components = array(
2. 'Cookie' => array(
3. 'name' => 'MyCookie'
4. ),
5. 'Auth' => array(
6. 'userModel' => 'MyUser',
7. 'loginAction' => array('controller' => 'users', 'action' => 'login')
8. )
9. );

Esto debería reducir la cantidad de código en los métodos beforeFilter().

EmailComponent

Ahora se puede obtener el contenido del correo electrónico creado, leyendo $this->Email->htmlMessage y
$this->Email->textMessage. Estas propiedades almacenan el contenido en html y en texto plano
respectivamente.
Muchos de los métodos privados (private) del EmailComponent's ahora son protegidos (protected) para
facilitar la extensión de los mismos.
EmailComponent::$to ahora también puede ser un array, facilitando la configuración de múltiples destinatarios,
y mejorando la consistencia con otras propiedades.
EmailComponent::$messageId ha sido añadida, y permite controlar el encabezado Message-ID del correo
electrónico.

# (#View-Helpers-1574) View & Helpers

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1574/View-Helpers) .. Mas info
sobre traduciones (/es/view/818)

Helpers can now be addressed at $this->Helper->func() in addition to $helper->func(). This allows view variables
and helpers to share names and not create collisions.

New JsHelper and new features in HtmlHelper

See JsHelper documentation (http://book.cakephp.org/view/1592/Js) for more information

Pagination Helper

Pagination helper provides additional css classes for styling and you can set the default sort() direction.
PaginatorHelper::next() and PaginatorHelper::prev() now generate span tags by default, instead of divs.

Helper

Helper::assetTimestamp() has been added. It will add timestamps to any asset under WWW_ROOT. It works with
Configure::read('Asset.timestamp'); just as before, but the functionality used in Html and Javascript helpers has
been made available to all helpers. Assuming Asset.timestamp == force

Plain Text View (#)

379 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. $path = 'css/cake.generic.css'
2. $stamped = $this->Html->assetTimestamp($path);
3. //$stamped contains 'css/cake.generic.css?5632934892'

The appended timestamp contains the last modification time of the file. Since this method is defined in Helper it is
available to all subclasses.

TextHelper

highlight() now accepts an array of words to highlight.

NumberHelper

A new method addFormat() has been added. This method allows you to set currency parameter sets, so you don't have
to retype them.

Plain Text View (#)


1. $this->Number->addFormat('NOK', array('before' => 'Kr. '));
2. $formatted = $this->Number->currency(1000, 'NOK');

FormHelper

The form helper has had a number of improvements and API modifications, see Form Helper improvements
(http://book.cakephp.org/view/1616/x1-3-improvements) for more information.

11.2.1 (#Logging-1575) Logging

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1575/Logging) .. Mas info sobre
traduciones (/es/view/818)

Logging and CakeLog have been enhanced considerably, both in features and flexibility. See New Logging features
(/view/1194/Logging) for more information.

# (#Caching-1580) Caching

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1580/Caching) .. Mas info sobre
traduciones (/es/view/818)

Cache engines have been made more flexible in 1.3. You can now provide custom Cache adapters in app/libs as well
as in plugins using $plugin/libs. App/plugin cache engines can also override the core engines. Cache adapters must
be in a cache directory. If you had a cache engine named MyCustomCacheEngine it would be placed in either app/libs
/cache/my_custom_cache.php as an app/libs. Or in $plugin/libs/cache/my_custom_cache.php as part of a plugin. Cache
configs from plugins need to use the plugin dot syntax.

Plain Text View (#)


1. Cache::config('custom', array(
2. 'engine' => 'CachePack.MyCustomCacheEngine',
3. ...
4. ));

New Cache methods

Cache has a few new methods for 1.3 which make introspection and testing teardown easier.

Cache::configured() returns an array of configured Cache engine keys.


Cache::drop($config) drops a configured Cache engine. Once dropped cache engines are no longer readable
or writeable.
Cache::increment() Perform an atomic increment on a numeric value. This is not implemented in FileEngine.
Cache::decrement() Perform an atomic decrement on a numeric value. This is not implemented in FileEngine.

# (#Models-Behaviors-and-Datasource-1576) Models, Behaviors and Datasource

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1576/Models-Behaviors-
and-Datasource) .. Mas info sobre traduciones (/es/view/818)

380 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

App::import(), datasources & datasources from plugins

Datasources can now be included loaded with App::import() and be included in plugins! To include a datasource in
your plugin you put it in my_plugin/models/datasources/your_datasource.php. To import a Datasource from a plugin
use App::import('Datasouce', 'MyPlugin.YourDatasource');

Using plugin datasources in your database.php

You can use plugin datasources by setting the datasource key with the plugin name. For example if you had a
WebservicePack plugin with a LastFm datasource (plugin/webservice_pack/models/datasources/last_fm.php), you
could do:

Plain Text View (#)


1. var $lastFm = array(
2. 'datasource' => 'WebservicePack.LastFm'
3. ...

Model

Missing Validation methods now trigger errors, making debugging why validation isn't working easier.
Models now support virtual fields (/view/1608/Virtual-fields)

Behaviors

Using behaviors that do not exist, now triggers a cakeError making missing behaviors easier to find and fix.

CakeSchema

CakeSchema can now locate, read and write schema files to plugins. The SchemaShell also exposes this functionality,
see below for changes to SchemaShell. CakeSchema also supports tableParameters. Table Parameters are non column
specific table information such as collation, charset, comments, and table engine type. Each Dbo implements the
tableParameters they support.

tableParameters in MySQL

MySQL supports the greatest number of tableParameters; You can use tableParameters to set a variety of MySQL
specific settings.

engine Control the storage engine used for your tables.


charset Control the character set used for tables.
encoding Control the encoding used for tables.

In addition to tableParameters MySQL dbo's implement fieldParameters. fieldParameters allow you to control MySQL
specific settings per column.

charset Set the character set used for a column


encoding Set the encoding used for a column

See below for examples on how to use table and field parameters in your schema files.

tableParameters in Postgres

....

tableParameters in SQLite

....

Using tableParameters in schema files

You use tableParameters just as you would any other key in a schema file. Much like indexes:

Plain Text View (#)

381 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

1. var $comments => array(


2. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'),
3. 'post_id' => array('type' => 'integer', 'null' => false, 'default' => 0),
4. 'comment' => array('type' => 'text'),
5. 'indexes' => array(
6. 'PRIMARY' => array('column' => 'id', 'unique' => true),
7. 'post_id' => array('column' => 'post_id'),
8. ),
9. 'tableParameters' => array(
10. 'engine' => 'InnoDB',
11. 'charset' => 'latin1',
12. 'collate' => 'latin1_general_ci'
13. )
14. );

is an example of a table using tableParameters to set some database specific settings. If you use a schema file that
contains options and features your database does not implement, those options will be ignored. For example if you
imported the above schema to a PostgreSQL server, all of the tableParameters would be ignore as PostgreSQL does not
support any of the included options.

# (#Console-1577) Console

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1577/Console) .. Mas info sobre
traduciones (/es/view/818)

Bake

Bake has had a number of significant changes made to it. Those changes are detailed in the bake updates section
(/view/1611/Bake-improvements-in-1-3)

Subclassing

The ShellDispatcher has been modified to not require shells and tasks to have Shell as their immediate parent
anymore.

Output

Shell::nl() has been added. It returns a single or multiple linefeed sequences. Shell::out(), err() and hr() now
accept a $newlines parameter which is passed to nl() and allows for controlling how newlines are appended to the
output.

Shell::out() and Shell::err() have been modified, allowing a parameterless usage. This is especially useful if you're
often using $this->out('') for outputting just a single newline.

Acl Shell

All AclShell commands now take node parameters. node parameters can be either an alias path like
controllers/Posts/view or Model.foreign_key ie. User.1. You no longer need to know or use the aco/aro id for
commands.

The Acl shell dataSource switch has been removed. Use the Configure settings instead.

SchemaShell

The Schema shell can now read and write Schema files and SQL dumps to plugins. It expects and will create schema
files in $plugin/config/schema

....

# (#Router-and-Dispatcher-1578) Router and Dispatcher

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1578/Router-and-Dispatcher) ..
Mas info sobre traduciones (/es/view/818)

Router

382 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

Generating urls with new style prefixes works exactly the same as admin routing did in 1.2. They use the same syntax
and persist/behave in the same way. Assuming you have Configure::write('Routing.prefixes', array('admin',
'member')); in your core.php you will be able to do the following from a non-prefixed url:

Plain Text View (#)


1. $this->Html->link('Go', array('controller' => 'posts', 'action' => 'index', 'member' => true));
2. $this->Html->link('Go', array('controller' => 'posts', 'action' => 'index', 'admin' => true));

Likewise, if you are in a prefixed url and want to go to a non-prefixed url, do the following:

Plain Text View (#)


1. $this->Html->link('Go', array('controller' => 'posts', 'action' => 'index', 'member' => false));
2. $this->Html->link('Go', array('controller' => 'posts', 'action' => 'index', 'admin' => false));

Route classes

For 1.3 the router has been internally rebuilt, and a new class CakeRoute has been created. This class handles the
parsing and reverse matching of an individual connected route. Also new in 1.3 is the ability to create and use your
own Route classes. You can implement any special routing features that may be needed in application routing classes.
Developer route classes must extend CakeRoute, if they do not an error will be triggered. Commonly a custom route
class will override the parse() and/or match() methods found in CakeRoute to provide custom handling.

Dispatcher

Accessing filtered asset paths, while having no defined asset filter will create 404 status code responses.

# (#Library-classes-1579) Library classes

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1579/Library-classes) .. Mas
info sobre traduciones (/es/view/818)

Inflector

You can now globally customize the default transliteration map used in Inflector::slug using Inflector::rules. eg.
Inflector::rules('transliteration', array('/å/' => 'aa', '/ø/' => 'oe'))

The Inflector now also internally caches all data passed to it for inflection (except slug method).

Set

Set has a new method Set::apply(), which allows you to apply callbacks (http://ca2.php.net/callback) to the results of
Set::extract and do so in either a map or reduce fashion.

Plain Text View (#)


1. Set::apply('/Movie/rating', $data, 'array_sum');

Would return the sum of all Movie ratings in $data.

L10N

All languages in the catalog now have a direction key. This can be used to determine/define the text direction of the
locale being used.

File

File now has a copy() method. It copies the file represented by the file instance, to a new location.

Configure

Configure::load() can now load configuration files from plugins. Use Configure::load('plugin.file'); to
load configuration files from plugins. Any configuration files in your application that use . in the name should
be updated to used _

App/libs

In addition to app/vendors a new app/libs directory has been added. This directory can also be part of plugins,

383 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

located at $plugin/libs. Libs directories are intended to contain 1st party libraries that do not come from 3rd parties
or external vendors. This allows you to separate your organization's internal libraries from vendor libraries.
App::import() has also been updated to import from libs directories.

Plain Text View (#)


1. App::import('Lib', 'ImageManipulation'); //imports app/libs/image_manipulation.php

You can also import libs files from plugins

Plain Text View (#)


1. App::import('Lib', 'Geocoding.Geocode'); //imports app/plugins/geocoding/libs/geocode.php

The remainder of lib importing syntax is identical to vendor files. So if you know how to import vendor files with
unique names, you know how to import libs files with unique names.

Configuration

The default Security.level in 1.3 is medium instead of high


There is a new configuration value Security.cipherSeed this value should be customized to ensure more
secure encrypted cookies, and a warning will be generated in development mode when the value matches its
default value.

i18n

Now you can use locale definition files for the LC_TIME category to retrieve date and time preferences for a specific
language. Just use any POSIX compliant locale definition file and store it at app/locale/ language/ (do not create a
folder for the category LC_TIME, just put the file in there).

For example, if you have access to a machine running debian or ubuntu you can find a french locale file at:
/usr/share/i18n/locales/fr_FR. Copy the part corresponding to LC_TIME into app/locale/fr_fr/LC_TIME file. You can
then access the time preferences for French language this way:

Plain Text View (#)


1. Configure::write('Config.language','fr-fr'); // set the current language
2. $monthNames = __c('mon',LC_TIME,true); // returns an array with the month names in French
3. $dateFormat = __c('d_fmt',LC_TIME,true); // return the preferred dates format for France

You can read a complete guide of possible values in LC_TIME definition file in this page (http://sunsson.iptime.org
/susv3/basedefs/xbd_chap07.html)

# (#Miscellaneous-1581) Miscellaneous

Todavia no hay una traducion de este texto. Por favor ayudanos y traducirla (/es/edit/1581/Miscellaneous) .. Mas info
sobre traduciones (/es/view/818)

Error Handling

Subclasses of ErrorHandler can more easily implement additional error methods. In the past you would need to
override __construct() and work around ErrorHandler's desire to convert all error methods into error404 when debug
= 0. In 1.3, error methods that are declared in subclasses are not converted to error404. If you want your error
methods converted into error404, then you will need to do it manually.

Scaffolding

With the addition of Routing.prefixes scaffolding has been updated to allow the scaffolding of any one prefix.

Plain Text View (#)


1. Configure::write('Routing.prefixes', array('admin', 'member'));
2. class PostsController extends AppController {
3. var $scaffold = 'member';
4. }

Would use scaffolding for member prefixed urls.

Validation

384 de 385 16/08/10 10:09


El manual :: 1.3 Colección :: El Cookbook http://book.cakephp.org/es/complete/876/The-Manual

After 1.2 was released, there were numerous requests to add additional localizations to the phone() and postal()
methods. Instead of trying to add every locale to Validation itself, which would result in large bloated ugly methods,
and still not afford the flexibility needed for all cases, an alternate path was taken. In 1.3, phone() and postal() will
pass off any country prefix it does not know how to handle to another class with the appropriate name. For example if
you lived in the Netherlands you would create a class like

Plain Text View (#)


1. class NlValidation {
2. function phone($check) {
3. ...
4. }
5. function postal($check) {
6. ...
7. }
8. }

This file could be placed anywhere in your application, but must be imported before attempting to use it. In your
model validation you could use your NlValidation class by doing the following.

Plain Text View (#)


1. var $validate = array(
2. 'phone_no' => array('rule' => array('phone', null, 'nl')),
3. 'postal_code' => array('rule' => array('postal', null, 'nl'))
4. );

When your model data is validated, Validation will see that it cannot handle the 'nl' locale and will attempt to delegate
out to NlValidation::postal() and the return of that method will be used as the pass/fail for the validation. This
approach allows you to create classes that handle a subset or group of locales, something that a large switch would
not have. The usage of the individual validation methods has not changed, the ability to pass off to another validator
has been added.

IP Address Validation

Validation of IP Addresses has been extended to allow strict validation of a specific IP Version. It will also make use of
PHP native validation mechanisms if available.

Plain Text View (#)


1. Validation::ip($someAddress); // Validates both IPv4 and IPv6
2. Validation::ip($someAddress, 'IPv4'); // Validates IPv4 Addresses only
3. Validation::ip($someAddress, 'IPv6'); // Validates IPv6 Addresses only

Validation::uuid()

A uuid() pattern validation has been added to the Validation class. It will check that a given string matches a uuid by
pattern only. It does not ensure uniqueness of the given uuid.

« 1.3 Colección (/es/view/875/x1-3-Colección) | El Cookbook » (/es/view/1/El-Cookbook)


Viaja con ADO Software Remuneración Curso de Programacion PHP Penny Auction Script
Con ADO Ahora Puedes Comprar en Gestiona Nómina, IMSS/Infonavit, Formación profesional a distancia con Don't get scammed. View our live Demo
Línea. Es Fácil y Seguro. Empleados, Reportes. ¡Pruébalo! certificación universitaria site. Try before you buy!
www.ADO.com.mx www.Nominax.com www.Aprender21.com www.phppennyauction.com

(http://www.cakephp.org/) (http://creativecommons.org/licenses/by-nc-nd/3.0/)

© Cake Software Foundation, Inc. (http://cakefoundation.org)

Privacy Policy (/es/pages/display/privacy)

385 de 385 16/08/10 10:09

S-ar putea să vă placă și