查看: 31614|回复: 27

[原 创] PHPCMS v9 全站搜索( all model) 全模型搜索 技术分享

  [复制链接]
发表于 2013-11-4 15:22:40 | 显示全部楼层 |阅读模式
  • 插件名称:PC V9 全站搜索(全模型) 技术分享
  • 适用版本:v9
  • 语言编码:GBK简体 UTF8简体 
  • 插件作者:刘波
  • 版权所属:PHPCMS_TH"3_TEAM (lamp兄弟连)
  • 支持网站:www.lampbrother.net/phpcms.html
  • 插件介绍:刘波:北京兄弟连教育PHP高级讲师;
    此扩展为满足低存储内容,但需要搜索多模型的数据的用户的一个扩展性开发。
  • 适用版本号:所有版本
本帖最后由 0793jay 于 2013-11-4 15:28 编辑

想要再次改造搜索模块,当前要先了解搜索模块。

很多同学会问,老师,你这个是斯芬克斯搜索吗?
我正面回答:不是。因为很多同学他用的是虚拟主机,没有这个环境,也没有那么能力去配置,而且,本身站点的数据也并不是特别多。那么,怎么去实现 多模型搜索呢?

我昨天用了一天的时间,采集了新浪400万条数据,并重复在两个模型里。就是为了今天给大家讲解 PHPCMS V9 搜索模块中的全站搜索!

