日志管理主要是在一个管理视图中列出日志,我们可以查看所有状态的日志,更新或删除它们。它们分别通过 admin
操作和 delete
操作实现。yiic
生成的代码并不需要太多修改。下面我们主要解释这两个操作是怎样实现的。
admin
操作在一个表格视图中列出了所有状态的日志。此视图支持排序和分页。下面就是 PostController
中的 actionAdmin()
方法:
public function actionAdmin()
{
$model=new Post('search');
if(isset($_GET['Post']))
$model->attributes=$_GET['Post'];
$this->render('admin',array(
'model'=>$model,
));
}
上面的代码由 yiic
工具生成,且未作任何修改。它首先创建了一个 search
场景(scenario) 下的 Post
模型。我们将使用此模型收集用户指定的搜索条件。然后我们把用户可能会提供的数据赋值给模型。 最后,我们以此模型显示 admin
视图。
下面就是 admin
视图的代码:
$this->breadcrumbs=array( 'Manage Posts', ); <h1>Manage Posts</h1> $this->widget('zii.widgets.grid.CGridView', array( 'dataProvider'=>$model->search(), 'filter'=>$model, 'columns'=>array( array( 'name'=>'title', 'type'=>'raw', 'value'=>'CHtml::link(CHtml::encode($data->title), $data->url)' ), array( 'name'=>'status', 'value'=>'Lookup::item("PostStatus",$data->status)', 'filter'=>Lookup::items('PostStatus'), ), array( 'name'=>'create_time', 'type'=>'datetime', 'filter'=>false, ), array( 'class'=>'CButtonColumn', ), ), ));
我们使用 CGridView 来显示这些日志。它允许我们在单页显示过多时可以分页并可以按某一列排序。我们的修改主要针对每一列的显示。例如,针对 title
列,我们指定它应该显示为一个超级链接,指向日志的详情页面。表达式$data->url
返回我们之前在 Post
类中定义的 url
属性值。
提示: 当显示文本时,我们要调用 CHtml::encode() 对其中的HTML编码。这可以防止 跨站脚本攻击(cross-site scripting attack).
在 admin
数据表格中,每行有一个删除按钮。点击此按钮将会删除相应的日志。在程序内部,这会触发如下实现的 delete
动作。
public function actionDelete()
{
if(Yii::app()->request->isPostRequest)
{
// we only allow deletion via POST request
$this->loadModel()->delete();
if(!isset($_POST['ajax']))
$this->redirect(array('index'));
}
else
throw new CHttpException(400,'Invalid request. Please do not repeat this request again.');
}
上面的代码就是 yiic
生成的代码,未经任何修改。我们想在此对判断 $_POST['ajax']
稍作解释。CGridView 小物件有一个非常好的特性:它的排序、分页和删除操作默认是通过AJAX实现的。这就意味着在执行上述操作时,整个页面不会重新加载。然而,它也可以在非AJAX模式下运行(通过设置它的 ajaxUpdate
属性为 false 或在客户端禁用JavaScript)。delete
动作区分两个场景是必要的:如果删除请求通过AJAX提交,我们就不应该重定向用户的浏览器,反之则应该重定向。
删除日志应该同时导致日志的所有评论被删除。额外的,我们应更新相关的删除日志后的 tbl_tag
表。 这两个任务都可以通过在 Post
模型类中写一个如下的 afterDelete
方法实现。
protected function afterDelete()
{
parent::afterDelete();
Comment::model()->deleteAll('post_id='.$this->id);
Tag::model()->updateFrequency($this->tags, '');
}
上面的代码很直观:它首先删除了所有 post_id
和所删除的日志ID相同的那些评论。然后它针对所删日志中的 tags
更新了 tbl_tag
表。
提示: 由于 SQLite 并不真正支持外键约束,我们需要显式地删除属于所删日志的所有评论。在一个支持此约束的DBMS (例如 MySQL, PostgreSQL)中,可以设置好外键约束,这样如果删除了一篇日志,DBMS就可以自动删除其评论。这样的话,我们就不需要在我们的代码中显式执行删除了。
Found a typo or you think this page needs improvement?
Edit it on github !
Signup or Login in order to comment.