【FuelPHP】Opauthを使う

とりあえずTwitterのOauthを題材にするです。
  

流れ

  1. composer.jsonの編集
  2. configの追加
  3. authのmigrate
  4. Myauthクラスの作成
  5. Myauthクラスの編集
  6. Authコントローラの作成 & 編集
  7. ユーザーのプロフィール保存用テーブルの作成
  8. create_userと同時にusers_profilesモデルに登録
  9. view

1. composer.jsonの編集

composer.json に以下の2行追加 & composer install

"require": {
  .
  .
  .
  "opauth/opauth": "0.4.*",
  "opauth/twitter" : "dev-master"
},

2. configの追加

fuel/packages/auth/config/ から auth.phpopauth
fuel/app/config/ へコピー

<?php
// auth.php
return array(
    'driver'                 => 'Myauth', // 後でMyauthクラスを追加する
    'verify_multiple_logins' => false,
    'salt'                   => '適当に',
    'iterations'             => 10000,
);
<?php
// opauth.php
return array(
  .
  .
  //'auto_registration' => false,                                                                                                                                                     
  'auto_registration' => true,
  .
  .
  'security_salt' => '適当に',
  .
  .
  'Strategy' => array(
    // https://apps.twitter.com/で取得
    'Twitter' => array(
      'key' => 'Consumer Key (API Key)',
      'secret' => '   Consumer Secret (API Secret)', 
    ),
  ),
);
'packages'  => array(
    'orm', // 後で使う
    'auth', // 追加
),

2.5 TwitterStrategyが無いとエラー吐かれる場合

cp fuel/vendor/opauth/twitter/TwitterStrategy.php fuel/vendor/opauth/opauth/lib/Opauth/Strategy/

