目前共有20篇帖子。
【方案】用PHP自帶的DOM類將HTML與PHP標籤分離
1樓 巨大八爪鱼 2016-1-15 12:17
【最終HTML輸出】
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>My PHP Template Example</title><style>
body {
    font-family: Arial;
    font-size: 12px;
}
mark {
    background-color: #F9F9F9;
    border: 1px solid #DDDDDD;
    border-radius: 2px;
    font-family: monospace, Courier;
    padding: 1px 4px;
}
p {
    line-height: 1.5em;
    margin: 3px 0px;
}

footer {
    background-color: #EEEEEE;
    font-size: 13px;
    margin-top: 20px;
    padding: 10px 0px;
    text-align: center;
}
footer span {
    color: red;
}

ul {
    margin: 2px 0px;
    padding-left: 16px;
}

ul.Navigator {
    background-color: #5F5F5F;
    font-family: "Segoe UI", Arial, sans-serif;
    letter-spacing: 1px;
    list-style: none;
    padding-left: 0px;
    overflow: hidden;
}

ul.Navigator li {
    float: left;
}

ul.Navigator a {
    color: white;
    display: inline-block;
    font-size: 17px;
    padding: 10px 15px 9px;
    text-decoration: none;
}
ul.Navigator a:hover {
    background-color: black;
}
ul.Navigator a.active {
    background-color: #73AF21;
}
</style></head><body>
<nav><ul class="Navigator"><li><a href="?language=HTML">HTML</a></li>
    <li><a href="?language=CSS" class="active">CSS</a></li>
    <li><a href="?language=JavaScript">JAVASCRIPT</a></li>
  </ul></nav><article><h1>microtime</h1>
  <p>microtime() returns <mark>the current Unix timestamp with microseconds</mark>. This function is only available on operating systems that support the gettimeofday() system call.</p>
  <ul><li><a href="http://www.php.net/">www.php.net</a></li><li><a href="http://www.youtube.com/">www.youtube.com</a></li>
  </ul></article><article><h1>Displaying the widget</h1>
  <p>This page explains how to display and customize the reCAPTCHA widget on your webpage.</p>
  <ul><li><a href="http://www.google.com/">www.google.com</a></li><li><a href="http://www.facebook.com/">www.facebook.com</a></li><li><a href="http://en.wikipedia.org/">en.wikipedia.org</a></li>
  </ul></article><footer>Time Elapsed: <span>0.000s</span></footer></body></html>

【最終頁面效果】
2樓 巨大八爪鱼 2016-1-15 12:18
【HTML模板文件:template_example.html,該模板文件不含任何PHP代碼塊】
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Untitled Document</title>
<style>
body {
    font-family: Arial;
    font-size: 12px;
}
mark {
    background-color: #F9F9F9;
    border: 1px solid #DDDDDD;
    border-radius: 2px;
    font-family: monospace, Courier;
    padding: 1px 4px;
}
p {
    line-height: 1.5em;
    margin: 3px 0px;
}

footer {
    background-color: #EEEEEE;
    font-size: 13px;
    margin-top: 20px;
    padding: 10px 0px;
    text-align: center;
}
footer span {
    color: red;
}

ul {
    margin: 2px 0px;
    padding-left: 16px;
}

ul.Navigator {
    background-color: #5F5F5F;
    font-family: "Segoe UI", Arial, sans-serif;
    letter-spacing: 1px;
    list-style: none;
    padding-left: 0px;
    overflow: hidden;
}

ul.Navigator li {
    float: left;
}

ul.Navigator a {
    color: white;
    display: inline-block;
    font-size: 17px;
    padding: 10px 15px 9px;
    text-decoration: none;
}
ul.Navigator a:hover {
    background-color: black;
}
ul.Navigator a.active {
    background-color: #73AF21;
}
</style>
</head>

<body>
<nav>
  <ul class="Navigator">
    <li><a class="active" href="?language=HTML">HTML</a></li>
    <li><a href="?language=CSS">CSS</a></li>
    <li><a href="?language=JavaScript">JAVASCRIPT</a></li>
  </ul>
</nav>
<article>
  <h1>Article Example</h1>
  <p>This HTML tutorial contains hundreds of HTML examples.<br>
With our online <mark>HTML editor</mark>, you can edit the HTML, and click on a button to view the result.</p>
  <ul>
    <li><a href="example">Link Example</a></li>
  </ul>
</article>
<footer>Time Elapsed: <span></span></footer>
</body>
</html>
3樓 巨大八爪鱼 2016-1-15 12:18
【index.php】
<?php
$start = microtime(); # 獲取腳本開始執行的時間
libxml_use_internal_errors(true); # 忽略不合法標籤的提示
$doc = new DOMDocument();
$doc->loadHTMLFile('template_example.html'); # 加載模板文件

