クッキングの高度なCGridView

この投稿は、Yiiフレームワークに精通し始めた人、つまり、このフレームワークの初級から中級レベルの知識を持つユーザー、およびどのフレームワークがよりクールであるかに興味を持っている人にとって興味深いものになります。



そのため、ここでは、CGridViewを柔軟に構成できること、リレーショナルデータに応じてさまざまなフィルターを追加する方法、CJuiDatePickerなどのウィジェットを追加する方法を示します。



必要なツール

投稿を書くとき、Yii Framework 1.1.12を使用し、MySQLをDBMSとして使用したため、指定されたコードのすべての例がそれらにバインドされます。



さあ、始めましょうか?

典型的なブログの状況を考えてみましょう。最も一般的な投稿、ユーザー、これらの投稿のカテゴリ、タグ、投稿へのコメントのプレートがあります。



CREATE TABLE IF NOT EXISTS `tbl_comment` ( `id` int(11) NOT NULL AUTO_INCREMENT, `content` text COLLATE utf8_unicode_ci NOT NULL, `status` int(11) NOT NULL, `create_time` int(11) DEFAULT NULL, `author` varchar(128) COLLATE utf8_unicode_ci NOT NULL, `email` varchar(128) COLLATE utf8_unicode_ci NOT NULL, `url` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL, `post_id` int(11) NOT NULL, PRIMARY KEY (`id`), KEY `FK_comment_post` (`post_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1; CREATE TABLE IF NOT EXISTS `tbl_post` ( `id` int(11) NOT NULL AUTO_INCREMENT, `title` varchar(128) COLLATE utf8_unicode_ci NOT NULL, `content` text COLLATE utf8_unicode_ci NOT NULL, `status` int(11) NOT NULL, `create_time` datetime NOT NULL, `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `author_id` int(11) NOT NULL, PRIMARY KEY (`id`), KEY `FK_post_author` (`author_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1; CREATE TABLE IF NOT EXISTS `tbl_posts_tags` ( `id` int(11) NOT NULL AUTO_INCREMENT, `id_post` int(11) NOT NULL, `id_tag` int(11) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; CREATE TABLE IF NOT EXISTS `tbl_tag` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(128) COLLATE utf8_unicode_ci NOT NULL, `frequency` int(11) DEFAULT '1', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ; CREATE TABLE IF NOT EXISTS `tbl_user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(128) COLLATE utf8_unicode_ci NOT NULL, `first_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL, `last_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL, `father_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL, `password` varchar(128) COLLATE utf8_unicode_ci NOT NULL, `salt` varchar(128) COLLATE utf8_unicode_ci NOT NULL, `email` varchar(128) COLLATE utf8_unicode_ci NOT NULL, `profile` text COLLATE utf8_unicode_ci, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=2 ;
      
      







ブログの投稿が主要なエンティティであり、他のすべてのエンティティがそれらに添付されているため、投稿ラベルにCgridViewを設定することを検討します。



投稿モデルの関係のカスタマイズ

 public function relations(){ return array( // 'tags' => array(self::MANY_MANY, 'Tag', 'tbl_posts_tags(id_post, id_tag)'), //  'author' => array(self::BELONGS_TO, 'User', 'author_id'), // 'comments' => array(self::HAS_MANY, 'Comment', 'post_id', 'condition'=>'comments.status='.Comment::STATUS_APPROVED, 'order'=>'comments.create_time DESC'), //   'commentCount' => array(self::STAT, 'Comment', 'post_id', 'condition'=>'status='.Comment::STATUS_APPROVED), ); }
      
      







コントローラーはほぼデフォルトのままにします

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







Tagモデルでは、フィルターにプレートをドロップダウンリストとして挿入するためのフォーマットに適した配列を返す新しいメソッドを追加します

  public function getForFilter(){ return CHtml::listData( self::model()->findAll(array( 'select' => array('id', 'name') )), 'id', 'name' ); }
      
      







ユーザーモデルにフルネームを返すメソッドを追加します

  public function getFullFio(){ return $this->last_name.' '.$this->first_name.' '.$this->father_name; }
      
      







同様のメソッドをPostモデルに追加して、記事に関連するすべてのタグのリストを表示する必要があります。

  public function getTagsToString(){ $t = CHtml::listData( $this->tags, 'id', 'name' ); return implode(',', $t); }
      
      







さらに、PostモデルとCGridViewが表示されるディスプレイのみで作業します。

MANY_MANYリレーショナルでタグを検索するには、投稿モデルで追加のフィールドを使用します

  public $id_tag = '';
      
      







フィルタリングするには、Post :: search()メソッドを拡張する必要があります。

私にはこのように見えます-

  public function search($defaultCriteria = null){ $criteria = $defaultCriteria != null ? $defaultCriteria : new CDbCriteria; //         //        ,           $criteria->with = array( 'tags' => array( 'select' => array('id', 'name') ), 'author' => array( 'select' => array('last_name', 'first_name', 'father_name') ), 'commentCount' ); $criteria->together = true; if(!empty($this->author_id)){ //  id_author          ,    $criteria->addSearchCondition( new CDbExpression( 'CONCAT(author.last_name, " ", author.first_name, " ", author.father_name)' ), $this->author_id ); } //   if(isset($this->id_tag) && !empty($this->id_tag)){ $criteria->compare('tags.id', '='.$this->id_tag, true); } $criteria->compare('t.id', '='.$this->id, true); $criteria->compare('t.create_time', '='.$this->create_time, true); $criteria->compare('t.update_time', '='.$this->update_time, true); $criteria->compare('t.title', $this->title, true); $criteria->compare('t.status', '='.$this->status); return new CActiveDataProvider('Post', array( 'criteria'=>$criteria, 'sort'=>array( 'defaultOrder'=>'t.status, t.update_time DESC', ), )); }
      
      







ラベル内のタグのリストを1行として表示するには、以前に作成したマジックメソッドPost :: getTagsToString()を使用します

  ... array( 'name'=>'id_tag', 'value'=>'$data->tagsToString', 'filter'=>Tag::model()->forFilter, ), ...
      
      







同様に、フルネームのマッピングを行います 投稿者

  ... array( 'name'=>'author_id', 'value'=>'isset($data->author) ? $data->author->fullFio : ""' ), ...
      
      







さらに興味深いことに、標準のCJuiDatePickerウィジェットをフィルタープレートに固定します

このようなパラメーターを使用して新しい列を追加します。

  ... array( 'name' => 'create_time', 'type' => 'raw', 'htmlOptions' => array('align' => 'center', 'style' => 'width: 123px;'), 'filter' => $this->widget('zii.widgets.jui.CJuiDatePicker', array( 'model' => $model, 'id' => 'create_time', 'attribute' => 'create_time', 'htmlOptions' => array('style' => 'width: 80px;'), 'options' => array( 'dateFormat' => 'yy-mm-dd', 'changeYear' => true ), ), true) ), ...
      
      







しかし、それだけではありません。プレートがajaxUpdateを使用している場合、プレートをajaxで更新した後、日付を含むフィルターが壊れます。 これを修正するには、afterAjaxUpdateイベントによってカレンダーを再初期化する必要があります。これは完了です。

  ... 'afterAjaxUpdate' => 'function(){ jQuery("#create_date").datepicker({ dateFormat: "yy-mm-dd", changeYear:true }); }', ...
      
      









タブレットのカスタマイズも非常に簡単です。たとえば、画像をボタンの1つに置き換えるか非表示にする必要がある場合、標準ボタンの場合はプロパティを使用できます-

{button_name} ButtonImageUrl

{button_name} ButtonLabel

{button_name} ButtonOptions

{button_name} ButtonUrl



たとえば、ボタンの画像を標準の更新ボタンに置​​き換えます

  ... array( 'class'=>'CButtonColumn', 'updateButtonImageUrl' => Yii::app()->baseUrl.'/images/configure.gif' ), ...
      
      







または、たとえば、独自のボタンを作成したい

 ... array( 'class' => 'ext.myButtonColumn', 'template'=> '{on} {off} ', 'buttons' => array( 'off' => array( 'label' => '', 'imageUrl' => Yii::app()->baseUrl.'/images/cancel.gif', 'visible' => '$data->active == 0', 'url' => 'Yii::app()->createAbsoluteUrl("post/on")', ), 'on' => array( 'label' => '', 'imageUrl' => Yii::app()->baseUrl.'/images/flag.gif', 'visible' => '$data->active == 1', 'url' => 'Yii::app()->createAbsoluteUrl("post/off")', ), ), ) ...
      
      







最後に

CGridViewのアップグレードに役立つ拡張機能への便利なリンクをここに残しておきます。

指定した基準に従って、標準ビューを非表示にし、ボタンを更新および削除できます

アルファベットのページネーション

タブレットをツリー形式で表示する



ソース 、内部ベースダンプ。



All Articles