読者です 読者をやめる 読者になる 読者になる

dari88's diary

これから趣味にするプログラミング/PHP/javascript/kohana/CMS/web design/

kohanaのテスト12-5・・・WordPressのユーザー登録ページを書く

 新規投稿のページを書く前に、ユーザー登録とログインのページを書いておく必要があります。今日はユーザー登録のページを書きます。

 

WordPressの データベースを kohana に移す

 phpMyAdmin を使って、WordPress のデータベースを kohana のデータベースにコピーします。

・データベース wordpress を開き、[エクスポート] タブを開きます。
・デフォルトの状態で [実行する] ボタンをクリックします。
wordpress.sql ファイルがダウンロードされます。
・これを kohana ディレクトリの分かりやすい所に保存します。
・データベース kohana にて、このファイルをインポートします。
・テーブル ***_uses に登録されているユーザーを削除します。

 

ビューを作る

 WordPress のユーザー登録ページにてメールアドレスを書かないで登録するとエラーメッセージが出ます。この状態のソースコードを利用してビューを作ります。

 ヘッドとかアサイドとか要素ごとにフォルダを区分しようかと思っていたのですが、収集が付かなくなりそうなので、ページ区分ごとにフォルダを作る方針に変更します。

・kohana/application/views/test12/auth/register.php
 変更を加えた部分だけ抜粋して記載します。

<link rel='stylesheet' id='wp-admin-css'  href='/kohana/loadcss?dir=rtl&load=wp-admin' type='text/css' media='all' />
<link rel='stylesheet' id='colors-fresh-css'  href='/kohana/loadcss?dir=rtl&load=colors-fresh' type='text/css' media='all' />

<p class="message register">このブログに登録</p>
<?php
if ($errors):
    echo '<div id="login_error">' . "\n";
    foreach ($errors as $value) {
        echo "<strong>エラー</strong>: $value<br />"."\n";
    }
    echo '</div>' . "\n";
endif;
?>
<form name="registerform" id="registerform" action="" method="post">

<input type="text" name="user_login" id="user_login" class="input" value="<?php echo $user_login ?>" size="20" tabindex="10" /></label>

<input type="email" name="user_email" id="user_email" class="input" value="<?php echo $user_email ?>" size="25" tabindex="20" /></label>

ref="/kohana/test12_login">ログイン</a> |
<a href="/kohana/test12_lostpassword" title="パスワード紛失取り扱い">パスワードをお忘れですか ?</a>
</p>    <p id="backtoblog"><a href="/kohana/test12" title="迷子になってしまいましたか ?">&larr; WordPress へ戻る</a></p>

 

Auth ドライバを書く

 テスト11で作った Auth ドライバをデータベースに合わせて書き換えます。さらに、パスワード発生メソッドを追加しています。

・kohana/application/classes/auth/wplogin.php
  mt_srand() は乱数発生器用にランダムなソルトを発生してくれます。
  mt_rand() は端点を含む整数をランダムに発生してくれます。

<?php defined('SYSPATH') or die('No direct access allowed.');

class Auth_Wplogin extends Auth {

// Logs a user in.
    protected function _login($username, $password, $remember) {

        if (is_string($password)) {
            $password = $this->hash($password);
        }

        $dbpassword = parent::instance()->password($username);

        if ($dbpassword == $password) {
            $this->complete_login($username);
            return TRUE;
        }

        return FALSE;
    }

// Get the stored password for a username.
    public function password($username) {

        $userdata = DB::select_array(array('ID', 'user_login', 'user_pass'))
                ->from('wp332_users')
                ->where('user_login', '=', $username)
                ->execute();

        $dbpassword = $userdata->get('user_pass', FALSE);
        return $dbpassword;
    }

// Compare password with original (hashed). 
    public function check_password($password) {

        $username = $this->get_user();
        if (!$username)
            return FALSE;

        $dbpassword = parent::instance()->password($username);
        if (!$dbpassword)
            return FALSE;

        return ($this->hash($password) == $dbpassword);
    }

    static function generate_password($length = 12, $special_chars = 0) {

        $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        if ($special_chars >= 1)
            $chars .= '!@#$%^&*()';
        if ($special_chars >= 2)
            $chars .= '-_ []{}<>~`+=,.;:/?|';

        $password = '';
        mt_srand();
        for ($i = 0; $i < $length; $i++) {
            $password .= substr($chars, (mt_rand(0,strlen($chars)-1)), 1);
        }

        return $password;
    }

}

 

モデルを書く

 やはりテスト11で書いたモデルを修正して作ります。ユニーク性検証のロジックを書きなおしています。

・kohana/application/classes/model/test12/register.php

<?php defined('SYSPATH') OR die('No direct access allowed.');