$languages = array('HTML', 'CSS', 'JavaScript');
$language = filter_input(INPUT_GET, 'language', FILTER_SANITIZE_STRING); # 獲取URL變量:?language
$id = array_search($language, $languages); # 確定當前選中的選項卡的編號
if ($id === false) {
    $id = 0; # 默認選中第一個選項卡
}

$path = new DOMXPath($doc);
$nodes = $path->query('/html/body/nav/ul/li/a');
if ($id != 0) {
    $nodes->item(0)->removeAttribute('class'); # 去除第一個選項卡默認的選中狀態
    $nodes->item($id)->setAttribute('class', 'active'); # 選中新的選項卡
}

$nodes = $path->query('/html/head/title');
$nodes->item(0)->nodeValue = 'My PHP Template Example'; # 設置網頁標題

/* 定義兩篇文章數組,這兩篇文章可以從數據庫中獲取 */
class Article {
    public $title;
    public $content;
    public $links;
}
$arr = array();
$arr[0] = new Article();
$arr[0]->title = 'microtime';
$arr[0]->content = 'microtime() returns <mark>the current Unix timestamp with microseconds</mark>. This function is only available on operating systems that support the gettimeofday() system call. ';
$arr[0]->links = array('www.php.net', 'www.youtube.com');
$arr[1] = new Article();
$arr[1]->title = 'Displaying the widget';
$arr[1]->content = 'This page explains how to display and customize the reCAPTCHA widget on your webpage.';
$arr[1]->links = array('www.google.com', 'www.facebook.com', 'en.wikipedia.org');

function removeChildren($node) {
    while ($node->childNodes->length > 0) {
        $node->removeChild($node->firstChild);
    }
}

function setInnerHTML($node, $newValue) {
    removeChildren($node);
    $doc = $node->ownerDocument;
    $fragment = $doc->createDocumentFragment();
    $fragment->preserveWhiteSpace = false;
    if (!empty($newValue)) {
        $fragment->appendXML(trim($newValue));
        $importedNode = $doc->importNode($fragment, true);
        $node->appendChild($importedNode);
    }
}

function getInnerHTML(DOMNode $element) {
    $innerHTML = '';
    foreach ($element->childNodes as $child) {
        $innerHTML .= $element->ownerDocument->saveHTML($child);
    }
    return $innerHTML;
}

# <artile> 標籤循環
$articleTemplate = $path->query('/html/body/article')->item(0); # 取<article>模板標籤
foreach ($arr as $article) {
    $articleNode = $articleTemplate->parentNode->insertBefore($articleTemplate->cloneNode(true), $articleTemplate); # 根據模板標籤新增節點,並插入到模板標籤之前
    $path->query('.//h1', $articleNode)->item(0)->nodeValue = $article->title; # nodeValue不允許存在HTML標籤
    setInnerHTML($path->query('.//p', $articleNode)->item(0), $article->content); # setInnerHTML允許存在HTML標籤
   
    # <li> 標籤循環
    $linkTemplate = $path->query('.//ul/li', $articleNode)->item(0); # 取<li>模板標籤
    foreach ($article->links as $link) {
        $linkNode = $linkTemplate->parentNode->insertBefore($linkTemplate->cloneNode(true), $linkTemplate);
        $anchorNode = $path->query('.//a', $linkNode)->item(0);
        $anchorNode->setAttribute('href', "http://$link/"); # 設置鏈接URL
        $anchorNode->nodeValue = $link; # 設置鏈接文本
    }
    $linkTemplate->parentNode->removeChild($linkTemplate); # 刪除模板標籤<li>
}
$articleTemplate->parentNode->removeChild($articleTemplate); # 刪除模板標籤<article>

# 在頁面底部顯示本頁面的總執行時間
$nodes = $path->query('/html/body/footer/span');
$now = microtime();
$nodes->item(0)->nodeValue = number_format($now - $start, 3) . 's';

echo $doc->saveHTML(); # 輸出整個頁面
?>
4樓 巨大八爪鱼 2016-1-15 12:21
製作HTML模板文件時,可用瀏覽器直接訪問這個HTML文件。

