2013-06-24 13 views
8

W prawie wszystkich samouczkach lub odpowiedziach na temat SO widzę popularny sposób wysyłania danych z kontrolera do widoku, widok klasy często wygląda podobnie do kodu poniżej:Przekazywanie danych z kontrolera do widoku w aplikacji PHP MVC

class View 
{ 
    protected $_file; 
    protected $_data = array(); 

    public function __construct($file) 
    { 
     $this->_file = $file; 
    } 

    public function set($key, $value) 
    { 
     $this->_data[$key] = $value; 
    } 

    public function get($key) 
    { 
     return $this->_data[$key]; 
    } 

    public function output() 
    { 
     if (!file_exists($this->_file)) 
     { 
      throw new Exception("Template " . $this->_file . " doesn't exist."); 
     } 

     extract($this->_data); 
     ob_start(); 
     include($this->_file); 
     $output = ob_get_contents(); 
     ob_end_clean(); 
     echo $output; 
    } 
} 

Nie rozumiem, dlaczego muszę umieścić dane w tablicy, a następnie wywołać extract ($ this -> _ data). Dlaczego nie wystarczy umieścić bezpośrednio pewne właściwości do widoku z kontrolera jak

$this->_view->title = 'hello world'; 

potem w moim układzie lub pliku szablonu mogłem tylko zrobić:

echo $this->title; 

Odpowiedz

7

Logicznie logicznie grupuje dane widoku i odróżnia je od właściwości klas widoku wewnętrznego.

PHP umożliwia dynamiczne przypisywanie właściwości, dzięki czemu można po prostu utworzyć instancję klasy View i przypisać dane widoku jako właściwości. Osobiście nie poleciłbym tego jednak. Co zrobić, jeśli chcesz powtórzyć dane widoku lub po prostu je zrzucić w celu debugowania?

Przechowywanie danych widoku w tablicy lub zawierających obiekt nie oznacza, że ​​należy użyć $this->get('x'), aby uzyskać do niego dostęp. Opcją jest użycie PHP5's Property Overloading, która pozwoli ci przechowywać dane jako tablicę, ale ma interfejs $this->x z danymi z szablonu.

Przykład:

class View 
{ 
    protected $_data = array(); 
    ... 
    ... 

    public function __get($name) 
    { 
     if (array_key_exists($name, $this->_data)) { 
      return $this->_data[$name]; 
     } 
    } 
} 

Sposób __get() zostanie wywołana przy próbie uzyskania dostępu do nieruchomości, która nie istnieje. Więc możesz teraz zrobić:

$view = new View('home.php'); 
$view->set('title', 'Stackoverflow'); 

W szablonie:

<title><?php echo $this->title; ?></title> 
+1

Dziękuję bardzo za wycinek, jest niesamowity;) – Matthew

1

moje przypuszczenie, że powodem może być po prostu " mniej pisania ", ale które mają kilka fajnych efektów ubocznych:

  • Pomaga, gdy ci, którzy piszą szablony, nie są zaznajomieni z php iw ten sposób nie muszą być zainteresowani" co c Czy to oznacza $this->? ".
  • Posiadanie osobnego kontenera dla zmiennych pomaga również wtedy, gdy istnieją pewne właściwości widoku, które powinny być prywatne dla tej klasy, a autorzy bibliotek nie chcą ujawniać ich autorom szablonów.
  • Zapobiega kolizjom nazw z właściwości widoku i zmienne dla szablonów.
  • Znacznie szybszy niż schematy dostępu oparte na metodach. Być może nie jest to już tak istotne, jak wtedy, gdy na przykład utworzono smarty (również z php4).
+0

Zgadzam się na pkt 1 i 3. Jednak w odniesieniu swój drugi punkt, nie sądzę, że pojemnik pozwala ukryć prywatny właściwości widoku, nadal możesz zrobić $ this-> somePrivateProperty, ponieważ plik został dołączony do klasy View (patrz powyższy kod). – Matthew

+0

Cóż, oczywiście, ale przynajmniej w ten sposób wyglądałby wyraźnie poza "normalnymi" zmiennymi, które powinny być dostępne. – complex857

+0

ok Dostałem twój punkt :) – Matthew

Powiązane problemy