本人粗略的注释了一下 搜索的 事件函数。
作为大家入门改造全站搜索的基础。
  1.         /**
  2.          * 关键词搜索
  3.          */
  4.         public function init() {
  5.                 if(isset($_GET['q'])&&isset($_GET['full'])){
  6.                         header("Location:index.php?m=search&c=index&a=fullsearch");
  7.                 }
  8.                 //获取siteid
  9.                 $siteid = isset($_REQUEST['siteid']) && trim($_REQUEST['siteid']) ? intval($_REQUEST['siteid']) : 1;
  10.                 #获得站点SEO 信息
  11.                 $SEO = seo($siteid);
  12.        
  13.                 //搜索配置
  14.                 $search_setting = getcache('search');
  15.                 #获得当前站点的搜索配置信息
  16.                 $setting = $search_setting[$siteid];
  17.                
  18.                 /*$setting
  19.                         array(6) {
  20.                                         ["fulltextenble"]=> string(1) "1"  全站检索
  21.                                         ["relationenble"]=> string(1) "0"  相关搜索
  22.                                         ["suggestenable"]=> string(1) "0"  建议搜索
  23.                                         ["sphinxenable"]=> string(1) "0"  斯芬克斯开关
  24.                                         ["sphinxhost"]=> string(0) ""   斯芬克斯主机
  25.                                         ["sphinxport"]=> string(0) ""   斯芬克斯端口
  26.                                 }
  27.                
  28.                 */
  29.                 $search_model = getcache('search_model_'.$siteid);
  30.                 /*
  31.                 搜索的模型
  32.                 Array (
  33.                         [1] => Array ( [typeid] => 1 [name] => 新闻 [sort] => 1 )
  34.                         [3] => Array ( [typeid] => 3 [name] => 图片 [sort] => 2 )
  35.                         [2] => Array ( [typeid] => 2 [name] => 下载 [sort] => 3 )
  36.                         [special] => Array ( [typeid] => 52 [name] => 专题 )
  37.                 )
  38.                 */
  39.                
  40.                 $type_module = getcache('type_module_'.$siteid);
  41.                 /*
  42.                 涉及搜索的分类
  43.                 Array ( [special] => 52 )
  44.                 */
  45.                
  46.                 if(isset($_GET['q'])) {
  47.                         # 搜索提交按钮后逻辑代码开始
  48.                         if(trim($_GET['q'])=='') {
  49.                         #如果提交过来的搜索内容为空,则 跳转回搜索模块首页
  50.                                 header('Location: '.APP_PATH.'index.php?m=search');exit;
  51.                         }
  52.                         #搜索类型若为空,则默认搜索类型值为  48 ,否则 采用 GET传递的值
  53.                         $typeid = empty($_GET['typeid']) ? 48 : intval($_GET['typeid']);
  54.                         # 按时间搜索的 条件;
  55.                         #时间类型必须在  
  56.                         #                all=>不限制,day=>一天内,month=> 一月内,year=>一年内,week => 一星期内
  57.                         # 否则 默认为所有不限制
  58.                         $time = empty($_GET['time']) || !in_array($_GET['time'],array('all','day','month','year','week')) ? 'all' : trim($_GET['time']);
  59.                         #定义当前分页页码
  60.                         $page = isset($_GET['page']) ? intval($_GET['page']) : 1;
  61.                         #定义每页步进数量
  62.                         $pagesize = 10;
  63.                         #安全处理 GET 过来的搜索词
  64.                         $q = safe_replace(trim($_GET['q']));
  65.                         #去除HTML,XML,PHP 标签并将预定义的字符转换为 HTML 实体
  66.                         $q = htmlspecialchars(strip_tags($q));
  67.                         $q = str_replace('%', '', $q);        //过滤'%',用户全文搜索
  68.                         $search_q = $q;        //搜索原内容
  69.                        
  70.                         //按文章发布时间搜索
  71.                         if($time == 'day') {
  72.                                 $search_time = SYS_TIME - 86400;  //一天内
  73.                                 $sql_time = ' AND adddate > '.$search_time;  // 搜索表里的加入时间  >
  74.                         } elseif($time == 'week') {
  75.                                 $search_time = SYS_TIME - 604800;
  76.                                 $sql_time = ' AND adddate > '.$search_time;
  77.                         } elseif($time == 'month') {
  78.                                 $search_time = SYS_TIME - 2592000;
  79.                                 $sql_time = ' AND adddate > '.$search_time;
  80.                         } elseif($time == 'year') {
  81.                                 $search_time = SYS_TIME - 31536000;
  82.                                 $sql_time = ' AND adddate > '.$search_time;
  83.                         } else {
  84.                                 $search_time = 0;
  85.                                 $sql_time = '';
  86.                         }
  87.                         if($page==1 && !$setting['sphinxenable']) {
  88.                                 //精确搜索
  89.                                 $commend = $this->db->get_one("`typeid` = '$typeid' $sql_time AND `data` like '%$q%'");
  90.                         } else {
  91.                                 $commend = '';
  92.                         }
  93.                         //如果开启sphinx
  94.                         if($setting['sphinxenable']) {
  95.                                 $sphinx = pc_base::load_app_class('search_interface', '', 0);
  96.                                 $sphinx = new search_interface();
  97.                                
  98.                                 $offset = $pagesize*($page-1);
  99.                                 $res = $sphinx->search($q, array($siteid), array($typeid), array($search_time, SYS_TIME), $offset, $pagesize, '@weight desc');
  100.                                 $totalnums = $res['total'];
  101.                                 //如果结果不为空
  102.                                 if(!empty($res['matches'])) {
  103.                                         $result = $res['matches'];
  104.                                 }
  105.                         } else {
  106.                                 pc_base::load_sys_class('segment', '', 0);
  107.                                 $segment = new segment();
  108.                                 //分词结果
  109.                                 $segment_q = $segment->get_keyword($segment->split_result($q));
  110.                                 //如果分词结果为空
  111.                                 if(!empty($segment_q)) {
  112.                                         $sql = "`siteid`= '$siteid' AND `typeid` = '$typeid' $sql_time AND MATCH (`data`) AGAINST ('$segment_q' IN BOOLEAN MODE)";
  113.                                 } else {
  114.                                         $sql = "`siteid`= '$siteid' AND `typeid` = '$typeid' $sql_time AND `data` like '%$q%'";
  115.                                 }

  116.                                 $result = $this->db->listinfo($sql, 'searchid DESC', $page, 10);
  117.                                 # 获得搜索索引的数据
  118.                         }

  119.                         //如果开启相关搜索功能
  120.                         if($setting['relationenble']) {
  121.                                 //如果关键词长度在8-16之间,保存关键词作为relation search
  122.                                 $this->keyword_db = pc_base::load_model('search_keyword_model');

  123.                                 if(strlen($q) < 17 && strlen($q) > 5 && !empty($segment_q)) {
  124.                                         $res = $this->keyword_db->get_one(array('keyword'=>$q));
  125.                                         if($res) {
  126.                                                 //关键词搜索数+1
  127.                                                 //$this->keyword_db->update(array('searchnums'=>'+=1'), array('keyword'=>$q));
  128.                                         } else {
  129.                                                 //关键词转换为拼音
  130.                                                 pc_base::load_sys_func('iconv');
  131.                                                 $pinyin = gbk_to_pinyin($q);
  132.                                                 if(is_array($pinyin)) {
  133.                                                         $pinyin = implode('', $pinyin);
  134.                                                 }
  135.                                                 $this->keyword_db->insert(array('keyword'=>$q, 'searchnums'=>1, 'data'=>$segment_q, 'pinyin'=>$pinyin));
  136.                                         }
  137.                                 }
  138.                                 //相关搜索
  139.                                 if(!empty($segment_q)) {
  140.                                         $relation_q = str_replace(' ', '%', $segment_q);
  141.                                 } else {
  142.                                         $relation_q = $q;
  143.                                 }
  144.                                 $relation = $this->keyword_db->select("MATCH (`data`) AGAINST ('%$relation_q%' IN BOOLEAN MODE)", '*', 10, 'searchnums DESC');
  145.                         }
  146.                         #相关搜索功能代码结束       
  147.                         //如果结果不为空
  148.                           if(!empty($result) || !empty($commend['id'])) {
  149.                                 //开启sphinx后文章id取法不同
  150.                                 if($setting['sphinxenable']) {
  151.                                         foreach($result as $_v) {
  152.                                                 $sids[] = $_v['attrs']['id'];
  153.                                         }
  154.                                 } else {
  155.                                         foreach($result as $_v) {
  156.                                                 $sids[] = $_v['id'];
  157.                                         }
  158.                                 }
  159.                                 // 按文章ID进行组装SQL语句
  160.                                 if(!empty($commend['id'])) {
  161.                                         $sids[] = $commend['id'];
  162.                                 }
  163.                                 $sids = array_unique($sids);
  164.                                 // 定义WHERE 条件
  165.                                 $where = to_sqls($sids, '', 'id');
  166.                                
  167.                                 //获取模型id
  168.                                 $model_type_cache = getcache('type_model_'.$siteid,'search');
  169.                                 $model_type_cache = array_flip($model_type_cache);
  170.                                 $modelid = $model_type_cache[$typeid];
  171.                                 #按照GET传值的类型ID,去匹配对应的数据库模型
  172.                                 //是否读取其他模块接口
  173.                                 if($modelid) {
  174.                                         #设置数据库表
  175.                                         $this->content_db->set_model($modelid);
  176.                                        
  177.                                         /**
  178.                                          * 如果表名为空,则为黄页模型
  179.                                          */
  180.                                         if(empty($this->content_db->model_tablename)) {
  181.                                                 $this->content_db = pc_base::load_model('yp_content_model');
  182.                                                 $this->content_db->set_model($modelid);

  183.                                         }
  184.                                 #如果开启斯芬克斯,则此斯芬克斯的搜索机制
  185.                                         if($setting['sphinxenable']) {
  186.                                                 $data = $this->content_db->listinfo($where, 'id DESC', 1, $pagesize);
  187.                                                 $pages = pages($totalnums, $page, $pagesize);
  188.                                         } else {
  189.                                         # 按照内容模型的搜索机制
  190.                                                 $data = $this->content_db->select($where, '*');
  191.                                                 #获得分页
  192.                                                 $pages = $this->db->pages;
  193.                                                 #获得搜索总量
  194.                                                 $totalnums = $this->db->number;
  195.                                         }
  196.                                
  197.                                         //如果分词结果为空
  198.                                         if(!empty($segment_q)) {
  199.                                                 $replace = explode(' ', $segment_q);
  200.                                                 foreach($replace as $replace_arr_v) {
  201.                                                         $replace_arr[] =  '<font color=red>'.$replace_arr_v.'</font>';
  202.                                                 }
  203.                                                 foreach($data as $_k=>$_v) {
  204.                                                         $data[$_k]['title'] = str_replace($replace, $replace_arr, $_v['title']);
  205.                                                         $data[$_k]['description'] = str_replace($replace, $replace_arr, $_v['description']);
  206.                                                 }
  207.                                         } else {
  208.                                                 foreach($data as $_k=>$_v) {
  209.                                                         $data[$_k]['title'] = str_replace($q, '<font color=red>'.$q.'</font>', $_v['title']);
  210.                                                         $data[$_k]['description'] = str_replace($q, '<font color=red>'.$q.'</font>', $_v['description']);
  211.                                                 }
  212.                                         }
  213.                                 } else {
  214.                                         //读取专辑搜索接口
  215.                                         $special_api = pc_base::load_app_class('search_api', 'special');
  216.                                         $data = $special_api->get_search_data($sids);
  217.                                         $totalnums = count($data);
  218.                                 }
  219.                         }
  220.                         $execute_time = execute_time();
  221.                         $pages = isset($pages) ? $pages : '';
  222.                         $totalnums = isset($totalnums) ? $totalnums : 0;
  223.                         $data = isset($data) ? $data : '';
  224.                        
  225.                         include        template('search','list');
  226.                         #加载搜索内容列表页面模板
  227.                         # 搜索提交按钮后逻辑代码结束
  228.                 } else {
  229.                         # 搜索页面布局
  230.                         include        template('search','index');
  231.                 }
  232.         }
