2009-07-21 9 views
3

Ich versuche, ein Skelett-View-System in PHP zu peitschen, aber ich kann nicht herausfinden, wie eingebettete Ansichten erhalten ihre Eltern Variablen erhalten. Zum Beispiel:Templating System Bereichsproblem

Ansicht Klasse

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 (Top-Level-Ansicht)

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

embed.php (eingebettet in test.php

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

Code:

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

Ausgang:

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

Das Problem sind die Variablen, die ich in der obersten Ebene festgelegt nicht auf die eingebettete Ansicht übergeben bekommen. Wie könnte ich das möglich machen?

Antwort

1

Also, ich beantworte nicht genau Ihre Frage, aber hier ist meine super-einfache handgewachsene Vorlage System. Es unterstützt, was Sie versuchen, obwohl die Schnittstelle anders ist.

+0

Danke. Dies hat mir gezeigt, dass Sie selbst in großen Frameworks die Ansicht in Ihrem Controller rendern und dann die gerenderte Ansicht in einer Variablen nur an die oberste Ebene übergeben müssen. Ich habe versucht, den Blick in eine andere Ansicht zu rendern. – ryeguy

0

Nun, Sie erstellen eine neue Instanz der Klasse, so dass keine Variablen in der eingebetteten Vorlage definiert sind. Sie sollten versuchen, das Objekt zu kopieren, anstatt ein neues Objekt zu erstellen.

edit: Ich spreche über die Factory-Methode

0

Das Hauptproblem ist, dass Ihre Ansichten keine direkte Kenntnis voneinander haben. Durch den Aufruf dieses:

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

in Ihrer „Eltern“ Ansicht, die Sie erstellen und Ausgang eine Vorlage, die keine Kenntnis von der Tatsache hat, dass es in einer anderen Vorlage ist.

Es gibt zwei Ansätze, die ich hier empfehlen könnte.

# 1 - Verknüpfen Sie Ihre Vorlagen.

Indem Sie Ihren eingebetteten Vorlagen "Children" einer übergeordneten Vorlage zuweisen, können Sie ihnen Zugriff auf die Variablen des übergeordneten Elements unter output() ermöglichen. Ich verwende diesen Ansatz in einem von mir erstellten View-System. Es geht ungefähr so:

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

Bei $pview->render() Zeit wird das Kind Blick leicht Zugriff auf die Variablen der Eltern gegeben.

Diese Methode erfordert möglicherweise eine Menge Refactoring für Sie, so dass ich die schmutzigen Details weglassen und in die zweite Vorgehensweise gehen werde.

# 2 - Pass die Mutter Variablen

Dies würde wahrscheinlich die einfachste Methode, um den Ansatz, den Sie bisher gemacht haben zu implementieren gegeben. Fügen Sie einen optionalen Parameter zu Ihrem Ausgabeverfahren, und schreiben sie etwas, wie folgt aus:

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; 
} 

Wenn Sie auch eine einfache Getter-Methode hinzu:

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

Dann können Sie Ihre Dateien mit einbinden, was effektiv Lesezugriff auf die Variablen der Eltern:

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

$this wird ein Verweis auf die aktuelle Vorlage, dh. das Elternteil. Beachten Sie, dass Sie über diese Methode wegen der zwei Aufrufe extract Variablennamen kollidieren können.

0

Sie könnten Ihre $ _vars Eigenschaft statisch, nicht besonders elegant, aber würde für das, was Sie versuchen zu erreichen.

On a side note ... Ihre array_merge() in der set() Funktion ist falsch, tauschen Sie Ihre 2 Variablen um.

+0

Wie könnte es falsch sein? Es führt 2 Arrays zusammen. Das ist wie 2 + 3 zu sagen! = 3 + 2 – ryeguy

+0

Sollten die Vars, die an die Funktion set() übergeben wurden, die alten überschreiben? Wenn Sie $ view-> set aufrufen (array ('title' => 'Title1')) -> set (array ('title' => 'Title2')) -> output(); // Titel wird Titel1 sein – Mario