Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: "Inny" system szablonów
Forum PHP.pl > Forum > PHP > Pro > Archiwum Pro
MStaniszczak
Jest sobie system szablonów (no, prawie już jest) ;-)
Działa jak każdy inny poza małym mykiem;-)

Może mała demonstracja:

Szablon test.tpl:
  1. <title>{$tytul}</title>
  2. </head>
  3. {$ala->coMa}<br>
  4. {$ala::coRobi['w domu']}<br>
  5. </body>
  6. </html>


teraz Mamy kod ala.php
  1. <?
  2. $tpl = new Template(); 
  3. $tpl->assign('tytul', 'Coś o Ali;-)');
  4. $tpl->display('test.tpl');
  5. ?>


A co z {$ala->coMa} i {$ala::coRobi[‘w domu’]}? Jest sobie klasa ala.class.php:
  1. <?php
  2. Class Ala {
  3.  public function getCoMa() {
  4. return 'Kota';
  5.  }
  6.  
  7.  static public function getCoRobi() {
  8. return array(
  9.  'w domu' => 'czyta kotu bajki',
  10.  'w szkole' => 'strzela z długopisu',
  11. );
  12.  }
  13. }
  14. ?>


To tak w dużym skrócie;-)
Co o tym sądzicie?


Pozdrawiam
Marin Staniszczak
hawk
Szczerze? Katastrofa. Dlaczego {$ala->cokolwiek} ma tworzyć nowy obiekt? Technicznie jest to ciekawe, praktycznie bezużyteczne. Przecież ja już będę miał jakieś obiekty, i to wypełnione danymi. I będę chciał wyświetlić zawartość tych konkretnie obiektów, a nie tworzyć jakiś nowy, przypadkowy, i co gorsza pusty obiekt. Zresztą spójrz na swój przykład - lepiej od razu napisać wszystko w statycznym HTMLu.
MStaniszczak
Ja to widzę inaczej:
  • aplikacja jako taka nie tworzy obiektów z danymi
  • w szablonie ("widok" tworzy tu szablon + klasa z metodami getXXX()) wywoływana jest odpowiednia metoda z klasy towarzyszącej szablon
  • w klasę z metodami getXXX() dopiero tworzy się odpowiednie, potrzebne obiekty, unikając jednocześnie tworzenia tych które nie będą i tak wykorzystane przez szablon
  • i jeszcze dodatkowo nie ładujesz do szablonu zbędnych danych
  1. <?php
  2. Czyli klasa z get może wyglądać tak (tamten przykład był banalny):
  3. class User {
  4.  function getName() {
  5. /* tu prosimy np. kontroler o stworzenie odpowiedniej klasy (tak aby przechowywał on jej obiekt to końca działania skryptu - w razie jak będzie on jeszcze potrzeby, żeby nie był ponownie tworzony) */
  6.  // pobieramy dane z utworzonej klasy
  7. return Dane_Otrzymane_Z_Utworzonego_Obiektu;
  8.  }
  9. }
  10. ?>


Stworzenie obiektu zwracającego dane możemy przenieść też do konstruktora, ale nie jest to raczej konieczne – zależy to od klasy przechowującej stworzone obiekty (jak sobie z nimi da rade;-)

Pozdrawiam
Marcin Staniszczak
Ace
hm, czyli w kodzie szablonu chcesz wykorzystac obiekty ? W smarty tez mozesz wykorzystywac obiekty, wystarczy ze przypiszesz obiekt do zmiennej, a w kodzie normalnie {$objekt->wartosc} ...

nie wiem czy o to chodzi, ale w twoim przykladzie wykorzystujesz obiekt w kodzie, w smarty tyz mozna...
MStaniszczak
Nie, nie wykorzystuje jako tako obiektów, a jedynie wywołuje odpowiednie funkcję pewnego obiektu, które zwracają już jakąś konkretną, gotową do wyświetlenia wartość (string, cyfra, tablica). Dodatkowo w związku ze zboczeniem nie ma dostępu bezpośrednio do pul klasy zwracającej wartości a jedynie do metod (moje zdanie jest takie że dostęp do pól klasy powinien być mocno ograniczony od i zewnątrz powinno się na nich operować metodami get i set). Czyli zwracają wartość gotową do użycia. Dodatkowo obiekt który jest wołany przez szablon utworzony zostaje dopiero przy jego pierwszym zawołaniu, lub jeśli takie zawołanie nie nastąpi - nigdy...

