2012-07-24 69 views
0

我在PHP中創建了一個基本的MVC結構化CMS,作爲學習MVC如何工作的手段(因此我沒有使用真正的預構建引擎)。我有一個基本版本,其結構與本教程here非常相似。不過,我想要自動加載視圖,而不需要模板類。如果強烈建議,我會堅持使用模板概念(如果有人可以解釋爲什麼它是如此必要,我將不勝感激)。無論如何,下面是我的路由器類,我修改了自動加載視圖文件沿控制器。PHP MVC - 模板/加載變量問題

public function loader() { 
     /*** check the route ***/ 
     $this->getPath(); 

     /*** if the file is not there diaf ***/ 
     if (is_readable($this->controller_path) == false) { 
      $this->controller_path = $this->path.'/controller/error404.php'; 
      $this->action_path = $this->path.'/view/error404.php'; 
     } 

     /*** include the path files ***/ 
     include $this->controller_path; 
     include $this->action_path; 

     /*** a new controller class instance ***/ 
     $class = $this->controller . 'Controller'; 
     $controller = new $class($this->registry); 

     /*** check if the action is callable ***/ 
     if (is_callable(array($controller, $this->action)) == false) { 
      $action = 'index'; 
     } else { 
      $action = $this->action; 
     } 
     $controller->$action(); 
    } 

    /** 
    * 
    * @get the controller 
    * 
    * @access private 
    * 
    * @return void 
    * 
    */ 
    private function getPath() { 

     /*** get the route from the url ***/ 
     $route = (empty($_GET['rt'])) ? '' : $_GET['rt']; 

     if (empty($route)) { 
      $route = 'index'; 
     } else { 
      /*** get the parts of the route ***/ 
      // mywebsite.com/controller/action 
      // mywebsite.com/blog/hello 
      $parts = explode('/', $route); 
      $this->controller = $parts[0]; 
      if(isset($parts[1])) { 
       $this->action = $parts[1]; 
      } 
     } 
     if(! $this->controller) { $this->controller = 'index'; } 
     if(! $this->action) { $this->action = 'index'; } 

     /*** set the file path ***/ 
     $this->controller_path = $this->path .'/controller/'. $this->controller . '.php'; 
     $this->action_path = $this->path .'/view/'. $this->controller . '/'. $this->action . '.php'; 
    } 

這是防止由控制器給出裝載的變量(教程網站有這更好的證明)我的觀點的文件,但設置$this->registry->template->blog_heading = 'This is the blog Index';時,因爲template.class繞過視圖不會加載它。基本上我問的是如何將template.class轉換爲加載函數?

+1

像你這樣選擇路由類中的視圖模板是一個壞主意。不僅你假設每個動作都會呈現一個視圖,而且視圖只能有一個模板。一個單獨的視圖對象與從動作級別分配的模板和變量是更好的解決方案。 – lafor 2012-07-24 08:55:41

回答

0

