12.2.1. Crear la aplicación Facebook
Para crear la aplicación es necesario disponer en primer lugar de una cuenta de Facebook con la aplicación "Developer" instalada. La única información necesaria para crear la aplicación es su nombre. Una vez creada, ya no es necesario configurar nada más.
12.2.2. Instalar y configurar sfFacebookConnectPlugin
El siguiente paso consiste en relacionar los usuarios de Facebook con los usuarios
de sfGuard
. Esta es la principal finalidad del plugin sfFacebookConnectPlugin
creado por Fabrice Bernhard y que incluye las contribuciones de muchos otros
programadores de Symfony. Después de instalar el plugin, es obligatorio configurarlo
correctamente para poder usarlo. Para ello, añade en el archivo de configuración
app.yml
la clave de la API y el ID
y el secreto de la aplicación:
# default values
all:
facebook:
api_key: xxx
api_secret: xxx
api_id: xxx
redirect_after_connect: false
redirect_after_connect_url: ''
connect_signin_url: 'sfFacebookConnectAuth/signin'
app_url: '/my-app'
guard_adapter: ~
js_framework: none # none, jQuery or prototype.
sf_guard_plugin:
profile_class: sfGuardUserProfile
profile_field_name: user_id
profile_facebook_uid_name: facebook_uid # WARNING this column must be of type varchar! 100000398093902 is a valid uid for example!
profile_email_name: email
profile_email_hash_name: email_hash
facebook_connect:
load_routing: true
user_permissions: []
Nota Si utilizas una versión antigua de Symfony, no olvides establecer la opción
load_routing
a false
, ya que utiliza el nuevo sistema de enrutamiento.
12.2.3. Configurar una aplicación Facebook
Si el proyecto es una aplicación Facebook, el otro parámetro importante que se
debe configurar es app_url
que apunta a la ruta relativa de la aplicación en
Facebook. Si por ejemplo la aplicación se puede acceder en http://apps.facebook.com/my-app
el valor del parámetro app_url
debería ser /my-app
.
12.2.4. Configurar un sitio web con Facebook Connect
Si el proyecto es un sitio web con Facebook Connect, es habitual dejar los valores por defecto en el resto de las opciones:
redirect_after_connect
permite modificar el comportamiento que se produce después de pulsar el botón "Connect with Facebook". Por defecto el plugin reproduce el comportamiento desfGuardPlugin
tras el registro de un usuario.js_framework
se emplea para indicar el framework JavaScript utilizado. Se recomienda utilizar un framework como jQuery en los sitios web con Facebook Connect porque el código JavaScript de Facebook es muy grande y puede causar errores en Internet Explorer 6 si no se carga bien.user_permissions
es un array con los permisos que se concederán a los nuevos usuarios de Facebook Connect.
12.2.5. Relacionando sfGuard con Facebook
La relación entre los usuarios de Facebook y los del plugin sfGuardPlugin
se
realiza mediante una columna llamada facebook_uid
en la tabla Profile
. El
plugin supone que la relación entre sfGuardUser
y su perfil se realiza mediante
el método getProfile()
. Aunque este es el comportamiento por defecto de
sfPropelGuardPlugin
, en el caso de sfDoctrineGuardPlugin
es preciso configurarlo
a mano. A continuación se muestra un posible archivo schema.yml
:
Para Propel:
sf_guard_user_profile:
_attributes: { phpName: UserProfile }
id:
user_id: { type: integer, foreignTable: sf_guard_user, foreignReference: id, onDelete: cascade }
first_name: { type: varchar, size: 30 }
last_name: { type: varchar, size: 30 }
facebook_uid: { type: varchar, size: 20 }
email: { type: varchar, size: 255 }
email_hash: { type: varchar, size: 255 }
_uniques:
facebook_uid_index: [facebook_uid]
email_index: [email]
email_hash_index: [email_hash]
Para Doctrine:
sfGuardUserProfile:
tableName: sf_guard_user_profile
columns:
user_id: { type: integer(4), notnull: true }
first_name: { type: string(30) }
last_name: { type: string(30) }
facebook_uid: { type: string(20) }
email: { type: string(255) }
email_hash: { type: string(255) }
indexes:
facebook_uid_index:
fields: [facebook_uid]
unique: true
email_index:
fields: [email]
unique: true
email_hash_index:
fields: [email_hash]
unique: true
relations:
sfGuardUser:
type: one
foreignType: one
class: sfGuardUser
local: user_id
foreign: id
onDelete: cascade
foreignAlias: Profile
Nota ¿Qué sucede si el proyecto utiliza Doctrine y el valor de la opción foreignAlias
no es Profile
. En ese caso, el plugin simplemente no funciona. Afortunadamente,
el problema se puede resolver añadiendo un método getProfile()
sencillo en
la clase sfGuardUser.class.php
y que apunte a la tabla Profile
.
También es importante que la columna facebook_uid
sea de tipo varchar
, ya
que los nuevos perfiles de Facebook tienen uids
con valores superiores a 10^15
.
Resulta más sencillo utilizar una columna de tipo varchar
con un índice asociado
en vez de intentar hacer funcionar las columnas de tipo bigint
con los
diferentes ORM.
Las otras dos columnas (email
y email_hash
) son menos importantes y sólo son
necesarias en el caso de los sitios web con Facebook Connect que ya tenían
usuarios registrados previamente. En ese caso, Facebook realia un proceso un
poco complicado para tratar de asociar las cuentas existentes con las nuevas
cuentas de Facebook mediante el hash de un email. El plugin sfFacebookConnectPlugin
facilita este proceso con una de las tareas que incluye, tal y como se describe
al final de este capítulo.
12.2.6. Symfony evita el problema de elegir entre FBML y XFBML
Ahora que ya está todo preparado, es posible empezar a programar la aplicación. Facebook ofrece muchas etiquetas especiales que permiten mostrar funcionalidades completas, como un formulario para invitar a amigos o un sistema completo de comentarios. Estas etiquetas se denominan FBML o XFBML. Los dos tipos de etiquetas son muy similares y la elección depende de si la aplicación se muestra dentro de Facebook o no. Si el proyecto es un sitio web de tipo Facebook Connect, sólo se pueden utilizar las etiquetas XFBML. Si se trata de una aplicación Facebook se pueden seleccionar cualquiera de las dos opciones:
- Si se embebe la aplicación dentro de un
<iframe>
de la página de la aplicación de Facebook, se emplea XFBML. - Si dejamos que Facebook embeba la aplicación de forma transparente, se utiliza FBML.
Facebook aconseja a los programadores que embeban sus aplicaciones de forma transparente, por lo que fomenta el uso de las aplicaciones FBML. En efecto, esta estrategia tiene algunas características muy interesantes:
- No se utiliza ningún
<iframe>
, que siempre es más complicado de gestionar porque tienes que tener en cuenta si los enlaces de la aplicación deben apuntar al<iframe>
o a la ventana contenedora. - El servidor de FBML interpreta las etiquetas especiales FBML, por lo que es posible mostrar información privada del usuario sin tener que realizar una comunicación previa con el servidor de Facebook.
- No es necesario pasar la sesión de Facebook de una página a otra manualmente.
FBML también tiene algunas desventajas importantes:
- Todos los archivos JavaScript se incluyen desde un sandbox, por lo que no pueden utilizar librerías externas como las de Google Maps, jQuery o cualquier otro sistema de estadísticas que no sea Google Analytics (soportado oficialmente por Facebook).
- Facebook asegura que es mucho más rápido porque alguna de las peticiones de la API se pueden sustituir por etiquetas FBML. No obstante, si la aplicación es sencilla, resulta mucho más rápido que disponga de su propio sitio web.
- Resulta más difícil depurar las aplicaciones, sobre todo los errores de tipo 500, que son interceptados por Facebook y se reemplazan por errores estándar.
¿Cuál es entonces la opción recomendada? La buena noticia es que gracias a
Symfony y al plugin sfFacebookConnectPlugin
, no debes tomar ninguna decisión.
Se pueden crear aplicaciones agnósticas cuyo código sirva tanto para las
aplicaciones ejecutadas en un <iframe>
, como para las aplicaciones embebidas
de forma transparente y también para los sitios con Facebook Connect. Esto es
posible ya que técnicamente, la principal diferencia entre ellas reside en el
layout, que en Symfony se puede modificar fácilmente. Estos son los ejemplos de
los dos tipos de layouts:
El layout de una aplicación FBML:
<?php sfConfig::set('sf_web_debug', false); ?>
<fb:title><?php echo sfContext::getInstance()->getResponse()->getTitle() ?></fb:title>
<?php echo $sf_content ?>
El layout de una aplicación XFBML o de tipo Facebook Connect:
<?php use_helper('sfFacebookConnect')?>
<!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" xmlns:fb="http://www.facebook.com/2008/fbml">
<head>
<?php include_http_metas() ?>
<?php include_metas() ?>
<?php include_title() ?>
<script type="text/javascript" src="/sfFacebookConnectPlugin/js/animation/animation.js"></script>
</head>
<body>
<?php echo $sf_content ?>
<?php echo include_facebook_connect_script() ?>
</body>
</html>
Para alternar entre uno y otro layout, simplemente añade el siguiente código
dentro del archivo actions.class.php
:
public function preExecute()
{
if (sfFacebook::isInsideFacebook())
{
$this->setLayout('layout_fbml');
}
else
{
$this->setLayout('layout_connect');
}
}
Nota Existe una pequeña diferencia entre FBML y XFBML que no se encuentra en el layout: las etiquetas FBML se pueden cerrar y las etiquetas XFBML no se pueden cerrar. Así que sustituye este tipo de etiquetas:
<fb:profile-pic uid="12345" size="normal" width="400" />
por esta otra etiqueta equivalente:
<fb:profile-pic uid="12345" size="normal" width="400"></fb:profile-pic>
Para que este cambio sea efectivo, la aplicación también debe ser configurada como de tipo Facebook Connect dentro de las opciones de la aplicación de Facebook, incluso aunque la aplicación sólo esté pensada para FBML. No obstante, la enorme ventaja de hacerlo es que se puede probar la aplicación de forma local.
Si vas a crear una aplicación de Facebook que utilice etiquetas FBML, algo casi inevitable, la única forma de ver el resultado final es publicar el código de la aplicación y ver cómo muestra el resultado Facebook. El uso de Facebook Connect permite utilizar las etiquetas XFBML fuera del sitio web facebook.com y como se ha explicado anteriormente, la única diferencia entre FBML y XFBML es el layout.
Por tanto, la solución presentada permite mostrar las etiquetas FBML de forma local, siempre que dispongas de conexión a Internet. Además, con un entorno de desarrollo accesible desde Internet (como por ejemplo un servidor o un simple ordenador con el puerto 80 abierto) incluso las partes que dependen de la autenticación de Facebook funcionan fuera del dominio facebook.com, gracias al sistema Facebook Connect. De esta forma, puedes probar la aplicación completa antes de subirla a Facebook.
12.2.7. La aplicación sencilla Hola, tu
Si añades el siguiente código en la plantilla de la portada del sitio, ya dispones de una aplicación que muestra el mensaje Hola, [tu nombre]:
<?php $sfGuardUser = sfFacebook::getSfGuardUserByFacebookSession(); ?>
Hello <fb:name uid="<?php echo $sfGuardUser?$sfGuardUser->getProfile()->getFacebookUid():'' ?>"></fb:name>
El plugin sfFacebookConnectPlugin
convierte automáticamente a cualquier
usuario que sea miembro de Facebook en un usuario de tipo sfGuard
. Así es muy
sencillo integrar Facebook con el código Symfony existente que haga uso del
plugin sfGuardPlugin
.