scottybo / laravel-facebook-sdk
为 Laravel 7.x 完整单元测试的 Facebook SDK v5 集成
Requires
- php: >=7.3
- illuminate/auth: ~7
- illuminate/config: ~7
- illuminate/database: ~7
- illuminate/routing: ~7
- illuminate/session: ~7
- illuminate/support: ~7
- scottybo/facebook-graph-sdk: ^5.0
Requires (Dev)
- mockery/mockery: ~0.9
- phpunit/phpunit: ~4.0|~5.0|~6.0|~7.0
- squizlabs/php_codesniffer: ~2.0
This package is not auto-updated.
Last update: 2024-09-25 04:57:20 UTC
README
一个完全单元测试的包,用于轻松将 Facebook SDK v5 集成到 Laravel 6。
- 安装
- 重定向示例中的用户登录
- 向 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 scottybo/laravel-facebook-sdk
自动发现: 从版本 3.5.0 开始,Laravel Facebook SDK 支持 Laravel 5.5 及更高版本的 自动发现。
服务提供者
在您的应用程序配置中,将 LaravelFacebookSdkServiceProvider 添加到提供者数组中。
'providers' => [ Scottybo\LaravelFacebookSdk\LaravelFacebookSdkServiceProvider::class, ];
对于 Lumen,将提供者添加到您的 bootstrap/app.php 文件中。
$app->register(Scottybo\LaravelFacebookSdk\LaravelFacebookSdkServiceProvider::class);
门面(可选)
如果您想使用门面,请将其添加到应用程序配置中的别名数组中。
'aliases' => [ 'Facebook' => Scottybo\LaravelFacebookSdk\FacebookFacade::class, ];
IoC 容器
IoC 容器将自动为您解析 LaravelFacebookSdk 依赖项。您可以通过多种方式从 IoC 容器中获取 LaravelFacebookSdk 的实例。
// Directly from the IoC $fb = App::make('Scottybo\LaravelFacebookSdk\LaravelFacebookSdk'); // Or in PHP >= 5.5 $fb = app(Scottybo\LaravelFacebookSdk\LaravelFacebookSdk::class); // From a constructor class FooClass { public function __construct(Scottybo\LaravelFacebookSdk\LaravelFacebookSdk $fb) { // . . . } } // From a method class BarClass { public function barMethod(Scottybo\LaravelFacebookSdk\LaravelFacebookSdk $fb) { // . . . } } // Or even a closure Route::get('/facebook/login', function(Scottybo\LaravelFacebookSdk\LaravelFacebookSdk $fb) { // . . . });
配置文件
注意: 从版本 3.4.0 开始,发布配置文件是可选的,只要您设置了您的 所需配置值。
另外请注意: 配置文件包含一个默认的 Graph API 版本,该版本会定期更新到最新的稳定版本,这可能在您更新此包的小版本或补丁版本时导致破坏性更改。建议您仍然发布配置文件,并在自己方便的时候更新 Graph API 版本,以防止破坏东西。
在Facebook创建应用后,您需要提供应用ID和密钥。在Laravel中,您可以使用artisan命令发布配置文件。
$ php artisan vendor:publish --provider="Scottybo\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(Scottybo\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(Scottybo\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登录”时,我们的真正意思是“通过Facebook获取用户访问令牌,以便代表用户调用Graph API”。这是通过Facebook通过OAuth 2.0完成的。有几种方法可以使用Facebook PHP SDK中的“辅助工具”使用Facebook登录用户。
支持的四种登录方法是
- 重定向登录(OAuth 2.0)
- 通过JavaScript登录(带有JS SDK Cookie)
- 通过App Canvas登录(带有签名请求)
- 通过Page Tab登录(带有签名请求)
重定向登录
将用户登录到您的应用的最常见方法之一是使用重定向URL。
想法是生成一个唯一的URL,用户点击该URL。一旦用户点击链接,他们将被重定向到Facebook,Facebook将请求他们授予您的应用程序请求的任何权限。一旦用户做出回应,Facebook将用户重定向回您指定的回调URL,无论是成功响应还是错误响应。
可以使用SDK的getRedirectLoginHelper()方法获取重定向辅助工具。
生成登录URL
您可以使用与Facebook PHP SDK v5相同的操作获取登录URL。
Route::get('/facebook/login', function(Scottybo\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(Scottybo\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(Scottybo\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,因此您需要在init() SDK时显式启用它,使用cookie: true。
FB.init({ appId : 'your-app-id', cookie : true, version : 'v2.10' });
使用FB.login()登录用户后,您可以从JavaScript SDK设置的cookie中获取用户访问令牌。
Route::get('/facebook/javascript', function(Scottybo\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 } });
从App Canvas登录
TokenMismatchException:默认Laravel安装将抛出
TokenMismatchException,当您尝试在Facebook中查看您的应用程序时。查看如何修复此问题。
如果您的应用程序位于Facebook应用程序画布的上下文中,您可以在首次页面加载时从发送到您的应用程序的签名请求中获取访问令牌。
注意:画布辅助工具仅从Facebook接收的签名请求数据中获取现有的访问令牌。如果访问您的应用程序的用户尚未授权您的应用程序或其访问令牌已过期,则
getAccessToken()方法将返回null。在这种情况下,您需要使用重定向或JavaScript登录用户。
使用SDK的画布辅助工具从签名请求数据中获取访问令牌。
Route::match(['get', 'post'], '/facebook/canvas', function(Scottybo\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安装将抛出
TokenMismatchException,当您尝试在Facebook中查看您的页面标签时。查看如何修复此问题。
如果你的应用位于Facebook页面标签页的上下文中,这等同于应用画布,并且“从应用画布登录”方法也可以用来获取访问令牌。但页面标签页在签名请求中还有额外的数据。
SDK提供了一个页面标签页辅助工具,用于在页面标签页的上下文中从签名请求数据中获取访问令牌。
Route::match(['get', 'post'], '/facebook/page-tab', function(Scottybo\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账户密码以确认他们的身份。这在在您的Web应用中更改或查看敏感数据之前添加另一个安全层非常有用。
您可以使用 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 Scottybo\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 模型中映射字段名。
数组的 keys 是Graph节点上的字段名。数组的 values 是本地数据库中的列名。
use Scottybo\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 Scottybo\LaravelFacebookSdk\SyncableGraphNodeTrait; class Event extends Eloquent { use SyncableGraphNodeTrait; protected static $graph_node_fillable_fields = ['id', 'name', 'start_time']; }
使用数据库列的名称。 例如,如果您已将数据库中的
id字段别名为facebook_id列,那么您希望指定facebook_id在您的$graph_node_fillable_fields数组中。
嵌套字段映射
由于 Graph API 会将某些请求的字段作为其他节点/对象返回,因此您可以使用 Laravel 的 array_dot() 表示法 来引用这些字段。
例如,您可能向 /me/events 端点发出请求,遍历所有事件并将它们保存到您的 Event 模型中。将返回的 事件节点 的 地点位置字段 作为 地点节点。响应数据可能如下所示
{
"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 Scottybo\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 Scottybo\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 Scottybo\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(Scottybo\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(Scottybo\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不会抛出任何自定义异常。
故障排除
在画布应用中获得TokenMismatchException
如果您的应用在画布应用或页面标签的上下文中提供服务,您在尝试在Facebook上查看应用时可能会遇到TokenMismatchException错误。这是因为Facebook将通过向它发送带有signed_request参数的POST请求来渲染您的应用,由于Laravel 5为每个非读取请求启用了CSRF保护,因此将触发错误。
虽然可以完全禁用此功能,但这绝对不推荐,因为CSRF保护是您网站上的一个重要安全功能,应默认在每条路由上启用。
在Laravel 5.1 & 5.2中禁用CSRF
将异常添加到您的画布端点中,在app\Http\Middleware\VerifyCsrfToken.php文件中的$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()方法。然后创建一个包含您画布应用或页面标签端点的路由数组。完整的文件如下
<?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驱动的strict设置为false。
测试
测试是用phpunit编写的。您可以从项目目录的根目录运行以下命令来运行测试。
$ ./vendor/bin/phpunit
贡献
有关详细信息,请参阅CONTRIBUTING。
鸣谢
本软件包由Scott Bowler维护。查看贡献者完整列表。
许可证
MIT许可证(MIT)。请参阅许可证文件获取更多信息。