.gitignoreの編集(こうする以外どうすりゃ良いのさ・・・

/fuel/vendor/*
!/fuel/vendor/opauth
/fuel/vendor/opauth/*
!/fuel/vendor/opauth/opauth
/fuel/vendor/opauth/opauth/*
!/fuel/vendor/opauth/opauth/lib
/fuel/vendor/opauth/opauth/lib/*
!/fuel/vendor/opauth/opauth/lib/Opauth
/fuel/vendor/opauth/opauth/lib/Opauth/*
!/fuel/vendor/opauth/opauth/lib/Opauth/Strategy
/fuel/vendor/opauth/opauth/lib/Opauth/Strategy/*
!/fuel/vendor/opauth/opauth/lib/Opauth/Strategy/TwitterStrategy.php

3. authのmigrate

db.phpを設定して以下コマンドを実行でテーブルが作成される

$ php oil r migrate --packages=auth

4. Myauthクラスの作成

参考: http://takobonge.hatenablog.com/entry/2016/01/14/215022

fuel/packages/auth/classes/auth/acl
fuel/packages/auth/classes/auth/group
fuel/packages/auth/classes/auth/login

fuel/app/classes/auth/ ディレクトリを作って入れる

んで各種ファイルをリネーム
fuel/packages/auth/classes/auth/acl/myacl.php
fuel/packages/auth/classes/auth/group/mygroup.php
fuel/packages/auth/classes/auth/login/myauth.php

クラス名もちゃんとリネーム & namespaceも削除。

<?php
// myauth.php
//namespace Auth;

//class Auth_Login_Simpleauth extends \Auth_Login_Driver
class Auth_Login_Myauth extends \Auth_Login_Simpleauth

この2ファイルはクラス名変えるだけで動く模様

// myacl.php
class Auth_Acl_Myacl extends \Auth_Acl_Simpleauth

// mygroup.php
class Auth_Group_Mygroup extends \Auth_Group_Simpleauth

5. Myauthクラスの編集

メールアドレスをマストなままにしとくとTwitterだとエラーを吐く
欲しければ一枚メールアドレスを入力させるページを噛ませるかこのメソッドをどうにかするか、適当に…

// myauth.php
    public function create_user($username, $password, $email, $group = 1, Array $profile_fields = array())
    {
        $password = trim($password);
        $email = filter_var(trim($email), FILTER_VALIDATE_EMAIL);

        if (empty($username) or empty($password))
        {
            throw new \SimpleUserUpdateException('Username, password or email address is not given, or email address is invalid', 1);
        }

        $same_users = \DB::select_array(\Config::get('simpleauth.table_columns', array('*')))
            ->where('username', '=', $username)
            ->or_where('email', '=', $email and '')
            ->from(\Config::get('simpleauth.table_name'))
            ->execute(\Config::get('simpleauth.db_connection'));

        if ($same_users->count() > 0)
        {
            throw new \SimpleUserUpdateException('Username already exists', 3);
        }

        $user = array(
            'username'        => (string) $username,
            'password'        => $this->hash_password((string) $password),
            'email'           => $email,
            'group'           => (int) $group,
            'profile_fields'  => serialize($profile_fields),
            'last_login'      => 0,
            'login_hash'      => '',
            'created_at'      => \Date::forge()->get_timestamp(),
        );
        $result = \DB::insert(\Config::get('simpleauth.table_name'))
            ->set($user)
            ->execute(\Config::get('simpleauth.db_connection'));

        return ($result[1] > 0) ? $result[0] : false;
    }

6. Authコントローラの作成 & 編集

$ php oil g controller auth oauth callback

あとは http://fuelphp.jp/docs/1.8/packages/auth/examples/opauth.html のoauthとcallbackをこp…拝借すれば動く(Messageクラスは存在しないはずなので全てコメントアウトした)
Opauth をアプリケーションで使う にあるlink_provider相当のことはtwitterだと既に行ってくれてる(Facebookだと要求する模様)

7. ユーザーのプロフィール保存用テーブルの作成

twitterアイコンニックネームtwitterへのurlを格納させるModel

$ php oil g model users_profile user_id:int[11] name:varchar[50] image:varchar[255] twitter_url:varchar[255]
$ php oil r migrate

8. create_userと同時にusers_profilesモデルに登録

解説はそのうち疲れてない時に書く
言い訳するとどうせ書き直すので適当なそーす

// fuel/app/classes/auth/login/myauth.php
    public function create_user($username, $password, $email, $group = 1, Array $profile_fields = array())
    {
        $password = trim($password);
        $email = filter_var(trim($email), FILTER_VALIDATE_EMAIL);

        if (empty($username) or empty($password))
        {
            throw new \SimpleUserUpdateException('Username, password or email address is not given, or email address is invalid', 1);
    }

        $same_users = \DB::select_array(\Config::get('simpleauth.table_columns', array('*')))
            ->where('username', '=', $username)
            ->from(\Config::get('simpleauth.table_name'))
            ->execute(\Config::get('simpleauth.db_connection'));

        if ($same_users->count() > 0)
        {
            throw new \SimpleUserUpdateException('Username already exists', 3);
        }

        $user = array(
            'username'        => (string) $username,
            'password'        => $this->hash_password((string) $password),
            'email'           => $email and '',
            'group'           => (int) $group,
            'profile_fields'  => serialize($profile_fields),
            'last_login'      => 0,
            'login_hash'      => '',
            'created_at'      => \Date::forge()->get_timestamp(),
        );

        // ユーザーのプロフィールの作成に失敗したら無かったことにしたいのでトラン
        $db = Database_Connection::instance();
        $db->start_transaction();
        try{
            $result = \DB::insert(\Config::get('simpleauth.table_name'))
                    ->set($user)
                    ->execute(\Config::get('simpleauth.db_connection'));

            if($result[1] > 0){
                $uid = $result[0]; // users.user_id
                $profile = array(
                    'user_id' => (int)$uid,
                    'name' => $username,
                    'image' => '',
                    'twitter_url' => '',
                    'created_at' => \Date::forge()->get_timestamp(),
                );

                if(Input::get('opauth')){
                    // opauthからのユーザー作成だった場合                                                                                                                                                          
                    $response = unserialize(base64_decode(Input::get('opauth')));

                    $profile['name'] = $response['auth']['info']['name'];
                    $profile['image'] = $response['auth']['info']["image"];
                    $profile['twitter_url'] = $response['auth']['info']['urls']['twitter'];
                }else{
                    // XXX: フォームからのユーザー作成だった場合                                                                                                                                                        
                }

                $presult = \DB::insert('users_profiles')->set($profile)->execute();
                if(!$presult[1] > 0){
                    throw new Fuel_Exception('error');
                }

            }else{
                throw new Fuel_Exception('error');
            }

            $db->commit_transaction();
        }catch (\Fuel_Exception $ex) {
            $db->rollback_transaction();
            //throw new Exception($ex->getMesssage());                                                                                                                                                             
            print '<pre>';
            var_dump($ex->getMesssage());
            print '</pre>';
            exit(11);
        }

        return ($result[1] > 0) ? $result[0] : false;
    }

9. view

// fuel/app/classes/controller/auth.php
    public function action_index(){
        // var_dump(Auth::check());                                                                                                                                                                                
        // var_dump(Auth::get_user_id());                                                                                                                                                                          

        $user = Model_Users_Profile::find('all', array('where'=>array(array('user_id', Auth::get_user_id()[1]))));
        // where句をORMで使う場合はなぜかarrayの中に入るので必要
        $user= array_shift($user);

        $data['image'] = $user->image;
        $this->template->title = 'Auth';
        $this->template->content = View::forge('auth/index', $data);
    }
// fuel/app/views/auth/index.php
<img alt="" src="<?php echo $image; ?>"/>

※完成予想図
Screen Shot 2016 07 31 at 9 20 56 PM

雑感

ここまでハマるとは思わなかったぞい
NEW GAME!のEDのNow Loading!!!!が今日の作業用BGMとして良い感じでしたまる
今日は1日がんばったぞい

コメントを残す