PHP和ASP是個很類似的東西,它都是一個以頁面為主的動態網頁開發程式,以前ASP寫了好幾年,也知道ASP的程式很不容易管理,就是一個散亂可以形容。但是從另一個角度來看,這樣的程式語言就是單純,什麼都是你很容易控制的。既然是重新轉戰,那麼就要將最新的技術整合進開發環境裏面,包含了SEO、AJAX、jQuery、網頁標準化等等。最好還能像ASP.NET一樣可以讓我們在開發的過程中少管一些事情。

先從SEO來考慮,SEO所談的東西很多,目的就是讓我們的網站能夠在搜尋引擎用關鍵字查詢時能夠排名在越前面越好,手法上就比較簡單,第一點就是要在每個頁面上加上meta標籤包含keyword、title、description這三個讓搜尋引擎更容易查詢的東西。

<meta name='keywords' content=''>
<meta name='title content=''>
<meta name='description' content=''>

第二點就是要儘量使用有意義的標籤,並且少用表格。這一點與網頁標準化其實是一樣的,就是儘量使用簡單的標籤來進行排版。對於程式設計師來說這麼做其實很簡單,就是多加利用div,h1...h6,ul,li等等的標籤來寫程式,並且在html程式上不要管排版的問題,將排版的問題全部交給CSS來處理。其實漠哥在上海開發程式的時候就曾經提出這樣的要求,也在後來工作的地方提出要這麼做,但是總被網頁美工沒有辦法配合所回絕。最近一兩年這個觀念終於開始被業界所接受,也開始有些美工人員願意去學習這方面的知識,使得這種做法變得沒有那麼困難。如果再配合jQuery所提供的強大控制能力,以前所很難做到的頁面效果,都可以用相對簡單的方式來完成。

接著考慮AJAX的功能,現在寫網頁程式如果沒有AJAX的能力,除非你還在維護舊的程式,否則幾乎就不用混了。幸好jQuery提供了相當簡單的AJAX處理解決方案,而這樣的處理動作,至少要成為一個模板,讓開發的動作能夠在“複製貼上改一改”的原則下做出來。

像PHP和ASP這樣的頁面導向程式,最重要的一項功能就是include,將頁面分成幾個部份維護,讓一些固定的內容分開成不同的檔案來維護,相信寫過這一類程式的人都能夠掌握這方面的知識。簡單說,就是將頁面<head></head>的部份,頁面的標題、選單、頁脚,等等分開來成為獨立的檔案,然後在頁面上引入,這樣就能讓細部開發人員專注在細節上。

<head></head>這一段是個比較特別的,它包含了前面提到的SEO處理的訊息,還包含了javascript、CSS Style的引入。因為jQuery的引入,使得一個頁面所要用到的外掛javascript和CSS Style的引入變得很多,開發人員需要在開發的過程中仔細檢查<head></head>段的引入,以免造成重複引入而浪費系統資源。

在ASP.NET裏面有個好東西叫做ScriptManager,其實說穿了就是個NameValue陣列,用來記錄所要掛上去的script,這樣的東西PHP裏面沒有,但是並不難開發出來。主要的程式碼如下:

<?PHP
class PageControl {
    var $scriptHeader;
    var $scriptFooter;
    var $styleHeader;

