記事の作成と修正
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 を参照してください。