Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Moduł do tworzenia elementów widoku
slawooo
post
Post #1





Grupa: Zarejestrowani
Postów: 4
Pomógł: 0
Dołączył: 26.01.2015

Ostrzeżenie: (0%)
-----


Chciałbym zaprezentować i poddać Waszej ocenie moduł ułatwiający oprogramowanie warstwy prezentacji (widoku) w modelu MVC.

W odróżnieniu od tego jak to standardowo bywa w różnych frameworkach PHP, tutaj widok nie jest "gołym" szablonem, nakładki typu smarty czy twig też nie mają z moim pomysłem nic wspólnego. Główna idea opiera się na potraktowaniu warstwy widoku jako kodu w pełni obiektowego, a więc korzystającego ze wszystkich korzyści z niego płynących, takich jak dziedziczenie, enkapsulacja itp.

Cała koncepcja opiera się na obiektach, które nazwałem komponentami. Chodzi tu po prostu o pewne odrębne elementy interfejsu - "komponenty" wizualne, rozumiane zupełnie dowolnie, jak np. menu, okno logowania, komentarze, galeria zdjęć czy cokolwiek innego widocznego na ekranie. Każdy z takich komponentów może składać się z zagnieżdżonych innych komponentów, a na samym "dole" znajdują się gotowe komponenty będące zwykłymi tagami HTML (lub w wyjątkowych przypadkach mogą to być też klasyczne szablony). Dzięki takiemu podejściu, budowanie elementów interfejsu jest prostsze, nie prowadzi do duplikowania kodu, no i kod nie wygląda jak oparty na include z PHP 4.x ;]

Moduł powstał przy tworzeniu aplikacji zbudowanej na frameworku kohana, ale bez większych akrobacji można go dopasować do własnych zastosowań.

Link do źródeł: https://github.com/SlawomirOlchawa/components

Ciekawy jestem Waszych opinii odnośnie takiego rozwiązania, odnośnie samego kodu również.
Przy okazji, jeśli ktoś spotkał się z podobnym podejściem w jakimś z frameworków to chętnie dowiem się więcej na ten temat.

Dla lepszego zrozumienia, przykładowe fragmenty kodu:

Widok:
  1. class Component_Category_Info extends Tag_Block
  2. {
  3. /**
  4.   * @var Model_Category
  5.   */
  6. protected $_category;
  7.  
  8. /**
  9.   * @param Model_Category $category
  10.   */
  11. public function __construct(Model_Category $category)
  12. {
  13. parent::__construct();
  14.  
  15. $this->_category = $category;
  16. Helper_Includer::addCSS('media/app/css/category.css');
  17. }
  18.  
  19. /**
  20.   * @return string
  21.   */
  22. protected function _render()
  23. {
  24. $this->addCSSClass('category_info');
  25.  
  26. $descriptionBlock = new Tag_Block($this->_category->description);
  27. $descriptionBlock->addCSSClass('lightBg');
  28. $descriptionBlock->addCSSClass('description');
  29.  
  30. $this->add($descriptionBlock);
  31.  
  32. return parent::_render();
  33. }
  34. }


Kontroler:
  1. class Controller_Category extends Controller_Entity
  2. {
  3. public function action_index()
  4. {
  5. $info = new Component_Category_Info($this->_entity);
  6. $info->cache($this->_entity->getURL().'/info');
  7. $this->layout->add($info);
  8. }
  9. }


Ten post edytował slawooo 5.11.2015, 02:08:34
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi
slawooo
post
Post #2





Grupa: Zarejestrowani
Postów: 4
Pomógł: 0
Dołączył: 26.01.2015

Ostrzeżenie: (0%)
-----


Dzięki za konkretną odpowiedź.

1. Masz oczywiście rację, choć przestrzenie nazw w PHP są nieco niedopracowane... (https://pornel.net/phpns/pl)
Zresztą jakiś czas temu próbowałem przerobić cały większy projekt (składający się również z modułu z tego wątku) na przestrzenie nazw, ale nie wystarczyło mi cierpliwości (IMG:style_emoticons/default/smile.gif)
Dokładnie nie pamiętam, ale utknąłem gdzieś na styku frameworka właśnie. Poza tym kilkanaście linijek "use" na początku każdego pliku zniechęciło mnie dość skutecznie.

2. To taka zaszłość z C++ (gdzie "this" jest opcjonalne), W PHP faktycznie nie ma uzasadnienia.
Jedyny plus, to wg mnie lepsza czytelność no i jak zauważyłeś wymuszenie przemyślenia widoczności metod na początku (IMG:style_emoticons/default/smile.gif)

3. Co do render, to muszę dokładniej wyjaśnić, wg mnie wszystko jest ok. Metoda publiczna - "render" zawiera ogólny mechanizm renderowania, w tym również obsługę cache. Oczywiście można ją nadpisać/rozszerzyć i dodać jakieś nowe działanie, ale generalnie komponenty dziedziczą ją bez żadnych zmian. Jest wywoływana przy tworzeniu głównego szablonu (layoutu) w kontrolerze i dlatego właśnie jest publiczna.

Natomiast metoda chroniona - "_render" nie jest (i nie powinna być) wywoływana nigdzie na zewnątrz komponentu i dlatego właśnie jest chroniona (IMG:style_emoticons/default/smile.gif) Opisuje tworzenie danego komponentu, bez wnikania w ogólne sprawy takie jak cache (aby nie duplikować kodu cache w każdym komponencie) i bardzo często wykorzystuje dziedziczenie i konstrukcję "parent::_render()".

Dzięki temu rozbiciu właśnie użycie cache jest bardzo proste - aby włączyć cache dla danego elementu wystarczy użyć:
  1. $element->cache($name)
(przykład jest w pierwszym poście). Domyślnie cache jest wyłączone i dla każdego elementu który ma być cacheowany trzeba użyć powyższej linijki.

Tak nawiasem mówiąc to konstrukcja z dwiema metodami (jedna publiczna, druga prywatna/chroniona) jest implementacją wzorca "metoda szablonowa" - https://pl.wikipedia.org/wiki/Metoda_szablo...zec_projektowy).

4. Faktycznie biblioteka nie jest przenośna i bez kohany nie ruszy, ale takich miejsc jest dosłownie kilka (i nie są to kluczowe fragmenty kodu) i łatwo można ją przerobić na potrzeby innego frameworka. Choć przyznam, że już mi się nie chciało za to zabierać (IMG:style_emoticons/default/smile.gif)

5. Możesz rozwinąć co masz tutaj na myśli mówiąc o interfejsach? "Component" jest klasą abstrakcyjną, a więc znacznie bliżej jej do interfejsu niż "konkretnej implementacji".
Teoretycznie mógłbym stworzyć interfejs dla komponentu i zawrzeć w nim metodę "render", a klasa "Component" by go implementowała, tylko czy nie byłaby to sztuka dla sztuki?
Go to the top of the page
+Quote Post

Posty w temacie


Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 11.10.2025 - 09:14