通过组件的方式实现文章列表,达到重复利用的目的。其他页面需要文章列表的时候只需要调用组件就可以了。
1、创建文章列表自定义组件目录
frontend下的widgets 表示存放自定义组件的目录,widgets下的post表示文章列表组件。以后有新的自定义组件只需参照文章列表组件的结构,将其放在frontend/widgets下即可。
views下的index.php为组件获取数据后的数据渲染页面
PostWidget.php为自定义组件类
2、创建文章列表组定义组件类
<?php namespace frontend\widgets\post; /** * 自定义文章列表组件 */ use common\models\PostsModel; use frontend\models\PostsForm; use yii\base\Widget; use yii\data\Pagination; use yii\helpers\Url; use Yii; class PostWidget extends Widget { //文章列表的标题 public $title = ''; //显示条数 public $limit = 6; //是否显示更多 public $more = true; //是否显示分页 public $page = false; public function run() { //获取当前页,若没有则默认当前页为1 $curPage = Yii::$app->request->get('page',1); //数据条件,获取已发布数据 $cond = ['=','is_valid',PostsModel::IS_VALID]; //获取文章列表数据 $res = PostsForm::getList($cond, $curPage, $this->limit); //设置文章列表属性 $result['title'] = $this->title?$this->title: '最新文章'; $result['more'] = Url::to(['posts/index']); $result['body'] = $res['data']?$res['data']:[]; //判断是否显示分页 if ($this->page){ $pages = new Pagination(['totalCount'=>$res['count'],'pageSize'=>$res['pageSize']]); } return $this->render('index',['data'=>$result]); } }
文章列表自定义组件到到这也就基本实现了,不过具体的数据获取方法还没有实现,所以接下来就要实现这些获取数据的方法。
2、组件中数据获取方法的实现
①getList方法实现 (PostForm 中)
/** * 获取文章列表 * @param $cond * @param int $curPage * @param int $pageSize * @param array $orderBy * @return mixed */ public static function getList($cond, $curPage = 1, $pageSize = 5, $orderBy = ['id'=> SORT_DESC]) { $model = new PostsModel(); //构造查询语句 //查询字段 $select = ['id', 'title', 'summary', 'label_img', 'cat_id', 'user_id', 'user_name', 'is_valid', 'created_at', 'updated_at']; $query = $model->find() ->select($select) ->where($cond) ->with('relate.tag','extend') ->orderBy($orderBy); //获取分页数据 //因为其他地方也有可能获取列表数据,所以单独用一个获取分页数据的方法来获取文章列表数据 //为了实现getPage方法的共用性,我们在BaseModel中实现这个方法 $res = $model -> getPage($query, $curPage, $pageSize); //格式化数据(主要格式化tag数据) $res['data'] = self::_formatList($res['data']); //把获取到的数据返回出去 return $res; }
②实现数据格式化方法(PostForm 中)
/** * 格式化数据 * @param $data * @return mixed */ public static function _formatList($data) { foreach ($data as &$list){ $list['tags'] = []; if (isset($list['relate']) && !empty($list['relate'])){ foreach ($list['relate'] as $lt){ $list['tags'][] = $lt['tag']['tag_name']; } //格式化后把原有的tag关联数据删除 unset($list['relate']); } } return $data; }
③在BaseModel中实现获取分页数据方法getPage
public function getPage($query, $curPage = 1, $pageSize = 10, $search = null) { //判断是否搜索,若搜索还需筛选数据 if ($search) $query = $query->andFilerWhere($search); //获取总条数 若总条数为0,返回初始配置,若不返回数据会报错 $data[ 'count'] = $query->count(); if (!$data['count']){ return ['count'=>0, 'curPage'=>$curPage, 'pageSize'=>$pageSize, 'start'=>0, 'end=>0', 'data'=>[] ]; } //当前页计算 防止人为输入的页面不存在 $curPage = (ceil($data['count'])/$pageSize<$curPage)?ceil($data['count'])/$pageSize<$curPage:$curPage; //当前页,将数据放入data中返回 $data['curPage'] = $curPage; //每页显示条数 $data['pageSize'] = $pageSize; //数据起始 $data['start'] = ($curPage-1)*$pageSize+1; //数据结束 $data['end'] = (ceil($data['count'])/$pageSize) == $curPage?$data['count']:$curPage*$pageSize; //数据获取 $data['data'] = $query->offset(($curPage-1)*$pageSize) ->limit($pageSize) ->asArray() ->all(); return $data; }
数据已经获取到,接下来把数据渲染到自定义文章列表组件的渲染页面index.php
<?php use yii\helpers\Url; use yii\widgets\LinkPager; ?> <div class="panel"> <div class="panel-title box-title"> <span><?=$data['title']?></span> <?php if($this->context->more):?> <span class="pull-right"><a href="<?=$data['more']?>" class="font-12">更多»</a></span> <?php endif;?> </div> <div class="new-list"> <?php foreach ($data['body'] as $list):?> <div class="panel-body border-bottom"> <div class="row"> <div class="col-lg-4 label-img-size"> <a href="#" class="post-label"> <img src="<?=($list['label_img']?\Yii::$app->params['upload_url'].$list['label_img']:\Yii::$app->params['default_label_img'])?>" alt="<?=$list['title']?>"> </a> </div> <div class="col-lg-8 btn-group"> <h1><a href="<?=Url::to(['post/detail','id'=>$list['id']])?>"><?=$list['title']?></a></h1> <span class="post-tags"> <span class="glyphicon glyphicon-user"></span><a href="<?=Url::to(['member/index','id'=>$list['user_id']])?>"><?=$list['user_name']?></a> <span class="glyphicon glyphicon-time"></span><?=date('Y-m-d',$list['created_at'])?> <span class="glyphicon glyphicon-eye-open"></span><?=isset($list['extend']['browser'])?$list['extend']['browser']:0?> <span class="glyphicon glyphicon-comment"></span><a href="<?=Url::to(['post/detail','id'=>$list['id']])?>"><?=isset($list['extend']['comment'])?$list['extend']['comment']:0?></a> </span> <p class="post-content"><?=$list['summary']?></p> <a href="<?=Url::to(['post/detail','id'=>$list['id']])?>"><button class="btn btn-warning no-radius btn-sm pull-right">阅读全文</button></a> </div> </div> <div class="tags"> <?php if(!empty($list['tags'])):?> <span class="fa fa-tags"></span> <?php foreach ($list['tags'] as $lt):?> <a href="#"><?=$lt?></a>, <?php endforeach;?> <?php endif;?> </div> </div> <?php endforeach;?> </div> <?php if($this->context->page):?> <div class="page"><?=LinkPager::widget(['pagination' => $data['page']]);?></div> <?php endif;?> </div>
不过这里有两个数据需要配置 'upload_url' (图片路径前缀),'default_label_img',当文章没有缩率图时显示的默认图片
'upload_url' => 'http://frontend.yii2.com', 'default_label_img' => '/statics/images/default.png',
文章列表自定义组件就算完成了,接下来就是调用,文章列表渲染页调用,其他页面调用文章列表自定义组件列表方法也是一样的
<?php use frontend\widgets\post\PostWidget; use yii\base\Widget; ?> <?=PostWidget::widget()?>
文章列表页需要添加的css样式(放到site.css页面即可),若不加css样式最后的页面显示可能会有点丑。
.panel-body h1 { font-size: 18px; height: 30px; line-height: 30px; margin: 0; overflow: hidden; } .post-label { background-color: #fff; border: 1px solid #ddd; display: block; line-height: 1.42857; padding: 4px; transition: border 0.2s ease-in-out 0s; border-radius: 0; margin-bottom: 5px; position: relative; } .post-label > img { margin-left: auto; margin-right: auto; display: block; height: 150px; width: 100%; } .post-tags { color: #999; font-size: 12px; } .post-tags span { margin-right: 4px; } .post-tags a { color: #999; } .tags { font-size: 12px; margin-left: 2px; } .font-12 { font-size: 12px; }
最后的文章列表调用效果: