0 フォロワー

投稿の管理

投稿の管理とは、主に管理画面に投稿を一覧表示し、すべてのステータスの投稿を表示、更新、削除できるようにすることを指します。 これらはそれぞれ `admin` 操作と `delete` 操作によって実現されます。 `Gii` によって生成されたコードは、ほとんど変更する必要がありません。 以下では、主にこれら 2 つの操作の実装方法について説明します。

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 を使用しています。 これにより、列でソートしたり、投稿が多すぎて 1 ページに表示できない場合はページネーションを行うことができます。 主な変更点は、各列の表示方法です。 たとえば、`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` アクションは、これら 2 つのシナリオを区別する必要があります。削除リクエストが 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 が関連するコメントを自動的に削除するように外部キー制約を設定できます。 その場合、コードでこの明示的な削除呼び出しを行う必要はなくなります。

タイプミスを見つけたり、このページの改善が必要だと思われる場合は、
github で編集してください !