首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP Smarty 模板引擎 foreach 循環語法與編譯實現完整指南

     編輯:PHP 相關知識

Smarty 的 {foreach} 是模板中遍歷數組、對象集合的核心標籤。本文涵蓋模板寫法、編譯器解析邏輯、緩存生成、實際調用示例四大部分。

模板文件完整示例

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>{$web_title}</title>
</head>
<body>
{$article_title}
<br/>
-- by {$author}
<hr/>
<br/>
{$content}
<br/>
-- publish @ {$time}

<br/><br/>
foreach test:

{foreach (from=url key=b item=c)}
    <a href="index.php?article_id={$b}">{$c}</a>
{/foreach}

<br/>
</body>
</html>

編譯器核心解析代碼

<?php
// 1. 普通變量替換:{$var} -> var_tpl_arr["var"]; ?>
$pattern_var = "/\{$left_tag\}\$([\w\d]+)\{$right_tag\}/";
$replace_var = 'var_tpl_arr["$1"]; ?>';
if (preg_match($pattern_var, $content)) {
    $content = preg_replace($pattern_var, $replace_var, $content);
}

// 2. 匹配 {foreach ...} 開始標籤
preg_match_all("/\{$left_tag}foreach\s+([^{]+?)\{$right_tag\}/is", $content, $match_foreach);

if (isset($match_foreach[1]) && is_array($match_foreach[1])) {
    foreach ($match_foreach[1] as $match_key => $match_value) {
        // 解析屬性:from=url key=b item=c
        $split_foreachs = array_filter(preg_split('/\s+/is', $match_value));
        $new_foreach_tag = array();
        
        foreach ($split_foreachs as $split_foreach) {
            $split = explode("=", $split_foreach);
            if (count($split) == 2) {
                if (in_array($split[0], array("from", "item", "key"))) {
                    $new_foreach_tag[$split[0]] = $split[1];
                }
            }
        }
        
        // 提取屬性
        $from = $key = $item = '';
        extract($new_foreach_tag);
        
        // 構建 key 部分:$key => 或空
        $key = ($key) ? '$' . $key . ' =>' : '';
        
        // 生成 PHP foreach 代碼
        $replace_foreach = 'var_tpl_arr["' . $from . '"] as ' . $key . ' $' . $item . ') { ?>';
        $content = str_replace($match_foreach[0][$match_key], $replace_foreach, $content);
    }
}

// 3. 處理 {/foreach} 閉合標籤
$pattern_foreach = "/\{$left_tag}\/foreach\{$right_tag\}/";
$replace_foreach = "";
if (preg_match($pattern_foreach, $content)) {
    $content = preg_replace($pattern_foreach, $replace_foreach, $content);
}

// 4. 循環內變量:{==var} -> 
// 注意:這裡使用雙 $ 實現變量變量($b、$c 為 foreach 產生的局部變量)
$pattern_var = "/\{$left_tag}==([\w\d]+)\{$right_tag\}/";
$replace_var = '';
if (preg_match($pattern_var, $content)) {
    $content = preg_replace($pattern_var, $replace_var, $content);
}
?>

編譯後緩存文件對照

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title><?php echo $this->var_tpl_arr["web_title"]; ?></title>
</head>
<body>
<?php echo $this->var_tpl_arr["article_title"]; ?>
<br/>
-- by <?php echo $this->var_tpl_arr["author"]; ?>
<hr/>
<br/>
<?php echo $this->var_tpl_arr["content"]; ?>
<br/>
-- publish @ <?php echo $this->var_tpl_arr["time"]; ?>

<br/><br/>
foreach test:

<?php foreach($this->var_tpl_arr["url"] as $b => $c) { ?>
    <a href="index.php?article_id=<?php echo $b; ?>"><?php echo $c; ?></a>
<?php } ?>

<br/>
</body>
</html>

PHP 業務代碼調用示例

<?php
require_once 'core/YATP.class.php';

$app = new YATP();
date_default_timezone_set("Asia/Shanghai");
$app->is_cache = false;

// 賦值變量
$article_title = "yet, it is a simple template engine";
$author = "sanwhiteyu@tencent.com";
$web_title = "just test";
$content = "It is easy to write a simple template engine for yourself, what u can do is try to do it!";
$time = date("Y-m-d H:i:s", time());

// 關鍵:傳入關聯數組供 foreach 遍歷
$url = array(
    "url1" => "https://www.111cn.net",
    "url2" => "https://www.baidu.com",
);

$app->assign("article_title", $article_title);
$app->assign("author", $author);
$app->assign("web_title", $web_title);
$app->assign("content", $content);
$app->assign("time", $time);
$app->assign("url", $url);

$app->display("index.html");
?>

關鍵技術細節解析

特性模板語法編譯邏輯注意點
數據源from=url映射到 $this->var_tpl_arr["url"]必須在 PHP 中 assign 同名變量
鍵名變量key=b生成 $b =>可選,省略則無鍵名
值變量item=c生成 $c必填
循環內引用{==b} {==c}轉為 (變量變量)雙 $ 關鍵,區別於普通 {$var}
嵌套循環支援遞歸編譯,變量作用域隔離內層 item/key 勿與外層重名

常見問題與最佳實踐

  • 性能優化:大數據集建議在 PHP 預處理分頁,模板僅渲染當前頁數據
  • 空數組處理:配合 {foreachelse} 標籤(Smarty 3+)或預判斷 {if $url|@count}
  • 變量作用域:foreach 產生的 $key/$item 僅在循環內有效,外部不可訪問
  • 緩存更新:修改模板後需清理 templates_c/ 目錄或設置 $smarty->force_compile = true

掌握 foreach 編譯機制,能更精準控制模板輸出,避免變量衝突與作用域陷阱。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved