![]() |
|
The Askeet Tutorial |
WARNING: The SVN source code found in the release_day tags is outdated. Please refer to the current version until each day code is updated.
You are currently reading "The Askeet Tutorial" which is licensed under the Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License license.
![]() |
This work is licensed under a
Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License.
Translation of this work into another language is explicitly allowed. |
Despu�s de siete horas de trabajo, la aplicaci�n askeet ha avanzado bien. La p�gina de inicio muestra una lista de preguntas, el detalle de una pregunta muestra sus respuestas, los usuarios tienen una p�gina de perfil, y una lista tem�tica esta disponible para cada p�gina en la sidebar. Nuestro FAQ mejorado-por-la-comunidad esta en la direcci�n correcta (mira la lista de acciones disponibles para ayer), y el usuario aun no puede alterar su propia informaci�n por ahora.
Si la base para la manipulaci�n de datos en la web han sido por mucho tiempo los formularios, hoy t�cnicas AJAX y mejoras en la usabilidad pueden cambiar la forma en una aplicaci�n es construida. Y eso aplica a askeet, tambi�n. Este tutorial le mostrara como agregar interacciones mejoradas-por-AJAX a askeet. El objetivo es permitir al usuario registrado declarar inter�s en una pregunta.
Mientras una petici�n as�ncrona est� pendiente, los usuario de website prove�dos de AJAX no tiene ninguna de las pistas usuales que su acci�n fue tomada en cuenta y que el resultado ser� pronto mostrado. Esta es la raz�n por la cual cada p�gina conteniendo interacciones AJAX deber�a ser capaz de mostrar un indicador de actividad.
Para este prop�sito, agregue arriba de <body>
en el layout.php
global:
<div id="indicator" style="display: none"></div>
Aunque oculto por defecto, este >div>
ser� mostrado cuando una petici�n AJAX este pendiente. Esta vac�o, pero la hoja de estilo main.cc
(ubicada en el directorio askeet/web/css
) le da forma y contenido:
div#indicator { position: absolute; width: 100px; height: 40px; left: 10px; top: 10px; z-index: 900; background: url(/images/indicator.gif) no-repeat 0 0; }
Una interacci�n ajax esta compuesta por tres partes: un llamador (un enlace, un bot�n o cualquier control que el usuario manipula para lanzar la acci�n), una acci�n en el servidor, y una zona en la p�gina para mostrar el resultado de la acci�n al usuario.
Vayamos de nuevo a la muestra de la pregunta. Si recuerdas el d�a cuatro, una pregunta puede ser mostrada en la lista de preguntas y en los detalles de una pregunta.
Es por eso que el c�digo para el titulo de la pregunta y el bloque inter�s fue refactorizado en el fragmento _interested_user.php
. Abre este fragmento nuevamente, y agregar un enlace para permitir a los usuario declarar sus intereses:
<?php use_helper('User') ?> <div class="interested_mark" id="mark_<?php echo $question->getId() ?>"> <?php echo $question->getInterestedUsers() ?> </div> <?php echo link_to_user_interested($sf_user, $question) ?>
Este enlace va a hacer m�s que simplemente redireccionar hacia otra p�gina. De hecho si ya declaro inter�s acerca de la pregunta, el/ella debe poder declararlo de nuevo. Y si el usuario no se encuentra autenticado... bueno, veremos este caso m�s tarde.
El enlace esta escrito en una funci�n helper, que necesita ser creada en askeet/apps/frontend/lib/helper/UserHelper.php
:
<?php use_helper('Javascript'); function link_to_user_interested($user, $question) { if ($user->isAuthenticated()) { $interested = InterestPeer::retrieveByPk($question->getId(), $user->getSubscriberId()); if ($interested) { // already interested return 'interested!'; } else { // didn't declare interest yet return link_to_remote('interested?', array( 'url' => 'user/interested?id='.$question->getId(), 'update' => array('success' => 'block_'.$question->getId()), 'loading' => "Element.show('indicator')", 'complete' => "Element.hide('indicator');".visual_effect('highlight', 'mark_'.$question->getId()), )); } } else { return link_to('interested?', 'user/login'); } } ?>
La funci�n link_to_remote
es el primer componente de
una interacci�n AJAX: El llamador. Declara cual es la acci�n debe ser
llamada cuando el usuario cliquea en el enlace (aqu�: user/interested
) y cual zona de la p�gina necesita ser actualizada con el resultado de la acci�n (aqu�: el elemento de id block_XX
). Dos manejadores de eventos (loading
y complete
) son agregados y asociados a las funciones javascript de prototype.
La librer�a prototype ofrece herramientas javascript muy �tiles para
aplicar efectos visuales en una p�gina web con un simple llamado
funci�n. Su �nico defecto es la falta de documentaci�n, pero el c�digo
es bastante sencillo.
Elegimos utilizar un helper en lugar de un parcial debido que esta funci�n contiene mucho m�s c�digo PHP que c�digo HTML.
No olvide agregar el id id="block_<?php echo $question->getId() ?>"
al fragmento question/_list
.
<div class="interested_block" id="block_<?php echo $question->getId() ?>"> <?php include_partial('interested_user', array('question' => $question)) ?> </div>
Esto funciona solo si defini� apropiadamente el alias
sf
en la configuraci�n de su servidor web, como fue explicado durante el d�a uno.
El atributo update
del helper javascript link_to_remote()
espec�fica la zona de resultados. En este caso, el resultado de la acci�n user/interested
remplazara el contenido del elemento de id block_XX
. Si se encuentra confundido, mire lo que la integraci�n del fragmento en la plantilla:
... <div class="interested_block" id="block_<?php echo $question->getId() ?>"> <!-- entre aqu� --> <?php use_helper('User') ?> <div class="interested_mark" id="mark_<?php echo $question->getId() ?>"> <?php echo $question->getInterestedUsers() ?> </div> <?php echo link_to_user_interested($sf_user, $question) ?> <!-- y aqu� --> </div> ...
La zona de resultado es la parte entre los dos comentarios. La acci�n, una vez ejecutada, remplazara este contenido.
El interese del segundo id (mark_XX
) es puramente visual. El manejador del evento complete
del helper link_to_remote
resalta el <div>
interested_mark
del inter�s clicqueado... despu�s que la acci�n retorne e incremente el n�mero de inter�s.
El llamado AJAX apunta a la acci�n user/interested
. Esta acci�n debe ser crear un nuevo registro en la tabla Interest
para la pregunta actual y el usuario actual. As� es como se hace en symfony:
public function executeInterested() { $this->question = QuestionPeer::retrieveByPk($this->getRequestParameter('id')); $this->forward404Unless($this->question); $user = $this->getUser()->getSubscriber(); $interest = new Interest(); $interest->setQuestion($this->question); $interest->setUser($user); $interest->save(); }
Recuerde que el m�todo ->save()
del objeto Interest
fue modificado para incrementar el campo interested_user
del User
relacionado. As� el n�mero de usuarios interesados acerca de la
pregunta actual ser� m�gicamente incrementada en la pantalla despu�s de
la llamada a la acci�n.
�Y que deber�a mostrar la plantilla interestedSuccess.php
resultante?
<?php include_partial('question/interested_user', array('question' => $question)) ?>
Muestra el fragmento _interested_user.php
del m�dulo question
. Este es el m�s grande inter�s de haber escrito este fragmento en primer lugar.
Tambi�n debemos desactivar el layout para esta plantilla (modules/user/config/view.yml
):
interestedSuccess:
has_layout: off
El desarrollo del inter�s AJAX esta terminado. Puedes probarlo
ingresando un login/password existente en la p�gina de login, mostrando
la lista de preguntas y luego clicqueando un enlace 'interested?'. El
indicador aparece mientras la petici�n es enviada al servidor.
Entonces, el numero es incrementado en remarcado cuando el servidor
responde. Note que el enlace 'interested?' es ahora un texto
'interested!' sin enlace, gracias a nuestro helper link_to_user_interested
:
Si desea m�s ejemplos acerca de los helpers AJAX, puedes leer el tutorial carrito de compra drag-and-drop, mira el screencast asociado o lee el capitulo relacionado del libro.
Previamente mencionamos que s�lo usuarios registrados pueden declarar inter�s sobre un pregunta. Esto significa que si un usuario-no-autorizado cliquea en un enlace 'interested?', la p�gina de login debe ser mostrada primero.
Pero espere. �Por que un usuario cargar�a una nueva p�gina para loguearse, y perder contacto con la pregunta que el/ella ha declarado inter�s? Una mejor idea ser�a tener un formulario de login en la p�gina. Eso es lo que vamos a hacer.
Abre el layout global (en askeet/apps/frontend/templates/layout.php
), y agrega (entre el div header
y el content
):
<?php use_helper('Javascript') ?> <div id="login" style="display: none"> <h2>Please sign-in first</h2> <?php echo link_to_function('cancel', visual_effect('blind_up', 'login', array('duration' => 0.5))) ?> <?php echo form_tag('user/login', 'id=loginform') ?> nickname: <?php echo input_tag('nickname') ?><br /> password: <?php echo input_password_tag('password') ?><br /> <?php echo input_hidden_tag('referer', $sf_params->get('referer') ? $sf_params->get('referer') : $sf_request->getUri()) ?> <?php echo submit_tag('login') ?> </form> </div>
Una vez m�s, este formulario esta escondido por defecto. La etiqueta referer
contiene el par�metro referer
de la petici�n si existe, o sino la actual URI.
�Recuerdas el helper User
que escribimos previamente? Ahora lidiaremos con el caso cuando el usuario no est� autenticado. Abre nuevamente el archivo askeet/lib/helper/UserHelper.php
y cambie la linea:
return link_to('interested?', 'user/login');
con est�:
return link_to_function('interested?', visual_effect('blind_down', 'login', array('duration' => 0.5)));
Cuando el usuario no esta autenticado, el enlace en la la palabra 'interested?' lanza un efecto javascript de prototype (blind_down
) que revela el elemento de id login
- y este es el formulario que acabamos de agregar al layout.
La acci�n user/login
ya fue escrita durante el quinto d�a, y refactorizado durante el d�a seis. �Debemos modificarlo nuevamente?
public function executeLogin() { if ($this->getRequest()->getMethod() != sfRequest::POST) { // display the form $this->getRequest()->getParameterHolder()->set('referer', $this->getRequest()->getReferer()); return sfView::SUCCESS; } else { // handle the form submission // redirect to last page return $this->redirect($this->getRequestParameter('referer', '@homepage')); } }
Despu�s de todo, no. Funciona perfectamente como esta, el manejo del referer, redireccionar� al usuario a la p�gina donde el/ella se encontraba cuando el enlace fue cliqueado.
Prueba la funcionalidad AJAX ahora. Un usuario sin registrarse ser� presentado con un formulario de login sin dejar la p�gina actual. Si el nickname y el password son reconocidos, la p�gina se refrescara y el usuario ser� capaz de cliquear en el enlace 'interested?' que intent� clicar anteriormente.
Nota: En muchas interacciones AJAX como esta, la plantilla del servidor es simplemente un
include_partial
. Esto es debido a que un resultado inicial es generalmente presentado cuando la p�gina se presenta por primera vez, y porque la parte que es actualizada por la acci�n AJAX es parte de la plantilla inicial.
Lo m�s dif�cil en dise�ar interacciones AJAX es definir
apropiadamente el llamador, la acci�n del server, y la zona resultante.
Una vez que los conoces, symfony provee los helpers que realizan el
resto. Para estar seguro de que entiendes, mira como implementamos el
mismo mecanismo para declarar inter�s para la declarar inter�s para la
relevancia de un respuesta. Esta vez, la acci�n AJAX llamada es user/vote
, el parcial es _answer.php
es separado en dos partes (creando el parcial _user_vote.php
), y dos helpers link_to_user_relevancy_up()
y link_to_user_relevancy_down
son creado en el helper User
. El m�dulo User
gano una acci�n vote
y una plantilla voteSuccess.php. No olvide de establecer el layout a
off` para esta plantilla tambi�n.
Askeet comienza a verse como una aplicaci�n web 2.0. Y es solo el comienzo: En unos d�as, le agregaremos algunas m�s interacciones AJAX. Ma�ana tomaremos la ocasi�n para hacer un repaso general de t�cnicas MVC en symfony, e implementar una librer�a externa.
Si encuentra un problema mientras tratas de seguir el tutorial de hoy, puedes descargar el c�digo completo etiquetado release_day_8
desde el repositorio SVN de askeet. Si no tienes ning�n problema, ven al foro askeet para responder preguntas de otros.
If you find a typo or an error, please register and open a ticket.
If you need support or have a technical question, please post to the user mailing-list or to the forum.