织梦获得物理文件名(动态网址返回url)函数GetFileName()

admin2023-01-181018

如果不去织梦的研究一翻,即使你天天制作织梦模板或天天仿站,那么,对这个函数可能从没有触过,做过二次开发的人可能遇到过,做前台的肯定不会遇到这个函数的问题,但是,这个函数其实,无论你做前台还是后台,特别是做前台的肯定一直在用,只是你不知道罢了。
例如在前台里面我们通过织梦标签{dede:article}[field:arclurl/]{/dede:article} 来调用文章网址,是这个底层模板调用出网址的,你有没有相过在底层模板里面[field:arcurl/]里面的arcurl为什么能够调取出网址来,那有的人会说这肯定是数据库表里面的字段,因为底层模板可以调用数据库表里的所有字段,当然,这个是数据库表里面的字段了,这样说不完全正确,一般来说是这样的底层模板是调用的数据库表里的字段,但是,还有一类底层模板比较特殊,调取的并不是特殊字段,而是,通过一个函数来实现的,例如本例子中的arcurl,还有typeurl这些底层循环代码是通过函数来组装起来的。
但是,话说回来了,无论再怎么组装,也是数据库表字段构成的。因为要获取url,就要先获得文件名,本教程研究的是如何获取文件名的函数GetFileName(),而获取文档url是以这个文件名为前提基础的,所以,我们要知道文档网址url就要先研究明白如何获取文件名(若是动态网址返回的就是url)。至于,获取文档url就简单了。
函数名:GetFileName($aid,$typeid,$timetag,$title,$ismake=0,$rank=0,$namerule='',$typedir='',$money=0,$filename='')
所在文件:include/helpers/channelunit.helper.php
功能:获得文件相对于主站点根目录的物理文件名(动态网址返回url)
参数:

  int  $aid  文档ID
  int  $typeid  栏目ID
  int  $timetag  时间戳
  string  $title  标题
  int  $ismake  是否生成
  int  $rank  阅读权限
  string  $namerule  名称规则
  string  $typedir  栏目dir
  string  $money  需要金币
  string  $filename  文件名称

返回类型:字符串
代码分析开始:
 1. global 几个全局变量,为什么要在函数里global一下? 只有在函数声明了global了,才能在外边使用,如果还不明白的,请阅读教程“函数从入门到深入理解函数调用”这个教程已经讲的非常详细,连函数在内存中都已经讲的非常清楚了。
因为这几个变量不常用,所以这里我一个一个的解释他们代表什么意思:
  $cfg_rewrite:是否使用伪静态
  $cfg_cmspath:DedeCMS安装目录
  $cfg_arcdir:文档HTML默认保存路径
  $cfg_special:专题列表的存放路径,当我们安装完织梦程序后,在根目录里面有一个文件叫special,这个就是存在专题内容的。
  $cfg_arc_dirname:是否允许用目录作为文档文件名,文档命名规则需改为:{typedir}/{aid}/index.html,这个全局变量只有在表#@__sysconfig才能找到它的解释。
  cfg_df_namerule:文档的默认命名规则 {typedir}/{Y}/{M}{D}/{aid}.html,请注意与$namerule区别,$namerule是我们自己定义的规则。
  这些参数是必须知道的,要不下面的代码无法分析,在看下面代码分析前,请把上面几个全局变量弄明白。
  2.若没有指定名称规则,则使用专题的规则作为规则。代码如下:

if(empty($namerule)) {
    $namerule = $cfg_special.'/arc-{aid}.html';
    $typeid = -1;
}

先判断一下参数里的规则是不是已经指定了,这里的规则指我们在建立栏目时,用到的规则也就是如下图所示文章规则:

然后,测试一下效果是不是跟上面这段代码设定的一样。生成一下内容如下图所示。

360截图20200110210135005.jpg

