0 关注者

管理文章

管理文章主要指在管理视图中列出文章,该视图允许我们查看所有状态的文章,并更新和删除它们。它们分别由admin操作和delete操作完成。由Gii生成的代码不需要太多修改。下面我们主要解释这两个操作是如何实现的。

1. 以表格形式列出文章

admin操作以表格形式显示所有状态的文章。该视图支持排序和分页。以下是PostController中的actionAdmin()方法

public function actionAdmin()
{
    $model=new Post('search');
    if(isset($_GET['Post']))
        $model->attributes=$_GET['Post'];
    $this->render('admin',array(
        'model'=>$model,
    ));
}

以上代码是由Gii工具生成的,没有任何修改。它首先在search 场景下创建一个Post模型。我们将使用此模型来收集用户指定的搜索条件。然后,我们将用户提供的数据(如果有)分配给模型。最后,我们使用该模型呈现admin视图。

以下是admin视图的代码

<?php
$this->breadcrumbs=array(
    'Manage Posts',
);
?>
<h1>Manage Posts</h1>
 
<?php $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 实体编码。这可以防止 跨站点脚本攻击

2. 删除文章

admin数据网格中,每一行都有一个删除按钮。点击该按钮应该删除相应的文章。在内部,这会触发如下实现的delete操作

public function actionDelete()
{
    if(Yii::app()->request->isPostRequest)
    {
        // we only allow deletion via POST request
        $this->loadModel()->delete();
 
        if(!isset($_GET['ajax']))
            $this->redirect(array('index'));
    }
    else
        throw new CHttpException(400,'Invalid request. Please do not repeat this request again.');
}

以上代码是由Gii工具生成的,没有任何更改。我们想稍微解释一下对$_GET['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 相同的评论;然后,它更新tbl_tag表以反映已删除文章的tags

提示:我们必须在这里显式删除已删除文章的所有评论,因为 SQLite 并不真正支持外键约束。在支持此约束的 DBMS(如 MySQL、PostgreSQL)中,可以设置外键约束,以便如果删除文章,DBMS 会自动删除相关的评论。在这种情况下,我们不再需要在代码中进行此显式删除调用。

发现错别字或您认为此页面需要改进?
在 github 上编辑它 !