====== CakePHP ====== ===== Instalación ===== * Al descomprimir te toparás con 3 carpetas. En la carpeta //app// será donde la aplicación sea desarrollada, en //cake// donde está el código de CakePHP y en //vendors// donde podemos colocar otras librerías. * Se basa en el patrón MVC (Modelo Vista Controlador) y por ello existen clases Modelo, clases Vista y clases Controlador que se guardan en los directorios /app/models, /app/view y /app/controllers respectivamente. * Necesitarás configurar el ''mod_rewrite'' de Apache para que CakePHP funcione, aquí tienes unos posibles pasos: - Si la dirección con la que accedes al index.php es: ''http://127.0.0.1/pruebas/cake/app/webroot/index.php'' y eso sigue sin funcionar, tendrás que editar los .htaccess de (siendo “tu_ruta” donde está el directorio raíz de cake): tu_ruta/.htaccess, tu_ruta/app/.htaccess y tu_ruta/app/webroot/.htaccess. Añadiendo: ''RewriteBase /pruebas/cake'' - Si la ventana de bienvenida aparece sin estilos ni imágenes es porque el mod_rewrite puede no estar funcionando correctamente. Habrá que configurarlo. - Instalalo en Apache y asegurate que está cargado mediante una llamada ''phpinfo();''. - Si está cargado y sigue sin ir, asegurate que los ''AllowOverride'' del fichero de configuración de Apache estén a ''All'' y no a ''None''. * Aún así puedes prescindir de el ''mod_rewrite'' (algo no recomendable) si en el fichero de configuración global (/app/config/core.php) descomentas la línea: ''define ('BASE_URL', env('SCRIPT_NAME'));'' ===== Configuración ===== * Necesitarás configurar la base de datos la primera vez que inicies una aplicación de CakePHP; para una configuración estándard renombra ''/app/config/database.php.default'' a ''/app/config/database.php''. * Para separar cakephp en distintos directorios tendrás que editar el fichero ''app/webroot/index.php'' y cambiar: * ROOT: la carpeta dónde se encuentra la carpeta app. * APP_DIR: la ruta de la carpeta app. * CAKE_CORE_INCLUDE_PATH: la carpeta donde se encuentra la carpeta cake (el framework en sí). Por ejemplo si la ruta completa de cake es: ''/home/alfred/Projects/PruebasWeb/cake'', haremos: ''define('CAKE_CORE_INCLUDE_PATH', '/home/alfred/Projects/PruebasWeb');'' * Para que los errores lanzados por CakePHP no sean descriptivos debes cambiar el valor en ''core.php'' de debug a uno más alto de 0. Esto hará también que los mensajes flash activen la redirección automática. * Para configurar la ruta de los ficheros que se van a cargar lo haremos en ''routes.php''. Este archivo nos permite indicar cual será el archivo a cargar, por ejemplo, como portada. La línea que indica la ruta por defecto es: $Route->connect('/', array('controller' => 'users', 'action' => 'display', 'home')); El primer parámetro es el directorio en cuestión que estamos tratando (/) controller y action las páginas controlador con su respectiva acción. A partir de ahí serán los parámetros a la acción. En este caso 'home' es el primero. ===== Modelos, Vistas y Controladores ===== ==== Nombres de clase y de archivos ==== Ejemplo para el elemento //Post// que tiene en la base de datos una tabla correspondiente llamada //posts//: * Para los modelos el nombre de la clase es el nombre de la tabla a la que están enlazados en singular (''Post''), el del archivo es este mismo nombre pero en minusculas (''post.php''). Este archivo ha de colocarse en ''/app/models/''. * Para los controladores el nombre de la clase es el modelo al que pertenecen pero en plural y seguido de //Controller// (''PostController''), el nombre del archivo es en minusculas y con una raya baja entre el elemento y el controller (''posts_controller.php''). Este archivo ha de colocarse en ''/app/controllers/''. * Las vistas se encuentran en ''/app/views//'' y son archivos .thtml. Por ejemplo, la view para ''PostController::add()'' estará en ''/app/views/posts/add.thtml''. ==== Controladores ==== * Son los que manejan la lógica de la aplicación. * Se puede crear el controlador de clase (AppController) de forma opcional (ha de heredar de Controller) en /app/app_controller.php, contendrá métodos que pueden ser accedidos por varios controladores de la aplicación. * Cada función es una de las características de la página para el elemento que "controla". \\ Por ejemplo: /app/controllers/videos_controller.php class VideosController extends AppController { function view($id) {} function rent($customer_id, $video_id) {} function search($query) {} } Será accedido como: * http://www.example.com/videos/view/253 * http://www.example.com/videos/rent/5124/0-235253 * http://www.example.com/videos/search/hudsucker+proxy === Métodos === * **set (var, valor)** Permite comunicar el controlador con la vista asignando variables. * **validate ()** Valida el formulario * **render (accion, layout, file)** Se llama automáticamente, pero puede que la necesites. * **redirect(url)** Redirige al usuario * **flash (msg, url, pause)** Muestra un msg por pause segundos en la capa de flash (app/views/layouts/flash.html) y luego redirige al usuario a la url. * **beforeFilter ()** Llamado antes de cada acción, para chequear sesiones y roles. * **afterFilter ()** Llamado después de cada acción. * **beforeRender ()** Llamaado justo antes de que la vista se muestre. * **requesAction (url, extra)** Para llamar a una acción del controlador (con el estilo: /controllername/actionname/params). Puedes coger datos o una vista ya renderizada de un controlador. (También es útil en casos que uses AJAX). * **postConditions (data)** Devuelve un array formateado de los data para ser pasado a otros métodos como findAll. * **log (msg, tipo)** Guardará un mensaje en /tmp, el tipo puede ser LOG_ERROR o LOG_DEBUG o ninguno (que sería un LOG_ERROR). === Variables === * **$name** Útil si usas php4, para asignar el nombre de la clase. * **$uses** Por si usas más de un modelo en un controlador (un controlador carga automáticamente su modelo). ''var $uses = array('su_modelo', 'modelo_xtra1', 'modelo_xtra2');'' * **$helpers** para cargar más helpers en la vista, automáticamente se carga el html, pero si agregas otros también deberás agregarlo: ''var $helpers = array('Html','Ajax','Javascript');'' * **$components** para cargar componentes. * **$layout** Indica el nombre del layout para el controlador. * **$autoRender** Si se pone a false se dejará automáticamente de llamar a las acciones de rendering. * **$beforeFilter** puedes definir acciones que se llamarán métodos de cada acción. Por ejemplo para validar un usuario. class ProductsController extends AppController { var $beforeFilter = array('checkAccess'); function checkAccess() {} function index() {} } Aquí se llamaría antes a checkAccess que a index === Parámetros === * **$this->data** Para recoger los datos enviados por POST \\ Los siguientes serían la xxx de ''$this->params['xxx']'': * **form** Recoge más datos del form * **bare** 1 si el layaut actual es vacío * **ajax** 1 si el layaut actual es ajax * **controller** nombre del controlador * **action** almacena la acción del controlador * **pass** coge el string que se le ha pasado * **url** recoge la url con la que se ha llamado ==== Modelos ==== Un modelo es un acceso a una base de datos (más concretamente a una tabla), su nombre es el de la tabla en singular (por ejemplo la tabla users tendrá el modelo user). También contendrá datos de validación y métodos específicos para esa tabla. \\ Los modelos se guardan en ''/app/models'' y han de heredar de la clase ''AppModel''. Para acceder a ellos, en el controlador correspondiente, tendrás un objeto a dicho modelo. Un ejemplo de modelo sería el siguiente: array('className' => 'Image')); function makeInactive($uid) {...} } ?> Si existen métodos que se comparten entre dos o más modelos puedes crear tu propio modelo por defecto en ''app/app_model.php''. === Definir funciones propias === Por ejemplo métodos para esconder u ocultar los post de un blog: id = $id; $this->saveField('hidden', '1'); } } function unhide ($id=null) { if ($id) { $this->id = $id; $this->saveField('hidden', '0'); } } } ?> === Funciones para recoger datos === * ''findAll (condiciones, campos, orden, límite, pagina recursivo)'', retorna un número (límite) de registros con los campos específicos (fields) empezando por la página indicada (página) y con unas condiciones (por ejemplo: ''$conditions = "race = 'wookie' AND thermal_detonators > 3"''). Puedes enlazar datos de otros modelos asociados asignando un valor mayor que 1 al parámetro recursivo. * ''find(condiciones, campos, orden, recursivo)'', retorna los campos (si campos tiene valor, si no los retornará todos) del primer registro que coincida con las condiciones. * ''findBy (valor)'' y ''findAllBy (valor)'' son funciones que se personalizan por cada modelo, sirven para encontrar valores por un campo concreto: $this->Post->findByTitle('My First Blog Post'); $this->Author->findByLastName('Rogers'); $this->Specimen->findAllByKingdom('Animalia'); * ''findNeighbours (condiciones, campo, valor)'' retorna los registros vecinos (anterior y posterior (por lo tanto muy útil para la funcionalidad anterior\siguiente)) de un registro concreto especificado por campo-valor. El valor sólo puede ser una fecha o un número. Por ejemplo, el siguiente código nos asinará la variable ''$neighbours['prev']['Image']['id']'' y ''$neighbours['next']['Image']['id']''. function view($id) { $this->set('image', $this->Image->find("id = $id")); // Imágen mostrada $this->set('neighbours', $this->Image->findNeighbours(null, 'id', $id)); } * ''field (nombre, condiciones, orden)'' retorna el valor del campo del primer registro indicado. * ''findCount(condiciones)'' retorna el número de campos que coinciden con las condiciones. * ''generateList (condiciones, orden, limite, keyPath, valuePath)'', una función para crear una lista de pares de clave\valor (un atajo para los tag select de html). Por ejemplo , para recoger una lista de roles: $this->set('Roles', $this->Role->generateList(null, 'role_name ASC', null, '{n}.Role.id', '{n}.Role.role_name')); /* Devolvería: array( '1' => 'Account Manager', '2' => 'Account Viewer', '3' => 'System Manager', '4' => 'Site Visitor' ); */ * ''read (campos, id)'', lee campos del registro actual cargado o del indicado por el id. * ''query(query)'' y ''execute (query)'' son llamadas a base de datos, la diferencia entre ellas es que query execute no hace un retorno de valores. function posterFirstName() { $ret = $this->query("SELECT first_name FROM posters_table WHERE poster_id = 1"); $firstName = $ret[0]['first_name']; return $firstName; } === Indicando condiciones === Podemos especificar las condiciones mediante un array que luego pasaríamos a un método find como ''$this->Post->find($conditions);'', ejemplos: $conditions = array("Post.title" => "This is a post"); array("Post.title" => "<> This is a post"); array("Post.title" => array("First post", "Second post", "Third post")); array ("or" => array ("Post.title" => array("First post", "Second post", "Third post"), "Post.created" => "> " . date('Y-m-d', strtotime("-2 weeks")))); array("Author.name" => "Bob", "or" => array ("Post.title" => "LIKE %magic%", "Post.created" => "> " . date('Y-m-d', strtotime("-2 weeks"))); === Guardando datos === Para guardar datos sólo has de pasar al método save del modelo un array del estilo: Array ( [ModelName] => Array ( [fieldname1] => 'value' [fieldname2] => 'value' ) ) Es muy sencillo utilizar el helper HTML ya que los datos los trae formateados para ser leidos por CakePHP ya que sólo has de añadir algo así: ''$html->input('Model/fieldname');''. \\ Los datos enviados desde un form se guardan automáticamente en el array ''$this->data'' del controlador. \\ Un ejemplo de una función de editar: function edit($id) { if (empty($this->data)) { $this->Property->id = $id; // El modelo se carga automáticamente en $this->Property $this->data = $this->Property->read(); } else { if ($this->Property->save($this->data['Property'])) $this->flash('Your information has been saved.', '/properties/view/'.$this->data['Property']['id'], 2); // Si algunos campos no son válidos o el guardado fallase, el formulario se volvería a mostrar } } La validación se hace de forma automática, pero si no quisieses que al guardar se validase tendrás que hacer la llamada así: ''save($data, false)''. \\ Otras funciones muy útiles: * ''del (id, enCascada)'', elimina del modelo el id específico. * ''saveField (nombre, valor)'', para guardar un simple valor en un campo. * ''getLastInsertId ()'', Devuelve el último ID creado. === Llamadas internas del modelo === Existen funciones que pueden ser sobreescritas y serán llamadas en el momento indicado, según la acción a la que correspondan: * beforeFind * afterFind * beforeValidate * beforeSave * afterSave * beforeDelete * afterDelete === Variables del modelo === * ''$primaryKey'', si la primary key del modelo no fuese el campo id asigna esta variable al nombre del campo. * ''$recursive'' asigna el número de niveles en el que Cake enlaza el modelo de datos en una llamada a ''find'' o ''findAll''. En un ejemplo en el que existen grupos con usuarios y cada uno con artículos los valores posibles serían: * ''-1'' no asocia data. * ''0'' Cake enlaza los grupos. * ''1'' Cake enlaza los grupos con los usuarios. * ''2'' Cake enlaza los grupos con los usuarios y los usuarios con sus artículos. * ''$transactional'', para activar\desactivar las transacciones (begin, commit, rollback). * ''$useTable'', para asingar el nombre de la tabla para el modelo si esta no tiene el nombre que cogería por defecto. * ''$validate'', donde se asigna los datos de validación * ''$useDbConfig'', por defecto utiliza la configuraciónd //default// de la base de datos en ''app/config/database.php'', pero puedes utilizar otra indicando en esta variable su nombre. === Asociaciones === ==== Vistas ==== Las vistas son la parte de una página correspondiente a una acción de un controlador. * Una vista puede contener código php, xml, una imágen... * A la view se le pasan los datos en un array llamado ''$data''. Puedes pasarle datos desde la función ''set()'' desde el controlador. * El helper HTML es añadido por defecto. === Los layouts === * Contienen todo el código que rodea una vista. * Se localizan en ''/app/views/layouts''. * Creando un ''/app/views/layouts/default.thtml'' se sobreescribirá el layout por defecto de CakePHP. \\ Al crear un layout has de indicar donde se colocará el código del controlador, para ello has de mostrar la variable ''$content_for_layout'' (también existe ''$title_for_layout''). <?php echo $title_for_layout?> Para indicar qué título se ha de mostrar en ''$title_for_layout'' sólo has de asignar un valor a la variable ''$pageTitle'': class UsersController extends AppController { function viewActive() { $this->pageTitle = 'View Active Users'; } } Puedes definir un layout para un controlador cambiando su variable ''$layout'', si quieres que una acción tenga un layout distinto tendrás que asignarlo dentro del método de la clase. class CoverController extends AppController { var $layout = "cover"; function index () { $this->layout = "default"; } ... === Elements === Los elementos son esas pequeñas porciones de código que se muestran repetidas veces en todo el site (banners, menús extra, controles de navegación...). Básicamente son pequeñas vistas que pueden ser incluidas en otras vistas. \\ Han de ser ubicados en ''/app/views/elements'' como ficheros .thtml. y tienen acceso a los datos declarados para ser usados en la vista. \\ Para mostrar un elemento, en la vista: renderElement('helpbox');?> Puedes pasar un array de datos como segundo parámetro a este método. renderElement('helpbox', array("helptext" => "Oh, this text is very helpful.")); ?> === Vistas de error === Puedes personalizar los mensajes de error creando los ficheros correspondientes a las vistas que CakePHP tiene definidas para los casos en los que un error aparece, están en ''/app/views/error'' estas son: * error404.thtml * missing_action.thtml * missing_component_class.thtml * missing_component_file.thtml * missing_connection.thtml * missing_controller.thtml * missing_helper_class.thtml * missing_helper_file.thtml * missing_layout.thtml * missing_model.thtml * missing_scaffolddb.thtml * missing_table.thtml * missing_view.thtml * private_action.thtml * scaffold_error.thtml Las plantillas por defecto están en ''cake/libs/view/template/errors'' y puedes copiarlas al directorio de tu aplicación y luego editarlas. \\ Por defecto muchas de las vistas no serán mostradas cuando el DEBUG sea más grande que 0. ===== Otros elementos ===== ==== Helpers ==== Son funciones que se necesitan a menudo en las vistas. === HTML === Las funciones de este helper se utilizan para generar tags html, y es accesible utilizando ''$html''. Además, si AUTO_OUTPUT (variable asignada en /app/config/core.php) está a true el helper automáticamente mostrará la tag sin tener que poner código php con echos. Aunque puedes cambiar esto específicamente para una función dándole el valor deseado en el parámetro ''$return''. \\ Las funciones que usa este helper están definidas en ''tags.ini.php'', si quieres editarlas sólo tendrás que copiar ''/cake/config/tags.ini.php'' en ''/app/config/''. \\ \\ Funciones (muy explícitas por sí solas como para ponerme yo a explicarlas) para crear tags: * ''charset (charset, return)'', para crear la meta-tag de charset, si no le pasa nada por parámetro creará una tag de utf-8. * css (path, rel, atributos, return) * image(path, atributos, return) * ''link (title, url, atributos, msgConfirmación, escapeTitulo, return)'', el msgConfirmación se usa para indicar si saldrá algún mensaje pidiendo la confirmación del usuario (por ejemplo al borrar un elemento de algúns sitio). * tableHeaders (nombres, opciones, opciones) * tacleCells (data, opcionesImpares, opcionesPares) * guiListTree (data, atributos, bodyKey, childrenKey, return) Más funciones HTML, pero estas para crear formularios: * submit (caption, atributos, return) * password (fieldName, atributos, return) * textarea (fieldName, atributos, return) * checkbox (fieldName, titulo, atributos, return) * file (fieldName, atributos, return) * hidden(fieldName, atributos, return) * input(fieldName, atributos, return) * ''radio (fieldName, options, inbetween, atributos, return)'', crea un grupo de radiobuttons, los parámetros indican: fieldName el nombre en la DB al que corresponden, options los valores con sus respectivos textos, inbetween el string entre radiobutton y radiobutton, atributos sería el correspondiente a los atributos de los tags. * tagErrorMsg(fieldName, msg) $html->radio('Note/status', array('1' => 'Complete', '2' => 'In Progress'), null, array('value' => '1')); === Cómo utilizar los helpers? === Los helpers generan automáticamente los tags, se rellenan si ocurre un error y muestran los menajes de error. Imaginemos que estamos montando una aplicación para tomar notas, en el NotesController tendremos una acción de edición: function edit($id) { //Lo primero es mirar si los datos se han enviado correctamente if (!empty($this->data['Note'])) { // Aquí intentaríamos validar el formulario if ($this->Note->save($this->data['Note'])) { // Si se ha guardado correctamente llevaríamos al usuario a un lugar concreto $this->flash('Your information has been saved.', '/notes/edit/' . $id); exit(); } else { // Si no generaríamos un error // llamaríamos a $this->Note->validates($this->data['Note']); si no estamos guardando // mostraríamos los errores $this->validateErrors($this->Note); // Y llamaríamos ya al método para mostrar la página $this->render(); } } // Si no hemos recibido datos es que los queremos editar, por lo tanto mostrar la info $this->set('note', $this->Note->find("id = $id")); $this->render(); } En el modelo Note tendríamos un id de nota, un id del editor y el cuerpo de la nota. La vista mostraría los datos de la nota y permitiría al usuario introducir nuevos y estaría en ''app/views/notes/edit.thtml'': formTag('/notes/edit/' . $html->tagValue('Note/id')) ?>
Body: textarea('Note/body', array('cols'=>'60', 'rows'=>'10')); ?> tagErrorMsg('Note/body', 'Please enter in a body for this note.') ?>
hidden('Note/id')?> hidden('note/submitter_id', $this->controller->Session->read('User.id'))?>
submit()?>
Algunas funciones necesitan que se les indique un $fieldName (por ejemplo tagErrorMsg), esto permite a CakePHP saber qué data le estás pasando y validarla correctamente, para ello se pasa en un string con valor "nombreModelo/nombreCampo", por ejemplo, para añadir un título a la nota: input('Note/title') ?> tagErrorMsg('Note/title', 'Please supply a title for this note.')?> Los mensajes de error se muestran en una div del estilo: ''
'' === Ajax === El helper de Ajax de CakePHP utiliza los scripts de [[http://script.aculo.us/|script.aculo.us]], por lo que para poder utilizarlos deberías tener las librerías en ''/app/webroot/js'' e incluirlas en la vista. También hay que tener en cuenta que la mayoría de estas funciones reciben un parámetro de opciones, este es un array de claves (url, update, confirm...) con valores, de esta forma se le asignan las propiedades. * ''link(title, href, options, confirm, escapeTitle)'' * ''remoteFunction(opcions)'', * ''remoteTimer(options)'', periodicamente hace una llamada a url, cada frecuencia (segundos). * ''form(action, type, options)'' retorna un tag del form a la action. * ''observeField(field_id, options)'', cada frequency hace una llamada a url. * ''observeForm(form_id, options)'' * ''autoComplete(field, url, options)'' * ''drag(id, options)'' * ''drop(id, options)'' * ''dropRemote(id, options, ajaxOptions)'' * ''sortable(id, options)'' * ''editor(id, url, options)'' === JavaScript === * ''codeBlock (string)'', retorna un script del string pasado. * ''link(url)'', retorna una tag url que apunta a la url pasada. * ''linkOut(url)'', como link pero para un dominio distinto. * ''event(object, event, observer, useCapture)'', enlaza un evento a un elemento (usando la librería Prototype). * cacheEvents() * writeEvents * includeScript === Numeros === * ''precision (numero, precision)'', número formateado a un nivel de precisión. * ''toReadableSize(bytes)'', se le pasa un número de bytes y los devuelve en kb, mb, gb, o tb. * ''toPercentage(numero, precision)'', retorna un número formateado como porcentage. === Texto === * highlight(texto, highlighter) * ''stripLinks(texto)'', de un link te retorna el texto interno. === Fecha hora === * ''fromString(dateString)'' * ''nice(dateString, return)'', retorna la fecha formateada larga. * ''niceShort(dateString, return)'', formate al fecha en formato corto. * ''isToday(date)'', retorna true si la fecha indicada corresponde a la de hoy. * ''daysAsSql(begin, end, fieldName, return)'', retorna un sql string a buscar entre dos fechas. * ''dayAsSql(date, field, return)'', retorna un sql string para buscar los registros de una misma fecha. * isThisYear * wasYesterday * isTomorrow * toUnix * toAtom * toRSS * ''timeAgoInWords(date, return)'', retorna cuanto tiempo ha pasado. * ''relativeTime (string, return)'', como timeAgoInWords pero para presente, pasado y futuro. * ''wasWithinLast(intervalo, date, return)'' retorna true si el datetime especifico está en el intervalo (2 days, 6 hours...). ==== Scaffolding ==== El Scaffolding es la capacidad que tiene CakePHP de agilizar el pantallas de inserción, consulta y adición a la base de datos generando el código. \\ Se analiza la base de datos y se auto-genera el código. \\ Sólo has de añadir $scaffold; la variable al controlador: ==== Validación ==== * En la clase modelo añadiremos un array llamado $validate que controlará que los campos de entrada tengan un formato correcto. * Para ello puedes utilizar expresiones regulares o constantes (VALID_NOT_EMPTY, VALID_NUMBER, VALID_EMAIL, VALID_YEAR). * Sólo has de crear un array llamado validate en el modelo deseado con cada campo que quieres validar y su formato: var $validate = array( 'login' => '/[a-z0-9\_\-]{3,}$/i', 'password' => VALID_NOT_EMPTY, 'email' => VALID_EMAIL, 'born' => VALID_NUMBER ); * La validación se hace en el método: Model::save() * Para validar los datos directamente utiliza: Model::validates() e Model::invalidFields() que devuelve un array de campos inválidos. ==== Sanitization ==== Sanitize es la clase dentro de cake que te permite filtrar las entradas a la base de datos, impidiendo que se lancen algunos carácteres que no quieres. uses('sanitize'); $mrClean = new Sanitize(); Métodos según lo que se quiera 'limpiar': * paranoid * html * sql * cleanArray ==== Sesiones ==== CakePHP puede salvar las sesiones de tres formas distintas, para indicar cual es la deseada hay que editar ''/app/config/core.php'' y cambiar el valor de CAKE_SESSION_SAVE por 'php' (que las maneja php), 'database' (las maneja la base de datos) o 'cake' (las maneja el mismo CakePHP). \\ Para utilizarlas puede hacer uso de las siguientes funciones: * ''check (nombre)'', comprueba si el nombre ha sido asignado como variable durante la sesión. * ''del (nombre)'', elimina la variable de sesión. * ''read(nombre)'', devuelve el valor de la variable indicada. * ''renew ()'', renueva la sesión asignándole un nuevo id de sesión. * ''valid()'', devuelve si la sesión es valida o no. Útil antes de leer una variable. * ''write (nombre, valor)'' asigna un valor a una variable. Cuando accedes a la session desde la view necesitarás usar el helper de Sesiones:

Nombre: read('user.username'); ?>

Cuando accedes a la sesión desde un controlador tienes el objeto ''Session'' dentro de este: if (!$this->Session->check('user')) { $this->redirect('/cover/index'); exit(); } Cuando almacenas un array de claves valor, tendrás que acceder a los datos mediante un string: $theUser = $this->User->findByUsername ($this->data['User']['username']); $this->Session->write('user', $theUser['User']); $this->set('name', $this->Session->read ('user.username')); ==== Components ==== Un componente se crea en el directorio app/controllers/components/ class FooComponent extends Object { var $someVar = null; var $controller = true; function startup(&$controller) {} function doFoo() { $this->someVar = 'foo'; } } La función startup se llama al iniciar, si no quieres que sea usada o llamada pon la variable de clase $disableStartup a true. \\ En el controlador se agregará el componente: var $components = array('Foo'); Y lo usuará: $this->Foo->doFoo(); ==== Componente Request Handler ==== Este componente viene con CakePHP y controla las peticiones AJAX, para usuarlo ha de ser declarado como un valor dentro de la variable del controlador ''$components'', una vez esté declarado puede ser accedido mediante la variable RequestHandler: class PostsController extends AppController { var $components = array('RequestHandler'); function beforeFilter () { if ($this->RequestHandler->accepts('html')) .... Sus funciones son: * ''accepts(tipo)'', se le pasa un string que indica un tipo da datos, si el cliente lo acepta esta función retornará true. * getAjaxVersion() * getClientIP () * ''getReferrer()'', retorna el nombre del servidor desde donde se ha hecho la petición. * ''isAjax ()'', retorna true si la petición actual es una XMLHttpRequest. * ''isAtom ()'', true si el cliente acepta contenido de feeds Atom. * ''isDelete()'', ''isGet()'', ''isPost()'' o ''isPut()'', retornan true si la petición se hico via DELETE, GET, POST o PUT. * ''isMobile ()'', retorna true si el cliente es un navegador de movil. * ''isXml()'', retorna true si el cliente acepta contenido XML. * ''setContent(nombre, tipo)'', indica un tipo de contenido. Puede que alguna vez queramos eliminar datos de la salida, para ello tenemos las siguientes funciones que eliminan tags: * striptImages(str) * stripScripts (str) * stripWhiteSpace (str) * stripAll (str) * ''stripTags (str, tag1, tag2...)'', elimina los tags indicados. ''setAjax'' es otra función muy util porque se usa para detectar automáticamente peticiones de ajax y asignar el layout del controlador como una vista AJAX: \\ El fichero list.thtml:
En el controlador: function list() { $this->RequestHandler->setAjax($this); $this->set('things', $this->Thing->findAll()); } ==== Plugins ==== * Combinación de modelos, vistas y controladores utilizados para simplificar tareas posteriores. * Si no se enlazan con la aplicación actuarán independientemente. * Se añaden a app/plugins en una carpeta, el nombre de esa carpeta será el nombre del plugin. * Es obligatorio definir un controlador y un modelo para el plugin, estos estarán en el mismo directorio: Estructura: /app /plugins /pizza /controllers /models /views /pizza_app_controller.php /pizza_app_model.php En ''/app/plugins/pizza/pizza_app_controller.php'': Y en ''/app/plugins/pizza/pizza_app_model.php'' * Los nombres dados a los controladores del plugin deberían de ser únicos en la aplicación (hemos de preveer que la aplicación tendrá un UsersController). * Los controladores heredan del controlador del plugin no directamente del AppController. Lo mismo pasa con los modelos. class PizzaOrdersController extends PizzaAppController { var $name = 'PizzaOrders'; function index() {} function placeOrder() {} } * Los controladores utilizan los layouts por defecto de la aplicación. * Puedes hacer llamadas internas en el plugin haciendo algo parecido a: $this->requestAction('/plugin/controller/action'); * Puedes acceder al plugin mediante: /pluginname/controllername/action ===== Montar una página ===== === Portada === Podemos crear la portada a nuestro site creando el archivo ''/app/views/pages/home.thtml'' ya que es tal como está configurado por defecto en el routes.php. Pero también podemos crear la nuestra propia creando por ejemplo un ''/app/views/pages/cover.thtml'' y cambiando la configuración de la ruta en routes.php por ''$Route->connect ('/', array('controller'=>'pages', 'action'=>'display', 'cover'));''. === Apariencia por defecto === Por defecto, toda página que crees aparecerá dentro de una página en la que se lee "CakePHP Rapid Development", ese es el layout por defecto que está en ''cake/libs/view/templates/layouts/default.thtml'', no es necesario que lo borres, simplemente con que crees el ''app/views/layouts/default.thtml'' ya lo tendrás. === Añadir CSS === Los archivos de estilo .css que quieras añadir a tu aplicación deberás hacerlo en la carpeta ''app/webroot/css'', luego, para añadirlos a tu layout, en el head, haz (si por ejemplo se llama //generic.css// el archivo de estilos): css('generic'); ?> === Añadir contenido === Para añadir contenido a un layout tienes varias variables en el helper de html que te serán de ayuda: * ''$content_for_layout'', si haces un echo de esta variable te escribirá la view del controlador actual. * ''$title_for_layout)'', lo mismo pero para el title. Para añadir links o direciones dentro del site utiliza ''$html->url'' para que te construya el path:
==== Un vistazo al acceso a DB ==== === Lectura === Imaginemos que tienes una DB de usuarios, cada uno con un perfil, es decir, dos tablas ''users'' y ''profiles'' en la que profiles se enlaza a users mediante un campo ''users_id'' dentro de esta. Cuando quieres mostrar un perfil para un usuario concreto, en el controlador puedes hacer un método del estilo: function showprofile ($id) { $this->set('profile', $this->Profile->findByUsers_id($id)); } Este busca en los perfiles por el campo ''users_id'' y lo asigna para la vista en una variable llamada ''profile'', ahora para acceder a ella desde la vista: Nombre: === Campos de la DB en el formulario === Cuando vayas a editar algún perfil probablemente prefieras mostrar un formulario con los campos actuales ya colocados en los cuadros de texto y preparados para ser editados, para que CakePHP lo haga automáticamente deberás asignar a la variable del controlador ''$data'' el perfil: $this->data = $this->Profile->findByUsers_id($this->Session->read('user.id')); Luego podrás acceder a esta mediante el helper de html: Nombre Real: input('Profile/realname', array('size' => 20)); ?> Esto nos sirve básicamente para indicar que un campo del formulario corresponde a un campo de la base de datos. \\ También puedes asignar estos campos manualmente en el controlador si editas la variable $data antes de llamar a la vista. $this->data = $this->Profile->findByUsers_id($this->Session->read('user.id')); $this->data['Profile']['users_id'] = $this->Session->read('user.id'); === Guardar y editar === Tanto para guardar como para editar existe la función ''save'', a esta le pasas los datos del modelo que, si el controlador ha sido llamado desde un formulario, los datos estarán en la variable ''$data''. \\ La única diferencia a la hora de guardar y actualizar es que para actualizar es obligatorio indicar el ''id'' (que el modelo ha de tener). $this->Profile->id = $this->data['Profile']['id']; $this->Profile->save($this->data['Profile']); Puedes guardar y editar los registros manualmente: $actualizar = array(); $actualizar['User'] = array(); $actualizar['User']['login'] = 'danguer1'; $actualizar['User']['password'] = 'hola'; $this->id = $id_guardado; $this->save($actualizar); === Acciones sobre la BD === == Contar registros == Por ejemplo desde el controlador: if ($this->Profile->findCount ("users_id = $id") == 0) // Perfil no definido { ... } O desde el modelo con una función que después podrá ser llamada desde el controlador como: ''$this->User->existsUsername('juan24');'': function existsUsername ($username) { return ($this->findCount ("User.username = '$username'") > 0); } Otros ejemplos: $this->findCount("User.login='danguer' AND Article.title LIKE '%php%'"); == Otras consultas == function hasProfile ($id) { $ret = $this->query("select COUNT(id) as count from profiles where users_id = " . $id); $num = $ret[0][0]['count']; return ($num > 0); } ==== Otras cosillas a tener en cuenta ==== * Recuerda como añadir de forma sencilla la tag de utf-8: ''$html->charset();''. * Puedes hacer una llamada a una página interna haciendo ''controlador/accion/parametro1/parametro2''. Si la accion de ese controlador tiene sus parámetros definidos del estilo ''function accion ($parametro1=false, $parametro2=false) {'', se podrá llamar a esa funcion sin pasarle parametros y por defecto estos serán false los dos. ==== Ejemplos ==== === Creación de validación de usuario (login) === - Crear la tabla ''users'', esta tendrá campos como ''username'', ''password''... - Crear el modelo ''User''. - Crear la view ''app/views/users/login.thtml'', a esta se le añadirán los cuadros de texto para la introducción de nombre y password. - Crear el controlador de usuarios ''/app/controllers/users_controller.php''. - Añadir al controlador de usuarios un método login, ver más abajo. En este se recoge al usuario y si el login es correcto se escriben sus datos en la sesión. - Añadir al controlador de usuarios un método de logout, ver más abajo. En este únicamente se elimina al usuario de la sesión. - Crear un ''/app/app_controller.php'', el controlador general de la aplicación donde añadiremos la función que chequeará si el usuario está logueado (checkSession). Para ello mira en la sesión y si no existe llama a ''exit()'', nota que es una llamada a exit, lo que cancela cualquier ejecución y redirige al usuario al home del site. - Ahora puedes añadir a cualquier otro controlador (de mensajes, de posts...) un método llamado ''beforeFilter'', este se llamará automáticamente antes de cada llamada a cualquier método del controlador, si añades ahí una llamada al checkSession será obligatorio hacer un login para editar los posts, mensajes... O puedes únicamente colocar el checkSession al inicio de los métodos que desees. Método login del controlador de usuarios: function login() { if (!empty($this->data)) { $theUser = $this->User->findByUsername ($this->data['User']['username']); $bEmptyPassword = empty($this->data['User']['password']); $bSamePassword = ($theUser['User']['password'] == $this->data['User']['password']); if ((!$bEmptyPassword) && ($bSamePassword)) { $this->Session->write('user', $theUser['User']); $this->redirect("/users/mainpage"); return; } } $this->set("error", true); $this->redirect ("/cover/index/1"); } Método de logout del usuario: function logout () { $this->Session->del('user'); $this->redirect("/cover/index"); } Controlador general de la aplicación: class AppController extends Controller { function checkSession() { if (!$this->Session->check('user')) { $this->redirect('/'); exit(); } } } Método beforeFilter: function beforeFilter() { $this->checkSession(); } ===== Tips & Tricks ===== === Páginas estáticas === Para crear páginas estáticas has de crearlas en ''/app/views/pages'' como archivo .thtml. Para acceder a ellas sería: /pages/, por ejemplo si se crea una página llamada ''/views/pages/about.thtml'' será accesible mediante ''http://www.example.com/pages/about''. === Variables globales === Podemos usar un objeto //Configure// para guardar lo que queramos y será accesible desde cualquier lugar de CakePHP. $config =& Configure::getInstance(); $config->myVar = 'test'; === Controlador sin modelo === Puedes crear un controlador sin modelo de base de datos asignando un array vacío a la variable ''$uses'': ===== Notas ===== ==== Convenciones de la Base de Datos ==== * Nombres de tablas en inglés y en plural. * Las tablas deben tener una clave primaria llamada id. * Para crear claves foráneas utiliza nombres del estilo nombretabla_id. * Campos como created o modified del tipo datetime se rellenarán automáticamente. ==== Ficheros ==== * {{fw:others:manual_cakephp.pdf|Manual de CakePHP}} * {{fw:others:cakesheet.pdf|Hoja resumen de CakePHP}} * {{fw:others:ocphp.pdf|Tutorial de CakePHP}} * {{sp:php:cook_up_websites_fast_with_cakephp.zip|Cook up websites fast with CakePHP}} * {{sp:php:the_cakephp_framework_your_first_bite.pdf|}} ==== Links ==== * [[http://cakephp.org/]] * [[http://www.carlosleopoldo.com/2007/09/17/tutoriales-muy-utiles-de-cakephp/]] * [[http://grahambird.co.uk/cake/]] * [[http://bakery.cakephp.org/]] * [[http://www.cakephp-es.org]]