記事の作成と修正
Post
モデルの準備ができたら、PostController
のためのアクションとビューを手直しします。このセクションでは、最初に CRUD 操作のアクセス制御をカスタマイズします。次に create
と update
の操作を実装しているコードを修正します。
アクセス制御のカスタマイズ
最初にやりたいのは、アクセス制御 のカスタマイズです。gii
が生成したコードは私達の要求に合っていません。
/wwwroot/blog/protected/controllers/PostController.php
ファイルを開いて、accessRules()
メソッドを以下のように修正します。
public function accessRules() { return array( array('allow', // 全てのユーザに 'index' と 'view' のアクションを許可 'actions'=>array('index', 'view'), 'users'=>array('*'), ), array('allow', // 認証されたユーザに全てのアクションを許可 'users'=>array('@'), ), array('deny', // 全てのユーザのアクセスを拒否 'users'=>array('*'), ), ); }
上記のルールでは、すべてのユーザが index
と view
アクションにアクセス可能です。認証済みユーザは、admin
アクションを含め、すべてのアクションにアクセス可能です。これ以外のシナリオではアクセスが拒否されます。ここで気をつけて欲しいのは、これらのルールはここに書き並べた順番で評価されるということです。そのときの状況に最初に一致したルールによって、アクセスの可否が決まります。例えば、ユーザがシステムオーナで記事作成ページを訪れようとした場合、2番目のルールが一致して、ユーザにアクセス権が与えられます。
create
操作と update
操作のカスタマイズ
create
操作と update
操作はよく似ています。両方とも、ユーザの入力を得るために HTML フォームを表示し、入力を検証し、データベースに保存します。大きな違いは、update
操作ではデータベースの既存のデータをあらかじめフォームにセットするという点です。このため gii
は部分的なビュー(partial view)として /wwwroot/blog/protected/views/post/_form.php
を生成し、これを create
と update
の両方のビューに埋め込んで HTML フォームを表示します。
最初に _form.php
ファイルを修正して、HTML フォームで集める入力値をユーザに入力させたい title
, content
, tags
, status
だけにします。はじめの3つの属性には通常のテキスト入力欄を使います。status
にはドロップダウンリストを使います。ドロップダウンリストの選択肢は、記事のステータスを表す文字列です。
echo $form->dropDownList($model,'status',Lookup::items('PostStatus'));
上の例では、記事が取り得るステータスの一覧を取得するために、Lookup::items('PostStatus')
を呼んでいます。
次に Post
クラスを修正し、記事がデータベースに保存される前にいくつかの属性 (create_time
や author_id
) が自動的にセットされるようにします。以下のように beforeSave()
メソッドをオーバーライドします。
protected function beforeSave() { if(parent::beforeSave()) { if($this->isNewRecord) { $this->create_time=$this->update_time=time(); $this->author_id=Yii::app()->user->id; } else $this->update_time=time(); return true; } else return false; }
記事を保存するときに、タグの出現頻度の変化を反映するために tbl_tag
テーブルを更新する必要があります。この処理は afterSave()
メソッドに書けばできます。この afterSave()
メソッドは、データベースへの記事の保存が成功した後に、Yii から自動的に呼ばれます。
protected function afterSave() { parent::afterSave(); Tag::model()->updateFrequency($this->_oldTags, $this->tags); } private $_oldTags; protected function afterFind() { parent::afterFind(); $this->_oldTags=$this->tags; }
実装においては、ユーザが既存の記事を更新するときにタグを変更したかどうか判定したいので、変更前のタグが何であったかを知る必要があります。このため、afterFind()
メソッドを書いて、_oldTags
変数に古いタグを保持するようにしました。この afterFind()
メソッドは、AR レコードにデータベースから取得したデータが投入されたときに、Yii から自動的に呼ばれます。
ここでは Tag::updateFrequency()
メソッドについて詳しく説明しません。興味のある方は /wwwroot/yii/demos/blog/protected/models/Tag.php
を参照してください。