【问题标题】:Laravel Socialite first and last nameLaravel 社交名流的名字和姓氏
【发布时间】:2015-09-04 22:50:59
【问题描述】:

我正在使用 Laravel 的 Socialite 向应用程序添加社交身份验证。我可以检索全名,但不能分别检索名字和姓氏。在回调发生并且社交名流正在处理它之后,用户被成功检索。如果我要转储从$user = this->social->driver('facebook')->user(); 回来的用户,我会得到以下信息:

object(Laravel\Socialite\Two\User)#459 (8) {
     ["token" ]=> string(209) "{token}"
     ["id"] => string(17) "{socialID}"
     ["nickname"] => NULL
     ["name"] => string(14) "{Full Name}"
     ["email"] => string(19) "{Email address}"
     ["avatar"] => string(69) "https://graph.facebook.com/v2.4/{socialID}/picture?type=normal"
     ["user"] => array(6) {
        ["first_name"] => string(6) "{First name}"
        ["last_name"] => string(7) "{Last mame}"
        ["email"] => string(19) "{Email address}"
        ["gender"] => string(4) "male"
        ["verified"] => bool(true)
        ["id"] => string(17) "{socialID}"
    }
    ["avatar_original"] => string(68) "https://graph.facebook.com/v2.4/{socialID}/picture?width=1920"

}

我可以通过$user->name$user->email 获得全名或电子邮件,但是我无法获得单独的名字和姓氏。我尝试过$user->first_name 以及尝试转储$user->user 数组,但我看到的只是未定义的属性错误。

我不想做一些奇怪的事情,比如当单独的名字和姓氏明显存在时从全名中提取它,因为当存在中间名时它会变得难看。

我在 Google 上搜索了一下,奇怪的是,没有人遇到这个问题。我错过了the docs 的某些内容吗? 非常感谢有关如何从 user 数组中检索名字和姓氏的任何建议。

【问题讨论】:

  • $user->user['first_name'] 应该可以解决问题
  • @koala_dev 出于某种神奇的原因,到目前为止,用户数组只是另一个未定义的属性。这很愚蠢 :) 请将此添加为答案,以便我将其标记为已回答。谢谢

标签: php laravel laravel-5.1


【解决方案1】:

你也可以使用AbstractUser类的socialite包中定义的offsetGet()方法,它返回$this->user[$offset];,所以使用它你可以得到名字和姓氏,

但对于 facebookgoogle,由于它们的响应不同,所以我在下面给出了 facebook 和 google 的代码。

谷歌和脸书

$providerUser = Socialite::driver($provider)->user(); // $provider can be facebook, google etc.

switch($provider){
   case 'facebook':
      $first_name = $providerUser->offsetGet('first_name');
      $last_name = $providerUser->offsetGet('last_name');
      break;

   case 'google':
      $first_name = $providerUser->offsetGet('given_name');
      $last_name = $providerUser->offsetGet('family_name');
      break;

 // You can also add more provider option e.g. linkedin, twitter etc.

   default:
      $first_name = $providerUser->getName();
      $last_name = $providerUser->getName();
}

$user = User::create([
                'first_name' => $first_name,
                'last_name' => $last_name,
                'email' => $providerUser->getEmail(),
                'image' => $providerUser->getAvatar(),
            ]);