复制代码
听课方式: ---------------2013-11-04--- YY 在线课,详细改造全站搜索------------------------------------------------
$ 兄弟连YY公开课频道:45661043
$ 听课方法:http://bbs.lampbrother.net/read-htm-tid-150234.html
$ 兄弟连原创PHP视频教程免费下载地址
$ 看视频、学习PHP中遇到问题可以里到这提问,刘波老师在线帮你解决问题
$ 听课请加QQ群:84281775

评分

参与人数 2鲜花 +22 收起 理由
7pakinek + 7 赞一个!
sinoers + 15 很给力!

查看全部评分

 楼主| 发表于 2013-11-4 15:22:41 | 显示全部楼层
板凳待坐
回复 支持 反对

使用道具 举报

发表于 2013-11-4 15:26:07 | 显示全部楼层
好东西·······老波我爱你~!
回复 支持 反对

使用道具 举报

发表于 2013-11-4 15:31:03 | 显示全部楼层
我也来凑热闹~
回复 支持 反对

使用道具 举报

发表于 2013-11-4 15:33:00 | 显示全部楼层
感谢分享!!!
回复 支持 反对

使用道具 举报

发表于 2013-11-4 15:33:43 | 显示全部楼层
支持波波老师
回复 支持 反对

使用道具 举报

