多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
什么是搜索? 在一堆数据里通过查询条件筛选出你想要的结果。 所以其实分页、标签、关键词、归档都叫搜索。 搜索分两部分:组装搜索条件、将搜索结果如实的反应在页面上即告诉用户我当前搜索的条件是什么,不要让用户只能通过url判断。 而在TP中。搜索的实现就是体现在怎么根据get或者post参数,动态生成一个查询条件数组。 ## 标签tag搜索 ~~~ //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); } ~~~ 标签搜索,我把他分解为搜素符合标签的id再通过 id in去筛选。 为什么不把FIND_IN_SET 放到map中? 首先,tp里只能用`_string` 用法来实现 字段中带函数的使用,但是后面归档也用了_string 防止以后还有这种情况,可能会造成冲突。干脆查出id,反正只有这种情况是子查询,查询结果也快。 然后,tag搜索虽然来自表签的点击,但是可以通过url伪造。分开写,不容易出安全问题。 find_in_set 是mysql 专门为以一个分隔符拼接多个值存一个字段时搜索提供的函数。 以往我们面对 1,2,3 这样的 只能 最后也加一个',' 变成1,2,3, 这样like "%$a,%" 这样hack的方式去搜索。 ## 关键词搜索 //关键词搜搜 ~~~ if(I('get.kw')){ $kw = trim(I('get.kw')); $search = array(); $search['title'] = array('like', '%{$kw}%'); $like_id = $postModel->where("content LIKE '%{$kw}%' OR description LIKE '%{$kw}%'")->getField('id', true); if($like_id) $search['id'] = array('in', $like_id); $search['_logic'] = 'or'; $map['_complex'] = $search; } ~~~ 搜索关键词,我们也分开搜索。匹配模糊查询content和description2个长文本字符串的文章id和匹配模糊查询的title。然后由于这2个条件是OR 或的关系,整个查询where 部分语句和其他的条件又是and 且的关系。所以我用了_complex来实现这个搜索。 由于我们只是演示功能如何实现,性能不是我们目前该考虑的。搜索慢的时候再去考虑要不要做全文检索。 关键词搜索,分开了以后也有机会做查询缓存。这样什么关键词匹配什么id。 不过以后可能考虑的是这个缓存怎么做。因为关键词搜索后面还要考虑全部数据搜索和当前用的搜索行为。 然后,搜索我们url “/Search?kw=关键词” 我们也分配了一个search方法: ~~~ //搜索 public function search(){ $kw = I('get.kw'); if(!$kw) $this->error('请输入关键字'); $this->assign('title', "包含关键字 {$kw} 的文章"); $this->assign('kw', $kw); $this->lists(I('get.page', 1)); $this->display('Index/index'); } ~~~ 处理了关键词为空的错误提示,和搜索时标题。 刚刚标签我们没有分配一个方法给它,而是在lists里指定了title。这样做是标签以后可能在其他地方符合搜索,比如我的空间里某个标签的文章。 就是 mine.html?tag=音乐 这样也支持。 这样如要要这个功能,我们只需要改前台生成标签的函数,和sidebar侧边栏上的全部热门标签那块。 如果要那么做,全部热门标签也得区分首页和个人的了,如果考虑别人空间的,也得显示为“XXX的热门标签”。 暂时先这么做。标签都是通用搜索。url上不特殊处理。知道以后很容易支持就好了。