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
lukaskolista
post
Post #2





Grupa: Zarejestrowani
Postów: 872
Pomógł: 94
Dołączył: 31.03.2010

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


Pozwolę sobie zwrócić uwagę na kilka rzeczy:
1. Przestrzenie nazw - ich brak w moim odczuciu dyskwalifikuje Twój projekt. Wiem, w kohanie ich nie ma, znam ten framework jak własną kieszeń i też dlatego go porzuciłem (na rzecz symfony)
2. Prywatne właściwości i obiekty zaczynające się od _ - kompletnie nie ogarniam tej praktyki (może ktoś mi wyjaśni skąd się to wzięło), jak będziesz chciał zmienić widoczność metody z np. chronionej na publiczną, to w całym projekcie będziesz zmieniał jej nazwę?
3. Brak interface'ów - czemu render jest protected?
  1. abstract class Component
  2. {
  3. protected $_cacheSettings = null;
  4.  
  5. public function render()
  6. {
  7. if (empty($this->_cacheSettings))
  8. {
  9. $content = $this->_render();
  10. }
  11. ....
  12. }
Publiczna metoda render() wywołuje prywatną, kiepski pomysł, już na pierwszy rzut oka źle to wygląda. Na pewno słyszałeś o dziedziczeniu i konstrukcji
  1. parent::method()
Wspominam o tym dlatego, że w publicznym render() korzystasz z cache'u. Co, jeżeli w jednym elemencie chcę używać cache'u, a w innym nie? Nie bardzo wiem, jak miałbym to osiągnąć. Do takich rzeczy, jak cache polecam aspekty (dosyć skomplikowany temat, bo wbrew pozorom stwarza kolejne problemy) lub dekoratory.

  1. class Template extends Component
  2. {
  3. ...
  4. if (defined('Kohana::DEBUG') AND Kohana::$environment == Kohana::DEBUG) {...}
  5. ....
  6. }
Samo wystąpienie nazwy frameworka świadczy o tym, że Twoja biblioteka nie jest przenośna i w moim vendorze się nie znajdzie, bo nie będę specjalnie kohany dociągał.

Na sam koniec najważniejsze:
  1. class Tag extends TagSingle {
  2. public function add(Component $component = null) {}
  3. }

Powyższe to tylko przykład. Uzależniasz działanie praktycznie wszystkiego od konkretnej implementacji, co z zasady jest błędem. Powinieneś zastosować interface'y (wspomniałem o tym wcześniej, ale tutaj kontekst jest inny), np. ComponentInterface plus zostawić to, co jest jako powiedzmy natywna dla Twojej biblioteki, aczkolwiek niekonieczna warstwa abstrakcji.
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: 13.10.2025 - 06:45