public function spam($entrada,$numero){ $spam=array('Muy bueno','Estupenda entrada','Eres un crack','Lo mejor que he leído','Ole y ole'); for($i=0;$i<$numero;$i++){ $com=$spam[rand(0,count($spam)-1)]; $new['asunto']=$com; $new['texto']=$com; $new['entrada_id']=$entrada; $this->Comentario->create(); $this->Comentario->save($new); } return $this->redirect(array('controller'=>'Entradas','action' => 'view',$entrada)); }
Función rellenar entradas
Esta función nos rellena la tabla de entradas con el número que le pasemos:
public function rellenar($cantidad) { for ($i = 0; $i < $cantidad; $i++) { $this->Entrada->create(); $this->Entrada->save( array( 'titulo' => 'titulo' . $i, 'texto' => 'texto' . $i ) ); } return $this->redirect(array('action' => 'index')); }
Rutas personalizadas en CakePHP
Podemos reenrutar cualquier url para que nos vaya a un controlador específico. Esto nos evita tener que poner nombres específicos a los controladores, entre otras cosas.
La configuración está en /app/config/routes.php y usa el siguiente formato:
Router::connect( 'URL', array('nombreParam' => 'valorPorDefecto'), array('nombreParam' => 'expresionRegular') )
Por ejemplo, si yo tengo el controlador ‘entradas’ para ver las entradas pero quiero acceder también con ‘posts’ podría hacer lo siguiente:
Router::connect( '/posts', array('controller' => 'entradas', 'action' => 'index') );
Router::connect(
'/:controller/:id', array('action' => 'view'), array(
'pass' => array('id'),
'id' => '[0-9]+'
)
);
Otros ejemplos:
Router::connect( '/contacto', array('controller' => 'pages', 'action' => 'display', 'contacto') ); Router::connect( '/vendedores/:action/*', array('controller' => 'proveedores') );
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.
En este ejemplo cambiamos la manera de pasar parámetros:
Router::connect( // E.g. /blog/3-CakePHP_Rocks '/blog/:id-:slug', array('controller' => 'blog', 'action' => 'ver'), array( // el orden importa, puesto que esto enviará ":id" como el parámetro $articuloID de tu acción. 'pass' => array('id', 'slug'), 'id' => '[0-9]+' ) )
Vistas en CakePHP
Las vistas en cakePhp se guardan dentro de la carpeta /app/views/, normalmente dentro de una carpeta con el mismo nombre que el controlador. Cuando se ejecuta una acción de un controlador, si no especificamos nada, se renderiza la vista con el mismo nombre de la acción.
Por ejemplo, si tengo lo siguiente:
class RecetasController extends AppController {
function ver($id) {
//la lógica de la acción va aqui…
}
}
Y llamo a la url:
localhost/recetas/ver
Se ejecuta la acción ver y se muestra la vista que esté situada en:
/app/views/recetas/ver.ctp
Las plantillas de las vistas tienen extensión .ctp
Podemos usar una vista diferente con el comando render:
$this -> render(`/OtraVista/index`);
Ejercicio repaso
Creamos la base de datos ’empresa’ con las siguientes tablas:
CREATE TABLE `empresa`.`proveedores` ( `id` INT NOT NULL AUTO_INCREMENT, `razon` VARCHAR(45) NULL, `nif` VARCHAR(15) NULL, `fecha_alta` DATE NULL, `credito` DECIMAL(6,2) NULL, PRIMARY KEY (`id`)); CREATE TABLE `empresa`.`productos` ( `id` INT NOT NULL AUTO_INCREMENT, `referencia` VARCHAR(45) NULL, `proveedor_id` INT NULL, `precio` DECIMAL(6,2) NULL, `activo` TINYINT NULL, PRIMARY KEY (`id`));
Queremos hacer mantenimiento en cakePHP.
Ningún campo puede tener un valor nulo.
Validaciones: crédito y precio, decimales. Referencia y nif, alfanuméricos. Referencia es, además, única.
La fecha tiene que validarse y tener un datepicker para escogerla.
El producto puede tener imágenes. Estas se añadirán en una vista aparte, guardándose dentro de la carpeta img de la raiz con una subcarpeta con la referencia del producto.
En la vista del producto (view) se deberán ver las imágenes si existen.
El campo ‘activo’ nunca será visible desde el mantenimiento en cakephp. Con este parámetro haremos otra cosa, pero más adelante.
Ejemplo de parámetros nombrados
El siguiente código filtra con like si pasamos un parámetro con nombre que coincida con un elemento de la tabla:
public function index() { $filtro = array(); foreach ($this->passedArgs as $clave => $valor) { if (in_array($clave, array_keys($this->Autor->schema()))) { $filtro['Autor.' . $clave . ' like'] = '%' . $valor . '%'; } } $this->Autor->recursive = 0; $this->set('autors', $this->Paginator->paginate( $filtro) ); }
Parámetros en cakePHP
Vimos que el formato por defecto de enrutamiento es:
http://example.com/controller/action/param1/param2/param3
Por ejemplo, si yo accedo a:
http://localhost/cakeblog/autors/index/ola/k/ase
Dentro de la función index del controlador de autores tengo la variable $this->passedArgs que vale lo siguiente:
Array | |
( | |
[0] => ola | |
[1] => k | |
[2] => ase | |
) |
Si yo paso parámetros con nombre el array es asociativo con el nombre del parámetro como clave. Ejemplo
http://localhost/cakeblog/autors/index/ola:5/k:7/ase:patata
Me da lo siguiente:
Array | |
( | |
[ola] => 5 | |
[k] => 7 | |
[ase] => patata | |
) |
Ejercicio buscar por edad
Controlador:
public function edad($inicio = 0, $fin = 30) { if (!empty($this->request->query['inicio'])) { $inicio = $this->request->query['inicio']; } if (!empty($this->request->query['fin'])) { $fin = $this->request->query['fin']; } $params = array( 'conditions' => array('Autor.edad BETWEEN ? AND ? ' => array($inicio, $fin)), 'recursive' => -1, 'order' => 'Autor.edad', ); $autores = $this->Autor->find('all', $params); $this->set(compact('autores', 'inicio', 'fin')); }
La vista:
<div class="autors view"> <h2><?php echo __('Autores entre ' . $inicio . " y " . $fin); ?></h2> <?php echo $this->Form->create('Edad', array('type' => 'get', 'url' => array('controller' => 'Autors', 'action' => 'edad'))); echo $this->Form->input('inicio', array( 'label' => 'Introduzca la edad de inicio', 'default'=>$inicio, )); echo $this->Form->input('fin', array( 'label' => 'Introduzca la edad final', 'default'=>$fin, )); echo $this->Form->end('Buscar'); ?> <?php foreach ($autores as $autor): ?> <dl> <dt><?php echo __('Id'); ?></dt> <dd> <?php echo h($autor['Autor']['id']) . " " . h($autor['Autor']['name']); ?> </dd> <dt><?php echo __('Edad'); ?></dt> <dd> <?php echo h($autor['Autor']['edad']); ?> </dd> </dl> <?php endforeach; ?> </div>
Hoja de referencia para cakePHP
Muy completa, y casi más útil que el manual:
A CakePHP cheat sheet (CakePHP reference page)
Opción upload para autores
//En index.ctp: <?php echo $this->Html->link(__('Upload'), array('action' => 'upload', $autor['Autor']['id'])); ?> //En el controlador public function upload($id = null) { if (!$this->Autor->exists($id)) { throw new NotFoundException(__('Invalid autor')); } if ($this->request->is(array('post', 'put'))) { $archivo = $this->request->data['Autor']['archivo']; move_uploaded_file($archivo['tmp_name'], WWW_ROOT . 'autores/' . $id . "/" . $archivo['name']); $this->Flash->success(__('Archivo subido.')); return $this->redirect(array('action' => 'index')); } else { $options = array('conditions' => array('Autor.' . $this->Autor->primaryKey => $id)); $this->set('autor', $this->Autor->find('first', $options)); } } //La vista (entera) <h2>Subiendo archivos para el autor <?=h($autor['Autor']['name'])?></h2> <div class="autors form"> <?php echo $this->Form->create('Autor', array('type' => 'file')); ?> <fieldset> <legend><?php echo __('Escoja el archivo a subir'); ?></legend> <?php echo $this->Form->file('archivo'); ?> </fieldset> <?php echo $this->Form->end(__('Submit')); ?> </div> <div class="actions"> <h3><?php echo __('Actions'); ?></h3> <ul> <li><?php echo $this->Form->postLink(__('Delete'), array('action' => 'delete', $this->Form->value('Autor.id')), array('confirm' => __('Are you sure you want to delete # %s?', $this->Form->value('Autor.id')))); ?></li> <li><?php echo $this->Html->link(__('List Autors'), array('action' => 'index')); ?></li> </ul> </div>