Dodatkowo Smarty z tego co kojarzę skorzysta z obiektu jeśli podasz mu go w assign. Tu nie musisz tego robić – szablon sam znajdzie i utworzy potrzebne obiekt. I to jest chyba główna różnica obu rozwiązań – możliwe całkowite wyeliminowanie assign i opóźnienie tworzenia potrzebnych obiektów aż do momentu aż naprawdę szablon ich będzie potrzebował.

Pozdrawiam
Marcin Staniszczak
Ace
hm, w sumie to tak - masz racje, szablon puki nie bedzie potrzebowal danych to nie poprosi o nie, wiec bedize mial tylko te dane ktore beda mu potrzebne, to jest plus, ale stworz teraz wlasny system tplow ktory bedzie dobry (dorownujacy smarty), troche czasu tobie to zajmie - czy warto smile.gif jesli stwierdzisz ze bedziesz to wykorzystywal, to warto jak najbardziej.
hawk
@MStaniszczak: Rozumiem twoje argumenty i jest w tym trochę racji, ale w dalszym ciągu uważam, że ten pomysł jest błędny. Podam kilka innych powodów:

1) Zaszywasz w szablonie nazwę klasy, która będzie wykorzystywana. Zaszywasz też pewnie w jakiś sposób ścieżkę do pliku z klasą, bo trzeba ten plik wczytać. Chyba że połączyć to z autoloaderem... w każdym razie takie ustawianie na stałe nazw klas jest złe, bo uniemożliwia późnijesze dziedziczenie, zabawę z interfejsami itd. Wzrasta coupling, przeciwieństwo dependency injection.

2) Nie możesz mieć dwóch obiektów tej samej klasy zwracającej inne dane (bo mających inny stan). Chociaż z tego co zrozumiałem, obiekt wymieniony w szablonie byłby swego rodzaju kontrolerem lub fasadą, która wywołuje inne obiekty. Więc mogę się mylić.

3) Szablon przejmuje rolę kontrolną. Nie chcę pisać "rolę kontrolera", żeby nie wdawać się w argumenty o MVC. Ale fakt, że od szablonu tak naprawdę się wszystko zaczyna, nie podoba mi się. Co się stanie, gdy wystąpi krytyczny błąd? Co się stanie, jeżeli trafi się warning? Normalnie, można byłoby bez problemów umieścić komunikat w szablonie. Tutaj nie można, bo szablon już się częściowo wykonał i jest po ptokach.

4) Nie wydaje mi się, aby takie rozwiązanie dawało jakieś oszczędności. Owszem, "nie ładujesz do szablonu zbędnych danych". Ale jeżeli mówimy o obiektach (a taki np. Smarty na swój sposób też wspiera obiekty), to nie wyobrażam sobie, aby ktoś "niechcący" lub niepotrzebnie assignował do szablonu zupełnie niepotrzebny obiekt. Niepotrzebny string - pewnie się zdarza. Ale cały obiekt - bez przesady. Gdzie tu więc oszczędność?
MStaniszczak
Cytat
1) Zaszywasz w szablonie nazwę klasy, która będzie wykorzystywana. Zaszywasz też pewnie w jakiś sposób ścieżkę do pliku z klasą, bo trzeba ten plik wczytać. Chyba że połączyć to z autoloaderem... w każdym razie takie ustawianie na stałe nazw klas jest złe, bo uniemożliwia późnijesze dziedziczenie, zabawę z interfejsami itd. Wzrasta coupling, przeciwieństwo dependency injection.


Nazwa klasy jest wydobywana z szablonu za pomocą ClassLocator-a (cyli nie w $klasa->zmienna nie $klasa nie musi być nazwa zmiennej, locator ja na jej podstawie określa oraz określa gdzie tej klasy szukać)

Cytat
2) Nie możesz mieć dwóch obiektów tej samej klasy zwracającej inne dane (bo mających inny stan). Chociaż z tego co zrozumiałem, obiekt wymieniony w szablonie byłby swego rodzaju kontrolerem lub fasadą, która wywołuje inne obiekty. Więc mogę się mylić.


OK Zgadza sie;-) Wiec dodałem:
{obj $nazwa_klasy=>$nazwa_obj} //do locatora
i terz mozna sie odwolywac do utworzonego obiektu:
{$nazwa_obj->zmienna}

w razie gdy system uznaje że obiekt $nazwa_obj jest utworzony korzysta z niego, w przeciwnym razie tworzy go. Dodatkowo teraz mozna i tak:
{obj $klasa=>$objekt($ilosc)}
;-) Ale to w planach - nie wiem czy jest sens;-)


