织梦自定义搜索分析


  为什么要自己定义搜索呢?当我们想根据自己需要,让用户按照站长的要求来搜索时,这时候往往会用到自定义搜索,前台那个搜索比较简单,不精确,而高级搜索里面也不一定是我们希望的,这时就要自定义搜索,在分析自定义搜索以前,先看一下如何进行自定义搜索?

  进入后台——>内容模型管理——>管理下面有个放大镜东西的图标,点进去,就可以自己定义搜索了。如下图,以商模型为例:
织梦自定义搜索模型

  这个自定义搜索管理,分五个部分,一个是频道ID,一个是频道名称,这二个都不用管,这个频道ID和频道名称是如何来的呢?这二个字段值是从mychannel_main.php里面,经过查询表dede_channeltype,后得到的,当我们点击自定义搜索的时候,就通过mychannel__edit.php传给模板mychannel__edit.htm了,显示出来了。

  接下来二部分就是我们要自己定义的探索字段了,一个是主表,一个是附加表,主表字段,总共五个,这五个是固定的,当然也可以在文件mychannel_main.php里面自己定义。如果频道ID是负数,这个主表字段是没有内容的,这是因为频道ID为负数,说明是单表独立模型,连主表都没有,哪来的主表字段。

  最后一项是自定义模板,这个模板是可以定义的,默认是advancedsearch.htm。

  以上是简单的介绍一下自定义搜索各项,如何定义呢?很简单,选择你想让用户搜索时的作为条件的选项,点下面的确定,程序即可以生成代码,把代码放入html里面即可。这样我们定义好的表单就是搜索表单,而advancedsearch.htm就是搜索结果页,处理搜索的程序文件就是advancedsearch.php文件。
 
  自定义搜索管理分析:

  自定义搜索管理对应的处理程序是mychannel_edit.php,对应的模板文件是mychannel_modifysearch.htm。自定义搜索主表字段和附加表字段如何实现?当我们选择好要搜索的字段,点确定后,下面生成的html代码又是如何实现的?要实现这二个功能,打开文件mychannel_edit.php,找到506行,从else if($dopost == 'modifysearch')开始,一直到else if($dopost == 'del')结束,之间的代码就是用来实现上面二个功能的,第二个功能的实现离不开模板文件mychannel_modifysearch.htm配合。

  先分析一下那主表字段和附加表字段,是如何得到的,这几百行代码通过变量$step分成二大部分,当$step=0 时,就是上面部分得到主表字段和附加表字段,如上面的图所示。当$step=1 时,即当点击确实后,生成的html代码,以及预览部分,如下图所示。


  织梦用了一个变量$step作为处理提交与不提交的分界点,即通过$step的状态的设置,来处理二个不同的状态下的功能,这在php编程里面的经常用到,一般把第一个作为初始状态,即$step一般设置为0或空,当实现第一个功能后,把$step设置成1,或者当$step=0,则在执行第一个功能代码前或后,把$step设置成1,这样当执行完代码后,这时当$step=1,即上面设置的1,这样就可以执行第二个功能代码。这个$step相当于if  else,但是要比if else灵活。

  在模板中的表单里面有一项隐藏域<input type='hidden' name='step' value='<?php echo $step?>'>,这里面的值value就是文件mychannel_edit.php里面的$step,这个模板里面的<?php echo $step?>这句代码,又是调用哪里的呢?这个其实是当我们在内容模型管理,点放大镜进入到“自定义搜索管理”界面时,此时,程序执行的是$step=0,这时,因为刚进入“自定义搜索管理”界面,当$step=0执行后,同时把$step设置成1,此时,我们就看到了“自定义搜索管理”界面,当我们看到这个界面后,$step就已经是1了,所以,上面的<?php echo $step?>这句代码的值就是1。

  分析当$step为空时的代码,如下面代码:
      if(empty($step))
    {
        $step = 1;
        $mid = intval($mid);
        $query = "SELECT mainfields, addonfields, template FROM dede_advancedsearch WHERE mid='$mid'";

  里面这个查询有一个$mid,这个$mid又时哪来的?正常情况这个应当是从模板接收而来的,没有错,这个也是,但是模板里面的我们发现是这句代码<input type='hidden' name='mid' value='<?php echo $mid?>'>,模板里里面的<?php echo $mid?>,这句又是调用哪里的?一般情况我们设计一个php 程序,例如:a.php在这个程序里包括a.htm模板,然后,在这个a.php文件里面从数据库查询出数据放入一个数组中,然后,在模板a.htm里面直接调用,当a.htm提交数据给a.php或其它php文件,就可以处理数据了。

  但是在mychannel_edit.php文件里面,我们无法找到从表中查询出字段mid来的代码?这个$mid到底如何而来?这还要回到“内容模型管理”界面,当我们点放大镜,进行自定义搜索时,实际上是点击的<a href='mychannel_edit.php?mid=6&dopost=modifysearch'><img src='images/gtk-search.png' alt='自定义搜索' title='自定义搜索' /></a> 这个超链接,这个链里面有mid=6,当我们进入“自定义搜索”时,文件mychannel_edit.php就通过$mid = intval($mid);这句代码,得到了mid=6,即模型ID为6,此时,模板也获得了mid=6,所以,我们在“自定义搜索”界面看到“频道ID:”的值为6。

  如果再追问一下,这个在“内容模型管理”里面这个mid=6又是如何获得呢?这个mid=6就是通过“内容模型管理”模板mychannel_main.htm里面的织梦标签{dede:field.id/}得到,而这个标签正是来自mychannel_main.php这个php文件里面的sql查询语句。

  接下来继续看代码:

  这段代码时从数据库表dede_advancedsearch中,查询出mid=6的一条记录,放入变量$searchinfo中,然后,判断一下这个变量是不是数组,若不是则说明,这个变量里面没有内容,即mid=6的记录没有。如果存在这个记录,而把主表字

段里面的字符串通过,下面二句代码:
        $searchinfo['mainfields'] = explode(',', $searchinfo['mainfields']);
        $searchinfo['addonfields'] = explode(',', $searchinfo['addonfields']);

  分别把主表中和附加表中的内容存储到数组$searchinfo['mainfields']和$searchinfo['addonfields']里面,即下图所示的字段对应的内容。

  接着向下执行代码:

 
  上面的代码的作用是:给主表字段设置默认选择。


  上面的代码是把主表字段列出存储到变量$mainfields里面,为得是在模板里面调用显示。
 
附件表自定义搜索字段处理:

  接着上面的代码,下面的代码是对附件表自定义字段处理。首页查询模型表dede_channeltype,查出一条记录放入$channel这个变量中,然后,定义一个搜索类型数组$searchtype,这是为后面的需要进行初始化工作。

  接着执行下面三行代码:

        $dtp = new DedeTagParse();
        $dtp->SetNameSpace("field", "<", ">");
        $dtp->LoadSource($channel['fieldset']);

  第一行用来实例化一个对象;

  第二行设置命名空间,默认情况下执行标签是{dede:标记名}{/dede:标记名}这种形式的,而这里重新定义标签为<field:字段名 ...></field:字段名>例如<field:price itemname="市场价" autofield="1" notsend="0" type="float"事处isnull="true" islist="1" default=""  maxlength="" page=""></field:price>。

  第三行:是把fieldset值即:


  把上面的值载入模板字符串,也就是根目录data/tplcache/md5加密码.inc,然后再通过方法(函数)LoadTemplate(md5加密码.inc)载入模板文件,若文件已经存在则直接解析模板,若缓存文件不存在,则把个文件进行缓存,虽然,这里就说了这几句,但是这一系统方法(函数)是比较复杂的,可以查看类文件dedetag.class.php文件。

  继续执行代码,if(is_array($dtp->CTags) && !empty($dtp->CTags))这一行代码,是判断$dtp->CTages是不是数据,若是并且存在,则对这个数组进行遍历。

  $dtp->CTags这是一个什么数组?这个数组是这样的,$dtp->CTags=array(
'<field:price itemname="市场价" autofield="1" type="float"></field:price> ',
'<field:trueprice itemname="优惠价" autofield="1"  type="float"  ></field:trueprice>',
'<field:brand itemname="品牌" autofield="1"  type="text" ></field:brand>',
'<field:units itemname="计量单位" autofield="1"  type="text" ></field:units>'
)

  这里作了简单,实际这个标记集合就是$channel['fieldset']这里面字符串,通过explode()函数分割出来的数组。

  通过下面的foreach($dtp->CTags as $ctag)循环,把数组里面的值,每当循环一条到$ctag里面,程序就通过ctag->GetAtt('type')和$ctag->GetName()得到类型和值。例如:第一条ctag->GetAtt('type')=float,$catg->GetName=price。

  代码 if($channel['issystem'] < 0)
                {
                    $_oo = array('channel','arcrank', 'title', 'senddate', 'mid', 'click', 'flag', 'litpic', 'userip', 'lastpost', 'scores', 'goodpost', 'badpost', 'endtime');
                    if(in_array($value, $_oo)) continue;
                }

  这一段判断是不是独立单表模型,例如分类信息,若是则判断$ctag->GetName()值在不是数组$_oo里面,若在里面,则去掉($_oo里面都是附件表不想在自定义搜索里面出现的,如果相在自定义搜索里面出现则可以改这个数组)则通过countinue跳出循环,继续下一个循环。

  若数据类型在我们定义的搜索类型$searchtype里面,则设置默认值,把要显示的字符串,存入字段$addonfields里面。

  到目前为止,“自定义搜索管理”界面结束。

下面是当$step=1即,当我们点击提交确定后,在下面显示代码以及预览信息的处理代码。

  这个处理同上面一样,也是分为二大部分,一是主表显示的处理,二是附件表的显示处理。

  下面部分代码相对比较简单,就是对我们在后台模型里面的添加的字段,和从数据库表dede_advancesearch查询出的mainfields 和addonfield进行比对,显示,最后把生成的表单通过echo forms显示出来,这其中用到的方法,值得我们学习一下。其它的就不用多说了。

  再一个比较重要的地方就是在模板mychannel_modifysearch.htm里面,织梦用了一个框架<iframe name="stafrm" frameborder="0" id="stafrm" width="100%" height="100%"></iframe>接收提交表单后的内容,在这个框架里显示,接收是通过<form name="form1" action="mychannel_edit.php" method="post" target="stafrm">里面的target="stafrm,这当然不是php 应用,而是简单的html应用,虽然简单,但是一个非常好的小技巧。以后进行二次开发,我们可以用得着这个东西。