发表于 2013-11-4 15:34:54 | 显示全部楼层
感谢分享~~~~~~~~~~~~~~~~~
回复 支持 反对

使用道具 举报

发表于 2013-11-4 15:39:20 | 显示全部楼层
呵呵,顶起。。。。。。。

波波大师,值不值得v9会不会增加商城模块
回复 支持 反对

使用道具 举报

发表于 2013-11-4 15:44:24 | 显示全部楼层
支持波波大师
回复 支持 反对

使用道具 举报

发表于 2013-11-4 16:09:00 | 显示全部楼层
辛苦了波大
回复 支持 反对

使用道具 举报

发表于 2013-11-4 16:14:50 | 显示全部楼层
感谢波波大师分享
回复 支持 反对

使用道具 举报

发表于 2013-11-4 16:17:38 | 显示全部楼层
这个必须顶一下
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-11-4 16:25:16 | 显示全部楼层
晚上现场免费教学!教会大家如何一步一步的去改造 PHPCMS V9 的全站搜索!
回复 支持 反对

使用道具 举报

发表于 2013-11-5 13:06:38 | 显示全部楼层
感谢分享~~~~~~~~~~~~~~~~~
回复 支持 反对

使用道具 举报

发表于 2013-11-5 13:49:23 | 显示全部楼层
额 才看到
能不能贴一下方法啊
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 点击这里注册

本版积分规则

小黑屋|Archiver|phpcms网站管理系统 ( 京ICP备14011169 )

GMT+8, 2019-6-19 05:00 , Processed in 0.213689 second(s), 11 queries , Memcache On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表