digitonic / laravel-facebook-sdk
完全单元测试的 Laravel & Lumen 5.x 的 Facebook SDK v5 集成
Requires
- php: >=7.3.0
- facebook/graph-sdk: ^5.0
- illuminate/auth: ^6.0|^7.0|^8.0
- illuminate/config: ^6.0|^7.0|^8.0
- illuminate/database: ^6.0|^7.0|^8.0
- illuminate/routing: ^6.0|^7.0|^8.0
- illuminate/session: ^6.0|^7.0|^8.0
- illuminate/support: ^6.0|^7.0|^8.0
Requires (Dev)
- mockery/mockery: ~1.0
- phpunit/phpunit: ^9.3.3
- squizlabs/php_codesniffer: ~2.0
README
一个完全单元测试的包,用于轻松地将 Facebook SDK v5 集成到 Laravel 和 Lumen 5.0、5.1、5.2 和 5.3 中。
此包适用于 Laravel 和 Lumen 5.0、5.1、5.2 和 5.3
- 对于 Laravel 4.2,请查看 1.3 分支。
- 安装
- 重定向示例中的用户登录
- 向 Facebook 发送请求
- Facebook 登录
- 在数据库中保存从 Facebook 获取的数据
- 在 Laravel 中登录用户
- 与多个应用一起工作
- 错误处理
- 故障排除
- 测试
- 贡献
- 鸣谢
- 许可证
我为什么不直接使用 Laravel Socialite 呢?
Laravel 5 内置了对 Socialite 的支持,允许您通过 OAuth 2.0 提供商进行身份验证。Facebook 登录使用 OAuth 2.0,因此 Socialite 支持 Facebook 登录。
如果您只需要认证一个应用并获取一个用户访问令牌以拉取有关用户的基本数据,那么 Socialite 或 The PHP League 的 Facebook OAuth Client 应该足以满足您的需求。
但如果您需要以下任何功能,您将希望将此包与 Facebook PHP SDK 结合使用
- 从签名请求中获取访问令牌
- 照片 或 视频上传
- 批处理请求
- 简单的分页
- 将图数据作为集合返回
安装
将 Laravel Facebook SDK 包添加到您的 composer.json
文件。
composer require sammyk/laravel-facebook-sdk
自动发现:自版本 3.5.0 以来,Laravel Facebook SDK 支持 Laravel 5.5 及更高版本的 自动发现。
服务提供者
在您的应用程序配置中,将 LaravelFacebookSdkServiceProvider
添加到提供者数组。
'providers' => [ SammyK\LaravelFacebookSdk\LaravelFacebookSdkServiceProvider::class, ];
对于 Lumen,将提供者添加到您的 bootstrap/app.php
文件。
$app->register(SammyK\LaravelFacebookSdk\LaravelFacebookSdkServiceProvider::class);
外观(可选)
如果您想使用外观,请将其添加到应用程序配置中的别名数组。
'aliases' => [ 'Facebook' => SammyK\LaravelFacebookSdk\FacebookFacade::class, ];
IoC 容器
IoC 容器将自动为您解决 LaravelFacebookSdk
依赖。您可以从 IoC 容器中获取 LaravelFacebookSdk
实例的多种方式。
// Directly from the IoC $fb = App::make('SammyK\LaravelFacebookSdk\LaravelFacebookSdk'); // Or in PHP >= 5.5 $fb = app(SammyK\LaravelFacebookSdk\LaravelFacebookSdk::class); // From a constructor class FooClass { public function __construct(SammyK\LaravelFacebookSdk\LaravelFacebookSdk $fb) { // . . . } } // From a method class BarClass { public function barMethod(SammyK\LaravelFacebookSdk\LaravelFacebookSdk $fb) { // . . . } } // Or even a closure Route::get('/facebook/login', function(SammyK\LaravelFacebookSdk\LaravelFacebookSdk $fb) { // . . . });
配置文件
注意:自版本 3.4.0 以来,发布配置文件是可选的,只要您设置了您的 必需配置值。
请注意:配置文件中包含默认的Graph API版本,该版本会定期更新到最新稳定版本,这可能在您更新此包的次要或补丁版本时导致破坏性更改。建议您仍然发布配置文件,并在自己的时间内更新Graph API版本,以防止破坏东西。
在Facebook中创建应用后,您需要提供应用ID和密钥。在Laravel中,您可以使用artisan
命令发布配置文件。
$ php artisan vendor:publish --provider="SammyK\LaravelFacebookSdk\LaravelFacebookSdkServiceProvider" --tag="config"
文件在哪里? Laravel 5会将配置文件发布到
/config/laravel-facebook-sdk.php
。
在Lumen中,您需要手动将配置文件从/src/config/laravel-facebook-sdk.php
复制到您基础项目目录中的配置文件夹。由于Lumen默认没有/config
文件夹,因此如果您还没有创建,您需要创建它。
所需配置值
您需要将配置文件中的app_id
和app_secret
值更新为您的应用ID和密钥。
默认情况下,配置文件将查找环境变量以获取您的应用ID和密钥。建议您使用环境变量存储此信息,以保护您的应用密钥免受攻击者侵害。请确保更新您的/.env
文件,并包含您的应用ID & 密钥。
FACEBOOK_APP_ID=1234567890
FACEBOOK_APP_SECRET=SomeFooAppSecret
重定向示例中的用户登录
以下是一个如何使用重定向方法登录用户到您的应用的完整示例。
此示例还演示了如何将短期访问令牌与长期访问令牌交换,如果条目不存在,则将用户保存到您的users
表中。
最后,它将使用Laravel内置的用户身份验证登录用户。
Lumen中的会话:“通过重定向登录”功能依赖于会话来存储CSRF令牌。由于Lumen 5.2+中没有会话,您需要使用不同的方法来获取访问令牌。对于测试,您可以直接从Graph API Explorer获取访问令牌(请确保从“应用程序”下拉菜单中选择您的应用)。
// Generate a login URL Route::get('/facebook/login', function(SammyK\LaravelFacebookSdk\LaravelFacebookSdk $fb) { // Send an array of permissions to request $login_url = $fb->getLoginUrl(['email']); // Obviously you'd do this in blade :) echo '<a href="' . $login_url . '">Login with Facebook</a>'; }); // Endpoint that is redirected to after an authentication attempt Route::get('/facebook/callback', function(SammyK\LaravelFacebookSdk\LaravelFacebookSdk $fb) { // Obtain an access token. try { $token = $fb->getAccessTokenFromRedirect(); } catch (Facebook\Exceptions\FacebookSDKException $e) { dd($e->getMessage()); } // Access token will be null if the user denied the request // or if someone just hit this URL outside of the OAuth flow. if (! $token) { // Get the redirect helper $helper = $fb->getRedirectLoginHelper(); if (! $helper->getError()) { abort(403, 'Unauthorized action.'); } // User denied the request dd( $helper->getError(), $helper->getErrorCode(), $helper->getErrorReason(), $helper->getErrorDescription() ); } if (! $token->isLongLived()) { // OAuth 2.0 client handler $oauth_client = $fb->getOAuth2Client(); // Extend the access token. try { $token = $oauth_client->getLongLivedAccessToken($token); } catch (Facebook\Exceptions\FacebookSDKException $e) { dd($e->getMessage()); } } $fb->setDefaultAccessToken($token); // Save for later Session::put('fb_user_access_token', (string) $token); // Get basic info on the user from Facebook. try { $response = $fb->get('/me?fields=id,name,email'); } catch (Facebook\Exceptions\FacebookSDKException $e) { dd($e->getMessage()); } // Convert the response to a `Facebook/GraphNodes/GraphUser` collection $facebook_user = $response->getGraphUser(); // Create the user if it does not exist or update the existing entry. // This will only work if you've added the SyncableGraphNodeTrait to your User model. $user = App\User::createOrUpdateGraphNode($facebook_user); // Log the user into Laravel Auth::login($user); return redirect('/')->with('message', 'Successfully logged in with Facebook'); });
有关用户身份验证的更多详细信息,请参阅Facebook登录。
向 Facebook 发送请求
对Facebook的请求是通过Graph API进行的。此包是官方Facebook PHP SDK v5的Laravel包装器,因此所有官方SDK提供的方法也在本包中可用。
获取用户信息
以下代码片段将检索表示已登录用户的用户节点。
try { $response = $fb->get('/me?fields=id,name,email', 'user-access-token'); } catch(\Facebook\Exceptions\FacebookSDKException $e) { dd($e->getMessage()); } $userNode = $response->getGraphUser(); printf('Hello, %s!', $userNode->getName());
Facebook 登录
当我们说“使用Facebook登录”时,我们实际上是指“获取一个用户访问令牌以代表用户调用Graph API”。这是通过Facebook通过OAuth 2.0完成的。使用Facebook PHP SDK中称为“辅助工具”的几种方法可以登录用户。
支持的四种登录方法如下
- 通过重定向登录(OAuth 2.0)
- 通过JavaScript登录(带有JS SDK cookie)
- 从应用程序画布登录(带有签名请求)
- 从页面标签登录(带有签名请求)
从重定向登录
将用户登录到您的应用程序的最常见方法之一是使用重定向URL。
想法是生成一个唯一的URL,用户点击该URL。一旦用户点击链接,他们将被重定向到Facebook,要求他们授予您的应用程序请求的任何权限。一旦用户做出回应,Facebook将使用成功响应或错误响应将用户重定向回您指定的回调URL。
可以通过使用SDK的getRedirectLoginHelper()
方法来获取重定向助手。
生成登录URL
您可以像使用Facebook PHP SDK v5一样获取登录URL。
Route::get('/facebook/login', function(SammyK\LaravelFacebookSdk\LaravelFacebookSdk $fb) { $login_link = $fb ->getRedirectLoginHelper() ->getLoginUrl('https://exmaple.com/facebook/callback', ['email', 'user_events']); echo '<a href="' . $login_link . '">Log in with Facebook</a>'; });
但如果您在配置文件中设置了default_redirect_uri
回调URL,则可以使用getLoginUrl()
包装方法,该方法将默认回调URL(default_redirect_uri
)和权限范围(default_scope
)设置为在配置文件中设置的任何内容。
$login_link = $fb->getLoginUrl();
或者,您可以传递权限和自定义回调URL到包装器以覆盖默认配置。
注意:由于权限列表有时会发生变化,但回调URL通常保持不变,因此权限数组是
getLoginUrl()
包装方法中的第一个参数,这与SDK的getRedirectLoginHelper()->getLoginUrl($url, $permissions)
方法的顺序相反。
$login_link = $fb->getLoginUrl(['email', 'user_status'], 'https://exmaple.com/facebook/callback'); // Or, if you want to default to the callback URL set in the config $login_link = $fb->getLoginUrl(['email', 'user_status']);
从回调URL获取访问令牌
用户点击上面的登录链接并确认或拒绝应用程序权限请求后,他们将被重定向到指定的回调URL。
在回调URL上获取访问令牌的“SDK”标准方法如下
Route::get('/facebook/callback', function(SammyK\LaravelFacebookSdk\LaravelFacebookSdk $fb) { try { $token = $fb ->getRedirectLoginHelper() ->getAccessToken(); } catch (Facebook\Exceptions\FacebookSDKException $e) { // Failed to obtain access token dd($e->getMessage()); } });
LaravelFacebookSdk中有一个用于getRedirectLoginHelper()->getAccessToken()
的包装方法,称为getAccessTokenFromRedirect()
,它默认回调URL为laravel-facebook-sdk.default_redirect_uri
配置值。
Route::get('/facebook/callback', function(SammyK\LaravelFacebookSdk\LaravelFacebookSdk $fb) { try { $token = $fb->getAccessTokenFromRedirect(); } catch (Facebook\Exceptions\FacebookSDKException $e) { // Failed to obtain access token dd($e->getMessage()); } // $token will be null if the user denied the request if (! $token) { // User denied the request } });
从JavaScript登录
如果您使用的是JavaScript SDK,则可以获取由JavaScript SDK设置的cookie中的访问令牌。
默认情况下,JavaScript SDK不会设置cookie,因此您必须在初始化SDK时显式启用它,使用cookie: true
。
FB.init({ appId : 'your-app-id', cookie : true, version : 'v2.10' });
使用FB.login()
使用JavaScript SDK登录用户后,您可以从JavaScript SDK设置的cookie中获取用户访问令牌。
Route::get('/facebook/javascript', function(SammyK\LaravelFacebookSdk\LaravelFacebookSdk $fb) { try { $token = $fb->getJavaScriptHelper()->getAccessToken(); } catch (Facebook\Exceptions\FacebookSDKException $e) { // Failed to obtain access token dd($e->getMessage()); } // $token will be null if no cookie was set or no OAuth data // was found in the cookie's signed request data if (! $token) { // User hasn't logged in using the JS SDK yet } });
从应用程序画布登录
TokenMismatchException:默认的Laravel安装会在您尝试在Facebook中查看应用程序时抛出
TokenMismatchException
。请参阅如何修复此问题。
如果您的应用程序存在于Facebook应用程序画布的上下文中,则可以在第一次页面加载时从发送到您的应用程序的签名请求中获取访问令牌。
注意:画布助手仅从从Facebook接收到的签名请求数据中获取现有的访问令牌。如果访问您的应用程序的用户尚未授权您的应用程序或其访问令牌已过期,则
getAccessToken()
方法将返回null
。在这种情况下,您需要使用重定向或JavaScript将用户登录。
使用SDK的画布助手从签名请求数据中获取访问令牌。
Route::match(['get', 'post'], '/facebook/canvas', function(SammyK\LaravelFacebookSdk\LaravelFacebookSdk $fb) { try { $token = $fb->getCanvasHelper()->getAccessToken(); } catch (Facebook\Exceptions\FacebookSDKException $e) { // Failed to obtain access token dd($e->getMessage()); } // $token will be null if the user hasn't authenticated your app yet if (! $token) { // . . . } });
从页面标签登录
TokenMismatchException: 默认的 Laravel 安装在您尝试在 Facebook 中查看页面标签时将抛出
TokenMismatchException
。请参阅如何修复此问题。
如果您的应用位于 Facebook 页面标签的上下文中,这相当于一个应用画布,并且“从应用画布登录”方法也可以用来获取访问令牌。但是页面标签在签名请求中还有额外的数据。
SDK 提供了一个页面标签辅助工具,用于从页面标签上下文中的签名请求数据中获取访问令牌。
Route::match(['get', 'post'], '/facebook/page-tab', function(SammyK\LaravelFacebookSdk\LaravelFacebookSdk $fb) { try { $token = $fb->getPageTabHelper()->getAccessToken(); } catch (Facebook\Exceptions\FacebookSDKException $e) { // Failed to obtain access token dd($e->getMessage()); } // $token will be null if the user hasn't authenticated your app yet if (! $token) { // . . . } });
其他授权请求
Facebook 支持两种其他类型的授权 URL - 重新请求和重新认证。
重新请求
重新请求(或重新请求?)会再次请求用户之前拒绝的权限。使用重新请求 URL 而不是仅仅用正常的登录链接重定向用户是很重要的,因为
一旦有人拒绝了某个权限,登录对话框就不会再次询问他们,除非您明确告诉对话框您正在重新请求被拒绝的权限。- Facebook 文档
您可以使用 getReRequestUrl()
方法生成一个重新请求 URL。
$rerequest_link = $fb->getReRequestUrl(['email'], 'https://exmaple.com/facebook/login'); // Or, if you want to default to the callback URL set in the config $rerequest_link = $fb->getReRequestUrl(['email']);
重新认证
重新认证通过要求用户再次输入他们的 Facebook 账户密码来确认他们的身份。这在在您的网络应用中更改或查看敏感数据之前添加另一层安全性时很有用。
您可以使用 getReAuthenticationUrl()
方法生成一个重新认证 URL。
$re_authentication_link = $fb->getReAuthenticationUrl(['email'], 'https://exmaple.com/facebook/login'); // Or, if you want to default to the callback URL set in the config $re_authentication_link = $fb->getReAuthenticationUrl(['email']); // Or without permissions $re_authentication_link = $fb->getReAuthenticationUrl();
保存访问令牌
在大多数情况下,除非您计划在用户不在浏览您的应用时(例如,例如凌晨 3 点的 CRON 作业)代表用户向 Graph API 发送请求,否则您不需要将访问令牌保存到数据库。
在获取访问令牌后,您可以将它存储在会话中以便用于后续请求。
Session::put('facebook_access_token', (string) $token);
然后在每个调用 Graph API 的脚本中,您可以从会话中提取令牌并将其设置为默认。
$token = Session::get('facebook_access_token'); $fb->setDefaultAccessToken($token);
在数据库中保存从 Facebook 获取的数据
将从 Graph API 接收的数据保存到数据库有时可能是一项繁琐的工作。由于 Graph API 以可预测的格式返回数据,因此 SyncableGraphNodeTrait
可以使将数据保存到数据库变得简单。
任何实现了 SyncableGraphNodeTrait
的 Eloquent 模型都将应用 createOrUpdateGraphNode()
方法。这个方法实际上使得直接从 Facebook 返回的数据在本地数据库中创建或更新变得非常容易。
use SammyK\LaravelFacebookSdk\SyncableGraphNodeTrait; class Event extends Eloquent { use SyncableGraphNodeTrait; }
例如,如果您有一个名为 Event
的 Eloquent 模型,以下是如何从 Graph API 中获取特定事件并将其作为新条目插入数据库或使用新信息更新现有条目的示例。
$response = $fb->get('/some-event-id?fields=id,name'); $eventNode = $response->getGraphEvent(); // A method called createOrUpdateGraphNode() on the `Event` eloquent model // will create the event if it does not exist or it will update the existing // record based on the ID from Facebook. $event = Event::createOrUpdateGraphNode($eventNode);
createOrUpdateGraphNode()
将自动将返回的字段名映射到数据库中的列名。例如,如果您的 events
表的列名与 事件 节点的字段名不匹配,您可以映射字段。
字段映射
由于您数据库中的列名可能与 Graph 节点的字段名不匹配,因此您可以使用 $graph_node_field_aliases
静态变量映射您的 User
模型中的字段名。
数组的关键字是Graph节点上字段的名称。数组的值是本地数据库中列的名称。
use SammyK\LaravelFacebookSdk\SyncableGraphNodeTrait; class User extends Eloquent implements UserInterface { use SyncableGraphNodeTrait; protected static $graph_node_field_aliases = [ 'id' => 'facebook_user_id', 'name' => 'full_name', 'graph_node_field_name' => 'database_column_name', ]; }
指定“可填充”字段
默认情况下,createOrUpdateGraphNode()
方法会尝试将节点的所有字段插入到数据库中。但有时Graph API会返回您没有特别请求且在您的数据库中不存在的字段。在这些情况下,我们可以使用 $graph_node_fillable_fields
属性来列出特定的字段。
use SammyK\LaravelFacebookSdk\SyncableGraphNodeTrait; class Event extends Eloquent { use SyncableGraphNodeTrait; protected static $graph_node_fillable_fields = ['id', 'name', 'start_time']; }
使用数据库列的名称。 例如,如果您已将
id
字段别名为数据库中的facebook_id
列,您将需要在您的$graph_node_fillable_fields
数组中指定facebook_id
。
嵌套字段映射
由于Graph API将请求中的一些字段作为其他节点/对象返回,因此您可以使用Laravel的array_dot()
语法来引用这些字段。
例如,您可能请求 /me/events
端点并遍历所有事件并将它们保存到您的 Event
模型中。 事件节点 将作为 位置节点 返回 place.location 字段。响应数据可能如下所示
{ "data": [ { "id": "123", "name": "Foo Event", "place": { "location": { "city": "Dearborn", "state": "MI", "country": "United States", . . . }, "id": "827346" } }, . . . ] }
假设您有一个类似这样的活动表
Schema::create('events', function(Blueprint $table) { $table->increments('id'); $table->bigInteger('facebook_id')->nullable()->unsigned()->index(); $table->string('name')->nullable(); $table->string('city')->nullable(); $table->string('state')->nullable(); $table->string('country')->nullable(); });
这是如何在您的 Event
模型中将嵌套字段映射到数据库表中的方法
use SammyK\LaravelFacebookSdk\SyncableGraphNodeTrait; class Event extends Eloquent { use SyncableGraphNodeTrait; protected static $graph_node_field_aliases = [ 'id' => 'facebook_id', 'place.location.city' => 'city', 'place.location.state' => 'state', 'place.location.country' => 'country', ]; }
日期格式
Facebook PHP SDK会将大多数日期格式转换为 DateTime
实例。当您想要将日期/时间值插入数据库(例如,事件节点 的 start_time
字段)时,这可能会出现问题。
默认情况下,SyncableGraphNodeTrait
将所有 DateTime
实例转换为以下 date()
格式
Y-m-d H:i:s
这应该是大多数关系型数据库上大多数情况下正确的格式。但这个格式缺少时区,这可能对您的应用程序很重要。此外,如果您以不同的格式存储日期/时间值,您将想要自定义 DateTime
实例转换到的格式。为此,只需向您的模型添加一个 $graph_node_date_time_to_string_format
属性并将其设置为任何 有效的日期格式。
use SammyK\LaravelFacebookSdk\SyncableGraphNodeTrait; class Event extends Eloquent { use SyncableGraphNodeTrait; protected static $graph_node_date_time_to_string_format = 'c'; # ISO 8601 date }
在 Laravel 中登录用户
Laravel Facebook SDK使您能够使用Laravel内置的认证驱动程序轻松登录用户。
更新用户表
为了使Facebook认证与Laravel内置的认证一起工作,您需要在用户表中存储Facebook用户的ID。
当然,您需要为用户想要保留的任何其他信息创建一个列。
如果需要代表用户在用户未浏览您的应用程序时(例如凌晨3点的cron作业)进行请求,则可以将访问令牌存储在数据库中。但通常不需要在数据库中存储访问令牌。
您需要生成一个迁移来修改您的 users
表并添加任何新列。
注意: 请确保将
<name-of-users-table>
替换为您的用户表名称。
$ php artisan make:migration add_facebook_columns_to_users_table --table="<name-of-users-table>"
现在更新迁移文件以包含您要在用户上保存的新字段。至少您需要保存Facebook用户ID。
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class AddFacebookColumnsToUsersTable extends Migration { public function up() { Schema::table('users', function(Blueprint $table) { // If the primary id in your you user table is different than the Facebook id // Make sure it's an unsigned() bigInteger() $table->bigInteger('facebook_user_id')->unsigned()->index(); // Normally you won't need to store the access token in the database $table->string('access_token')->nullable(); }); } public function down() { Schema::table('users', function(Blueprint $table) { $table->dropColumn( 'facebook_user_id', 'access_token' ); }); } }
别忘了运行迁移。
$ php artisan migrate
如果您计划使用Facebook用户ID作为主键,请确保您有一个名为id
的列,该列是无符号大整数并已建立索引。如果您将Facebook ID存储在不同的字段中,请确保该字段存在于数据库中,并确保在您的模型中将它映射到自定义的id名称。
如果您使用Eloquent ORM并将访问令牌存储在数据库中,请确保在您的User
模型中隐藏access_token
字段以防止可能的泄露。
别忘了将SyncableGraphNodeTrait
添加到您的用户模型中,这样您就可以将模型与Graph API返回的数据同步。
# User.php use SammyK\LaravelFacebookSdk\SyncableGraphNodeTrait; class User extends Eloquent implements UserInterface { use SyncableGraphNodeTrait; protected $hidden = ['access_token']; }
在Laravel中登录用户
用户使用Facebook登录并且您已从Graph API获取用户ID后,可以通过将已登录用户的User
模型传递给Auth::login()
方法,在Laravel中登录用户。
class FacebookController { public function getUserInfo(SammyK\LaravelFacebookSdk\LaravelFacebookSdk $fb) { try { $response = $fb->get('/me?fields=id,name,email'); } catch (Facebook\Exceptions\FacebookSDKException $e) { dd($e->getMessage()); } // Convert the response to a `Facebook/GraphNodes/GraphUser` collection $facebook_user = $response->getGraphUser(); // Create the user if it does not exist or update the existing entry. // This will only work if you've added the SyncableGraphNodeTrait to your User model. $user = App\User::createOrUpdateGraphNode($facebook_user); // Log the user into Laravel Auth::login($user); } }
与多个应用一起工作
如果您想在同一脚本中使用多个Facebook应用或想在运行时调整设置,您可以创建一个新的LaravelFacebookSdk
实例并使用自定义设置。
Route::get('/example', function(SammyK\LaravelFacebookSdk\LaravelFacebookSdk $fb) { // All the possible configuration options are available here $fb2 = $fb->newInstance([ 'app_id' => env('FACEBOOK_APP_ID2'), 'app_secret' => env('FACEBOOK_APP_SECRET2'), 'default_graph_version' => 'v2.10', // . . . ]); });
错误处理
Facebook PHP SDK会抛出Facebook\Exceptions\FacebookSDKException
异常。每当Graph响应有错误时,SDK会抛出继承自Facebook\Exceptions\FacebookSDKException
的Facebook\Exceptions\FacebookResponseException
。如果抛出Facebook\Exceptions\FacebookResponseException
,您可以从getPrevious()
方法中获取与错误相关的特定异常。
try { // Stuffs here } catch (Facebook\Exceptions\FacebookResponseException $e) { $graphError = $e->getPrevious(); echo 'Graph API Error: ' . $e->getMessage(); echo ', Graph error code: ' . $graphError->getCode(); exit; } catch (Facebook\Exceptions\FacebookSDKException $e) { echo 'SDK Error: ' . $e->getMessage(); exit; }
LaravelFacebookSdk不会抛出任何自定义异常。
故障排除
在canvas应用中获取TokenMismatchException
如果您的应用在app canvas或Page tab的上下文中提供服务,您可能会在尝试在Facebook上查看应用时看到TokenMismatchException
错误。这是因为Facebook将通过发送带有signed_request
参数的POST请求来渲染您的应用,由于Laravel 5为每个非读取请求启用了CSRF保护,因此会触发错误。
尽管可以完全禁用此功能,但这绝对不推荐,因为CSRF保护是网站的重要安全功能,应默认启用在每个路由上。
在Laravel 5.1 & 5.2中禁用CSRF
在您的app\Http\Middleware\VerifyCsrfToken.php
文件中将canvas端点的异常添加到$except
数组中。
<?php namespace App\Http\Middleware; use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier; class VerifyCsrfToken extends BaseVerifier { /** * The URIs that should be excluded from CSRF verification. * * @var array */ protected $except = [ 'facebook/canvas', 'facebook/page-tab', // ... insert all your canvas endpoints here ]; }
在Laravel 5.0中禁用CSRF
在Laravel 5.0中禁用CSRF验证有些复杂,但有一篇文章解释了如何在Laravel 5.0中禁用特定路由的CSRF保护。
在您的app\Http\Middleware\VerifyCsrfToken.php
文件中,添加一个excludedRoutes()
方法。然后创建一个包含您canvas应用或页面标签端点的路由数组。完整的文件如下所示
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier; use Illuminate\Session\TokenMismatchException; class VerifyCsrfToken extends BaseVerifier { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed * * @throws TokenMismatchException */ public function handle($request, Closure $next) { if ($this->isReading($request) || $this->excludedRoutes($request) || $this->tokensMatch($request)) { return $this->addCookieToResponse($request, $next($request)); } throw new TokenMismatchException; } /** * Ignore CSRF on these routes. * * @param \Illuminate\Http\Request $request * @return bool */ private function excludedRoutes($request) { $routes = [ 'my-app/canvas', 'my-app/page-tab', // ... insert all your canvas endpoints here ]; foreach($routes as $route){ if ($request->is($route)) { return true; } } return false; } }
在保存用户时获取QueryException
如果您使用MySQL,您可能会在尝试使用createOrUpdateGraphNode()
将用户保存到数据库时遇到QueryException
。
QueryException in Connection.php line 754:
SQLSTATE[HY000]: General error: 1364 Field 'password' doesn't have a default value
这是因为默认情况下启用了严格模式,将sql_mode
设置为包括STRICT_TRANS_TABLES
。由于我们不需要为使用Facebook登录的用户设置密码,此字段将为空。解决此错误的办法是在您的config/database.php
文件中将MySQL diver的strict
设置为false
。
测试
这些测试是用 phpunit
编写的。您可以从项目目录的根目录运行以下命令来执行测试。
$ ./vendor/bin/phpunit
贡献
有关详细信息,请参阅 贡献指南。
鸣谢
此软件包由 Sammy Kaye Powers 维护。请参阅 贡献者完整列表。
许可证
MIT 许可证(MIT)。有关更多信息,请参阅 许可文件。