etahamer / laravel-facebook-sdk
完全单元测试的 Facebook SDK v5 集成,适用于 Laravel 8.x
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 auto-updated.
Last update: 2024-09-14 01:02:29 UTC
README
一个完全单元测试的包,可轻松将 Facebook SDK v5 集成到 Laravel 8。
- 安装
- 从重定向示例中用户登录
- 向 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 etahamer/laravel-facebook-sdk
自动发现:从版本 3.5.0 开始,Laravel Facebook SDK 支持 Laravel 5.5 及更高版本的 自动发现。
服务提供者
在您的应用程序配置中,将 LaravelFacebookSdkServiceProvider
添加到提供者数组。
'providers' => [ Etahamer\LaravelFacebookSdk\LaravelFacebookSdkServiceProvider::class, ];
对于 Lumen,将提供者添加到您的 bootstrap/app.php
文件中。
$app->register(Etahamer\LaravelFacebookSdk\LaravelFacebookSdkServiceProvider::class);
外观(可选)
如果您想使用外观,请将其添加到应用程序配置中的别名数组。
'aliases' => [ 'Facebook' => Etahamer\LaravelFacebookSdk\FacebookFacade::class, ];
IoC 容器
IoC 容器将自动为您解决 LaravelFacebookSdk
依赖项。您可以从 IoC 容器中通过多种方式获取 LaravelFacebookSdk
实例。
// Directly from the IoC $fb = App::make('Etahamer\LaravelFacebookSdk\LaravelFacebookSdk'); // Or in PHP >= 5.5 $fb = app(Etahamer\LaravelFacebookSdk\LaravelFacebookSdk::class); // From a constructor class FooClass { public function __construct(Etahamer\LaravelFacebookSdk\LaravelFacebookSdk $fb) { // . . . } } // From a method class BarClass { public function barMethod(Etahamer\LaravelFacebookSdk\LaravelFacebookSdk $fb) { // . . . } } // Or even a closure Route::get('/facebook/login', function(Etahamer\LaravelFacebookSdk\LaravelFacebookSdk $fb) { // . . . });
配置文件
注意:从版本 3.4.0 开始,只要设置了您的 必需的配置值,发布配置文件是可选的。
另外注意:配置文件包含一个默认的 Graph API 版本,该版本会定期提升到最新的稳定版本,这可能导致在更新此包的次要或补丁版本时发生破坏性更改。建议您仍然发布配置文件,并在您方便时自行更新 Graph API 版本,以防止破坏东西。
在Facebook创建应用后,您需要提供应用ID和密钥。在Laravel中,您可以使用artisan
命令发布配置文件。
$ php artisan vendor:publish --provider="Etahamer\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(Etahamer\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(Etahamer\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将把用户重定向回您指定的回调URL,并带有成功响应或错误响应。
可以通过SDK的getRedirectLoginHelper()
方法获得重定向助手。
生成登录URL
您可以像使用Facebook PHP SDK v5一样获取登录URL。
Route::get('/facebook/login', function(Etahamer\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(Etahamer\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(Etahamer\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(Etahamer\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安装会在您尝试在Facebook中查看应用程序时抛出
TokenMismatchException
。请参阅如何解决这个问题。
如果您的应用程序位于Facebook应用程序画布的上下文中,您可以从第一次页面加载时通过POST
到您的应用程序的已签名请求中获取访问令牌。
注意:画布助手仅从Facebook接收的已签名请求数据中获取现有的访问令牌。如果访问您的应用程序的用户尚未授权您的应用程序或其访问令牌已过期,则
getAccessToken()
方法将返回null
。在这种情况下,您需要使用重定向或JavaScript登录用户。
使用SDK的画布助手从已签名请求数据中获取访问令牌。
Route::match(['get', 'post'], '/facebook/canvas', function(Etahamer\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(Etahamer\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 Etahamer\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 Etahamer\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 Etahamer\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 Etahamer\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 Etahamer\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 Etahamer\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(Etahamer\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(Etahamer\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
将异常添加到您的canvas端点,在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()
方法。然后创建一个包含您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驱动器的strict
设置为false
。
测试
测试是用phpunit
编写的。您可以使用以下命令从项目目录的根目录运行测试。
$ ./vendor/bin/phpunit
贡献
有关详细信息,请参阅CONTRIBUTING。
鸣谢
本软件包由Scott Bowler维护。查看贡献者完整列表。
许可
MIT许可证(MIT)。请参阅许可证文件以获取更多信息。