Está en la página 1de 29

CakePHP 2.

1+
Fundamentos
Daniel Glez-Pea

Daniel Glez-Pea

CakePHP es un framework que se basa en el patrn Modelo-Vista-


Controlador para la Web, tambin !ono!ido !omo framework basado
en acciones"

#a fun!ionalidad de la apli!a!in se di$ide en%

Modelos" &e!uperan, 'uardan ( $alidan datos en la base de datos"

Controladores" )mplementan la l'i!a de ne'o!io"

Vistas" Generan el H*+# final de respuesta"

*odos se implementan en len'ua,e PHP"

- ma(ores, !akePHP define%

Componentes" )mplementan fun!ionalidad para apo(ar a los !ontroladores"

Helpers o a(udantes para las $istas"

.lementos para !rea!in de plantillas, es de!ir, partes !omunes a todas las


$istas /Layouts, View Blocks y lements0"

Daniel Glez-Pea

Cmo se despa!1a una peti!in



Daniel Glez-Pea

2n +odelo es una !lase PHP"

3e en!ar'a de re!uperar ( 'uardar datos"

2bi!ados en app/Model"

3e suele !rear un modelo por !ada entidad de la 4D"

#os modelos de !akePHP se basan en el patrn -!ti$e&e!ord, por lo que


realizan dos misiones"

Permiten re!uperar, insertar, eliminar re'istros"

&epresentan un 5ni!o re'istro de una tabla re'istro a!ti$o en !ada momento, !on
a!!eso para leer6es!ribir la !olumna del ob,eto 7a!ti$o8"

!mportante" La clase y el #ic$ero de%en nom%rarse como la


entidad en la B&. 'Principio Con(ention o(er Con#i)uration*
<?php
//fichero app/Model/Ingredient.php
class Ingredient extends AppModel {
public $name = 'Ingredient';
}

Daniel Glez-Pea

-l'unos mtodos ( atributos de los +odelos"

-tributo id" Cla$e primaria del re'istro a!ti$o a!tual"

s o%li)atorio de#inir en todas las ta%las un id auto incremental.

3e estable!e autom9ti!amente despus de !rear un re'istro /mtodo create0"

+todos

find(...)" De$uel$e re'istros de la base de datos en forma de arra(" :o


modifi!an el re'istro a!ti$o"

create(...)" Crean un nue$o re'istro en la base de datos" .l atributo id pasa a


ser el del re'istro !reado"

read(...)" #ee un re'istro de la base de datos que a1ora ser9 el re'istro a!ti$o"

set(...)" .stable!e un $alor de un !ampo en el re'istro a!ti$o /no lo 'uarda en


la 4D0, para ello se usa save(...)"

save(...)" Guarda datos en un re'istro que pueden ser ;0 pas9dos !omo


par9metros mediante arra( o <0 los $alores presentes en el re'istro a!ti$o"

updateAll(...)" .stable!e $arios $alores en los re'istros que !umplan una


!ondi!in"

Daniel Glez-Pea

.,emplos b9si!os"

Crear6-!tualizar /mtodos create(), save() ( updateAll()0

.liminar
// Crear (create + save): id no establecido o es null
$this->Recipe->create();
$this->Recipe->save(array("name"=>"spaguetti carbonara"));
// Actualizar un registro (establecer id + save)
$this->Recipe->id = 2;
$this->Recipe->save(array("name"=>"spaguetti carbonara"));
// Actualizar varios registros: updateAll(campos, condiciones)
$this->Recipe->updateAll(array("approved => true), array("name LIKE"
=> "%spaguetti%"));
//Eliminar un registro
$this->Recipe->delete($id);
//Eliminar varios registros
$this->Recipe->deleteAll(array("name" => "spaguetti carbonara"));

Daniel Glez-Pea

.,emplos b9si!os /))0

&e!uperar

.l mtodo find(modo, parametros) permite re!uperar datos de la


4D"

#os modos m9s b9si!os /e=isten m9s ( se pueden definir propios0 son%

null" &e!upera el 5ni!o re'istro !u(o id sea el del re'istro a!ti$o

7all8" &e!uperar todas las filas que !umplan las !ondi!iones" De$uel$e un arra(
aso!iati$o, a'rupando primero por n5mero de fila, lue'o por tabla /a $e!es una
!onsulta tiene $arias tablas0 ( lue'o por !ampo"

7!ount8" De$uel$e la !uenta de filas que !umplen las !ondi!iones"


//Select * from recipe where recipe.id = $this->Recipe->id
$this->Recipe->find()
//Select * from recipe
$this->Recipe->find('all');
//Select * from recipes where name LIKE "spaguetti%
$this->Recipe->find('all',
array("conditions => array("name LIKE => "spagetti%))

Daniel Glez-Pea

&ela!iones"

#as rela!iones entre las entidades deben estable!erse en las


!lases +odelo"

.n fun!in del tipo de rela!in /;%;, ;%:, :%;, :%+0, se debe usar
un atributo distinto"

.se atributo es, !omo m>nimo, el nombre del otro modelo rela!ionado"
3e pueden indi!ar $arias rela!iones del mismo tipo, empleando un arra("

#a si'uiente tabla muestra qu atributo se debe usar%



Daniel Glez-Pea

&ela!iones /))0"

.,emplo
<?php
class User extends AppModel {
public $name = 'User';
public $hasMany = 'Comment';
}
//Resultado de $this->User->find()
Array
(
[User] => Array
(
[id] => 121
[name] => Gwoo the Kungwoo
[created] => 2007-05-01 10:31:01
)
[Comment] => Array
(
[0] => Array
(
[id] => 123
[user_id] => 121
[title] => On Gwoo the Kungwoo
[body] => The Kungwooness is not so Gwooish
[created] => 2006-05-01 10:31:01
)
[1] => Array
(
[id] => 124
[user_id] => 121
[title] => More on Gwoo
[body] => But what of the Nut?
[created] => 2006-05-01 10:41:01
)
)
)
+i no se de#ine, se asume
,ue las cla(es #or-neas se
nom%ran as."
<tablaRelacionada>_id

Daniel Glez-Pea

&ela!iones /)))0"

-l re!uperar, se re!uperan por defe!to todos los re'istros


rela!ionados"

Para e$itarlo, se debe espe!ifi!ar "recursive" => 0.

-l tener un modelo rela!ionado !on otro, desde uno se


puede a!!eder al otro"

.l mtodo delete(), re!ibe el par9metro !as!ade para


de!idir si se deben eliminar los re'istros rela!ionados"
$this->Recipe->delete($id, true);
$this->Recipe->Ingredient->find('all') $this->Recipe->Ingredient->find('all')
$this->Recipe->find('all', array("recursive"=>0))

Daniel Glez-Pea

?alida!in"

#a l'i!a de $alida!in de datos tambin se in!lu(e en los +odelos"

CakePHP propor!iona mu!1as re)las de (alidaci/n por defe!to"

#as re'las de $alida!in se estable!en en el atributo validate en el


+odelo"

*ambin se pueden !rear re'las de $alida!in propias que de$ol$er9n


un booleano si el !ampo es !orre!to o no"
public User extends AppModel{
public $validate = array(
'login' => array(
'loginRule-1' => array(
'rule' => 'alphaNumeric',
'message' => 'Only alphabets and numbers allowed',
),
'loginRule-2' => array(
'rule' => array('minLength', 8),
'message' => 'Minimum length of 8 characters'
)
)
);
}

Daniel Glez-Pea

2n Controlador es una !lase PHP"

3e en!ar'a de atender una peti!in ( e,e!utar la l'i!a de ne'o!io !orrespondiente"

2bi!ados en app/Controller"

3e !ompone de un !on,unto de a!!iones /!ada a!!in es un mtodo0" #a a!!in por


defe!to es index()"
# /app/Controller/RecipesController.php
class RecipesController extends AppController {
public function view($id) {
//action logic goes here..
}
public function share($customerId, $recipeId) {
//action logic goes here..
}
public function search($query) {
//action logic goes here..
}
}

Daniel Glez-Pea

#as peti!iones H**P lle'an a los !ontroladores en fun!in de la 2&#"


.,emplo% la 2&#% 1ttp%661ost6produ!ts6sear!16pizza
se !on$ierte en la llamada%
ProductsController::search("pizza")

#a peti!in H**P est9 en el atributo $this->request

#os datos pasados por formulario P@3* est9n en $this->request->data

#os par9metros pasados por G.* est9n en $this->request->query

@tros, !omo la !abe!era &eferer, est9n dire!tamente en $this->referer()

Ci!lo de $ida" .=isten 1ooks que se pueden sobrees!ribir para a!tuar de


forma 'enri!a antes o despus de !ualquier a!!in"

beforeFilter()" 3e e,e!uta antes de !ada a!!in" 4uen lu'ar para !omprobar


permisos, elementos de sesin, et!"

beforeRender()" Despus de la a!!in ( antes de pasar a renderizar la $ista"

afterFilter()" Despus de la a!!in ( de que se 1a(a renderizado la $ista"



Daniel Glez-Pea

Controladores ( +odelos"

#os !ontroladores tienen a!!eso a un +odelo en fun!in de su


nombre"

.,emplo% el !ontrolador 0ecipesController, tiene a!!eso a 0ecipe, a


tra$s de $this->Recipe

Controladores ( ?istas"

#os !ontroladores t>pi!amente pasan resultados a la $ista


estable!iendo $ariables !on el mtodo set"

.n la $ista, e=istir9n $ariables !on el nombre ( $alor indi!ados

*ambin es 1abitual que un !ontrolador quiera responder


rediri)iendo al !liente /H**P AB=0"

Por e,emplo, tras un P@3*, para implementar P@3*-&.D)&.C*-G.*"


$this->set('recipes', $this->Recipe->find('all'))
$this->redirect(array('action' => 'index'));

Daniel Glez-Pea

.=isten dos !ontroladores por defe!to"

Pa'esController /pa'es0"

Controlador para !ontenido est9ti!o /sin apenas l'i!a


de ne'o!io0

*oda peti!in 6pa'es6al'o, simplemente renderizar9 la


plantilla 6?iew6Pa'es6al'o"p1p

-ppController

Clase base para los !ontroladores" 4uen lu'ar para


poner !omportamiento 'enri!o a todos los
!ontroladores"

Daniel Glez-Pea

#os !ontroladores pueden emplear componentes, que


aaden fun!ionalidad a los !ontroladores"

3e definen en el atributo components mediante un arra( que


aso!ia el nombre del !omponente a usar ( op!iones parti!ulares
del mismo"

#os !omponentes est9n disponibles en $this->Componente


class PostsController extends AppController {
public $components = array(
'Session',
'Auth' => array(
'authorize' => array('controller'),
'loginAction' => array('controller' => 'users', 'action'
=> 'login')
),
'Cookie' => array('name' => 'CookieMonster')
);
$this->Session->setFlash("Recipe added successfully)

Daniel Glez-Pea

-l'unos !omponentes"

3essions"

+ane,o de sesiones" *iene mtodos a ma(ores que el mane,o propio de PHP"

Por e,emplo, setFlash(), que permite meter mensa,es temporales en sesin /e,% 7produ!to
p dado de alta !orre!tamente80" Ctil para implementar P@3*-&.D)&.C*-G.*" .n el P@3* se
e,e!uta setFlas1, ( en el G.* la plantilla renderizar9 el mensa,e flas1 una sla $ez, mediante
el SessionHelper::flash.

-!!ess !ontrol lists"

)mplementa el modelo -C#, es de!ir, permite autorizar6dene'ar la realiza!in de


!iertas a!!iones sobre !iertos elementos a !iertos usuarios" #os permisos se
pueden 'uardar en base de datos /Db-!l0 o en fi!1eros ):) /)ni-!l0"

-ut1enti!ation /-ut10"

@tros% 3e!urit(, -!!ess !ontrol lists, Cookies, .mails, et!"



Daniel Glez-Pea

#as $istas son fi!1eros PHP /!on e=tensin "!tp0" *>pi!amente H*+# !on PHP
in!rustado"

2bi!adas en /app/View/<Controlador>/<accion.ctp>

.n la $ista est9n definidas las $ariables estable!idas pre$iamente en el


!ontrolador mediante set(nombre_variable, valor)"

.n la $ista se pueden emplear -(udantes o Helpers, que deben ser de!larados


en el !ontrolador !on el atributo helpers

Por defe!to, la $ista se !orresponde !on la a!!in del !ontrolador e,e!utada" 3in
embar'o, el !ontrolador puede emplear otra $ista si lo desea, simplemente
in$o!ando $this->render()
<?php
class PostsController extends AppController {
public $helpers = array('Html', 'Form');
<?php
// Render the element in /View/Elements/ajaxreturn.ctp
$this->render('/Elements/ajaxreturn');

Daniel Glez-Pea

.,emplo de $ista
<!-- File: /app/View/Posts/index.ctp -->
<h1>Blog posts</h1>
<table>
<tr>
<th>Id</th>
<th>Title</th>
<th>Created</th>
</tr>
<!-- Recorremos $posts, que ha sido establecido mediante set en el controlador -->
<?php foreach ($posts as $post): ?>
<tr>
<td><?php echo $post['Post']['id']; ?></td>
<td>
<?php echo $this->Html->link($post['Post']['title'],
array('controller' => 'posts', 'action' => 'view', $post['Post']['id'])); ?>
</td>
<td><?php echo $post['Post']['created']; ?></td>
</tr>
<?php endforeach; ?>
<?php unset($post); ?>
</table>

Daniel Glez-Pea

CakePHP define un me!anismo para or'anizar las partes !omunes en las $istas"
3e basa en ?iew 4lo!ks /desde !akePHP <";0, #a(outs, ?iews ( .lements"

View Blocks" Definen 7slots7 que se insertan en un sitio /'eneralmente el #a(out0, pero
se rellena desde otras partes /t>pi!amente las ?iews0"

.l blo!k por defe!to es 7!ontent7, que es donde se inserta el !ontenido renderizado por ?iew que no
sea de otro blo!k"

@tros blo!ks predefinidos son 7meta8, 7!ss8, 7s!ript8, que permite que las $istas definan meta-ta's,
1o,as de estilos ( s!ripts" Para rellenar esos bloques se puede utilizar HtmlHelper, que tiene una
fun!in para aadir !ontenido a !ada uno"

#a plantilla por defe!to est9 /App/View/Layouts/default.ctp

#os $iew blo!k se insertan !on $this->fetch("nombrebloque) ( su !ontenido se en !ualquier


$ista, !on los mtodos start6append6end"
<?php
// In the view: create the sidebar block.
$this->start('sidebar');
echo "this is the sidebar content;
$this->end();
echo "this is for the content;
// Append into the sidebar later on.
$this->append('sidebar');
echo "more content to the sidebar;
$this->end();
<?php
// in the layout
<html>
<body>
<div id=sidebar>
<? echo $this->fetch('sidebar'); ?>
</div>
<div id=content>
<? echo $this->fetch('content'); ?>
</div>
</body>

Daniel Glez-Pea

Views" #as que renderizan el !ontenido propio de la a!!in e,e!utada" 3u


!ontenido se !ar'a en el blo!k 7!ontent8"

Layout" Plantilla prin!ipal ( !om5n a las $istas" #a ma(or>a de los $iew


blo!ks son in$o!ados en ella"
<html>
<head>
<title><?php echo $title_for_layout?></title>
<?php
echo $this->fetch('meta');
echo $this->fetch('css');
echo $this->fetch('script');
?>
</head>
<body>
<!-- If you'd like some sort of menu to
show up on all of your views, include it here -->
<div id="header"> ... </div>
<!-- Here's where I want my views to be displayed -->
<?php echo $this->fetch('content'); ?>
<!-- Add a footer to each displayed page -->
<div id="footer">...</div>
</body>
</html>
#o que renderi!e la $iew
!on!reta $a aqu> /slot
!ontent0

Daniel Glez-Pea

lements" Definen fra'mentos de $ista reutilizables ( parametrizables, que


son llamados !on $this->element desde !ualquier $ista o la(out"

3uele ser 1abitual que los element requieran de l'i!a de ne'o!io /e,% un element que
!ar'a los produ!tos m9s !omprados ( que forman parte de la plantilla 'lobal0"

Para ello se re!omienda in$o!ar a una a!!in de un !ontrolador /e,%


6Produ!ts6bestsellers0, para respetar el +?C"

Para llamar a una a!!in dire!tamente desde un element, se debe usar $this-
>requestAction() en el element"

.n el Controlador se debe distin'uir si la peti!in es nomal o $iene pedida desde un


requestAction, (a que en el primer !aso debe usar set para en$iar el resultado a
la plantilla ( en el se'undo debe de$ol$er el resultado !omo $alor de retorno"

Daniel Glez-Pea

.,emplo de .lement insertado en un #a(out (


que usa un Controlador"
<!-- Element /app/View/Elements/best.ctp -->
<h2>Best sellers</h2>
<?php
$bests = $this->requestAction('products/best');
?>
<?php foreach ($bests as $best): ?>
<ol>
<li><?php echo $best['Product']['name']; ?
></li>
</ol>
<?php endforeach; ?>
//Controller
<?php
class ProductsController extends AppController {
// ...
public function best() {
$best = // find best products in the BD;
if ($this->request->is('requested')) {
return $best;
} else {
$this->set('bests', $best);
}
}
}
<!-- In the Layout -->
...
<div id=best>
<?php echo $this->element('best'); ?>
</div>
...

Daniel Glez-Pea

Consisten b9si!amente en !lases que a(udan en tareas t>pi!as de


la $ista"

Deben ser de!larados en el !ontrolador !on el atributo helpers"

#os m9s 1abituales son Html, Form ( 3ession"

HtmlHelper" Generar Html m9s f9!il, !omo la !abe!era D@C*DP.,


tablas, 2&#s basados en la sem9nti!a !ontroladorEa!!in,et!"

FormHelper" Genera!in del Html de formularios, $alida!in ( rellenado


autom9ti!o"

3essionHelper" ?isualiza!in de $ariables de sesin /pre$iamente


estable!idas !on el 3essionComponent0"
<?php
class BakeriesController extends AppController {
public $helpers = array('Form', 'Html', 'Session');
}

Daniel Glez-Pea

3e emplea para !rear formularios desde la $ista PHP"

#le$an a !abo tareas t>pi!as de formularios sobre entidades de una 4D"

3ele!!ionan el !omponente $isual m9s ade!uado en fun!in del tipo de dato de la base de datos"

-(udan en la $alida!in b9si!a" +uestran los errores de $alida!in estable!idos en los modelos"

.stable!en $alores por defe!to /5til para formularios de edi!in de un re'istro de la 4D0"

.s altamente !onfi'urable, aunque si no se dan op!iones, siempre 1a( un !omportamiento


por defe!to"

#os $alores por defe!to de los !ampos se pueden estable!er pre$iamente desde el
!ontrolador en Ft1is-Grequest-Gdata
<?php
echo $this->Form->create(); //Modelo por defecto, el del controlador
actual
echo $this->Form->input('username'); //text
echo $this->Form->input('password'); //password
echo $this->Form->input('approved'); //day, month, year, hour, minute,
meridian
echo $this->Form->input('quote'); //textarea
echo $this->Form->end('Add'); //incluye un botn de submit

Daniel Glez-Pea

3e puede emplear -H-I en CakePHP del si'uiente modo"

#as a!!iones pasan a 'enerar una $ista H3@:6I+#"

#as $istas 1a!en peti!iones -H-I desde s!ripts Ha$a3!ript"

@ tambin se puede emplear HsHelper que a(uda a 'enerar


Ha$a3!ript basado en Hquer( /u otras librer>as0 desde PHP"

Para 1abilitar H3@: ( que todas las peti!iones terminadas


en .1son pasan a 'enerar la $ista en ese formato%

.,emplo% /recipes/index.json

)n!luir Routes::parseExtensions("json) en routes.php

)n!luir el !omponente RequestHandler en el !ontrolador

.stable!er la $ariable de $ista _serialize a aquella6s $ariable6s


de $ista que se desean sa!ar en ,son si se soli!ita este formato"

Daniel Glez-Pea

.,emplo%
class BooksController extends AppController{
public $components = array('RequestHandler');
public $helpers = array('Js', 'Html');

function index(){
$this->set("books", array("quijote", "divina comedia"));
$this->set("_serialize", array("books"));
}
}
<?
echo $this->Html->script('jquery');
//ATENCION DESCARGAR jquery y ponerlo en /app/webroot/js/jquery.js
?>
<input type="button" id="boton" value="test!"></input>
<?
$this->Js->get("#boton");
$this->Js->event(
'click',
$this->Js->request(
array('action' => 'index', 'controller'=>'links','ext'=>'json'),
array('async' => true,'success'=>alert(data['books'))
)
);
echo $this->Js->writeBuffer(); // Write cached scripts
?>
Router::parseExtensions("json");
6app6Confi'6routes"p1p
6app6Controller64ooksController"p1p
6app6?iew64ooks6inde="!tp

Daniel Glez-Pea

*odas las 2&#s entrantes son diri'idas a un !ontrolador (


una a!!in"

3e !onfi'ura en app6Confi'6routes"p1p

Por defe!to las 2&#s son%

http://host/<controlador>/<accion>/<p1>/<p2>

3i no 1a( <accion>, la a!!in por defe!to es index()

3i no 1a( <controlador>, el !ontrolador es pa'es ( la


a!!ion es home()

2n uso 1abitual de routes $ale para estable!er una a!!in por


defe!to !omo 1ome"

CakePHP 2.1+
Fundamentos
Daniel Glez-Pea

También podría gustarte