【讨论】:

    【解决方案2】:

    我发现有时用户对象不会包含名字和姓氏,除非您指定需要这些字段。

    //get the driver and set desired fields
    $driver = Socialite::driver('facebook')
                    ->fields([
                        'name', 
                        'first_name', 
                        'last_name', 
                        'email', 
                        'gender', 
                        'verified'
                    ]);
    // retrieve the user
    $user = $driver->user();
    

    那么你可以像这样得到名字和姓氏

    $user->user['first_name'] and $user->user['last_name']
    

    您可以要求的其他内容:

    https://developers.facebook.com/docs/graph-api/reference/user/

    对于谷歌加:

    $user->firstname = $user->user['name']['givenName'];
    $user->lastname = $user->user['name']['familyName'];
    

    【讨论】:

    • 这不适用于linkedin:/你有什么想法吗?
    【解决方案3】:

    根据$user var 的转储,您应该能够通过以下方式访问名称值:

    $user->user['first_name']$user->user['last_name']

    【讨论】:

    • 请注意,每个提供商的名称部分都不同,因此对于 Google,例如它是 $user->user['name']['givenName']$user->user['name']['familyName']
    • 由于不同的提供者以不同的方式提供名字和姓氏值,是否有一种一致的方式将名字和姓氏作为与社交名流分开的值?类似于$user->getFirstname$user->getLastname
    • 使用 offsetExists 方法检查值是否存在,否则会报错
    【解决方案4】:

    在linkedin中,您可以像这样从提供者那里获取名字和姓氏。

    $linkedinUser = $this->socialite->driver('linkedin')->user());
    
    $attributes = [
            'first_name' => $linkedinUser->user['firstName'],
            'last_name' => $linkedinUser->user['lastName'],
            'email' => $linkedinUser->email,
            'avatar' => $linkedinUser->avatar,
            'linkedin_id' => $linkedinUser->id
        ];
    

    【讨论】:

    • 另外,在谷歌中,您可以在用户对象中将名字作为“givenName”,将姓氏作为“familyName”。
    【解决方案5】:

    在遇到同样的问题后,我注意到我用于注册/登录的所有社交网络(Facebook、Twitter、Google+、Github)都发回了“name”属性。该属性可以是空的(如果用户没有添加任何信息)或带有一个值。

    我所做的是创建一个方法 (getFirstLastNames()),它将获取“name”值并将其分解为 first_namelast_name 在检测到一个或多个空格时分解它们。然后我用它们来填充我的用户表:

    protected function getFirstLastNames($fullName)
    {
        $parts = array_values(array_filter(explode(" ", $fullName)));
    
        $size = count($parts);
    
        if(empty($parts)){
            $result['first_name']   = NULL;
            $result['last_name']    = NULL;
        }
    
        if(!empty($parts) && $size == 1){
            $result['first_name']   = $parts[0];
            $result['last_name']    = NULL;
        }
    
        if(!empty($parts) && $size >= 2){
            $result['first_name']   = $parts[0];
            $result['last_name']    = $parts[1];
        }
    
        return $result;
    }
    

    $fullName 变量是:

    Socialite::driver($provider)->getName();
    

    对于这个实现,我假设:

    1. 无论用户有多少个名字,我都会使用字符串的第一部分作为first_name,第二部分作为last_name。 [如果我的名字是 POPPY PETAL EMMA ELIZABETH DEVERAUX,那么我将使用 POPPY 作为 first_name,使用 PETAL 作为 last_name。其余的将被忽略]。如果“name”属性返回为空或只有一个名称,那么我将 NULL 插入到我没有得到任何值的用户表中。
    2. 如果用户在分隔名称(或名称前后)时使用了多个空格,此方法将删除它们并仅保留字符串。

    现在您已经有了数组中的数据,您可以在创建用户时使用它们:

    $userFirstLastName = $this->getFirstLastNames(Socialite::driver($provider)->getName());
    
    $user = User::create([
                'email'         => Socialite::driver($provider)->getName()->getEmail(),
                'first_name'    => $userFirstLastName['first_name'],
                'last_name'     => $userFirstLastName['last_name'],
            ]);
    

    ps1:确保更改 users 表的迁移(Laravel 5.3 仅使用“name”字段。如果您需要“first_name”和“last_name”你应该改变它。当然运行“php artisan migrate:refresh”来实现改变。所有数据都会丢失。

    ps2:确保 first_namelast_namepassword 字段可以为空。否则会报错。

    ps3:在 User 模型中,在 $fillable 属性中添加 first_namelast_name 并删除 name

    ps4:[不是 Playstation 4] 如果上述过程使用您的第二名作为 first_name 或 last_name。您无法预测每个用户使用什么作为全名,因此您需要做出假设。

    希望这会有所帮助!

    【讨论】:

    【解决方案6】:

    你可以这样做:

    $NameArray = explode(' ',$user->getName());
    $First_name = $NameArray[0];
    $Last_name = $NameArray[1];
    

    【讨论】:

    • 这不能很好地处理包含多个单词的名字,这在姓氏中并不少见,但在名字中甚至可能是这种情况(例如 Gabriel José de la Concordia García Márquez) .
    猜你喜欢
    • 1970-01-01
    • 2016-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-16
    • 1970-01-01
    • 2015-08-20
    • 2021-08-18
    相关资源
    最近更新 更多