2011-03-22 60 views
0

我想知道什麼是更好的方式來設計我的網站,應該在MVC(模型 - 視圖 - 控制器)結構中爲瀏覽器和JSON移動設備輸出HTML。如何設計我的網站作爲使用MVC的網絡服務?

我的想法是簡單地添加if/else語句來確定在控制器中的操作中輸出HTML或JSON,但我覺得有一個更好的(或更靈活的)方法來做到這一點。

有沒有人可以教我這個或告訴我我應該用什麼關鍵字來搜索?

謝謝!

回答

1

你基本上正在尋找一個抽象的視圖層。我會這樣做的方式是定義一個視圖接口,它只是簡單地獲取數據並返回一個字符串響應。事情是這樣的:

interface View { 
    function render($viewName, $data); 
} 

現在你可以創建一個這樣的實現:

class PhpFileView implements View { 
    private $baseDir; 
    private $format; 

    public function __construct($baseDir) { 
     $this->baseDir = $baseDir; 
     $this->format = 'html'; 
    } 

    public function setFormat($format) { 
     $this->format = $format; 
    } 

    public function render($viewName, $data) { 
     ob_start(); 
     require "{$this->baseDir}/$viewName.{$this->format}.php"; 
     return ob_get_clean(); 
    } 
} 

現在你可以給你的控制器PhpFileView類的一個實例,做這樣的事情:

class MyController { 
    protected $view; 

    public function __construct($config) { 
     $this->view = new PhpFileView($config['view_dir']); 
    } 

    public function indexAction($params) { 
     $this->view->setFormat($params['format']); 
     return $this->view->render('my/index', array(
      'some_var' => 'some value', 
     )); 
    } 
} 

$config = array('view_dir' => 'app/views'); 
$controller = new MyController($config); 
// format could be dynamically set to 'xml', yaml, anything 
$params = array_merge($_REQUEST, array('format' => 'html')); 
echo $controller->indexAction($params); 

這給了你很大的靈活性,因爲你可以在$params['format']中設置你想要的任何格式,然後用它來包含$viewdir/$viewName.$format.php。在我們的例子中,它會渲染app/views/my/index.html.php

在該視圖文件中,您可以訪問$data變量。所以你可以做一些像<?php echo $data['some_var']; ?>

這樣一個系統的巨大優勢是你可以很容易地添加對替代視圖引擎的支持,比如Twig(你應該看看它)。

+0

是不是這樣的:$ this-> view-> setFormat是一個PhpFileView的實現細節。 setFormat未在界面視圖中列出? – Marcus 2011-03-22 20:21:26

+0

當然你是對的,我已經調整了這個例子來反映這一點。並通過刪除抽象基本控制器來簡化該示例。 – igorw 2011-03-22 20:32:00

0

更好的主意是爲HTML和JSON使用單獨的視圖。

在正確實現的MVC框架中,您可以設置要用於呈現輸出的視圖類(或模板)。這可以是JSON,HTML,XML或其他。

0
//From ur controller. 
public handleResponse($responseData) 
{ 
    $responseInf = Util::getResponseObject($headers,$responseData); 
    $responseInf->flushOutput(); 
} 


class Util 
{ 
    static function getResponseObject($headers,$responseData) 
    { 
     $responseInf = false; 
     if($headers specific mobile) 
     $responseInf = new JSON_Output($responseData); 
     else 
     $responseInf = new HTML_Output($responseData); 

     return $responseInf; 
    } 
} 

Interface ResponseInf 
{ 
    public function flushOutput(); 
} 

class JSON_Output implements ResponseInf 
{ 
    private $responseData = false; 

    function ___construct($data) 
     $this->responseData = $data; 

    public function flushOutput() 
    { 
     //Convert $this->responseData to JSON object 
     //flush json object from here. 
    } 
} 

class HTML_Output implements ResponseInf 
{ 
    private $responseData = false; 

    function ___construct($data) 
     $this->responseData = $data; 

    public function flushOutput() 
    { 
     //Convert $this->responseData to HTML string 
     //flush html from here. 
    } 
}