smarty的replace陷阱
来源:互联网 发布:襄阳seo 编辑:程序博客网 时间:2024/05/17 21:56
1. 问题
为描述方便,我们简化下问题。
{assign var="star" value="胡哥;吴秀波;王宝强;三小只"}{$star|regex_replace:'/;/':'/'}
在smarty模板中,将“;”(半角分号)替换为“/”。在看这段代码时,第一反应是用replace替代regex_replace,效率会高些。于是动手改了一行代码:
{assign var="star" value="胡哥;吴秀波;王宝强;三小只"}{$star|replace:';':'/'}
测试无误,上线!
上线后问题来了,线上环境中的”;”居然没有被替换为”/”!无奈回滚。
2. 追踪
smarty手册说到:replace等同与php函数的str_replace。所以首先怀疑是php版本问题,但一个replace,真会和php版本有关系么?于是分别在两个环境上直接尝试用php的str_replace做上文的字符替换,都没有问题。
看来smarty的replace实现并不是直接调用了php的str_replace,只能读smarty源码定位问题了。
replace的实现位于Smarty/plugins/modifier.replace.php
function smarty_modifier_replace($string, $search, $replace){ if (Smarty::$_MBSTRING) { require_once(SMARTY_PLUGINS_DIR . 'shared.mb_str_replace.php'); return smarty_mb_str_replace($search, $replace, $string); } return str_replace($search, $replace, $string);}
其中Smarty :: $_MBSTRING在./Smarty.class.php中定义
define('SMARTY_MBSTRING', function_exists('mb_split'))
逻辑很清晰了,当安装了mbstring扩展时,使用smarty_mb_str_replace进行替换,否则用php的str_replace进行替换(是谁说equivalent to the PHP’s str_replace() function来着…可以枪毙一会儿)。
我的php有mbstring扩展,只能继续跟进了。
smarty_mb_str_replace核心逻辑可以简化如下:
function smarty_mb_str_replace($search, $replace, $subject){ $parts = mb_split($search, $subject); $subject = implode($replace, $parts); return $subject;}
先用待替换字符切分源串,再用目标字符拼接得到结果串。不得不说这个实现思路有点…好吧,吐槽的事暂时放放,先追问题。
debug发现,问题出在mb_split,在线上环境(出问题的环境)中,此处我们得到的$parts结果为
array(1) { [0]=> string(36) "胡哥;吴秀波;王宝强;三小只" }
字串没有被切为预期的四部分。what’s wrong!
解决方案
受php手册mb_split例子的启发(还是php手册靠谱),想到可能是编码问题导致。在问题环境测试
echo mb_internal_encoding();echo mb_regex_encoding();
得到的结果居然是EUC-JP!一个日文字符集。我堂堂天朝公司的线上php版本居然默认字符集是日文…好在哥不是反日愤青,不然必格盘而后快。
知道问题所在就好解决了。
- 方法1:在php执行smarty前设置
mb_regex_encoding('UTF-8');
- 方法2:直接在php.ini中设置
mbstring.internal_encoding = UTF-8
然后重启php-fpm让配置生效。
怎么做更好
继续看smarty源码,regex_replace最终是使用php的preg_replace实现。介于replace的无语实现方法,二者哪个快还真不一定,实测下吧。我们每次测试者渲染模板1000次,测5次取均值,实验结果如下:
regex_replace胜出了!
直接用php的str_replace,自己实现一个modifier会怎么样呢?
采用上面同样的测试方法,得到的结果是0.179s,比regex_replace只是略有提高。
综合考虑,regex_replace不依赖环境,不用额外代码,速度也还好,性价比最高。
结论
- 如果php安装了mbstring扩展,在smarty模板中进行字符替换时,推荐使用regex_replace。未安装,则使用replace。
- 直觉这东西,有时挺不靠谱的,还得看实验。
- 手册偶尔也不靠谱,还得看源码。
- smarty的replace陷阱
- trim和replace的陷阱实践
- smarty 字符串连接替换cat,replace
- 什么是smarty,Smarty的优点?
- '\'的陷阱
- :?的陷阱
- smarty 的注意事项和smarty的安装
- Smarty中文手册,Smarty教程,Smarty模板的入门教材
- Smarty中文手册,Smarty教程,Smarty模板的入门教材
- Smarty的基本配置【smarty.inc.php】
- 【smarty】smarty保留变量的使用
- Smarty入门教程一----Smarty的安装
- 【Smarty】Smarty的下载、配置与Helloworld
- Perl的replace函数
- javascript replace的使用
- pb的replace完善
- Coldfusion的另类replace。
- MySQL Replace 的使用
- .Net 高效开发之不可错过的实用工具
- 第十章 String()
- Unity开发学习路线在哪里【蓝鸥Unity学习路线】
- asm技术学习
- 勾股数圆整程序
- smarty的replace陷阱
- "==" 和 .equals()方法的区别
- mysqldump导入导出数据
- Xcode 快速开发 代码块
- 利用swiper和css3实现手机滑屏与动画效果
- HBase记录
- BZOJ 1008 越狱(快速幂)
- 系统日志监控脚本,程序关闭和启动
- HTTP抓包工具fiddler