2009-07-21 47 views
3

我想在PHP中掀起一個框架查看系統,但我無法弄清楚如何獲得嵌入式視圖來接收父母的變量。例如:模板系統範圍問題

視圖類

class View 
{ 
    private $_vars=array(); 
    private $_file; 

    public function __construct($file) 
    { 
     $this->_file='views/'.$file.'.php'; 
    } 

    public function set($var, $value=null) 
    { 
     if (is_array($var)) 
     { 
      $this->_vars=array_merge($var, $this->_vars); 
     } 
     else 
      $this->_vars[$var]=$value; 

     return $this; 
    } 

    public function output() 
    { 
     if (count($this->_vars)) 
      extract($this->_vars, EXTR_REFS); 
     require($this->_file); 
     exit; 
    } 

    public static function factory($file) 
    { 
     return new self($file); 
    } 
} 

test.php的(頂層視圖)

<html> 
    <body> 
     Hey <?=$name?>! This is <?=$adj?>! 
     <?=View::factory('embed')->output()?> 
    </body> 
</html> 

embed.php(嵌入在test.php的

<html> 
    <body> 
     Hey <?=$name?>! This is an embedded view file!! 
    </body> 
</html> 

代碼:

$vars=array(
    'name' => 'ryan', 
    'adj' => 'cool' 
); 
View::factory('test')->set($vars)->output(); 

輸出:

Hey ryan! This is cool! Hey [error for $name not being defined] 
this is an embedded view file!! 

的問題是我在頂級視圖設置的變量沒有得到傳遞給內嵌視圖。我怎麼能做到這一點?

回答

1

所以,我並沒有完全回答你的問題,但這裏是我的超級簡單的手工模板系統。它支持你想要做的事,儘管界面是不同的。

// Usage 
$main = new SimpleTemplate("templating/html.php"); 
$main->extract($someObject); 
$main->extract($someArray); 
$main->name = "my name"; 
$subTemplate = new SimpleTemplate("templating/another.php"); 
$subTemplate->parent($main); 
$main->placeholderForAnotherTemplate = $subTemplate->run(); 
echo $main; // or $main->run(); 

// html.php 
<html><body><h1>Title <?= $name ?></h1><p><?= $placeHolderForAnotherTemplate ?></p></body></html> 

    <?php 
// SimpleTemplate.php 
function object_to_array($object) 
{ 
    $array = array(); 
    foreach($object as $property => $value) 
    { 
     $array[$property] = $value; 
    } 

    return $array; 
} 

class SimpleTemplate 
{ 
    public $source; 
    public $path; 
    public $result; 
    public $parent; 

    public function SimpleTemplate($path=false, $source=false) 
    { 
     $this->source = array(); 
     $this->extract($source); 
     $this->path($path); 
    } 

    public function __toString() 
    { 
     return $this->run(); 
    } 

    public function extract($source) 
    { 
     if ($source) 
     { 
      foreach ($source as $property => $value) 
      { 
       $this->source[$property] = $value; 
      } 
     } 
    } 

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

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

    public function __set($name, $value) 
    { 
     $this->source[$name] = $value; 
    } 

    public function __get($name) 
    { 
     return isset($this->source[$name]) ? $this->source[$name] : ""; 
    } 

    public function mergeSource() 
    { 
     if (isset($this->parent)) 
      return array_merge($this->parent->mergeSource(), $this->source); 
     else 
      return $this->source; 
    } 

    public function run() 
    { 
     ob_start(); 
     extract ($this->mergeSource()); 
     include $this->path; 
     $this->result = ob_get_contents(); 
     ob_end_clean(); 
     return $this->result; 
    } 
} 
+0

謝謝。這讓我意識到,即使在大型框架中,您也應該在控制器中渲染視圖,然後將變量中的渲染視圖傳遞到頂層視圖。我試圖在另一個視圖內渲染視圖。 – ryeguy 2009-07-21 18:36:34

0

好吧,你創建了一個新的類實例,所以在嵌入模板中沒有定義變量。您應該嘗試複製該對象,而不是創建一個新對象。

編輯:我說的是工廠方法

0

的主要問題是,你的意見對彼此沒有直接的知識。通過調用這個:

<?=View::factory('embed')->output()?> 
在你的「父母」的觀點

,創建和輸出一個沒有的事實,這是另一個模板內知識的模板。

我可以在這裏推薦兩種方法。

#1 - 關聯您的模板。

通過將父模板的嵌入式模板設置爲「子」,您可以允許它們在output()時間訪問父變量。我在我構建的View系統中使用這種方法。它是這樣的:

$pView = new View_Parent_Class(); 
$cView = new View_Child_Class(); 
$pView->addView($cView); 

$pview->render()時候,孩子視圖輕易的獲得了父母的變量。

此方法可能需要進行大量重構,因此我將省去骯髒的細節,並進入第二種方法。

#2 - 通過父變量

這很可能是爲了實現給您到目前爲止所採取的做法最簡單的方法。如果你添加一個簡單的getter方法以及

public function output($extra_vars = null) 
{ 
    if (count($this->_vars)) 
     extract($this->_vars, EXTR_REFS); 
    if (is_array($extra_vars)) extract($extra_vars, EXTR_REFS); 
    require($this->_file); 
    exit; 
} 

public function get_vars() 
{ 
    return $this->_vars; 
} 

然後你可以嵌入什麼是文件的可選參數添加到您的輸出方法,並稍微改寫它,這樣有效讀取訪問父的變量:

<?=View::factory('embed')->output($this->get_vars())?> 

$this將是當前模板的引用,即。父母。請注意,由於兩個extract調用,您可以通過此方法發生變量名衝突。

0

你可以讓你的$ _vars屬性是靜態的,不是特別優雅,但可以用於你想要達到的目的。

在附註中...您的array_merge()在set()函數中是錯誤的,請交換兩個變量。

+0

它怎麼會是錯的?它將2個數組合並在一起。這就像說2 + 3!= 3 + 2 – ryeguy 2009-07-22 12:16:18