プロトタイピング - データベースのセットアップ

作成日:2009/03/29
最終更新日:2009/03/29

スケルトンアプリケーションを作り、データベースの設計が終わりました。 このセクションでは実際にデータベースを作成し、スケルトンアプリケーションと接続します。

データベースの作成

データベースはSQLiteを使います。 YiiのデータベースサポートはPDOの上に構築されているため、 アプリケーションコードを変更することなく、MySQLやPostgreSQLといった異なるDBMSを利用することができます。

データベースファイルとして、blog.dbを作ります。このファイルは/wwwroot/blog/protected/dataに置きます。 ディレクトリとファイルはともにWebサーバプロセスとSQLiteにより書き込み可能である必要があります。 ここでは単に/wwwroot/yii/demos/blog/protected/data/blog.dbにあるブログデモのデータベースファイルをコピーすることにします。 もしくは/wwwroot/yii/demos/blog/protected/data/schema.sqlite.sqlにある、SQLファイルを実行することでもデータベースを生成できます。

ヒント:SQL文の実行には、sqlite3コマンドラインツールを利用できます。 詳しくはSQLiteの公式ウェブサイトを参照してください。

データベースと接続する

ブログデータベースを使うには、アプリケーションの設定を変更する必要があります。 設定ファイルは/wwwroot/blog/protected/config/main.phpにあります。 このスクリプトはキーと値のペアで構成された連想配列を返します。 これらの値はアプリケーションインスタンスを初期化するために使われます。

以下のようにアプリケーションのcomponentプロパティに、dbという名前のエントリを追加します。

        
return array(
    ......
    'components'=>array(
        ......
        'db'=>array(
            'class'=>'CDbConnection',
            'connectionString'=>'sqlite:/wwwroot/blog/protected/data/blog.db',
        ),
    ),
    ......
);
        
        

上記の設定は、CDbConnectionクラスのdbコンポーネントを持つことを示します。 dbコンポーネントのconnectionStringプロパティはsqlite:/wwwroot/blog/protected/data/blog.dbに初期化されます。

訳者注:yii-1.0.3以降のデモでは、'class'=>'CDbConnection'の記述はなくなっています。

この設定の場合、Yii:app()->dbを通じてDBコネクションオブジェクトにアクセスすることができます。 Yii::app()が、エントリスクリプトで作成されたアプリケーションインスタンスを返すことに注意して下さい。 DBコネクションのメソッドやプロパティに興味があれば、クラスリファレンスを参照して下さい。 しかし、多くの場合このDBコネクションを直接利用することはありません。 そのかわりにいわゆるActiveRecordを利用してデータベースにアクセスします。

スキャッフォールディング

作成、読み出し、更新、そして削除(CRUD)はデータベースにおける四つの基本操作です。 ブログアプリケーションでは、記事とコメントに対してCRUD操作を実装することが主なタスクになります。 このセクションではyiicツールを用いてこのタスクを完了します。 このプロセスはまたスキャッフォールディング(足場生成)として知られています。

コマンドプロンプトを開き、以下のコマンドを実行します。


% /wwwroot/yii/framework/yiic shell /wwwroot/blog/index.php
Yii Interactive Tool v1.0
Please type 'help' for help. Type 'exit' to quit.
>> model User
......
>> model Post
......
>> model Tag
......
>> model Comment
......
>> crud Post
......
>> crud Comment
......
>> exit
        

情報:PHPのインストール状態によっては、コマンドラインのPHPコマンドに異なったphp.iniを使っていることがあります。 その結果、yiicコマンドを実行する際に、"YiiBase::include(PDO.php): failed to open stream..." もしくは "...could not find driver"といったエラーが発生することがあります。 その場合、以下のようにしてCLI PHPの設定を再チェックしてください。

php -r "phpinfo();"
このコマンドの結果は、使用されているphp.iniを表示します。 もしことなったphp.iniが使われている場合、以下のコマンドを実行することで正しいファイルを指定することができます。
php -c php.ini /wwwroot/yii/framework/yiic.php shell /wwwroot/blog/index.php

上記コマンドによって二つのタスクが達成されます。まず一つ目は、modelコマンドによって、 各データベーステーブルに対応するmodelクラスが生成されます。 二つ目に、crudコマンドによって、PostモデルとCommentモデルのCRUD操作に必要なコードが生成されます。

以下のURLにアクセスすることで生成されたコードをテストすることができます。


http://www.example.com/blog/index.php?r=post
http://www.example.com/blog/index.php?r=comment
        

自動生成されたコードによる記事とコメントの機能は、それぞれ完全に独立していることに注意してください。 また、新しい記事やコメントを作る際に、authIdcreateTimeといった情報を入力する必要があります。 これらの情報は実際のアプリケーションではプログラムによって設定するべきです。 しかし心配することはありません。次のマイルストーンまでにこれらの問題を解決します。 今のところは、このプロトタイプがほぼすべての機能をそなえていることに、それなりに満足すべきでしょう。

次のマイルストーンへの準備として、生成されたファイルを少し詳しく見てみましょう。 すべてのファイルは/wwwroot/blog/protected以下にあります。 説明のため、ファイルをモデルファイルコントローラファイルビューファイルに分類します。

これらのファイルがどう使われるかをよりよく理解するために、記事の一覧が表示される場合のワークフローを示します。

  1. エントリスクリプトが実行され、アプリケーションインスタンスが作成・初期化された後、リクエストを処理します。
  2. アプリケーションはPostControllerのインスタンスを作成し、実行します。
  3. PostControllerは要求されたlistアクションを、actionList()メソッドを呼ぶことで実行します。
  4. actionList()メソッドはデータベースに問い合わせを行い、最近の記事リストを取り出します。
  5. actionList()メソッドは、listビューを表示します。

