標籤:style http io ar color os 使用 sp strong
PHP架構現在是一種很流行的東西了,很多朋友開發應用與網站都會選擇一個PHP架構或模板了,下面我們來看看PHP架構是如何?的吧。
本文主要來聊聊架構理論,但不針對任何一款架構,不過任何一款架構都離不開這個理論,首先我們瞭解下架構的來龍去脈,任何技術的出現都是為瞭解決某個問題,之前的部落格有講過smarty,其存在就是為了html和php更好地分離開來。而所謂的“架構”是一種為了統一書寫格式,訪問方式而進行的自我約束行為,其實按照這個說法我們每個人基本上都或多或少的使用過自己定義的架構,比如說在沒使用架構之前自己開發一個項目,有時候是一天無法完成的,我們為了防止混亂,為了更好地記憶我們會進行目錄規劃和程式的規劃,潛意識的把程式分類,放到不同的檔案夾,於是架構應運而生了,又比如說我們曾經做了一個CMS系統,如果我們又接手一個類似的項目,你會重複書寫代碼嗎,答案肯定不會,但如果是別人的項目你拿來改其實是一件很蛋疼的事情的,因為你根本不知道他的這個CMS的規則是什麼,即使是自己的項目時間久了如果自己沒有固定的規範的話也是很容易忘記的,那麼怎麼樣才能保證自己每次寫的代碼都可以按照一定的規範呢,把每個項目要用的東西挑出來,目錄結構挑出來,以後無論什麼項目都在這個基礎上書寫,那麼屬於自己的架構就出來了。
但架構單純這樣是不完善的,那麼架構應該有哪些能力呢,與其這樣說我們不妨想想我們平時一定會寫的代碼一定會做的事情是什麼呢,首先解決的是什麼呢,為了減少路徑問題,目錄結構的安排其實很重要,有時候檔案包含 再進行檔案的移動總是一件很蛋疼的事情,最好的辦法是什麼呢,絕對路徑,但同時存在了一個類似E:www 這樣的問題,但這個值我們可以通過預定義變數$_SERVER["DOCUMENT_ROOT"]獲得,我們可以將其定義為常量,define("ROOT_PATH", $_SERVER["DOCUMENT_ROOT"]);include ROOT_PATH . "/lib/mysql.php";類似這樣的檔案夾怎麼移動都不會有事的,那麼就出現了一個固定的寫法,為瞭解決路徑問題而存在的寫法,幾乎每一頁都會用到,還有模板的輸出,資料庫的串連,那麼我們可以把這些代碼封裝起來,或者分離出來,每一頁包含即可,被分離的這些部分其實就是一個小架構,為什麼這麼說呢,如果我們包含它們進來,例如smarty模板,肯定是執行個體化好的對象,那個量名已經固定,可能是$smarty 如果我們包含了這麼個檔案進來,這個量就不能再次進行賦值使用,這樣下面部分的代碼就無法進行使用了,由於包含的類,如資料類 上傳類 映像類 分頁類 位置已經寫死在這個公用檔案裡,為了不改代碼 這個目錄就成了必須存在的了,目錄格式固定,編寫代碼方式的約束,這就形成了架構。
多年來的程式員的總結交流及開發經驗,大家總結了一些優秀的編寫方式,最經典的是單點入口,什麼是單點入口呢,之前我們總結了一些幾乎每個程式都要用到的功能,這裡依然存在一些問題,例如 在公用檔案包含之前我們還是不知道根目錄是多少,如果我們在每一個檔案夾下面都放一個公用檔案存在代碼重複問題,哪天修改的話需要全部修改,需要找到需要多少個這樣的檔案,現在是多個程式包含一個程式,然後使用者訪問n個程式來完成各個功能,於是程式員就想可不可以反過來我用一個程式包含這些不同功能的程式,使用者只訪問這個程式就可以了呢,於是單點入口模式出現了,在網站首頁的 index.php 寫上每個程式都要用的部份 然後跟據某個量,比如一個 get 量來判斷當前實際要執行的程式是哪一個,由 index.php 把它包含進來運行,這種由一個程式。完成所有功能的方式,稱為 單點入口, 於是由這個入口程式和它對應的各個目錄結構成為了一個架構。
出於安全在包含檔案的時候往往都會固定目錄,不然就容易出漏洞 所以,往往會在路徑頭尾加個限制。例如
| 代碼如下 |
複製代碼 |
<?PHP
include "./app/" . $_GET[‘url‘] . ".php";
?> |
那路徑就只能寫成類似這樣index.php?url=news/list,實際包含的是 /app/news/list.php 當然了,實際的情況,還要檢查一下這個程式檔案是否存在之類的。
完整一點的話。我們可以這樣寫這個入口檔案。
| 代碼如下 |
複製代碼 |
|
<?php
//這裡寫絕對路徑
//這裡寫資料庫連接
//這裡寫模板初始化,配置
//這裡判斷串連變數
//這裡包含檔案進來運行
//這裡輸出模板
//這裡關閉資料庫
?> |
一個面向過程的單點入口架構就完成了, 是不是有覺得每次都在地址欄帶一個 get 不方便? 那我們可以換一個寫法,例如 tp 架構最喜歡用的 http://localhost/index.php/news/list後面的 /news/list 由程式轉成 php 路徑包含進來就可以了。在 Apache 環境中,這個 /news/list 可以由伺服器變數的 PATH_INFO 取得,如果沒有的話。也可以用 REQUEST_URI 取得接近的 ,IIS 下面,有 HTTP_X_REWRITE_URL 可以取得這個值 ,自從單點入口模式出現之後,而且oop開發模式從php5開始大行其道,各種oop設計的架構讓我們眼花繚亂,但是萬變不離其宗,依然是什麼入口方式,路徑結構是什麼樣的,檔案名稱的命名規則,用什麼樣的訪問方式,可以運行哪個程式。用oop開發的架構,不外乎就是把主程式改寫成為了一個類,
例如:
//包含共用檔案,執行個體化各個類啥的
頁面->初始化();
//把使用者發來的網址轉成要包含的路徑
頁面->處理網扯();
//在這裡包含程式運行
頁面->運行()
//輸出模板
頁面->輸出()
各種各樣的架構只是為我們準備了一個規矩罷了。。在我們的開發累計的過程中,我們常常會把一些常用的類封裝成類,例如,資料庫類,檔案上傳類,圖片處理類,郵件收發類,遠端存取類,各種介面類……這個時候,我們就會希望架構能給我們提供一個好一點調用類的方法, 也就是所謂的“擴充性” ,比如 TP 架構的 Db 類 。如果不用其內建的類庫只用它們的核心架構,其實幾個檔案就夠了。
TP 架構支援三種訪問格式。
/news/list
/index.php/news/list
/index.php?m=news&a=list
第一種需要伺服器的 urlrewrite 支援,後面兩種可以直接用,
事實上,Zend 架構也差不多 檔案的包含方式是。以類的形式包含,執行的其實是:/檔案夾/對象/方法,這種做法有優勢。因為在同一個功能中,相似的代碼很多,封裝到同一個類裡面,可以更高效的重複使用代碼 ,
比如這樣
| 代碼如下 |
複製代碼 |
|
class NewsAction {
public function head() {
在這裡處理每一頁頭部
}
public function index() {
$this->head();
在這裡處理這一頁
}
public function show() {
$this->head();
在這裡處理這一頁
} |
還可以利用建構函式等,使每一個功能,在剛進來的時候就都做了同一件事情。以上就是簡單架構的理論。
製作應用原理
index.php 主入口檔案
| 代碼如下 |
複製代碼 |
<?php
define(‘ISEXIST‘,true);
require "init.php";
$control = new Controller();
$control -> Run();
?> |
---------------------------------------------------------------------------------------------
init.php 檔案
| 代碼如下 |
複製代碼 |
<?php
if(!defined(‘ISEXIST‘))
exit("請從入口檔案運行程式");
header("Content-Type:text/html;charset=utf-8");
if(!defined(‘ROOT_PATH‘))
//這裡動態聲明,‘‘是轉義反斜線,預設‘‘為逸出字元
define(‘ROOT_PATH‘,str_replace(‘‘,‘/‘,dirname(__FILE__)));
require ROOT_PATH.‘/a/config.php‘;
require ROOT_PATH.‘/a/controller.class.php‘;
require ROOT_PATH.‘/a/view.class.php‘;
require ROOT_PATH.‘/a/model.class.php‘;
?> |
----------------------------------------------------------------------------------------------
config.php 檔案
| 代碼如下 |
複製代碼 |
<?php
if(!defined(‘ISEXIST‘))
exit("請從入口檔案運行程式");
$C = array(
‘URL_MODE‘=>1,//url模式,1為普通模式,2為path_info模式
‘DEFAULT‘=>‘welcome‘,//預設的控制器
‘DEFAULT_ACTION‘=>‘index‘//預設的方法
);
?> |
-----------------------------------------------------------------------------------------------
controller.class.php 檔案
| 代碼如下 |
複製代碼 |
<?php
class Controller
{
public function Run()
{
$this->Analysis();
//開始解析URL獲得請求的控制器和方法
$control = $_GET[‘con‘];
$action = $_GET[‘act‘];
$action = ucfirst($action);
//這裡構造出控制器檔案的路徑
$controlFile = ROOT_PATH . ‘/Controllers/‘ . $control . ‘.class.php‘;
if(!file_exists($controlFile)) //如果檔案不存在提示錯誤, 否則引入
{
exit("{$control}.class.php控制器不存在<br>". "請檢查: ".$controlFile."是否存在<br>");
}
include($controlFile);
$class = ucfirst($control); //將控制器名稱中的每個單字首大寫,來當作控制器的類名
if(!class_exists($class)) //判斷類是否存在, 如果不存在提示錯誤
{
exit("{$control}.class.php中未定義的控制器類" . $class);
}
$instance = new $class(); //否則建立執行個體
if(!method_exists($instance, $action)) //判斷執行個體$instance中是否存在$action方法, 不存在則提示錯誤
{
exit("$class類中不存在方法:". $action);
}
$instance->$action();
}
protected function Analysis()
{
//$GLOBALS[‘C‘][‘URL_MODE‘];
global $C; //包含全域配置數組, 這個數組是在Config.ph檔案中定義的,global聲明$C是調用外部的
if($C[‘URL_MODE‘] == 1)
//如果URL模式為1 那麼就在GET中擷取控制器, 也就是說url地址是這種的 [url=http://localhost/index.php?c]http://localhost /index.php?c[/url]=控制器&a=方法
{
$control = !empty($_GET[‘con‘]) ? trim($_GET[‘con‘]) : ‘‘;
$action = !empty($_GET[‘act‘]) ? trim($_GET[‘act‘]) : ‘‘;
}
else if($C[‘URL_MODE‘] == 2) //如果為2 那麼就是使用PATH_INFO模式, 也就是url地址是這樣的 [url=http://localhost/index.php/]http://localhost/index.php/[/url]控制器/方法 /其他參數
{
if(isset($_SERVER[‘PATH_INFO‘]))
{
//$_SERVER[‘PATH_INFO‘]URL地址中檔案名稱後的路徑資訊, 不好理解, 來看看例子
//比如你現在的URL是 [url=http://www.php100.com/index.php]http://www.php100.com/index.php[/url] 那麼你的$_SERVER[‘PATH_INFO‘]就是空的
//但是如果URL是 [url=http://www.php100.com/index.php/abc/123]http://www.php100.com/index.php/abc/123[/url]
//現在的$_SERVER[‘PATH_INFO‘]的值將會是 index.php檔案名稱後的內容 /abc/123/
$path = trim($_SERVER[‘PATH_INFO‘], ‘/‘);
$paths = explode(‘/‘, $path);
$control = array_shift($paths);
$action = array_shift($paths);
}
}
//這裡判斷控制器的值是否為空白, 如果是空的使用預設的
$_GET[‘con‘] = !empty($control) ? $control : $C[‘DEFAULT‘];
//和上面一樣
$_GET[‘act‘] = !empty($action) ? $action : $C[‘DEFAULT_ACTION‘];
}
}
?> |
--------------------------------------------------------------------------------------------------
welcome.class.php 檔案
| 代碼如下 |
複製代碼 |
<?php
class Welcome
{
function Index()
{
echo ‘歡迎使用此CMS系統‘;
}
function Run()
{
echo ‘Hello‘;
}
function Show()
{
echo ‘方法名show‘;
}
}
?> |
php架構原理