    var $doc_title;
    var $seo_title;
    var $seo_keywords;
    var $seo_description;
    function PageControl($doc_title) {
        $this->doc_title = $doc_title;
    }
    function registedScriptHeader($key, $script) {
        if (array_key_exists($key, $this->scriptHeader)==false) {
            $this->scriptHeader[$key] = $script;
        }
    }
    function registedScriptHeaderFile($file) {
        $script = "<script src='$file' type='text/javascript'></script>\n";
        $this->registedScriptHeader($file, $script);
    }
    function registedScriptFooter($key, $script) {
        if (array_key_exists($key, $this->scriptFooter)==false) {
            $this->scriptFooter[$key] = $script;
        }
    }
    function registedStyle($key, $script) {
        if (array_key_exists($key, $this->styleHeader)==false) {
            $this->styleHeader[$key] = $script;
        }
    }
    function registedStyleFile($file) {
        $script = "<link href='$file' rel='stylesheet' type='text/css' />\n";
        $this->registedStyle($file, $script);
    }
    function includeJQuery() {
        $this->registedScriptHeaderFile("/javascript/jquery-1.4.3.min.js");
    }
    function includeJQueryUI() {
        $this->includeJQuery();
        $this->registedScriptHeaderFile("/javascript/jquery-ui-1.8.5.custom.min.js");
        $this->registedScriptHeaderFile("/javascript/ui/i18n/jquery.ui.datepicker-zh-TW.js");
        $this->registedStyleFile("/CSS/jquery-ui-1.8.5.custom.css");
    }
    function includeSuperFish() {
        $this->includeJQuery();
        $this->registedScriptHeaderFile("/javascript/hoverIntent.js");
        $this->registedScriptHeaderFile("/javascript/superfish.js");
        $this->registedStyleFile("/css/superfish.css");
        $this->registedStyleFile("/css/superfish-navbar.css");
    }
    function setEnterLikeTab() {
        $this->includeJQuery();
        $this->registedScriptHeaderFile("/javascript/changeenter.js");
        $this->registedScriptHeader("setEnterLikeTab", $script);
    }
    function onLoadFocus($Selector) {
        $this->includeJQuery();
        $script = "$('$Selector').focus();\n";
        $this->registedScriptFooter("onloadfocus", $script);
    }
    function bindTopNavBar($Selector) {
        $this->includeSuperFish();
    }
    function bindDatePicker($Selector) {
        $this->includeJQueryUI();
        $script = "$('$Selector').datepicker({dateFormat:'yy/mm/dd',showOn:'both',buttonImageOnly:true,buttonImage:'/images/datepicker.gif'});\n";
        $this->registedScriptFooter($ControlID."datepicker", $script);
    }
    function renderHeader() {
        $html = "<title>".$this->doc_title."<title>\n";
        $html .= "<meta http-equiv='Content-Type' content='text/html; charset=utf-8'>\n";
        $html .= "<meta name='robots' content='index, follow' />\n";
        $html .= ($this->seo_keyword == "") ? "" : "<meta name='keywords' content='".$this->seo_keyword."' />\n";
        $html .= ($this->seo_title == "") ? "" : "<meta name='title' content='".$this->seo_title."' />\n";
        $html .= ($this->seo_description =="") ? "" : "<meta name='description' content='".$this->seo_description."' />\n";
        foreach(array_values($this->scriptHeader) as $scriptPart) {
            $html .= $scriptPart;
        }
        foreach(array_values($this->styleHeader) as $scriptPart) {
            $html .= $scriptPart;
        }
        echo $html;
    }
    function renderFooter() {
        if (sizeof($this->scriptFooter)>0) {
            $html = "<script type='text/javascript'>\n";
            $html .= "$(document).ready(function() {\n";
            foreach(array_values($this->scriptFooter) as $scriptPart) {
                $html .= $scriptPart;
            }
            $html .= "});\n";
            $html .= "</script>\n";
            echo $html;
        }
    }
}
?>

核心工程師還可以根據個別的功能增加這個類的方法,比如說像是:

function includeJQuery() {
    $this->registedScriptHeaderFile("/javascript/jquery-1.4.3.min.js");
}
function includeJQueryUI() {
    $this->includeJQuery();
    $this->registedScriptHeaderFile("/javascript/jquery-ui-1.8.5.custom.min.js");
    $this->registedScriptHeaderFile("/javascript/ui/i18n/jquery.ui.datepicker-zh-TW.js");
    $this->registedStyleFile("/CSS/jquery-ui-1.8.5.custom.css");
}

你也可以根據個別特殊用途寫出獨立的方法,比如像是:

function onLoadFocus($Selector) {
        $this->includeJQuery();
        $script = "$('$Selector').focus();\n";
        $this->registedScriptFooter("onloadfocus", $script);
}

程式會根據你所登錄的Key去識別所要用到的script是否重複引入,這個例子幾乎都是檔案,所以直接用檔案當成Key。而且在方法裏面還引入了必須引入的檔案,可以省去個別檢查的問題。而頁面的內容會變成這樣

<?PHP
define('app_root',$_SERVER['DOCUMENT_ROOT']);    //每一頁一定要加,這樣才能正確使用require_once、include
require_once(app_root."/include/PageControl.php");
$PageC = new PageControl("旅館管理系統");
$PageC->registedStyleFile("/css/default.css");
$PageC->onLoadFocus("#username");
?>
<html>
<head>
<?PHP $PageC->renderHeader() ?>
</head>
<body>
    <div id="header"></div>
    <div id="wrapper"></div>
<script type="text/javascript">
    $(document).ready(function() {
         //這個頁面所需要的特殊script
    });
</script>
<?PHP $PageC->renderFooter() ?>
</body>
</html>

特別一提,由於PHP的引入語法中,引入的網頁必須使用實體位置或相對位置來指定,但是因為開發環境與產品主機上的檔案佈局位置未必相同(windows和linux差別更大),不可能使用實體位置來標示引入檔案,若使用相對位置又會因為每一個檔案存放的資料夾不同,而使得每一次引入都必須要重新審視檔案的相對位置,因此使用define('app_root',$_SERVER['DOCUMENT_ROOT']);來定義出一個常數,內容就是這個web伺服器的根目錄位置,這樣就能讓每一個引入變得完全相同,不會因為頁面不同而需要去更改。

另外一點,由於開發使用了jQuery,所以使用jQuery的selector來定位頁面上的控件必須變成一種顯學,這樣用習慣了才能讓我們的程式碼更加的強大。(有關jQuery的selector請參考jQuery神奇的選擇器(Selector)

更正:如果沒有先判斷是否為陣列會發生警告訊息,需要更正程式碼如下:

if ((is_array($this->scriptHeader)==false)||(array_key_exists($key, $this->scriptHeader)==false)) {

創作者介紹

人生四十宅開始 二號宅

漠哥 發表在 痞客邦 留言(0) 人氣()