Mi primera aplicación CakePHP (2)

22 agosto 2008 at 10:50 am 27 comentarios

Continuando con lo visto en la primera parte de la entrada, vamos a solucionar algunas pequeñas pegas de nuestra aplicación.

Primero, vamos a darle nuestro propio diseño (bastante discreto eso sí) a nuestra aplicación. Para ello y como ya comentamos, creamos un layout por defecto (default.thtml) y lo situamos en /app/views/layouts. Su contenido es:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
    <?php echo $html->charset("iso-8859-1"); ?>
    <title>TCYMU CakePHP Gestión de Enlaces</title>
</head>
<body>
<h1>Tus ceros y mis unos</h1>
<h2>Gestión de enlaces</h2>
<?php echo $content_for_layout ?>
<h3>TCYMU por Miguel Orbegozo</h3>
</body>
</html>

Lo que debemos tener en cuenta es la línea con el echo $content_for_layout, que es la forma en la que le indicamos a CakePHP dónde insertar el contenido de las vistas. He utilizado también el HtmlHelper para añadir una cabecera con el charset.

Una segunda cosita que podemos solucionar, es que ahora para entrar en nuestra aplicación tenemos que añadir en la ruta del navegador /links/, para indicar que queremos ir a la acción por defecto del controlador links. Para evitar esto, debemos enrutar la ruta / a dicho controlador. Para ello debemos modificar el archivo /app/config/routes.php modificando la línea que empieza por Router::connect('/' dejándola como sigue:

Router::connect(‘/’, array(‘controller’ => ‘links’, ‘action’ => ‘index’));

Por último vamos a añadir algo más de funcionalidad, permitiendo añadir comentarios a los enlaces almacenados. Esto es una relación de uno a muchos (un enlace puede tener varios comentarios).

Para llevarlo a cabo lo primero es crear la tabla para los comentarios. Al igual que en la entrada anterior, lo haré mediante el PhpMyAdmin.

Destacamos de su estructura lo siguiente:

  • Puntos ya vistos en la primera parte: el nombre de tabla (plural del modelo), la clave primaria id y el campo created.
  • De nombre fijo es también link_id, que es el campo que relaciona un comentario con un enlace en particular.

Vamos con el nuevo modelo, el relativo a los comentarios (app/models/comment.php):

class Comment extends AppModel {
	var $name = 'Comment';

	var $belongsTo = array('Link' => array('className' => 'Link'));

	var $validate = array(
        'comment' => array(
			'rule' => array('maxLength', '200'),
            'required' => true,
			'allowEmpty' => false,
            'message' => 'Menos de 200 caracteres'
		)
    );
}

Como novedad respecto a lo visto anteriormente tenemos la variable $belongsTo, mediante la que indicamos la relación entre un comentario y un enlace (el comentario pertenece a un enlace).

También necesitamos retocar el modelo de enlace ya visto en la primera parte, añadiendo la relación con los comentarios. Se trata sólo de una línea que no precisa demasiada explicación:

var $hasMany = array('Comment' => array('className' => 'Comment'));

Vamos ya con el controlador para los comentarios (app/controllers/comments_controller.php):

class CommentsController extends AppController {

	var $name = 'Comments';

	function add($link_id = false) {
		if (!empty($this->data)) {
			if ($this->Comment->save($this->data)) {
				$this->redirect('/links/');
			}
		} else {
			$this->set('link_id', $link_id);
		}
	}
}

Es un controlador más sencillo que el visto para los enlaces, ya que este sólo define el método add. Las únicas novedades respecto al anterior son:

  • En el método add diferenciamos dos casos:
    1. El caso de recibir el formulario (!empty($this->data)) que es cuando se guarda en la base de datos el comentario.
    2. Si no estamos recibiendo el contenido del formulario es que se va a mostrar el mismo y necesitamos pasarle a la vista el identificador del enlace.
  • Tras añadir un enlace se hace una redirección ($this->redirect('/links/');).

En el controlador de los enlaces no necesitamos añadir nada, ya que al estar relacionados mediante el modelo, al hacer findAll() se recuperan de la base de datos los enlaces junto con todos sus comentarios.

Una nota respecto a findAll(), en las últimas versiones de CakePHP han deprecado findAll(), debiendo ser sustituido por find('all'), aunque no lo voy a cambiar ya que sigo utilizando la misma versión de Cake que en la primera entrada. Supongo que es lo que tiene no haber sido marcada como estable todavía.

Por último vamos con las vistas. En la vista index de los enlaces (app/views/links/index.thtml) añadimos un segundo bucle en el que recorremos los comentarios de cada enlace para mostrarlos en forma de lista. También añadimos el enlace que nos permite añadir un nuevo comentario (en este caso como último elemento de la lista anterior). Pongo el código completo, aunque sólo cambia la parte entre los <ul>.

<h3>Enlaces disponibles</h3>
<?php foreach ($links as $link): ?>

<a href="<?php echo $link&#91;'Link'&#93;&#91;'url'&#93;; ?>"><?php echo $link&#91;'Link'&#93;&#91;'title'&#93;; ?></a>

Añadido: <?php echo $link&#91;'Link'&#93;&#91;'created'&#93;; ?>
<ul>
<?php foreach ($link&#91;'Comment'&#93; as $comment): ?>
	<li><?php echo $comment&#91;'comment'&#93; . ' (' . $comment&#91;'created'&#93; . ')'; ?></li>
<?php endforeach; ?>
	<li><?php echo $html->link('Añadir comentario', '/comments/add/' . $link['Link']['id']);?></li>
</ul>
<?php endforeach; ?>
<?php echo $html->link('Añadir enlace', '/links/add');?>

Podemos ver que en el enlace para añadir un nuevo comentario se le pasa como parámetro el identificador del enlace (recordemos que luego se lo pasamos a la vista de añadir comentario.

La vista de añadir comentario (app/views/comments/add.thtml)queda así:

Añadir comentario.
<?php
echo $form->create('Comment');
echo $form->hidden('link_id', array('value' => $link_id));
echo $form->textarea('comment', array('label' => 'Comentario'));
echo $form->submit('Añadir',array('escape'=>false));
echo $form->end();
?>

Lo único nuevo respecto a los visto en la primera entrega es la creación de un input hidden mediante $form->hidden.

Ahora si dirigimos nuestro navegador al raíz de nuestro servidor podemos ver lo siguiente:

Ya podemos ver el efecto de nuestro propio diseño y los nuevos enlaces para añadir comentario. Pulsando sobre «Añadir comentario» para uno de nuestros enlaces llegamos a la vista para añadir comentario:

Y si añadimos el comentario volvemos a nuestra página principal en la que se aprecia el comentario recién añadido.

Y con esto hemos llegado al final de la segunda entrada. Por supuesto quedaría mucho trabajo por hacer en nuestro gestor de enlaces, y puede que retome el ejemplo en futuras entradas sobre CakePHP.

Espero que os haya gustado (si es el caso un comentario no estaría mal jeje).

Entry filed under: PHP. Tags: , .

Encontrar la ruta absoluta de un jar de mi aplicación Blogday 2008

27 comentarios Add your own

  • 1. Jordi  |  24 noviembre 2008 a las 3:47 pm

    Hola Miguel, ¿qué tal?

    Sigo en línea y te comento 😉 una duda de tu primer fragmento de código en este post. ¿Cómo es que utilizas el juego de caracteres latin1 y no el utf-8?

    ¡Muchas gracias y saludos!

    Jordi

  • 2. Miguel  |  24 noviembre 2008 a las 3:59 pm

    Hola Jordi, ¡saludos de nuevo!.

    La verdad es que no hay razón especial a usar el latin1. Es como lo probé, pero supongo que con utf8 funcionará exactamente igual.

  • 3. Luis Minaya  |  14 enero 2009 a las 5:27 pm

    Hola y muchas gracias!!!
    De verdad este año 2009, he decidido aprender cake yeste ejemplo me da ese primer paso, de verdad que es muy buena manera de pempezar con cake!
    Gracias otra vez y sigue adelante!

  • 4. Miguel  |  14 enero 2009 a las 5:52 pm

    Gracias Luis.

    Siempre son bienvenidos los comentarios de apoyo.

  • 5. Luis Minaya  |  14 enero 2009 a las 10:12 pm

    una pregunta, me ha salido este error y eso que hasta le he hecho copiar y pegar…

    Añadir
    Notice: Undefined variable: form in C:\AppServ\www\cake\app\views\links\add.thtml on line 3

    Fatal error: Call to a member function create() on a non-object in C:\AppServ\www\cake\app\views\links\add.thtml on line 3

  • 6. Luis Minaya  |  14 enero 2009 a las 11:00 pm

    Leyendo los comentarios de la primera parte vi que este error se debia a que yo estaba utilizando la version 1.1 y este ejemplo esta desarrollado por la version 1.2.

    E instalado tambien la version 1.2 y ahora si corre. Muy buena Miguel…

  • 7. juan  |  29 enero 2009 a las 7:29 pm

    podrías explicarnos un poco en el controlador Comment la parte de:

    add($link_id = false)

    porque haces eso? ($link_id = false) ?
    cómo es que te has inventado esa variable?
    hasta donde entiendo es el valor que agarras desde la url /add/ pero, es la forma de extraerlo? es decir, qué sucede si tienes más valores?

    y ahora, cómo podría hacer si en la vista del add (Comment) se le quiere agregar algo como:

    Agregar comentario a «titulo del link»…?
    es decir poner el nombre del titulo de ese id (como utilizar el modelo de Link pero en la vista del controlador Comments)…
    he intentado de varias formas pero aun no comprendo bien eso de las relaciones…

    venga, ya muchas preguntas!

    sería interesante ver más capitulos como este, muchas gracias!

  • 8. Miguel  |  29 enero 2009 a las 8:06 pm

    Hola Juan, bienvenido a mi blog.

    Te voy a contestar por partes.

    $link_id es un parámetro que se le pasa a add (y por defecto es false).

    CakePHP hace el mapeo de urls /controlador/vista/parametro1/parametro2 y así sucesivamente.

    Te pego unos ejemplos sacados de la documentación de CakePHP sobre rutas:

    URL: /monkeys/jump
    Mapping: MonkeysController->jump();

    URL: /products
    Mapping: ProductsController->index();

    URL: /tasks/view/45
    Mapping: TasksController->view(45);

    URL: /donations/view/recent/2001
    Mapping: DonationsController->view('recent', '2001');

    Mañana te intento responder a la segunda pregunta.

    Gracias por postear.

  • 9. Miguel  |  30 enero 2009 a las 9:50 am

    Y continuo con tu respuesta.

    Para poder poner el título necesitas acceder al modelo de Link desde el controlador de Comment. Para ello hay que añadir en dicho controlador:

    var $uses = array('Comment', 'Link');

    Ahora en el método add a la vez que pasar a la vista el link_id podemos recuperar y pasar el título:


    $link = $this->Link->findById($link_id);
    $this->set('link_title',$link['Link']['title']);

    Y ya tendríamos el título disponible en la vista.

    También se podría haber hecho mediante otro parámetro, pero queda más feo (aunque se ahorra una consulta a BBDD).

    Espero haberte ayudado.

  • 10. juan  |  3 febrero 2009 a las 5:54 pm

    excelente!
    muchas gracias…

    saludos!

  • […] de la aplicación que desarrollamos en “Mi primera aplicación CakePHP” (parte 1 y parte 2), que era un pequeño gestor de enlaces. Empezamos con el scaffolding, que podemos traducir como […]

  • 12. ivan  |  27 febrero 2009 a las 12:18 pm

    Está muy bien para empezar, yo es el primer contacto que tengo con cakephp y me está sirviendo para ver como trabaja, aunque hecho en falta alguna explicación más de los códigos.

    Ahora, en la parte de los comentarios, me da estos errores:

    Notice (8): Undefined index: Comment [APP\views\links\index.thtml, line 8]
    Warning (2): Invalid argument supplied for foreach() [APP\views\links\index.thtml, line 8]

    He copiado en el index.thtml de app/views/index.thtml tal y como sale en la página, en la base de datos se guardan bien los comentarios, el añadir funciona bien… el problema es al mostrarlos, que salta este error y no encuentro la manera.

    A ver si me podeis echar una mano, que no consigo localizar el error…

  • 13. Miguel  |  27 febrero 2009 a las 12:39 pm

    Hola Iván. Lo primero gracias por tu comentario.

    En cuanto al error que te aparece, ¿Está bien definida la relación en los modelos de links y comments (las variables hasMany y belongsTo)?. Parece como si en los links no estuvieran los comentarios.

    De todas maneras, ¿me puedes indicar que versión de CakePHP estás utilizando?. A ver si ha cambiado algo que deje el ejemplo inválido.

  • 14. ivan  |  28 febrero 2009 a las 9:30 pm

    Hola Miguel,

    los códigos los he copiado tal cual, desde la vista de texto, ahora mismo no lo tengo delante pues está en el trabajo, la versión con la que estoy trabajando es la 1.2.1.8004.

    Puede ser que en el $belongsTo y el $hasMany, el className aparece con 3 s?

    Un saludo y gracias por responder.

  • 15. Miguel  |  28 febrero 2009 a las 10:32 pm

    Pues eso efectivamente es un error y puede que sea el causante de tu problema.

    Pruébalo y me cuentas por favor.

  • 16. ivan  |  2 marzo 2009 a las 10:18 am

    Hola Miguel,

    el error era mio, que en models en vez de crear el fichero link.php lo había puesto como links.php.

    Gracias!

  • 17. Jorge Gomez  |  14 junio 2009 a las 2:09 am

    Hola en tu ejemplo cuando no cumplo los requisitos a validar (dejo en blanco o hago mas de 200 caracteres, no me muestra el mensaje de validacion sino:
    Notice (8): Undefined variable: link_id [APP/views/comments/add.ctp, line 4]

  • 18. Miguel  |  15 junio 2009 a las 5:05 pm

    Hola Jorge, perdona por la tardanza en responder.

    Ahora mismo no tengo montado este proyecto, pero yo creo que el problema es en la línea 7 del controlador de comentarios.

    Donde dice if ($this->Comment->save($this->data)) {. Esa condición no se cumple, y por tanto en el else también se debería dar valor al identificador de enlace $this->set('link_id', $link_id); (o dejándolo al final para no duplicar código).

    Espero que te ayude.

  • 19. Billy Camacho  |  23 junio 2009 a las 7:09 am

    Miguel, Buenas noches, tratando de hacer el ejemplo que postea Juan, las 2 lineas
    $link = $this->Link->findById($link_id);
    $this->set(‘link_title’,$link[‘Link’][‘title’]);
    en que parte irian los he puesto en comments_controller pero no puedo visualizar el titulo,
    Podrias ayudarme a etenderlo mejor

    Gracias de antemano y felicidades por el site

  • 20. Miguel  |  23 junio 2009 a las 8:54 am

    Hola Billy, a ver si te puedo ayudar.

    Efectivamente lo tienes que poner en el controlador de comentarios. Tienen que ir en la parte del else, por ejemplo tras la línes $this->set('link_id', $link_id);.

    Acuérdate que tienes que poner también en la cabecera de dicho controlador la línea var $uses = array('Comment', 'Link');.

    Por último, para el caso de errores en el formulario aplicaría lo que digo en el comentario 18.

    Un saludo y ya me contarás.

  • 21. entetangente  |  16 febrero 2010 a las 5:44 am

    Hola: Buen tutorial, me has dado una idea de como solucionar un problema que tengo. Espero que me resulte.

  • 22. Miguel  |  16 febrero 2010 a las 9:27 am

    Gracias por tu comentario y espero de verdad que te ayude.

    Y sigue con tu blog!!

  • 23. guille  |  10 abril 2010 a las 7:06 pm

    hola! estoy luchando con el AuthComponent de cakephp que parece muy utiil y lo que no me queda claro es:
    Donde defino a que grupo pertenece el usuario en la BBDD?? en un registro “user.group” o agrego una nueva tabla “group” referenciada desde “user.group_id”. ayuda!!

  • 24. Syl  |  14 julio 2010 a las 1:55 am

    Buen aporte viejo, me sirvio de mucho

  • 25. Erick  |  21 julio 2010 a las 11:49 pm

    Hola, me ha servido de mucho este y el anterior articulo, pero estoy teniendo problemas con el findAll porque al parecer no esta trayendo los comentarios asociados al link.
    Yo estoy usando la version 1.2.5, no se si esto influya en algo.
    El error que me da es el siguiente:
    Notice (8): Undefined index: Comment [APP\views\links\index.thtml, line 8]

  • 26. jose  |  16 febrero 2013 a las 8:42 pm

    Me aparece esto despues de cada link

    Notice (8): Undefined index: Comment [APP/View/Links/index.ctp, line 8]

    Warning (2): Invalid argument supplied for foreach() [APP/View/Links/index.ctp, line 8]

  • 27. teresa  |  24 abril 2013 a las 5:29 pm

    hola podrias ayudarme con un ejemplo de listas desplegable tengo una tabla ccesorios y lo que ne cesito es que cuando seleccione el nombre del accesorio se me activen solo algunos campos de todos los que tengo en la tabla espero me puedas ayudar gracias

Deja un comentario

Trackback this post  |  Subscribe to the comments via RSS Feed


Mi perfil

View Miguel Orbegozo's profile on LinkedIn

Feedjit

Feeds

Otros…

BlogESfera Directorio de Blogs Hispanos - Agrega tu Blog

Bitacoras.com

Add to Technorati Favorites