dede独立模型中的联动类型字段是如何在文章页面中显示枚举名的

dede的联动类型是是通过将字段和系统枚举表dede_sys_enum相关联的,独立模型的表中联动类别字段存储的是表dede_sys_enum的枚举值,这是一个数值,类似于代号的意思,当要显示独立模型的联动类别字段时,首先根据这个枚举值在dede_sys_enum中找出相应枚举名,然后才显示出来。在模版文件中我们不需要知道这个过程是如何进行的,只需按照显示一般字段的方式就能正确显示联动类型了。

这篇文章主要讨论的就是在dede代码中是如何显示联动类型字段的。

不管是在文章页面还是列表页面都能直接使用[field:codecategory/]这样的方式来显示联动类型,这里就以列表页面为例。

显示独立模型的列表是通过/include/arc.sglistview.class.php来完成的,在arc.sglistview.class.php的GetArcList方法中如下代码完成了对独立模型所有字段的特殊处理:

foreach($this->ChannelUnit->ChannelFields as $k=>$arr)
{
     if(isset($row\[$k\]))
     {
          $row\[$k\] = $this->ChannelUnit->MakeField($k,$row\[$k\]);
     }
}

没有这段代码独立模型的联动字段就显示的是乱七八糟的数字。ChannelUnit的MakeField的在/include/channelunit.class.php中,用于处理某个字段的值,代码如下:

/**
 *  处理某个字段的值
 *
 * @access    public
 * @param     string  $fname  字段名称
 * @param     string  $fvalue  字段值
 * @param     string  $addvalue  增加值
 * @return    string
 */
function MakeField($fname, $fvalue, $addvalue='')
{       
    //处理各种数据类型
    $ftype = $this->ChannelFields\[$fname\]\['type'\];
    if($fvalue=='')
    {
        if($ftype != 'checkbox') $fvalue = $this->ChannelFields\[$fname\]\['default'\];
    }
    if($ftype=='text')
    {
        $fvalue = HtmlReplace($fvalue);
    }
    else if($ftype=='textdata')
    {
        if(!is_file($GLOBALS\['cfg_basedir'\].$fvalue))
        {
            return '';
        }
        $fp = fopen($GLOBALS\['cfg_basedir'\].$fvalue,'r');
        $fvalue = '';
        while(!feof($fp))
        {
            $fvalue .= fgets($fp,1024);
        }
        fclose($fp);
    }
    else if($ftype=='addon')
    {
        $foldvalue = $fvalue;
        $tmptext = GetSysTemplets("channel_addon.htm");
        $fvalue  = str_replace('~link~',$foldvalue,$tmptext);
        $fvalue  = str_replace('~phpurl~',$GLOBALS\['cfg_phpurl'\],$fvalue);
    }
    else if(file_exists(DEDEINC.'/taglib/channel/'.$ftype.'.lib.php'))
    {       echo "$fname-";
    echo "$fvalue $ftype<br>";
        include_once(DEDEINC.'/taglib/channel/'.$ftype.'.lib.php');
        $func = 'ch_'.$ftype;
        echo "$func";
        $fvalue = $func($fvalue,$addvalue,$this,$fname);
    }
    return $fvalue;
}

其中,上面的不同case值处理不同字段类型,联动类型在最后一个case中,他引入了\include\taglib\channel\stepselect.lib.php文件(因为联动类型的$ftype``值为stepselect),然后最终的代码进入stepselect.lib.php的ch_stepselect方法中。

<?php
if(!defined('DEDEINC')) exit("Request Error!");
function ch_stepselect($fvalue,&$arcTag,&$refObj,$fname='')
{
    return GetEnumsValue2($fname,$fvalue);
}
/**
 * 获取二级枚举的值
 *
 * @version        $Id: stepselect.lib.php 16:24 2010年7月26日Z tianya $
 * @package        DedeCMS.Taglib
 * @copyright      Copyright (c) 2007 - 2010, DesDev, Inc.
 * @license        http://help.dedecms.com/usersguide/license.html
 * @link           http://www.dedecms.com
 */
function GetEnumsValue2($egroup,$evalue=0)
{
    if( !isset($GLOBALS\['em_'.$egroup.'s'\]) )
    {
        $cachefile = DEDEDATA.'/enums/'.$egroup.'.php';
        if(!file_exists($cachefile))
        {
            require_once(DEDEINC.'/enums.func.php');
            WriteEnumsCache();
        }
        if(!file_exists($cachefile))
        {
            return '';
        }
        else
        {
            require_once($cachefile);
        }
    }
    if($evalue>=500)
    {
        if($evalue % 500 == 0)
        {
            return (isset($GLOBALS\['em_'.$egroup.'s'\]\[$evalue\]) ? $GLOBALS\['em_'.$egroup.'s'\]\[$evalue\] : '');
        }
        else if (preg_match("#(\[0-9\]{1,})\\.(\[0-9\]{1,})#", $evalue, $matchs))
        {
            $esonvalue = $matchs\[1\];
            $etopvalue = $esonvalue - ($esonvalue % 500);
            $esecvalue = $evalue;
            $GLOBALS\['em_'.$egroup.'s'\]\[$etopvalue\] = empty($GLOBALS\['em_'.$egroup.'s'\]\[$etopvalue\])? ''
                                                     : $GLOBALS\['em_'.$egroup.'s'\]\[$etopvalue\];
            $GLOBALS\['em_'.$egroup.'s'\]\[$esonvalue\] = empty($GLOBALS\['em_'.$egroup.'s'\]\[$esonvalue\])? ''
                                                     : $GLOBALS\['em_'.$egroup.'s'\]\[$esonvalue\];
            $GLOBALS\['em_'.$egroup.'s'\]\[$esecvalue\] = empty($GLOBALS\['em_'.$egroup.'s'\]\[$esecvalue\])? ''
                                                     : $GLOBALS\['em_'.$egroup.'s'\]\[$esecvalue\];
            return $GLOBALS\['em_'.$egroup.'s'\]\[$etopvalue\].' -- '.$GLOBALS\['em_'.$egroup.'s'\]\[$esonvalue\].' -- '.$GLOBALS\['em_'.$egroup.'s'\]\[$esecvalue\];
        }
        else
        {
            $elimit = $evalue % 500;
            $erevalue = $evalue - $elimit;
            $GLOBALS\['em_'.$egroup.'s'\]\[$erevalue\] = empty($GLOBALS\['em_'.$egroup.'s'\]\[$erevalue\])? ''
                                                     : $GLOBALS\['em_'.$egroup.'s'\]\[$erevalue\];
            $GLOBALS\['em_'.$egroup.'s'\]\[$evalue\] = empty($GLOBALS\['em_'.$egroup.'s'\]\[$evalue\])? ''
                                                     : $GLOBALS\['em_'.$egroup.'s'\]\[$evalue\];
            return $GLOBALS\['em_'.$egroup.'s'\]\[$erevalue\].' -- '.$GLOBALS\['em_'.$egroup.'s'\]\[$evalue\];
        }
    }
}

其实我并没有去研究ch_stepselect方法以及其调用的GetEnumsValue2方法,因为这里的关键是arc.sglistview.class.php的GetArcList方法中的那段代码。