2013-01-12 125 views
3

我想了解並找出在自定義框架中的控制器之間切換的好方法。以下示例是我目前的想法,爲了演示目的而進行了簡化,但如果有更好的方法,我會非常感謝一些專家的建議。在控制器之間切換(MVC)

class BaseController() { 
    function __construct() { 
     $this->model = new ModelFactory(); 
     $this->view = new View(); 

     if(isset($_SERVER['QUERY_STRING'])) { 
      list($controller, $action) = explode('=', $_SERVER['QUERY_STRING']); 
      self::process($controller); 
     } 
    } 

    public function process($controller) { 
     switch($controller) { 
      case 'user': 
       $user = new UserController($action); 
      break; 

      case 'forum': 
       $forum = new ForumController($action); 
      break; 

      default: 
       // use base controller 
       switch($action) { 
        case 'contact': 
         $this->view->load($action); 
        break; 
       } 
     } 
    } 
} 

// inside UserController.php 
switch($action) { 
    case 'register': 
    break; 

    case 'login': 
    break; 
} 

// inside ForumController.php 
switch($action) { 
    case 'new_thread': 
    break; 

    case 'edit_post': 
    break; 
} 
+1

您是否打算允許您的框架用戶使用自定義操作實現自定義控制器? –

+0

@ bob-the-destroyer如果這樣可以使代碼更加通用,並且我假設它會,那麼是的。 –

回答

3

這真的是一個部分的答案,希望能給你一些好的指針。我相信有更好答案的人會出現。

  1. 您示例中的BaseController可能是錯誤的。您擁有的內容使其看起來更像是一個控制器工廠,而不是所有其他控制器類可能派生的基本控制器。看起來這更像是一個「路由」類,所以你應該考慮給它一個更合適的名字來完成它的工作。

  2. 如果你希望你的框架,用戶可以用自定義操作創建自定義控制器:

    a)你肯定會想創造至少爲所有控制器類來實現的接口。叫它IController或類似的東西。這用於下一步。

    b)您將不得不使用字符串作爲類名創建對象。 IE「$controllerObject = new $controller();」在「Route」處理程序類中。原因在於要運行的控制器和操作名稱直接來自請求URL。這部分有混淆的方法,但這完全是另一個問題。做而不是忘記驗證和/或白名單從客戶端傳入的這些「控制器」類名稱。驗證:使用PHP函數class_exists($controller),然後如果是true,請檢查以確保控制器類使用PHP的內置class_implements($controller)實現IController。只有然後您應該執行$controllerObject = new $controller();以實際創建控制器對象。

    你的「路線」 process方法就變成了更多的東西一樣(和記住這是一個非常簡化的例子):

    public function process($controller, $action) { 
        if (!class_exists($controller)) { 
         throw new Exception('Controller class does not exist.'); 
        } 
        if (!in_array("IController", class_implements($controller))) { 
         throw new Exception('Route is not a valid controller.'); 
        } 
        if (!method_exists($controller, $action)) { 
         throw new Exception('No such action for requested controller.'); 
        } 
        $ctrl = new $controller(); 
        return $ctrl->$action(); 
    } 
    

    三)沒有你的控制器聲明任何方法(即命名與任何$action可能的價值)你不希望客戶直接使用這種上述設計模式執行。希望你的框架用戶也能理解這一點。只要確保正確記錄了它的內部工作方式,以使您的框架用戶瞭解。

當然,還有比這更多的方法,但這取決於你 - 框架設計師。此外,該行動應該在使用「觀點」時擁有最終決定權。如果操作沒有明確說明要使用的視圖,可以設置默認值。但是,這又是一個問題。

+0

+1用於重命名該類。假設控制器有一個父級基類,這對名稱來說是一個更好的選擇。 – Chief

0

你真的應該首先看看MVC究竟是什麼。我建議先從福勒的GUI Architectures開始。因爲有一件事是非常確定的 - 你擁有的不是它。

看起來,你所命名的BaseController實際上是處理路由。它表示用戶的請求URL,幷包含基於您從所述URL檢索到的文件的文件。這既不是面向對象編程,也不是程序編程。你在那裏有什麼被稱爲non-structured programming

除了這種瘋狂,你應該創建一個單獨的類,它爲你的應用程序實現路由機制。根據你用上述結構提取的數據,你應該啓動特定的控制器實例,並調用一個方法。

喜歡的東西:

$request = new Request('QUERY_STRING'); 

$router = new Router; 
$router->import('/path/to/routing/config.file'); 
$router->route($request); 

$klass = $request->getParameter('controller'); 

if (class_exists($controller)) 
{ 
    $command = $request->getMethod() . $request->getParameter('action'); 
} 
else 
{ 
    $klass = 'Error'; 
    $command = 'getMessage'; 
} 

$controller = new $klass; 
$controller->{$command}($request); 

當然,這是一個非常簡化版本。 MVC模式旨在爲大型項目帶來一些訂單。如果你使用它來創建一個簡單的博客/名片網站,這看起來像是一個矯枉過正(假設頁面不增長)。

P.S.您可能會發現以下對您的學習有用的鏈接:this,this,thisthis