Más con Symfony

12.4. Buenas prácticas en las aplicaciones Facebook

Las secciones anteriores han explicado cómo el plugin sfFacebookConnectPlugin se integra perfectamente con sfGuardPlugin y cómo permite crear aplicaciones agnósticas que pueden convertirse en aplicaciones FBML, de tipo <iframe> o de tipo Facebook Connect. No obstante, para crear una aplicación real más compleja y que utilice características avanzadas de Facebook es necesario seguir algunos de los siguientes consejos para aprovechar también las funcionalidades de Symfony.

12.4.1. Utilizando los entornos de Symfony para probar diferentes servidores Facebook Connect

Depurar rápidamente las aplicaciones y facilitar sus pruebas es uno de los principios de Symfony. Desarrollar aplicaciones Facebook puede dificultar seriamente estas opciones, ya que muchas características requieren una conexión a Internet para comunicarse con el servidor de Facebook y un puerto 80 abierto para intercambiar las cookies de autenticación. Además, existe la limitación de que las aplicaciones que utilizan Facebook Connect sólo pueden conectarse a un servidor.

Esta última limitación es un gran problema si la aplicación se desarrolla en una máquina, se prueba en otra, se pone en pre-producción en una tercer máquina y por último se sube a producción en otra máquina. Con Symfony la forma habitual de proceder en este caso sería crear una aplicación para cada servidor y crear un entorno para cada máquina. Realizar todo esto en Symfony es tan sencillo como hacer una copia del archivo frontend_dev.php en otro archivo llamado frontend_preprod.php y modificarlo para indicar que el nuevo entorno se llama preprod (de pre-producción) y no dev:

$configuration = ProjectConfiguration::getApplicationConfiguration('frontend', 'preprod', true);

A continuación, modifica el archivo app.yml para configurar aplicaciones Facebook diferentes en función de cada entorno:

prod:
  facebook:
    api_key: xxx
    api_secret: xxx
    api_id: xxx

dev:
  facebook:
    api_key: xxx
    api_secret: xxx
    api_id: xxx

preprod:
  facebook:
    api_key: xxx
    api_secret: xxx
    api_id: xxx

Ahora la aplicación ya se puede probar en cada uno de os diferentes servidores utilizando como punto de entrada el correspondiente archivo frontend_xxx.php.

12.4.2. Depurando FBML con los mensajes de log de Symfony

La estrategia de cambiar el layout permite desarrollar y probar aplicaciones FBML fuera del sitio web de Facebook. Sin embargo, las pruebas finales sobre Facebook pueden mostrar mensajes de error inesperados y difíciles de comprender. En efecto, el principal problema de mostrar FBML directamente en Facebook es que los errores de tipo 500 se interceptan y reemplazan por unos mensajes de error estándar poco útiles. Además, la barra de depuración web de Symfony tampoco se muestra dentro del frame de Facebook. Afortunadamente, todos estos problemas se pueden solucionar gracias a los mensajes de log de Symfony. El plugin sfFacebookConnectPlugin crea mensajes de log para todas las acciones importantes, y es muy sencillo añadir nuevos mensajes de log desde cualquier lugar de la aplicación:

if (sfConfig::get('sf_logging_enabled'))
{
  sfContext::getInstance()->getLogger()->info($message);
}

12.4.3. Utilizar un proxy para evitar las redirecciones erróneas de Facebook

Uno de los errores más peculiares de Facebook es que una vez que Facebook Connect se ha configurado en la aplicación, el servidor de Facebook Connect se considera la página de inicio de la aplicación. Aunque esta página de inicio se puede configurar, siempre debe pertenecer al mismo dominio del host de Facebook Connect. Así que no queda otro remedio que configurar la portada de la aplicación a una acción simple de Symfony que redirija a la URL adecuada. El siguiente ejemplo muestra el código para redirigir a una aplicación de Facebook:

public function executeRedirect(sfWebRequest $request)
{

  return $this->redirect('http://apps.facebook.com'.sfConfig::get('app_facebook_app_url'));
}

12.4.4. Utilizar el helper fb_url_for() en las aplicaciones Facebook

El enrutamiento es uno de los mayores problemas de que las aplicaciones sean agnósticas y puedan funcionar como FBML dentro de Facebook o como XFBML dentro de un <iframe>:

  • Si se trata de una aplicación FBML, los enlaces internos de la aplicación tienen que apuntar a /app-name/ruta-symfony
  • Si se trata de una aplicación con <iframe>, es importante pasar la información de la sesión de Facebook de una página a otra.

El plugin sfFacebookConnectPlugin incluye un helper especial llamado fb_url_for() y que se encarga de los dos casos.

12.4.5. Redirigiendo dentro de una aplicación FBML

Los programadores de Symfony están acostumbrados a redirigir al usuario a una nueva página tras una operación exitosa, de forma que se evite repetir esa misma operación. Sin embargo, en las aplicaciones FBML las redirecciones no funcionan tal y como se espera. En su lugar, es necesario utilizar una etiqueta especial llamada <fb:redirect> y que ordena a Facebook realizar la redirección. Para que la aplicación funcione correctamente en cualquier caso (etiqueta FBML o redirección normal de Symfony) la clase sfFacebook incluye una función especial para redirecciones que se puede utilizar por ejemplo al guardar una acción:

if ($form->isValid())
{
  $form->save();

  return sfFacebook::redirect($url);
}

12.4.6. Relacionando los usuarios existentes con sus cuentas de Facebook

Uno de los objetivos de Facebook Connect es facilitar el proceso de registro de los nuevos usuarios. De todos modos, otro de sus usos más interesantes es el de relacionar los usuarios ya existentes en el sitio web con sus respectivas cuentas de Facebook, ya sea para obtener más información de los usuarios o para comunicarse a través de su Facebook. Esto se puede conseguir de dos formas:

  • Obligar a los usuarios de tipo sfGuard existentes a que pulsen el botón "Connect with Facebook". La acción sfFacebookConnectAuth/signIn no crea nuevos usuarios de tipo sfGuard si detecta que ese usuario ya existe, pero si que crea cualquier nuevo usuario conectado a través de Facebook Connect. Tan simple como eso.
  • Utilizar el sistema de reconocimiento de emails de Facebook. Cuando un usuario utiliza Facebook Connect en un sitio web, Facebook puede proporcionar un hash especial de sus emails, que se puede comparar con los hash de emails existentes en la base de datos, de forma que se puedan reconocer las cuentas de Facebook pertenecientes a los usuarios que ya estaban creados. No obstante, por razones de seguridad, Facebook sólo proporciona estos hashes si el usuario se ha registrado previamente utilizando su API. Por tanto, resulta imprescindible registrar de forma habitual los emails de todos los nuevos usuarios de forma que puedan ser reconocidos más adelante. Esto es precisamente lo que hace la tarea registerUsers, que ha sido portada a Symfony 1.2 por Damien Alexandre. Esta tarea se debería ejecutar cada noche para registrar todos los nuevos usuarios. También se puede realizar el registro justo después de crear un usuario, mediante el método registerUsers() de sfFacebookConnect:
sfFacebookConnect::registerUsers(array($sfGuardUser));