本文目录导读:

在PHP模板引擎中自定义标签有多种方式,下面介绍主流模板引擎(Smarty、Twig、Blade)的自定义方法:
Smarty 自定义标签
自定义函数(简单标签)
// 注册自定义函数
$smarty->registerPlugin('function', 'hello', 'smarty_function_hello');
function smarty_function_hello($params, $smarty) {
$name = $params['name'] ?? 'World';
return "Hello, $name!";
}
模板中使用:
{hello name="John"}
自定义块标签
// 注册块插件
$smarty->registerPlugin('block', 'upper', 'smarty_block_upper');
function smarty_block_upper($params, $content, $smarty, &$repeat) {
if (!$repeat) {
return strtoupper($content);
}
}
模板中使用:
{upper}hello world{/upper}
Twig 自定义标签
自定义函数
// 创建扩展类
class MyTwigExtension extends \Twig\Extension\AbstractExtension {
public function getFunctions() {
return [
new \Twig\TwigFunction('greeting', [$this, 'greetingFunction']),
];
}
public function greetingFunction($name) {
return "Hello, $name!";
}
}
// 注册扩展
$twig->addExtension(new MyTwigExtension());
模板中使用:
{{ greeting('John') }}
自定义标签(复杂)
class UpperTokenParser extends \Twig\TokenParser\AbstractTokenParser {
public function parse(\Twig\Token $token) {
$parser = $this->parser;
$stream = $parser->getStream();
$stream->expect(\Twig\Token::BLOCK_END_TYPE);
$body = $parser->subparse(function($token) {
return $token->test('endupper');
}, true);
$stream->expect(\Twig\Token::BLOCK_END_TYPE);
return new UpperNode($body, $token->getLine(), $tag);
}
public function getTag() {
return 'upper';
}
}
Blade 自定义标签(Laravel)
自定义指令
// 在 AppServiceProvider 的 boot 方法中
public function boot() {
Blade::directive('hello', function ($expression) {
return "<?php echo 'Hello, ' . {$expression}; ?>";
});
Blade::directive('uppercase', function ($expression) {
return "<?php echo strtoupper({$expression}); ?>";
});
}
模板中使用:
@hello('John')
@uppercase('hello world')
自定义 if 语句
Blade::if('admin', function () {
return auth()->check() && auth()->user()->isAdmin();
});
模板中使用:
@admin
<p>Welcome Admin!</p>
@else
<p>Welcome User!</p>
@endadmin
原生 PHP 模板引擎自定义
简单模板引擎实现
class SimpleTemplate {
private $customTags = [];
public function registerTag($tag, $callback) {
$this->customTags[$tag] = $callback;
}
public function render($content, $data = []) {
foreach ($this->customTags as $tag => $callback) {
$pattern = '/\{\{' . $tag . ':(.*?)\}\}/';
$content = preg_replace_callback($pattern, function($matches) use ($callback, $data) {
$params = array_merge($data, ['value' => $matches[1]]);
return call_user_func($callback, $params);
}, $content);
}
return $content;
}
}
// 使用
$template = new SimpleTemplate();
$template->registerTag('hello', function($params) {
return "Hello, {$params['value']}!";
});
$content = "{{hello:World}}";
echo $template->render($content); // 输出: Hello, World!
通用最佳实践
安全考虑
// 始终对用户输入进行转义
$smarty->registerPlugin('function', 'safe_output', function($params) {
return htmlspecialchars($params['value'], ENT_QUOTES, 'UTF-8');
});
性能优化
// 缓存编译结果
class CachedCustomTag {
private $cache = [];
public function process($tag, $params) {
$key = md5($tag . serialize($params));
if (isset($this->cache[$key])) {
return $this->cache[$key];
}
$result = $this->renderTag($tag, $params);
$this->cache[$key] = $result;
return $result;
}
}
注意事项
- 命名规范:使用有意义的前缀避免冲突
- 文档化:详细记录标签参数和用途
- 测试:为自定义标签编写单元测试
- 兼容性:考虑不同PHP版本的语法差异
- 性能:避免在标签中进行复杂的数据库操作
选择哪种方式取决于你的项目使用的模板引擎,推荐优先使用官方支持的扩展机制来实现自定义标签。