Cytat
3) Szablon przejmuje rolę kontrolną. Nie chcę pisać "rolę kontrolera", żeby nie wdawać się w argumenty o MVC. Ale fakt, że od szablonu tak naprawdę się wszystko zaczyna, nie podoba mi się. Co się stanie, gdy wystąpi krytyczny błąd? Co się stanie, jeżeli trafi się warning? Normalnie, można byłoby bez problemów umieścić komunikat w szablonie. Tutaj nie można, bo szablon już się częściowo wykonał i jest po ptokach.


Nie do końca. Zawsze w razie wystąpienia błędu można zawołać innych szablon. Szablon zostaje wyświetlony dopiero po napotkaniu jego końca - nie jest tak jak to wygląda najczęściej wysyłany partiami do przeglądarki. W razie wystąpienia błędu (wyjątek etc.) można wyświetlić inny szablon - po napotkaniu wyjątku, wyświetlanie jest zaniechane. Mam nadzieje że napisałem w miarę jasno;-)

Dodatkowo klasa zwracająca dane może dowolnie dziedziczyć - ważne tylko żeby posiadała odpowiednie metody.

Cytat
4) Nie wydaje mi się, aby takie rozwiązanie dawało jakieś oszczędności. Owszem, "nie ładujesz do szablonu zbędnych danych". Ale jeżeli mówimy o obiektach (a taki np. Smarty na swój sposób też wspiera obiekty), to nie wyobrażam sobie, aby ktoś "niechcący" lub niepotrzebnie assignował do szablonu zupełnie niepotrzebny obiekt. Niepotrzebny string - pewnie się zdarza. Ale cały obiekt - bez przesady. Gdzie tu więc oszczędność?


Dla mnie wygoda - klasy i tak mają najczęściej już metody get. Dodatkowo szablon nie robi nic poza proszeniem o dane. A czy to jest niezgodne z MVC? Z tego co się orientuje widok może poprosić o dane sam bez pośrednictwa kontrolera.
A przecież widok i tak się nie wywoła sam - to już może robić kontroler.

Pozdrawiam
Marcin Staniszczak
hawk
Teraz to nam się zrobiła całkiem ciekawa dyskusja biggrin.gif. Nasunęło mi się jeszcze kilka myśli:

1) Pomysł z ClassLocatorem i z {obj $nazwa_klasy=>$nazwa_obj} jest dobry. Ale w tym momencie system szablonów wkracza w obszar dependency injectora. Warto? Może lepiej byłoby oprzeć to np. o pico (lub phemto) i zostawić tą funkcjonalność wyspecjalizowanemu komponentowi?

2) Jak masz podane czarno na białym assigny w szablonie, to wiesz, czego ten szablon używa. A jak dodamy do twojego pomysłu jeszcze ClassLocatory itd, to robi się to mniej przejrzyste.

3) Gdzieś już chyba na tym forum widziałem "nakładkę" na Smarty, która pozwalała zainicjować i używać w szablonie obiektu bez jego wcześniejszego deklarowania w assign.

4) O poprawność w sensie MVC nie będziemy się spierać, bo taka dyskusja zabija kreatywność. Ale ja jestem przyzwyczajony do modelu, w którym akcja np. prosi model o listę artykułów i pakuje to do szablonu, a szablon wyświetla listę w pętli. Powiedzmy, że wyciąga artykuły z konkretnego działu, bazując na parametrze GET. Teraz twój szablon musiałby używać do tego jakiejś klasy, która ma metodę sprawdzającą ten parametr GET i wyciągającą te artykuły jak wyżej. Na jedno wychodzi, ale mi bardziej odpowiada model działania, w którym ta logika zawarta jest w kodzie akcji, a nie umieszczona w pomocniczej klasie. Chociaż nie jestem pewny, czy dobrze rozumiem, jak powinien działać twój system.

5) Co do ClassLocatora, to nie jest takie proste. Powiedzmy, że mam tą listę artykułów. I nagle chcę na to wrzucić w jednym miejscu dekorator, który jakoś tą listę wstępnie obrobi. W klasycznym modelu bym to wrzucił do kodu akcji, a widok nie zauważyłby różnicy - w końcu to dekorator. W twoim systemie trzeba byłoby chyba zmienić wpis w ClassLocatorze. Z czego wynika, że ClassLocator nie jest częścią biblioteki, ale projektu (bo zmienia się z projektu na projekt).

Zresztą, co będzie, jeżeli będę chciał użyć tego samego szablonu, raz z pełną listą artykułów, raz z moim dekoratorem? Kod szablonu powinien być ten sam - w końcu to tylko prezentacja danych, w obu przypadkach identyczna. Po czym ClassLocator pozna, którą klasę do artykułów ma zainicjować?
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.