たこぼんげブログ

大学院博士課程から脱落してWEB業界に就職しました。

【FuelPHP】simpleauthをカスタマイズして拡張する

FuelPHPのsimpleauthは便利でよく使います。
ただ、決まったフィールド以外のパラメータはprofile_fieldsにシリアライズしてぶち込む仕様となっています。
カスタマイズしてちゃんとカラムとして追加できるようにしました。
まず、以下のファイルを用意します。

fuel/app/config/auth.php

<?php

return array(
    'driver'                 => 'Myauth',
    'verify_multiple_logins' => false,
    'salt'                   => 'random_string',
);

driverをこれから作成するclass名に設定します。ここでは「Myauth」としました。
saltにはランダムな文字列を入れてください。

次に、

fuel/app/classes/auth/acl/myacl.php  
fuel/app/classes/auth/group/mygroup.php  
fuel/app/classes/auth/login/myauth.php  

の3つのファイルを作成します。
これらのファイルの中身をそれぞれ

fuel/packages/auth/classes/auth/acl/simpleacl.php  
fuel/packages/auth/classes/auth/group/simplegroup.php  
fuel/packages/auth/classes/auth/login/simpleauth.php  

からコピーします。

この時、classを

class Auth_Login_Myauth extends \Auth_Login_Simpleauth

のように元のsimpleauthのクラスを継承し、configに描いたdriverの名前でclass名を定義します。

あとは、カスタマイズしたいメソッド以外は削除して、カスタマイズするメソッドをこちらのMyauthに記述すればカスタマイズできます。

冒頭で書いた任意のカラムを追加できるようにカスタマイズする場合は、
ユーザー作成とユーザー編集のメソッドをカスタマイズします。

fuel/app/classes/auth/login/myauth.php

<?php

class Auth_Login_Myauth extends \Auth_Login_Simpleauth
{
    /**
    * @var  array  value for guest login
    */
    protected static $guest_login = array(
        'id'         => 0,
        'username'   => 'guest',
        'group'      => '0',
        'login_hash' => false,
    );

    /**
    * Create new user
    *
    * @param   string
    * @param   string
    * @param   string  must contain valid email address
    * @param   int     group id
    * @param   Array
    * @return  bool
    */
    public function create_user($username, $password, $email, $group = 1, Array $user = [])
    {
        $password = trim($password);
        $email = filter_var(trim($email), FILTER_VALIDATE_EMAIL);

        if (empty($username) or empty($password) or empty($email))
        {
            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)
            ->from(\Config::get('simpleauth.table_name'))
            ->execute(\Config::get('simpleauth.db_connection'));

        if ($same_users->count() > 0)
        {
            if (in_array(strtolower($email), array_map('strtolower', $same_users->current())))
            {
                throw new \SimpleUserUpdateException('Email address already exists', 2);
            }
            else
            {
                throw new \SimpleUserUpdateException('Username already exists', 3);
            }
        }

        $user['username']   = (string) $username;
        $user['password']   = $this->hash_password((string) $password);
        $user['email']      = $email;
        $user['group']      = $group;
        $user['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;
    }

    /**
    * Update a user's properties
    * Note: Username cannot be updated, to update password the old password must be passed as old_password
    *
    * @param   Array  properties to be updated including profile fields
    * @param   string
    * @return  bool
    */
    public function update_user($values, $username = null)
    {
        $username = $username ?: $this->user['username'];
        $current_values = \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 (empty($current_values))
        {
            throw new \SimpleUserUpdateException('Username not found', 4);
        }

        $update = [];
        if (array_key_exists('username', $values))
        {
            throw new \SimpleUserUpdateException('Username cannot be changed.', 5);
        }
        if (array_key_exists('password', $values))
        {
            if (empty($values['old_password'])
                or $current_values->get('password') != $this->hash_password(trim($values['old_password'])))
            {
                throw new \SimpleUserWrongPassword('Old password is invalid');
            }

            $password = trim(strval($values['password']));
            if ($password === '')
            {
                throw new \SimpleUserUpdateException('Password can\'t be empty.', 6);
            }
            $update['password'] = $this->hash_password($password);
            unset($values['password']);
        }
        if (array_key_exists('old_password', $values))
        {
            unset($values['old_password']);
        }
        if (array_key_exists('email', $values))
        {
            $email = filter_var(trim($values['email']), FILTER_VALIDATE_EMAIL);
            if ( ! $email)
            {
                throw new \SimpleUserUpdateException('Email address is not valid', 7);
            }
            $matches = \DB::select()
                ->where('email', '=', $email)
                ->where('id', '!=', $current_values[0]['id'])
                ->from(\Config::get('simpleauth.table_name'))
                ->execute(\Config::get('simpleauth.db_connection'));
            if (count($matches))
            {
                throw new \SimpleUserUpdateException('Email address is already in use', 11);
            }
            $update['email'] = $email;
            unset($values['email']);
        }
        if (array_key_exists('group', $values))
        {
            if (is_numeric($values['group']))
            {
                $update['group'] = (int) $values['group'];
            }
            unset($values['group']);
        }

        $update = $update + $values;

        $update['updated_at'] = \Date::forge()->get_timestamp();

        $affected_rows = \DB::update(\Config::get('simpleauth.table_name'))
            ->set($update)
            ->where('username', '=', $username)
            ->execute(\Config::get('simpleauth.db_connection'));

        // Refresh user
        if ($this->user['username'] == $username)
        {
            $this->user = \DB::select_array(\Config::get('simpleauth.table_columns', array('*')))
                ->where('username', '=', $username)
                ->from(\Config::get('simpleauth.table_name'))
                ->execute(\Config::get('simpleauth.db_connection'))->current();
        }

        return $affected_rows > 0;
    }

}

以上です。
うまくいってない部分あったら教えて下さい。