首先,编辑composer .项目根文件夹中包含Facebook SDK的json:
{
"require" : {
"facebook/graph-sdk" : "~5.0"
}
}
Next run composer update
at shell prompt to pull in the sdk to the vendor folder.
现在,我们想在我们的应用程序中使用Facebook SDK作为服务Provider .但在此之前,让我们先设置app_id
、app_secret
和default_graph_version
,这是向Facebook API发出请求时所需的参数.app_id和app_secret可在Facebook Developers网站注册获得.
一旦我们从Facebook获得这些凭据,我们现在将编辑项目根文件夹中的.env
个文件.将它们添加到末尾:
FACEBOOK_APP_ID=xxxxxxxxxxxxxxxx
FACEBOOK_APP_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
FACEBOOK_DEFAULT_GRAPH_VERSION=v2.8
Replace the xxx.. with the values provided to you. Note that the variable names are just my own creation. You can name them whatever you'd like. We would now have to use these variables to setup a separate config file. We need to do this so that we can use Laravel's config() helper function to retrieve the values wherever we want within the app. So let's create facebook.php in the config folder and add the following:
<?php
return [
'config' => [
'app_id' => env('FACEBOOK_APP_ID', null),
'app_secret' => env('FACEBOOK_APP_SECRET', null),
'default_graph_version' => env('FACEBOOK_DEFAULT_GRAPH_VERSION', 'v2.8'),
],
];
With this simple setup we can now call config('facebook.config')
from anywhere in the app. It would return the array along with the relevant values matched from the .env file.
现在,让我们将其设置为服务Provider ,这样我们就不必每次调用Facebook API时都检索这些凭据并构建新的Facebook对象.
In Laravel 5.4, open the file app\Providers\AppServiceProvider.php
. If you don't have this file or want to make a separate one, then you could create a new service provider at shell:
php artisan make:provider FacebookServiceProvider
We can now edit FacebookServiceProvider.php
in the Providers folder instead. The only difference is that we need to register this in the our config/app.php
file. You would add the following at the end of the $providers
array:
App\Providers\FacebookServiceProvider::class,
为了继续相关代码,在AppServiceProvider.php
或新的FacebookServiceProvider.php
中,我们首先包括:use Facebook\Facebook;
在顶部.然后在register() method
中添加以下内容:
$this->app->singleton(Facebook::class, function ($app) {
return new Facebook(config('facebook.config'));
});
You might notice that I am binding the class as a singleton
since for my app I would like to reuse the same object from the service container. There are other types of bindings provided by Laravel that you might want to check out.
整个代码如下所示(我使用的是AppServiceProvider.php):
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Facebook\Facebook;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
//
}
/**
* Register any application services.
*
* @return void
*/
public function register()
{
$this->app->singleton(Facebook::class, function ($app) {
return new Facebook(config('facebook.config'));
});
}
}
就这样.我们现在有了Facebook作为应用的一项服务.我们现在可以在应用程序中的任何地方使用facebook对象.从这里开始,人们只需按照Facebook documentation中的说明调用API即可
Extra Stuff, just as an example:个
Before proceeding, I'd like to mention that I found the series of posts written by the folks at Symfony to be very helpful to understand the concepts of Service Container
and Dependency Injection
. You can find them here
现在让我们试着做一个基本的操作,比如从facebook检索一个人的名字.为了获取facebook用户的信息,我们需要通过发送基本参数来调用facebook API:用户的facebook id和访问令牌.让我们分别称之为uid
和access_token
.你需要使用Facebook的一种方法来检索这些信息:
- FacebookRedirectLoginHelper - when you want facebook authentication to happen from server side.
- FacebookCanvasHelper-用于基于客户端画布的应用程序身份验证
- FacebookJavaScriptHelper-用于客户端javascript身份验证
你可以按照Facebook的getting started指南中提供的步骤设置你想要的身份验证类型.
我的应用程序非常简单,所以我使用了客户端javascript身份验证.我还同时使用jquery.因为我使用了Laravel的blade引擎,所以我的javascript直接嵌入到视图文件中,这样我就可以包括Laravel的csrf_token()
,并使用其他辅助函数,比如url()
.客户端javascript如下所示.记住用您的值替换appId
,并将文件另存为login.blade.php
.
<html>
<head>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<button id="btn-login" type="button" class="btn btn-primary btn-lg">
<span> Login with Facebook</span>
</button>
<script>
$(document).ready(function() {
$.ajaxSetup({ cache: true }); // since I am using jquery as well in my app
$.getScript('//connect.facebook.net/en_US/sdk.js', function () {
// initialize facebook sdk
FB.init({
appId: 'xxxxxxxxxxxxxxxx', // replace this with your id
status: true,
cookie: true,
version: 'v2.8'
});
// attach login click event handler
$("#btn-login").click(function(){
FB.login(processLoginClick, {scope:'public_profile,email,user_friends', return_scopes: true});
});
});
// function to send uid and access_token back to server
// actual permissions granted by user are also included just as an addition
function processLoginClick (response) {
var uid = response.authResponse.userID;
var access_token = response.authResponse.accessToken;
var permissions = response.authResponse.grantedScopes;
var data = { uid:uid,
access_token:access_token,
_token:'{{ csrf_token() }}', // this is important for Laravel to receive the data
permissions:permissions
};
postData("{{ url('/login') }}", data, "post");
}
// function to post any data to server
function postData(url, data, method)
{
method = method || "post";
var form = document.createElement("form");
form.setAttribute("method", method);
form.setAttribute("action", url);
for(var key in data) {
if(data.hasOwnProperty(key))
{
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", key);
hiddenField.setAttribute("value", data[key]);
form.appendChild(hiddenField);
}
}
document.body.appendChild(form);
form.submit();
}
</script>
</body>
</html>
If your app has a different set of permissions needed from user, then edit the scope
field. For all available facebook permissions see here.
所以基本上,我的代码有一个登录按钮,当用户点击它时,javascript sdk就会启动并弹出一个登录窗口.用户登录后,我会将数据发回服务器,就像发布表单一样.
Now back to server side, since we have uid
and access_token
we can store these to database and then make a simple call to Facebook API from our server. Set up a route in routes/web.php
to receive the form data:
Route::post('login', 'FacebookUser@store');
Make FacebookUser
controller at shell:
php artisan make:controller FacebookUser
And the controller's code is as follows:
<?php
namespace App\Http\Controllers;
use Request;
use App\User; // you need to define the model appropriately
use Facebook\Facebook;
class FacebookUser extends Controller
{
public function store(Facebook $fb) //method injection
{
// retrieve form input parameters
$uid = Request::input('uid');
$access_token = Request::input('access_token');
$permissions = Request::input('permissions');
// assuming we have a User model already set up for our database
// and assuming facebook_id field to exist in users table in database
$user = User::firstOrCreate(['facebook_id' => $uid]);
// get long term access token for future use
$oAuth2Client = $fb->getOAuth2Client();
// assuming access_token field to exist in users table in database
$user->access_token = $oAuth2Client->getLongLivedAccessToken($access_token)->getValue();
$user->save();
// set default access token for all future requests to Facebook API
$fb->setDefaultAccessToken($user->access_token);
// call api to retrieve person's public_profile details
$fields = "id,cover,name,first_name,last_name,age_range,link,gender,locale,picture,timezone,updated_time,verified";
$fb_user = $fb->get('/me?fields='.$fields)->getGraphUser();
dump($fb_user);
}
}
请注意,通过使用setDefaultAccessToken()
,可以在APP代码库的后续处理的任何部分中从服务容器检索$fb对象.$fb可以直接用于发出Facebook API请求.在当前请求-响应生命周期中,不需要使用app_id和app_ret再次构建$fb,也不需要再次为当前用户设置访问令牌.这是因为$fb是单例的,所以在当前请求-响应生命周期中为Facebook服务调用服务容器时会返回相同的对象.
如果您无法执行方法注入来获取$fb对象,那么有other ways of resolving it个.我个人最喜欢使用resolve()
helper,因为它与类中的对象上下文或静电函数无关.
$fb = resolve('Facebook\Facebook');