用 PHP5 打造簡易的 MVC 架構


The Model
‘M’或MVC系統的mdel部份用來查詢資料庫(或是其他的外部資源)並且提供資料給控制器,我們可以依據請求來載入適當的model,但我傾向model跟controller的這幾行模糊起來,所以控制器會使用DB抽象函式庫來直接查詢DB,而不使用個別的模式,這是依照個人的喜好,所以你也可以不這樣做。

我們必須做的一件事就是新增需要的程式碼來設定資料庫的連結,並且把它新增到我們的index首頁,有很多可用的DB抽象函式庫(包括我自己的AutoCRUD)但是PHP5已經有一個很棒的DB函式庫- PDO -所以不需要一個不同的函式庫。

將下面的程式碼放入index檔案中(在含括起始檔後):

# Connect to DB$db = new PDO(‘mysql:host=localhost;dbname=demo’, ‘[user]’, ‘[password]’);
$registry->set (‘db’, $db);

在上面的例子中,我們建構PDO函式庫一個新的實體,然後連結到我們的MySQL資料庫,然後我們使用Registry類別來製作$db全域資料。

現在我們很高興我們系統的model部份已經完成,讓我們繼續下個步驟:撰寫控制器。

撰寫控制器意味著我們必須寫一個 Router類別, Router類別依照請求(透過URL來傳遞$router 變數)來載入目前的控制器,讓我們先寫這個Router類別。

Router類別

我們的Router類別必須解析請求,然後載入目前的方法,第一個步驟就是建構Router類別的骨架:

<?phpClass Router {

private $registry;

private $path;

private $args = array();

function __construct($registry) {

$this->registry = $registry;

}

}

?>

然後將下面這幾行加到index.php中:

# Load router$router = new Router($registry);

$registry->set (‘router’, $router);

現在我們已經將Router類別加到我們的MVC系統,但是現在它還是沒有做什麼事,所以讓我們再加些需要的方法到Router類別中。

我們第一個想要增加的方法是setPath()方法,這是用來設定我們掌握我們所有控制器的目錄setPath()方法看起來像這樣,而且需要加到Router類別中:

function setPath($path) {
$path = trim($path, ‘/);$path .= DIRSEP;

if (is_dir($path) == false) {

throw new Exception (‘Invalid controller path: `’ . $path . ‘`’);

}

$this->path = $path;

}

然後將下一行加到index.php中:

$router->setPath (site_path . ‘controllers’);

現在我們已經設定了控制器的路徑,我們可以寫真正用來載入正確控制器的方法,這方法是elegate(),它會解析請求,這方法的第一部份看起來像這樣:

function delegate() {// Analyze route

$this->getController($file, $controller, $action, $args);

就像你看到的,它使用了另一個方法getController() 來取得控制器名稱以及一些其他變數,這方法看起來像這樣:

private function getController(&$file, &$controller, &$action, &$args) {$route = (empty($_GET[‘route’])) ? : $_GET[‘route’];

if (empty($route)) { $route = ‘index’; }

// Get separate parts

$route = trim($route, ‘/);

$parts = explode(‘/’, $route);

// Find right controller

$cmd_path = $this->path;

foreach ($parts as $part) {

$fullpath = $cmd_path . $part;

// Is there a dir with this path?

if (is_dir($fullpath)) {

$cmd_path .= $part . DIRSEP;

array_shift($parts);

continue;

}

// Find the file

if (is_file($fullpath . ‘.php’)) {

$controller = $part;

array_shift($parts);

break;

}

}

if (empty($controller)) { $controller = ‘index’; };

// Get action

$action = array_shift($parts);

if (empty($action)) { $action = ‘index’; }

$file = $cmd_path . $controller . ‘.php’;

$args = $parts;

}

讓我們看一下這方法,首先它先取得$route查詢字串變數的值,然後使用explode()函式將它分成幾個部份,假如請求是’members/view’它就會分成array(‘members’, ‘view’)。

然後我們使用foreach迴圈來運作每一部份,首先確認這個部份是否是目錄,假如是就將它加入到filepath然後確認下一個部份,這樣可以允許我們將控制器放到子目錄,然後使用層級的控制器,假如這個部份不是目錄而是檔案,我們就將其存到$controller變數,因為我們找到了我們要的控制器我們就離開迴圈。

在迴圈之後我們首先是否有找到控制器,假如沒有我們就使用預設的’index’,接下來我們需要進行action的取得,控制器是一個含有不同方法的類別,而action會指到某一個方法,假如沒有指定action我們會使用預設的’index’。

最後我們會取得控制器連續的完整路徑、名稱及其擴充。

現在請求被解析就可以用delegate()方法來載入控制器及執行action,完整的delegate()方法如下所示:

function delegate() {// Analyze route

$this->getController($file, $controller, $action, $args);

// File available?

if (is_readable($file) == false) {

die (‘404 Not Found’);

}

// Include the file

include ($file);

// Initiate the class

$class = ‘Controller_’ . $controller;

$controller = new $class($this->registry);

// Action available?

if (is_callable(array($controller, $action)) == false) {

die (‘404 Not Found’);

}

// Run action

$controller->$action();

}

在使用getController()方法解析請求後,我們先確認檔案是否真的存在,如果沒有我們會傳回一個簡單的錯誤訊息。

接下來我們要做的是含括控制器檔案,然後初始化類別,這個類別總是以Controller_[name]這樣的格式來命名,稍後我們會學習更多控制器相關的內容。

接下來我們使用 is_callable()函式來確認action是否存在而且可以執行,最後我們執行這個action,完成這個router的角色任務。

現在我們有一個可以完整運作的delegate()方法,我們新增下面這一行到index.php中:

$router->delegate();

假如你現在執行系統,而且尚未新增’controllers’ 目錄的話,你不是會得到下面的錯誤:

Fatal error: Uncaught exception ‘Exception’ with message ‘Invalid controller path: `g:ProjectsPHPitcontentsimple mvc php5democontrollers`’ in g:ProjectsPHPitcontentsimple mvc php5democlassesrouter.php:18 Stack trace: #0 g:ProjectsPHPitcontentsimple mvc php5demoindex.php(13): Router->setPath(‘g:ProjectsPHP…’) #1 {main} thrown in g:ProjectsPHPitcontentsimple mvc php5democlassesrouter.php on line 18

就是’404 Not Found’的錯誤,因為尚未有任何的控制器,但是我們接下來會馬上處理這個部份。

感謝你看到這裡,很快就可以離開了,但最好的獎勵行動就是按一下幫我分享或留言,感恩喔~

點我分享到Facebook

頁次: 1 2 3 4 5

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *