B.2. 認証と継続チェック

まずは、顧客管理システムにアクセスしようとする、ユーザに関する情報を保存する方法が必要です。私たちが使用する顧客管理システムは、ユーザ情報を次の SQL で作成されたデータベーステーブルに保存します:

B.1. テーブル 'users', 架空のクライアントマネージメントシステムのデータベース

CREATE TABLE `users` (
  `id` int(11) NOT NULL auto_increment,
  `username` varchar(255) NOT NULL,
  `password` varchar(32) NOT NULL,
  `first_name` varchar(255) NOT NULL,
  `last_name` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
)

かなり単純ですね。Cake のモデルもかなりありのまま、という感じで次のようになります:

<?php
class User extends AppModel
{
    var $name = 'User';
}
?>

最初に必要なのは、ログインビューとログインアクションです。ユーザがログインしようとする、またアプリケーションがその情報を確認して、システムへのアクセスを許可するかどうか決める仕方となります。ビューは単なる HTML フォームで、 Cake の HTML ヘルパーの助けを借りて作成します:

Example B.2. /app/views/users/login.thtml

<?if ($error): ?>
<p>入力されたログイン情報を確認できませんでした。もういちど入力してください。</p>
<? endif; ?>

<form action="<?php echo $html->url('/users/login'); ?>" method="post">
<div>
    <label for="username">ユーザ名:</label>
    <?php echo $html->input('User/username', array('size' => 20)); ?>
</div>
<div>
    <label for="password">パスワード:</label>
    <?php echo $html->password('User/password', array('size' => 20)); ?>
</div>
<div>
    <?php echo $html->submit('ログイン'); ?>
</div>
</form>

このビューは、シンプルなログインフォームです。ユーザはここからシステムにアクセスしようとします。このフォームに対するアクションは、 /users/login となり、 UsersController 内に存在して下記のようになります:

/app/controllers/users_controller.php (一部)

<?php
class UsersController extends AppController
{
    function login()
    {
        //データが送信されていない場合にはエラーメッセージを表示しない。
         $this->set('error', false);

        // もしユーザがフォームデータを送信したら:
        if (!empty($this->data))
        {
            // まず、データベース内にユーザ情報があるかを
            // フォームを使用したユーザが入力したユーザ名で確認。

            $someone = $this->User->findByUsername($this->data['User']['username']);

            // ここで、 $someone にはユーザデータが入っているか、空になっているかのどちらか。
             // フォームで送信されたパスワードと、データベースに
            // 記録されているものとを比較。

            if(!empty($someone['User']['password']) && $someone['User']['password'] == $this->data['User']['password'])
            {
                 // 注意:DB内のパスワードはハッシュで暗号化されているほうが望ましい。
                // その場合の比較は次のようになる:
                // md5($this->data['User']['password']) == ...

                // ここに来たということは、同じだという意味になる。ここで、幾つかの基本的なセッション情報を作成して、
                // このユーザが「ログイン済み」であることを記憶する。

                $this->Session->write('User', $someone['User']);

                // セッション内に記録したので、アプリケーションの適当なページに
                 // 移動させる。

                $this->redirect('/clients');
            }
            // そうでなければ、入力されたデータが不正:
            else
            {
                // ビューに $error という変数があったことを覚えていますか。これを true に設定:
                $this->set('error', true);
            }
        }
    }

    function logout()
    {
        // ユーザがログアウトボタンを押したらこのアクションにリダイレクトされる。
        // ここでは、セッション情報を捨てるだけ:

        $this->Session->delete('User');

        // たぶん、ここでもどこかに飛ばす必要があるだろう...
     
        $this->redirect('/');
    }
}
?>

悪くないですね: 簡潔にすれば、 login() アクションは20行以内に収まります。このアクションの結果としては、 1: ユーザ情報がセッションに入り、アプリケーションの次なるページに飛ばす。または、 2: ログインスクリーンのページに戻し、ログインフォームを表示する。(追加のエラーメッセージと共に。)