正好与上面的$cfg_special.'/arc-{aid}.html'对应,也就是这个栏目里面生成的文章全部是以这种格式生成的。现在你应当明白了这个函数的历害之处了吧!从上面的实验我们可以看出,实际上在生成文章内容时,就已经调用了函数GetFileName(),我们每发布一篇文章都会调用一下这个函数,虽然,平常你没有感觉到,但是,织梦程序却是实实在在的在调用这个函数。
 3.接下来函数一个条件判断,也就是下面全部的代码就是一个条件判断,这个函数就是由二个条件判断来组成的。
 条件判断:if($rank!=0 || $ismake==-1 || $typeid==0 || $money>0) 条件内容织梦基地一一解释:
 $rank !=0 :若是阅读权限不是开放浏览,也就是文章是注册会员或是等待审核稿件,都属于这个条件范围。
 $ismake==-1:在官方解释里面这个字段指的是否生成,生成html用1表示,动态用0表示,而这里是-1指的是这二者都不存在的情况下。
 $typeid==0:这个好理解,栏目id为零的情况,实际上栏目id可能为零吗?正常是不可能的,因为,栏目id是从1开始的递增的,排除这种情况是因为,有时候为了特殊需要,就把栏目设置为0。关于这一点有很多的文章有用到。
 $money>0:需要金币数量大于零。
若符合上面条件里面的任何一种,那么,就执行下面的代码:

if($cfg_rewrite == 'Y')
{
return $GLOBALS["cfg_plus_dir"]."/view-".$aid.'-1.html';
}
else
{
return $GLOBALS['cfg_phpurl']."/view.php?aid=$aid";
}

这里面又一个小判断,判断一下是不是已经开启了伪静态,若是,则使用上面的规则生成文章内容,如果要开启需要你的服务器支持;若没有开启则生成的网站用下面的规则生成内容。

进行实验一下:
我把“DedeCMS V5.6 开发日志及新建议提交贴”这篇文章设置为需要10金币才能浏览,也就是上面条件中$money>0如下图所示。

360截图20200110210135005.jpg

然后,打开这个连接如下图所示。

360截图20200110210135005.jpg

也就是www.dedebase.com/plus/view.php?aid=92,是不是与上面的规则一致!
若上面四个条件中都不成立,那么,就要执行else后面的代码了。
4. 处理栏目显示链接,代码为:
 $articleDir = MfTypedir($typedir);
因为,生成的栏目连接一般都是以{cmspath}开始的,所以,通过函数MfTypedir()把这个符号替换为系统安装路径,并且,把栏目链接里面多个//替换为一个,因为,有时个可能我们在建立栏目时,可能多写了一个或多个//符号,这时就要替换掉。若是站外连接,直接不用处理。
把规则全部转换为小写:$articleRule = strtolower($namerule)

接下来的代码,就比较简单:

$articleRule = strtolower($namerule);
if($articleRule=='')
{
$articleRule = strtolower($GLOBALS['cfg_df_namerule']);
}
if($typedir=='')
{
$articleDir  = $GLOBALS['cfg_cmspath'].$GLOBALS['cfg_arcdir'];
}

把命名规则转换成小写;判断一下规则是不是空,若是空则用默认的规则,这个默认规则在文件common.inc.php里面定义好的;然后,判断是不是栏目目录,为空,也就是没有填写,这时就用这个的路径:www.dedebase.com/a/来存在生成的文档,这个在我们后台建立栏目时,有时候不写程序会把生成的内容放到根目录里面的文件夹/a/里面,就是这个地方起的作用。

时间处理:

$dtime = GetDateMk($timetag);
list($y, $m, $d) = explode('-', $dtime);
$arr_rpsource = array('{typedir}','{y}','{m}','{d}','{timestamp}','{aid}','{cc}');
$arr_rpvalues = array($articleDir,$y, $m, $d, $timetag, $aid, dd2char($m.$d.$aid.$y));

若在调用这个函数时,有时间参数,那么,就要处理这个参数,因为从数据库时面查询出来的参数是一串数字,所以,这里用函数GetDateMk()函数,把时间变成类似2015-7-11这种形式。
然后,通过函数 explode()把时间分别存入对应的变量$y,$m,$d里面。
判断文件名是否存在:

