日志的创建与更新
===========================

准备好了 `Post` 模型，我们现在需要调整控制器 `PostController` 的动作和视图了。在这一节里，我们首先自定义CRUD操作的访问权限控制；然后我们修改代码实现 `创建` 与 `更新` 操作。


自定义访问控制
--------------------------

我们想做的第一件事是自定义 [访问控制（Access control）](http://www.yiiframework.com/doc/guide/topics.auth#access-control-filter) ，因为 `yiic` 工具生成的代码并不符合我们的需求。

我们将 `/wwwroot/blog/protected/controllers/PostController.php` 文件中的 `accessRules()` 方法修改如下：

~~~
[php]
public function accessRules()
{
	return array(
		array('allow',  // allow all users to perform 'list' and 'show' actions
			'actions'=>array('index', 'view'),
			'users'=>array('*'),
		),
		array('allow', // allow authenticated users to perform any action
			'users'=>array('@'),
		),
		array('deny',  // deny all users
			'users'=>array('*'),
		),
	);
}
~~~

上面的规则说明：所有用户均可访问 `index` 和 `view` 动作，已通过身份验证的用户可以访问任意动作，包括 `admin` 动作。在其他场景中，应禁止用户访问。注意这些规则将会按它们在此列出的顺序计算。第一条匹配当前场景的规则将决定访问权。例如，如果当前用户是系统所有者，他想尝试访问日志创建页，第二条规则将匹配成功并授予此用户权限。


自定义 `创建` 和 `更新` 操作
--------------------------------------------

`创建` 和 `更新` 操作非常相似。他们都需要显示一个HTML表单用于收集用户的输入的信息，然后对其进行验证，然后将其存入数据库。主要的不同是 `更新` 操作需要把从数据库找到的已存在的日志数据重现在表单中。鉴于此，`yiic` 工具创建了一个局部视图 `/wwwroot/blog/protected/views/post/_form.php` ，它会插入 `创建` 和 `更新` 视图来渲染所需的HTML表单。

我们先修改 `_form.php` 这个文件，使这个HTML表单只收集我们想要的输入：`title`, `content`, `tags` 和 `status`。我们使用文本域收集前三个属性的输入，还有一个下拉列表用来收集 `status` 的输入。此下拉列表的选项值就是可用的日志状态文本。

~~~
[php]
<?php echo $form->dropDownList($model,'status',Lookup::items('PostStatus')); ?>
~~~

在上面的代码中，我们调用了 `Lookup::items('PostStatus')` 以带回日志状态列表。

然后我们修改 `Post` 类，使它可以在日志被存入数据库前自动设置几个属性 (例如 `create_time`, `author_id`)。我们覆盖 `beforeSave()` 方法如下：

~~~
[php]
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` 表以反映 Tag 的使用频率。我们可以在 `afterSave()` 方法中完成此工作，它会在日志被成功存入数据库后自动被Yii调用。

~~~
[php]
protected function afterSave()
{
	parent::afterSave();
	Tag::model()->updateFrequency($this->_oldTags, $this->tags);
}

private $_oldTags;

protected function afterFind()
{
	parent::afterFind();
	$this->_oldTags=$this->tags;
}
~~~

在这个实现中，因为我们想检测出用户在更新现有日志的时候是否修改了 Tag ，我们需要知道原来的 Tag 是什么, 鉴于此，我们还写了一个 `afterFind()` 方法把原有的 Tag 信息保存到变量 `_oldTags` 中。方法 `afterFind()` 会在一个 AR 记录被数据库中的数据填充时自动被 Yii 调用。

这里我们不再列出 `Tag::updateFrequency()` 方法的细节，读者可以参考 `/wwwroot/yii/demos/blog/protected/models/Tag.php` 文件。


<div class="revision">$Id: post.create.txt 2120 2010-05-10 01:29:41Z qiang.xue $</div>