ユーザ認証

このブログアプリケーションでは、システムオーナとゲストユーザの区別が必要です。 したがって、ユーザ認証機能を実装する必要があります。

スケルトンアプリケーションにはすでにユーザ認証機能が備わっています。 demo/demoもしくはadmin/adminでログインすることができます このセクションでは、認証をUserテーブルに基づいて行うよう、対応するコードを修正します。

ユーザ認証はIUserIdentityインターフェイスを実装するクラスで行われます。 スケルトンアプリケーションは/wwwroot/blog/protected/components/UserIdentity.phpにあるUserIdentityクラスを使っています。

規約により、クラスファイル名は対応するクラス名に接尾辞に拡張子.phpをつけたものになります。 この規約に従って、path aliasを使ったクラス参照が可能になります。 例えば、UserIdentityクラスを、application.components.UserIdentityというエイリアスで参照することができます。 Yiiの多くのAPIにおいて、パスエイリアスを利用可能です。(例:application.components.UserIdentity)。 そして、パスエイリアスを使うことは、絶対パスを埋め込む必要をなくします。 絶対パスを記述することはしばしばアプリケーション配置の際のトラブルの元になります。

UserIdentityクラスを以下のように修正します。

			
<?php
class UserIdentity extends CUserIdentity
{
    private $_id;
 
    public function authenticate()
    {
        $username=strtolower($this->username);
        $user=User::model()->find('LOWER(username)=?',array($username));
        if($user===null)
            $this->errorCode=self::ERROR_USERNAME_INVALID;
        else if(md5($this->password)!==$user->password)
            $this->errorCode=self::ERROR_PASSWORD_INVALID;
        else
        {
            $this->_id=$user->id;
            $this->username=$user->username;
            $this->errorCode=self::ERROR_NONE;
        }
        return !$this->errorCode;
    }
 
    public function getId()
    {
        return $this->_id;
    }
}				
			
		

authenticate()メソッドにおいて、Userクラスを用いてUserテーブルの行を参照しています。 Userテーブルのusername列は与えられたusernameという大文字小文字を区別しないものと同一です。 Userクラスは前のセクションでyiicツールによって作られたものであることを思い出してください。 UserクラスはCActiveRecordを継承しているため、 ActiveRecordの機能を、オブジェクト指向にのっとったやり方で利用することができます。

UserIdentityクラスでは、元の実装はusernameを返すようになっていましたが、getId()メソッドをオーバーライドしてユーザのidを返すようにしています。 usernameidはともにユーザセッションに保存され、コードのどこからでもYii::app()->userでアクセスすることが可能です。

UserIdentityクラスにおいて、対応するクラスファイルを読み込むことなくCUserIdentityを参照しています。 これはCUserIdentityがYii frameworkのコアクラスであるためです。 Yiiはコアクラスのファイルが最初に参照されたときに、自動的のそのファイルを読み込みます。Userでも同じことが行われています。 なぜなら、Userクラスファイルが、/wwwroot/blog/protected/models以下にあり、このディレクトリ設定ファイルでPHPのinclude_pathに追加されているからです。

			
return array(
    ......
    'import'=>array(
        'application.models.*',
        'application.components.*',
    ),
    ......
);				
			
		
上記の設定は/wwwroot/blog/protected/models/wwwroot/blog/protected/componentsの下にあるいかなるクラスファイルも、最初に参照された時点で自動的に読み込まれることを示します。

UserIdentityクラスは主にLoginFormクラスで、ユーザ名とパスワードを元にユーザを認証するために使われます。 以下コードフラグメントはどのようにUserIdentityが使われるのかを示します。


$identity=new UserIdentity($username,$password);
$identity->authenticate();
switch($identity->errorCode)
{
    case UserIdentity::ERROR_NONE:
        Yii::app()->user->login($identity);
        break;
    ......
}			
		

identityとuserコンポーネントはしばしば混同されます。 前者は認証を行う方法のことであり、後者は現在のユーザに関する情報をあらわします。 アプリケーションがもてるuserコンポーネントはひとつだけですが、identityクラスは複数持つことができます。 identityクラスはどのような認証方法がサポートされるかによります。 いったん認証されると、identityインスタンスからuserコンポーネントへ情報が渡され、 アプリケーション全体から Yii::app()->user を用いてアクセス可能になります。

修正後のUserIdentityクラスを確認するため、ブラウザでhttp://www.example.com/blog/index.phpにアクセスし、Userテーブルのユーザ名とパスワードでログインしてみてください。 ブログデモではdemo/demoでアクセスできるはずです。このブログシステムにはユーザ管理機能はありません。ユーザ管理機能は将来の機能拡張として検討されるでしょう。

まとめ

マイルストーン1が完了しました。

これまでにやったことをまとめてみましょう。

  1. 必要機能を洗い出しました
  2. Yiiフレームワークをインストールしました
  3. スケルトンアプリケーションを作成しました
  4. ブログデータベースを設計し、作成しました
  5. データベースと接続できるよう設定を変更しました
  6. 記事とコメントのCRUD操作ができるようコードを実装しました
  7. 認証メソッドを変更し、Userテーブルに対してチェックするようにしました

新しいプロジェクトでは、多くの場合1から4の手順をこなすことになるでしょう。

その3.記事の管理