if($filename != '')
{
$articleRule = dirname($articleRule).'/'.$filename.$GLOBALS['cfg_df_ext'];
}
$articleRule = str_replace($arr_rpsource,$arr_rpvalues,$articleRule);

若存在则$articleRule=/a/Html/dedebase.html这样的结构显示文件,把固定的内容,通过上面的$arr_rpvalues来替换掉我们自己定义的或系统自动生成的时间。

拼音处理:

if(preg_match("/\{p/", $articleRule))
{
$articleRule = str_replace('{pinyin}',GetPinyin($title).'_'.$aid,$articleRule);
$articleRule = str_replace('{py}',GetPinyin($title,1).'_'.$aid,$articleRule);
}

若文章命名规则是以:{typedir}/{Y}/{M}{D}/{py}.html或{typedir}/{Y}/{M}{D}/{pinyin}.html命名的,则进行调用拼音处理函数GetPinyin()。
实验测试:{py}.html这种方法的话,生成的文章,是以文章标题每个字的第一个字母构成的文章名,如下图所示。

生成的内容如下图所示。

360截图20200110210135005.jpg

若是以{pinyin}.html则表示以文件标题的全拼来生成文章名的。这个根上面一样设置,这里就不测试了。
处理连接第一个斜杠问题:

$articleUrl = '/'.preg_replace("/^\//", '', $articleRule);
例如上例中文章名为:/a/webbase/div-css/2010/0407/nydljd5gCSS3xjs_33.html,若第一个符号是"/"只有一个,这是正常的情况,若是二个"//"怎么办?这一行就是处理这个问题的,有可能大家对上面的这个正规替换不理解,没有关系,织梦基地在这里实验一下,只要不懂的大家就要测试,作为一个技术员,马虎不得。
建立一个文件test.php,然后,在这个文件里面写下如下代码:

<?php
$articleRule="/a/webbase/div-css/2010/0407/nydljd5gCSS3xjs_33.html";
echo preg_replace("/^\//", '', $articleRule)
?>

然后,执行一下,得到如下图所示效果。

这就说明这个正则是替换的是第一个"/",而是不所有的。关于为什么要替换上面说到若是二个这个没有什么作用,是不是织梦写的有问题?还是我不理解。若是以////a/webbase/开头的,上面替换后的结果仍然不变,所以,不起什么作用。从这里可以看出这行代码应当是错的。
正确的应当是这样与正则匹配规则:preg_replace("/^\/{1,}/", '', $articleRule),这样就实现了如下问题,即这个a前面无论多少个符号"/",都能把它替换为空,这样就是正常的了。
测试如如下:假设我把$articleRule设置为:$articleRule="//////a/webbase/div-css/2010/0407/nydljd5gCSS3xjs_33.html";
这样在浏览器里面执行一下test.php得到的就根上面的一样,也就是正常处理了a前面任意多个"/"问题,我认为是织梦写错了。因为,他那段代码实际根没有执行一样。

用目录作为文档名:
大家有见过一些博客或用过框架像thinkphp框架等,他们生成的文章内容并不像织梦那样以.html为后缀的,而是以一个数字或单词,如下图所示。

360截图20200110210135005.jpg

这个网页是以good结束,而不是以good.html结束的。
织梦可以不以也这样设置呢?当然,完全可以,只需要在文章规则里面设置如下规则:

也就是:{typedir}/{aid}/index.html
然后,看看效果如下图所示。

360截图20200110210135005.jpg

下面这段代码就是这样处理这个问题的。

    if(preg_match("/index\.html/", $articleUrl) && $cfg_arc_dirname=='Y')
    {
    $articleUrl = str_replace('index.html', '', $articleUrl);
    }

而且织梦在配置文件中已经启用这一项了。
在$articleUrl里面包含index.html且,$cfg_arc_dirname=='Y',那么,就替换index.html为空。这样就实现了上面的效果了。
代码分析结束,这个函数功能强大吧。包含的知识点非常多,如果你能把这个函数消化掉,你将对织梦底层的编程规则有一个深刻了解。

网友评论