Architecture for Zend Framework + Facebook Connect
I'm currently building out an application using ZF and want to integrate Facebook Connect - had some questions about architecture.
Functionality: All logins go through FB connect, there is no other login form. When a user first clicks 'Connect', the application needs to create an entry for them in the database to tie extra data to (reviews, profile, etc).
The header should have a 'Login with FB Connect' button on all pages if the user isn't logged in, and a welcome message/picture/profile completion % bar if he or she is.
Architecture As far as I can see, there's two components - a JS call that handles the login, redirect, and cookie writing (fb:login-button) and some PHP that reads the cookie. I'm a little confused about what should go where.
The login button is via JS, so I've loaded it in my layout.phtml and handled the cookie check via a View Helper - the helper retrieves the cookie and returns it to the view. That's fine, but I need to handle things like checking if the user exists and adding new users to the database - that doesn't seem like something that belongs in a helper.
I refactored it to include the cookie PHP in the user controller, but I need the cook开发者_如何学JAVAie in the view, which is rendered by a different controller. I called a view action helper, but that seems to be more for returning partial pages, and I can't get the cookie array variable out of it.
I'm fairly new to MVC, and it seems like I'm missing something fairly obvious - thoughts?
Code is right off the FB developers site:
class Zend_View_Helper_FacebookCookie extends Zend_View_Helper_Abstract
{
public function facebookCookie()
{
$FACEBOOK_APP_ID = 'xxx';
$FACEBOOK_SECRET = 'xxx';
$cookie = $this->getFacebookCookie($FACEBOOK_APP_ID, $FACEBOOK_SECRET);
//Zend_Debug::dump($cookie);
return $cookie;
}
public function getFacebookCookie($app_id, $application_secret)
{
$args = array();
parse_str(trim($_COOKIE['fbs_' . $app_id], '\\"'), $args);
ksort($args);
$payload = '';
foreach ($args as $key => $value) {
if ($key != 'sig') {
$payload .= $key . '=' . $value;
}
}
if (md5($payload . $application_secret) != $args['sig']) {
return null;
}
return $args;
}
}
and in the view:
if ($cookie) { ?>
Your user ID is <?= $cookie['uid'] ?>
<?php } else { ?>
<fb:login-button></fb:login-button>
<?php } ?>
The way I've implemented this in the past is via a single preDispatch plugin -- it checks the status of the user with the Facebook API and then modifies their local state (i.e. logged in / not logged in) and stores that state using Zend_Auth and/or Zend_Session.
If the user is authenticated with Facebook but not yet in your database, then the preDispatch plugin creates the record in your database before setting their local state.
Then, you can query Zend_Auth later in the application to determine whether the user is logged in.
The benefit here is that if you implement other authentication mechanisms (OpenID or others) you can simply create another plugin to do this and you don't have to modify the rest of your the user is ultimately 'locally' authenticated by Zend_Auth).
精彩评论