ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
## 数据获取 像一般应用一样,我们首页就是Index/index 方法。 看看代码: ~~~ public function index($page = 1){ $this->lists($page); $this->display(); } ~~~ 怎么这么短,参数绑定了一个分页参数page。 这个Common模块里设置了一下: `'VAR_PAGE'=>'page',` 因为考虑到默认的p参数可能以后会被占用。page更语义化点。 列表数据的逻辑主要集中在lists方法里。 So,我们来一探它的究竟。 ~~~ public function lists($page = 1){ $map = array(); $list_row = I('r', 10); $postModel = D('Post'); //tag搜索 $tags = I('get.tag'); if($tags){ $ids = $postModel->where(" FIND_IN_SET('{$tags}',tags)")->getField('id', true); $this->assign('title', "标签 <i>{$tags}</i> 下的文章"); if(!empty($ids)) $map['id'] = array('in',$ids); } //关键词搜搜 if(I('get.kw')){ $kw = trim(I('get.kw')); $map['title'] = array('like',"%{$kw}%"); $like_id = $postModel->where("content LIKE '%{$kw}%' OR description LIKE '%{$kw}%'")->getField('id', true); if($like_id) $map['id'] = array('in', $like_id); } //区分所有人和本人发布的文章 if( false !== strpos(__SELF__, 'mine') && is_login()){ $map['member_id'] = session('user.uid'); } //归档搜索 if(isset($_GET['year']) && isset($_GET['month'])){ $year = CONTROLLER_NAME; $month = ACTION_NAME; $map['_string'] = "`deadline` LIKE binary('{$year}-{$month}%')"; } $map['deadline'] = array('elt', datetime()); $this->assign('list', $postModel->where($map)->page($page, $list_row)->order('`deadline` DESC')->select()); /* 分页 */ $total = $postModel->where($map)->count(); $page = new \Think\Page($total, $list_row); $page->rollPage = 5; $page->setConfig('prev','上一页'); $page->setConfig('next','下一页'); $page->setConfig('theme','<div class="pager">%UP_PAGE% %DOWN_PAGE%</div>'); $p = $page->show(); $this->assign('_page', $p? $p: ''); //tag列表 $this->assign('tags', M('Tags')->order('count DESC')->select()); //获取归档 $list = $postModel->where($map)->order('`deadline` DESC,`id` DESC')->select(); $date = $time = array(); foreach ($list as $key => $value) { if($value['deadline']) $time[] = date('F Y', strtotime($value['deadline'])); } $time = array_unique($time); foreach ($time as $key => $value) { $date[] = array( 'text'=> $value, 'link'=> date('Y/m', strtotime($value)) ); } $this->assign('archive', $date); } ~~~ ~~~ $map = array(); $list_row = I('r', 10); $postModel = D('Post'); ~~~ 先定义一个查询用的map数组变量。 并且每页展示数量获取r get或post参数。并且默认值为10。先这样写,支持以后通过传参控制每页显示多少篇文章。 定义一个变量存储实例化Post的模型。 然后就开始查数据并赋值模板变量$list: ~~~ $map['deadline'] = array('elt', datetime()); $this->assign('list', $postModel->where($map)->page($page, $list_row)->order('`deadline` DESC')->select()); ~~~ 默认查询是发布文章截止发布日期时间过后,也就是当前时间大于截止发布时间的文章。 然后用了查询里的page 方法传 $page 页数和 $list_row 每页数量 并按发布截止时间降序 分页后查询。 这里用了一个技巧,直接赋值 而不是先定义一个变量等于查询结果。多一个变量就多占一部分内存,而且这个变量后面我们不会再操作和用到。 而且$postModel 因为后面要用到。所以我们用变量缓存Post 模型实例。并且,因为我们查询需要用到Post模型的类方法,所以用D。如果只是简单查询,最好还是用M函数。 主要列表数据查完后,就是分页和其他额外数据查询。 分页后面会讲。 额外数据标签查询。 也是一句话: ~~~ //tag列表 $this->assign('tags', M('Tags')->order('count DESC')->select()); ~~~ 然后我们看下index模板, ~~~ <extend name="Index/base" /> <block name="header"> <div class="blog-header"> <h4>{$title|default=""}</h4> </div> </block> <block name="main"> <volist name="list" id="post" key="post_k"> <assign name="tpl" value="$post.type"/> <switch name="tpl"> <case value="text"><include file="Index/text" /></case> <case value="picture"><include file="Index/picture" /></case> <case value="music"><include file="Index/music" /></case> <case value="video"><include file="Index/video" /></case> </switch> </volist> <empty name="list"> <div class="text-center"> <img src="__IMG__/logo-grey.png" alt="" width="135"> <br><br> 对不起,没有相应的文章 </div> </empty> {$_page} </block> <block name="sidebar"> <include file="Index/post_btn" /> <div class="sidebar-module sidebar-module-inset"> <h4>热门标签</h4> <ul class="list-unstyled side-tracked-tag"> <volist name="tags" id="tag"> <li> <a class="followed-tag clearfix" href="{:U('/')}?tag={$tag['title']}"> <span class="glyphicon glyphicon-tag" aria-hidden="true"></span> &nbsp;&nbsp; <span class="">{$tag.title}</span> </a> </li> </volist> </ul> </div> <div class="sidebar-module"> <h4>归档</h4> <ol class="list-unstyled"> <volist name="archive" id="vo"> <li><a href="{:U($vo['link'])}">{$vo.text}</a></li> </volist> </ol> </div> </block> <block name="script"> <script type="text/javascript" src="__BOWER__/audiojs/audiojs/audio.min.js"></script> <script src="__STATIC__/swipebox/js/jquery.swipebox.js"></script> <link rel="stylesheet" href="__STATIC__/swipebox/css/swipebox.css"> <script type="text/javascript"> $(function(){ var single = audiojs; single.events.ready(function() { var a1 = single.createAll('', $('.single audio')); }); //图片灯箱 $( '.swipebox' ).swipebox(); }) </script> </block> ~~~ 继承Index/base 父模板,header block部分提供一个默认为空的标题。 ~~~ <block name="header"> <div class="blog-header"> <h4>{$title|default=""}</h4> </div> </block> ~~~ 然后 main block是列表显示。 ~~~ <block name="main"> <volist name="list" id="post" key="post_k"> <assign name="tpl" value="$post.type"/> <switch name="tpl"> <case value="text"><include file="Index/text" /></case> <case value="picture"><include file="Index/picture" /></case> <case value="music"><include file="Index/music" /></case> <case value="video"><include file="Index/video" /></case> </switch> </volist> <empty name="list"> <div class="text-center"> <img src="__IMG__/logo-grey.png" alt="" width="135"> <br><br> 对不起,没有相应的文章 </div> </empty> {$_page} </block> ~~~ 逻辑就是 遍历 list变量,然后 通过assign 模板标签临时赋值tpl为文章类型,本来想通过这个类型动态include的模板的,结果发现不行。include 标签的file属性不支持动态变量。 如果你想动态加载的模板个数有限, 就像我这样switch 后 case里include写死的模板吧。 然后还通过empty 标签 考虑了没数据list的样式。 可爱的小鹿: ![2015-06-30/5592afd665aa8](http://box.kancloud.cn/2015-06-30_5592afd665aa8.png) 这也是搜索不到数据的呈现。 各个文章类型的,前面讲发布时顺带说过部分代码, 现在只说明一个类型文本。 ~~~ <div class="blog-post text"> <present name="post.title"><h2 class="blog-post-title">{$post.title}</h2></present> <p class="blog-post-meta">{$post.update_at|friendly_datetime} by <a href="#">{$post.author}</a></p> <section class="blog-post-content"> {$post.content|htmlspecialchars_decode} </section> <section> <neq name="Think.const.CONTROLLER_NAME" value="Post"> <a href="{:U('/Post/'.$post['id'])}" class="more" target="_blank">未完,继续阅读→</a> <?php if (is_login() && is_login() == $post['member_id']): ?> <a href="/api.php/post?id={$post.id}" class="ajax-delete confirm">删除</a> <?php endif ?> <br> <br> </neq> {$post.tags|get_tag} </section> </div> ~~~ 基本容器都会带上各自类型的类名,如文本就是text,以此类推。 然后就是 更新时间,已经发布者昵称加空间链接。然后就是内容显示,有的类型是描述字段,注意最新版tp,i函数默认用htmlspecialchars过滤了 读出来必须htmlspecialchars_decode。否则看到的是html标签。 如这样: ![2015-06-30/5592b1c024d5f](http://box.kancloud.cn/2015-06-30_5592b1c024d5f.png) 接下来就是空间文章的权限操作显示,并且在详情页时没有这块的显示。 通过neq 标签+控制器常量区分 `<neq name="Think.const.CONTROLLER_NAME" value="Post"` 然后里面比详情页就多了 “查看更多” 、“删除”链接。 然后是标签显示: `{$post.tags|get_tag} ` get_tag函数也简单: ~~~ /** * 获取标签的显示 */ function get_tag($tags, $link = true){ if($link && $tags){ $tags = explode(',', $tags); $link = array(); foreach ($tags as $value) { $link[] = '<a href="'. U('/') . '?tag='.$value.'"><span class="label label-info">' . $value . '</span></a>'; } return join($link,' '); }else{ return $tags? $tags : ''; } } ~~~ 需要生成带链接标签时,分割,然后拼上url参数后join 空格。如果不要url就直接返回字段。