為了讓正式服務器上的HTML模板文件不能被惡意訪問,可以創建一個目錄專門存放HTML模板,然後在該目錄下設置一個.htaccess文件,寫上Deny from all(注意Apache 2.2和2.4使用的指令完全不同)。
5樓 巨大八爪鱼 2016-1-15 12:34
網站目錄結構:
/css 存放CSS樣式
/templates 存放HTML模板文件
/xxx.php 實際PHP頁面
當使用Dreamweaver製作HTML模板文件時,為了在設計視圖中能正確顯示CSS樣式,可以將<link>標籤中的CSS href文件路徑寫成"../css/xxx.css"的格式。
而在xxx.php中調用HTML模板文件的時候,自動把所有引用CSS的<link>標籤中的文件路徑全部改為「css/xxx.css」。(當然如果使用了URL重寫規則的話,則再作其他判斷)

如果使用了gettext多語言庫,可以在HTML模板文件上全寫英文原文,這樣可以在Dreamweaver設計視圖中顯示,方便製作網頁。然後PHP在調用HTML模板的時候,自動將模板文件中的所有標籤(也可以設置一個標籤列表)的nodeValue全部執行一次_()函數,將其翻譯成當前所設語言的mo文件中的內容。
6樓 巨大八爪鱼 2016-1-15 12:41
在PHP自帶的DOM類中,還有getElementById和getElementsByTagName方法,使用這兩個方法可以簡化模板標籤的提取。
在上面的例子中,<article>標籤循環的基本思路是:先取出模板文件中的<article>標籤,複製該標籤後插入到該標籤的前面,循環結束後刪除模板標籤。
7樓 巨大八爪鱼 2016-1-15 15:51
【示例2】
下面這個示例演示了如何把一段用戶輸入的亂七八糟的HTML代碼顯示到模板HTML文檔中。
<?php
libxml_use_internal_errors(true);
$doc = new DOMDocument();
$doc->loadHTMLFile('template_example.html');

function removeChildren($node) {
    while ($node->childNodes->length > 0) {
        $node->removeChild($node->firstChild);
    }
}

function setInnerHTML($node, $html) {
    removeChildren($node);
    if (empty($html)) {
        return;
    }
    
    $doc = $node->ownerDocument;
    $htmlclip = new DOMDocument();
    $htmlclip->loadHTML($html);
    $clipNode = $doc->importNode($htmlclip->getElementsByTagName('body')->item(0), true);
    while ($item = $clipNode->firstChild) {
        $node->appendChild($item);
    }
}

$articleNode = $doc->getElementsByTagName('article')->item(0);
$html = '<P ID=id10 class=strangeclass>A paragraph<BR>   </p><br>
<NAV class=sxxx>A HTML5 LABEL</NAV><p>Another paragraph</p><label><BR><A id=a48';
setInnerHTML($articleNode, $html);

echo $doc->saveHTML();
libxml_clear_errors();



【最終輸出】
article標籤附近:
<article><p id="id10" class="strangeclass">A paragraph<br></p><br><nav class="sxxx">A HTML5 LABEL</nav><p>Another paragraph</p><label><br><a id="a48"></a></label></article>

【顯示效果】

8樓 巨大八爪鱼 2016-1-15 15:56
對於亂七八糟破爛不堪的HTML代碼,如果使用3樓所示的setInnerHTML函數的話,運行就會出現錯誤。因此,示例2中的setInnerHTML函數更完善一些,也更符合DOM標準。
另外,關於在3樓的代碼中用到的DOMDocumentFragment::appendXML函數,PHP官方手冊上提到過這樣一句話:If you want to stick to the standards, you will have to create a temporary DOMDocument with a dummy root and then loop through the child nodes of the root of your XML data to append them.
這說明DOMDocumentFragment::appendXML是不符合DOM標準的。
9樓 巨大八爪鱼 2016-1-15 16:06
index.php中的代碼仍然比較亂。但是如果把頁面處理封裝成一個類,並繼承HTMLPage類,且把removeChildren、setInnerHTML、getInnerHTML這樣的通用函數放置到HTMLPage類中的話,代碼就要簡潔很多。
在頁面處理類IndexPage類中,顯示底部footer的PHP代碼可以單獨弄一個方法,循環顯示文章列表再單獨弄一個函數,把所有函數公用的變量都設置為類實例變量,訪問控制屬性設置為privare。這樣的話,就會使得以後的閱讀和維護工作更加方便。
10樓 巨大八爪鱼 2016-1-15 16:09
在HTMLPage類中,可以加入一個方法,使得模板頁面中所有的TextNode中的文字全部自動被gettext庫翻譯一次(也就是執行_()函數)。當然,也要允許子類重寫這個方法。

回復帖子

內容:
用戶名: 您目前是匿名發表
驗證碼:
 
 
©2010-2024 Arslanbar [手機版] [桌面版]
除非另有聲明,本站採用創用CC姓名標示-相同方式分享 3.0 Unported許可協議進行許可。