class Model_Test12_register extends Model {

    public function register($array) {
        $id = DB::insert(array_keys($array))
                ->values($array)
                ->table('wp332_users')
                ->execute();

        return $id;
    }

    public function unique_username($user_login) {

        $users = DB::SELECT('user_login')
                ->from('wp332_users')
                ->where('user_login', '=', $user_login)
                ->execute();

        $result = $users->get('user_login', FALSE);
        if ($result)
            return FALSE;
        return TRUE;
    }

    public function unique_email($user_email) {

        $emails = DB::SELECT('user_email')
                ->from('wp332_users')
                ->where('user_email', '=', $user_email)
                ->execute();

        $result = $emails->get('user_email', FALSE);
        if ($result)
            return FALSE;
        return TRUE;
    }

}

?>

 

登録メール用の定義ファイルを書く

 ユーザー登録したらパスワードをメールで送信する必要があります。テスト7で作成した定義ファイルを改造して定義ファイルを作ります。

・kohana/application/config/test12.php

<?php defined('SYSPATH') or die('No direct access allowed.');

$body1 = <<< EOT
WordPress風kohanaサイトへようこそ!
ユーザー登録を致しましたのでパスワードをお届けします。
EOT;

$body2 = <<< EOT
WordPress風kohanaサイトをよろしくお願いします。

 ウエッブマスター kohana太郎
                                     
EOT;

return array
(
        'mail_register' => array
        (
                'from'       => 'kohana_master@gmail.com',
                'subject' => '[kohana] あなたのユーザー名とパスワード',
                'body1'      => $body1,
                'body2'      => $body2,
        ),

);

 

コントローラを書く

 最後にコントローラを書いているようですが、実際にはみんな並行して書いています。セキュリティー対策はコントローラの仕事か、ビューの仕事か考えたのですが、ビューのロジックは出来るだけシンプルにしたいので、コントローラの仕事にすることにしました。

・kohana/application/classes/controller/test12/register.php
  アクセスは http://localhost/kohana/test12_register になります。

<?php defined('SYSPATH') OR die('No direct access allowed.');

class Controller_Test12_register extends Controller {

    public function action_index() {

        $user = Model::factory('test12_register');

        if (isset($_POST['user_login'])) {
            $post = Validation::factory($_POST)
                    ->rule('user_login', 'not_empty')
                    ->rule('user_login', 'max_length', array(':value', 24))
                    ->rule('user_login', 'regex', array(':value', '/^[a-z0-9_.]++$/iD'))
                    ->rule('user_login', array($user, 'unique_username'))
                    ->rule('user_email', 'max_length', array(':value', 60))
                    ->rule('user_email', 'email')
                    ->rule('user_email', 'email_domain')
                    ->rule('user_email', array($user, 'unique_email'));

            $posts = $post->data();

            if ($post->check()) {
                $password = Auth_Wplogin::generate_password();
                $post_array = array(
                    'id' => '',
                    'user_login' => $posts['user_login'],
                    'user_pass' => auth::instance()->hash($password),
                    'user_nicename' => $posts['user_login'],
                    'user_email' => $posts['user_email'],
                    'user_url' => '',
                    'user_registered' => date('Y-m-d H:i:s'),
                    'user_activation_key' => '',
                    'user_status' => 0,
                    'display_name' => $posts['user_login']
                );
                $user->register($post_array);


                $config = Kohana::$config->load('test12')->mail_register;
                foreach ($config as $key => $value) {
                    $$key = $value;
                }
                
                $user_login = $posts['user_login'];
                $date = Date::formatted_time();

                $body = <<< EOT
$user_login

$body1

ユーザー名: $user_login
パスワード: $password
http://localhost/kohana/test12

$body2 $date

EOT;

                $Z_Mail = new Zend_Mail('localhost');
                $Z_Mail
                        ->setBodyText($body)
                        ->setFrom($from)
                        ->addTo($posts['user_email'])
                        ->setSubject($subject)
                        ->send();

                $this->request->redirect('test12');
            }

            $errors = $post->errors('test11');
            $user_login = HTML::chars($_POST['user_login']);
            $user_email = HTML::chars($_POST['user_email']);
        } else {
            $user_login = "";
            $user_email = "";
        }

        $this->response->body(View::factory('test12/auth/register')
                        ->bind('user_login', $user_login)
                        ->bind('user_email', $user_email)
                        ->bind('errors', $errors));
    }

}

?>

 

動作確認

 ほぼ完璧にWordPressの登録画面とその機能を再現しています。エラーメッセージはテスト11のものを流用しているので、表現がちょっと違うかもしれません。WordPress の登録メールは素っ気ないですが、こちらはもうちょっとマシにしてあります・・・(^^;;;