thinkphp 模板代码中数值比较的正确写法,thinkphp 模板如何进行纯真的数值比较

在thinkphp中,编写模板时需要用到比较,例如,假设定义了一个模板变量 $msgcount 为整数,然后,如下书写模板代码:

{gt name="msgcount" value="0"}
<div class="hx-message-num"><span>{$msgcount|raw}</span></div>
{/gt}

 则thinkphp 将模板编译(所谓编译就是翻译成php代码)后将产生如下php代码:

<?php if($msgcount > '0'): ?>
<div class="hx-message-num"><span><?php echo $msgcount; ?></span></div>
<?php endif; ?>

明显是将 $msgcount 与  '0'  这个字符串进行字符串比较,虽然目前的php版本本身能够将字符串转变为数字进行比较,但不能保证php的后续版本一定会这么做(例如php8.0以后),而且这种用比较也不是很优雅。

但如果将模板的写法写成如下:

{gt name="msgcount" value=":0"}
<div class="hx-message-num"><span>{$msgcount|raw}</span></div>
{/gt}

 然后编译后产生的php代码如下:

<?php if($msgcount > 0): ?>
<div class="hx-message-num"><span><?php echo $msgcount; ?></span></div>
<?php endif; ?>

生成的比较语句为 if($msgcount > 0),为数值比较,这个显然符合预期。

原因何在,通过查看thinkphp处理模板的源代码,可以知道这个是将错就错,碰巧成功

通过查看thinkphp的模板处理代码,如下:

/**
 * compare标签解析
 * 用于值的比较 支持 eq neq gt lt egt elt heq nheq 默认是eq
 * 格式: {compare name="" type="eq" value="" }content{/compare}
 * @access public
 * @param  array $tag 标签属性
 * @param  string $content 标签内容
 * @return string
 */
public function tagCompare(array $tag, string $content): string
{
	$name  = $tag['name'];
	$value = $tag['value'];
	$type  = isset($tag['type']) ? $tag['type'] : 'eq'; // 比较类型
	$name  = $this->autoBuildVar($name);
	$flag  = substr($value, 0, 1);

	if ('$' == $flag || ':' == $flag) {
		$value = $this->autoBuildVar($value);
	} else {
		$value = '\'' . $value . '\'';
	}

	switch ($type) {
		case 'equal':
			$type = 'eq';
			break;
		case 'notequal':
			$type = 'neq';
			break;
	}
	$type     = $this->parseCondition(' ' . $type . ' ');
	$parseStr = '<?php if(' . $name . ' ' . $type . ' ' . $value . '): ?>' . $content . '<?php endif; ?>';

	return $parseStr;
}

该函数通过判断标签的 value,如果value 以 '$' 或者 ':' 开头,则调用 autoBuildVar($value); 进行处理,否则就翻译成字符串。在thinkphp模板手册中,以  ':' 开头 的值是当作函数来处理的,thinkphp的模板编译处理函数autoBuildVar 的代码如下:

/**
 * 自动识别构建变量
 * @access public
 * @param  string    $name       变量描述
 * @return string
 */
public function autoBuildVar(string &$name): string
{
	$flag = substr($name, 0, 1);

	if (':' == $flag) {
		// 以:开头为函数调用,解析前去掉:
		$name = substr($name, 1);
	} elseif ('$' != $flag && preg_match('/[a-zA-Z_]/', $flag)) {
		// XXX: 这句的写法可能还需要改进
		// 常量不需要解析
		if (defined($name)) {
			return $name;
		}

		// 不以$开头并且也不是常量,自动补上$前缀
		$name = '$' . $name;
	}

	$this->tpl->parseVar($name);
	$this->tpl->parseVarFunction($name, false);

	return $name;
}

thinkphp的 TagLib 处理以':' 开头的标识时去掉其前面的':' 。
所以碰巧用到了thinkphp的模板的一个缺陷,将错就错的达到了预期。

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值