在我自己開發的MVC中,加載一個視圖的方法和你所擁有的類似,但是以一種比你所鏈接的例子更簡單的方式。 (當我第一次決定嘗試學習MVC時,我看到了這個例子,並且我記得它讓我感到困惑;

本質上,在確定文件存在後,您只需要(是的,我覺得沒有找到文件是停止腳本在這種情況下執行的一個很好的理由)

所以..而不是整個模板類的東西(我希望我不是躲閃你的問題並獲得太遠基地,這裏有一種具有控制器打開查看文件的一個簡單的例子。

<?php 
class Pizza_Shop_Controller extends Base_Controller 
{ 
    public function index() 
    { 
     $data['users'] = array('bob','lisa','bertha'); 
     $data['some_string'] = "Whoa I'm a string!"; 

     $this->render_view('index',$data); 
    } 

    public function contact() 
    { 
     if($_POST) 
     { 
      Contact::process($_POST); 
      return $this->render_view('contact_success'); 
     } 
     else 
     { 
      return $this->render_view('contact_form'); 
     } 
    } 


} 

class Base_Controller 
{ 

    protected function render_view($view_name,$data = array()) 
    { 
     /* 
     * I also think render_view should take care of loading the layout, and then inject the content into the middle of the layout file, 
     * so that you aren't trapping yourself to a specific layout, and repeating the header and footer inside of every view file 
     */ 

     extract($data); //places all $data variables into the local scope.. very clean and ezy ;]. 
     require($this->root_directory.DS."$view_name.php"); 
    } 

    /**********************************/ 
    public function _no_action($view_name) //Called if there is no corresponding action 
    { 
     /* You can use method_exists to test if a method exists within the controller, if it does not exist, 
     * you can then call this function, and pass it the name of the view that is attempting to be opened 
     */ 
     if($this->view_exists($view_name)) 
     { 
      $this->render_view($view_name,$data); 
     } 
     else 
     { 
      $this->render404(); 
     } 
    } 

} 
+0

雖然這解決了變量的問題,但我認爲OP需要它,因此視圖會根據控制器操作自動加載。我在家裏有這樣的東西,當我回來時我會發布,但我想它會被回答,然後哈哈 – andy 2012-07-24 08:49:29

+0

哈哈,好的。我添加了一個名爲_no_action的方法來表示如果沒有對應於視圖文件的顯式操作,則調用它。 – Anther 2012-07-24 08:54:11

+0

這是有效的,但我只會說你需要把它放在調用控制器的部分。這樣,如果你有50多個控制器哈哈,你不必再重複該代碼。除此之外,它的作品! – andy 2012-07-24 08:55:59

1

我知道這是不是難以置信的幫助現在給你,但幾個月前我有同樣的問題。這是基於框架我建:

https://github.com/andyhmltn/Cherry-Framework-Blog-Example/

我不完全知道從哪裏或者是怎樣做的,因爲我還沒有真正在一段時間看着它,但各地採取一捅和加載控制器,設置變量然後加載視圖的代碼可能在庫文件夾中。它可以讓你做到這一點:

/** Controller **/ 
class ExampleController extends Controller { 
    public function index() { 
     $helloworld = 'Hello world'; 
     $this->set('hello_world', $helloworld); 
     #Renders view automatically 
    } 
} 

/** View **/ 
echo $hello_world; 
+0

我會看看,希望這是我正在尋找。 – 2012-07-24 08:59:46

+0

你需要的是在那裏挑釁,它只是一個適應它的情況,以適應你自己的框架,因爲我確信它的行爲非常不同。 – andy 2012-07-24 09:01:26

+0

找到它設置變量,然後決定渲染的變量:https://github.com/andyhmltn/Cherry-Framework/blob/master/library/template.class.php – andy 2012-07-24 09:02:43

2

相當常見的誤解「的觀點僅僅是一個愚蠢的模板」主要是由的Ruby-on-Rails和跟隨他們破碎的ORM - 模板適配器那些長期存在。我不能直接面對他們作爲模型 - 視圖 - 控制器實現的...

視圖應該處理MVC和MVC設計模式模式中的表示邏輯。這使得它們成爲對象,並具有處理多個模板的能力。根據你的Web應用使用哪種MVC啓發模式(用PHP實現傳統的MVC是不可能的),你的Views將從Controller類結構(MVP和MVVM模式)接收數據,或者能夠直接從模型層請求信息(Model2 MVC和HMVC模式)。我個人更喜歡活躍的意見,從模型層獲取數據。

P.S.這樣的代碼$this->registry->template->blog_heading使得Demeter流血。

P.P.S.關於如何實現純php模板,請閱讀this article

+0

我會檢查出來,感謝指針! – 2012-07-24 11:39:05

+0

您發送的鏈接非常翔實,並且符合我的最終目標。對於php模板鏈接,教程叫做「$ view-> render('main.php');」我怎麼能夠設置我的系統自動渲染,而不是每次手動輸入? – 2012-07-24 11:42:49

+0

你可以通過爲對象實現['__toString()'](http://www.php.net/manual/en/language.oop5.magic.php#object.tostring)方法來模仿,那麼你可以只需使用'echo $ view;'並觸發該方法。但我會建議避免它。有詳細的代碼,然後添加隱藏的魔法好多了。此外,該鏈接的部分原因是向你展示,你被稱爲「視圖」的實際上是**模板**。這將導致演示邏輯泄漏到控制器中。 – 2012-07-24 13:16:52