Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [mvc] Pare pytan, lancuchy akcji etc.
Forum PHP.pl > Forum > PHP > Object-oriented programming
Helios
Tak sobie od kilku dni czytam ksiazeczke na temat programowania obiektowego i chce zrozumiec wzorzec MVC. Sklecilem taki kod i chce zebyscie go zweryfikowali czy moje rozumowanie idzie w dobra strone.
Bez obslugi bledow, bez pojedynczych instancji, prosty kod zeby sie przekonac czy dobrze rozumuje itd. Narazie sie bawie...
Zerknijcie okiem i napiszcie cos od siebie. Dzieki z gory za wszelkie uwagi!

  1. <?php
  2.  
  3. /**
  4. * Interfejs kontrolera - kazdy niech ma metode ustawiania widoku
  5. */
  6. interface Controller {
  7. public function setView($viewName);
  8. }
  9.  
  10. /**
  11. * Interfejs widoku - kazdy niech ma metode wyswietlania
  12. */
  13. interface View {
  14. public function display();
  15. }
  16.  
  17. /**
  18. * Klasa widoku produktu z zaimplementowanym interfejsem widoku
  19. */
  20. class ProductView implements View {
  21.  
  22. private $vars = array();
  23.  
  24. public function setVar($varName, $varValue = false){
  25. $this->vars[$varName] = $varValue;
  26. }
  27.  
  28. public function display(){
  29. foreach($this->vars AS $varName => $varValue){
  30. print "[{$varName}] => {$varValue}\n";
  31. }
  32. }
  33.  
  34. }
  35.  
  36.  
  37. /**
  38. * Klasa pojedynczego produktu
  39. */
  40. class Product {
  41.  
  42. protected $title;
  43. protected $price;
  44.  
  45. public function setTitle($title){
  46. $this->title = $title;
  47. }
  48.  
  49. public function setPrice($price){
  50. $this->price = $price;
  51. }
  52.  
  53. public function getTitle(){
  54. return $this->title;
  55. }
  56.  
  57. public function getPrice(){
  58. return $this->price;
  59. }
  60.  
  61. }
  62.  
  63. /**
  64. * Klasa kontrolera produktow korzysta z klasy Product i implementuje interfejs k
    ontrolera
  65. * Wywolanie akcji addProduct powoduje ustawienie title, price, widoku ProductVie
    w i wyswietlenie danych
  66. */
  67. class ProductController extends Product implements Controller {
  68.  
  69. private $viewObj;
  70.  
  71. public function addProduct($title, $price){
  72. $this->setTitle($title);
  73. $this->setPrice($price);
  74. $this->setView('ProductView');
  75. $this->viewObj->setVar($this->getTitle(), $this->getPrice());
  76. $this->execView();
  77. }
  78.  
  79. public function setView($viewName){
  80. $this->viewObj = new $viewName;
  81. }
  82.  
  83. public function execView(){
  84. $this->viewObj->display();
  85. }
  86.  
  87. }
  88.  
  89. /**
  90. * Tu powinien byc jakis front controller ktory wywola akurat kontroler produktow
     ale do tego jeszcze nie doszedlem
  91. */
  92. $o = new ProductController;
  93. $o->addProduct('Nazwa 1', '44.99');
  94.  
  95. ?>
NoiseMc
Front controller powinien tylko wywolac akcje kontrolera, a nie decydowac o tym czy kontroler doda rekord czy nie, dopiero w akcji okreslasz co masz zrobic dalej. Kontroler nie powinien byc sprzezony z modelem ani z widokiem, powinienes w kontrolerze stworzyc sobie nowy obiekt Product i na nim operowac, a nie dziedziczyc z tej klasy. W skrocie ja to widzialbym tak:
  1. <?php
  2.  
  3. /**
  4. * Interfejs widoku - kazdy niech ma metode wyswietlania
  5. */
  6. interface View {
  7. public function display();
  8. }
  9.  
  10. /**
  11. * Klasa widoku produktu z zaimplementowanym interfejsem widoku
  12. */
  13. class ProductView implements View {
  14.  
  15. private $vars = array();
  16.  
  17. public function setVar($varName, $varValue = false){
  18. $this->vars[$varName] = $varValue;
  19. }
  20.  
  21. public function display(){
  22. foreach($this->vars AS $varName => $varValue){
  23. print "[{$varName}] => {$varValue}\n";
  24. }
  25. }
  26.  
  27. }
  28.  
  29. /**
  30. * Klasa pojedynczego produktu
  31. */
  32. class Product {
  33.  
  34. protected $title;
  35. protected $price;
  36.  
  37. public function setTitle($title){
  38. $this->title = $title;
  39. }
  40.  
  41. public function setPrice($price){
  42. $this->price = $price;
  43. }
  44.  
  45. public function getTitle(){
  46. return $this->title;
  47. }
  48.  
  49. public function getPrice(){
  50. return $this->price;
  51. }
  52.  
  53. }
  54.  
  55. /**
  56.  * Model produktu
  57.  */
  58. class ProductModel
  59. {
  60. public function add (Product $product){
  61. // Tutaj rozebranie obiektu Product i zapisanie go do bazy
  62. }
  63. }
  64.  
  65. class ProductController {
  66.  
  67. private $request;
  68. private $response;
  69.  
  70. private $view;
  71. private $model;
  72.  
  73. public function __construct ($request, $response){
  74. $this->request = $request;
  75. $this->response = $response;
  76.  
  77. $this->view = new ProductView();
  78. $this->model = new ProductModel();
  79. }
  80.  
  81. public function addproductAction(){
  82. $product = new Product();
  83.  
  84. /**
  85.  * Zakladajac ze mamy obiekt request ktorzy przechowuje wszystkie dane z GET i P
    OST
  86.  */
  87. $product->setTitle($this->request->getParam('title'));
  88. $product->setPrice($this->request->getParam('price'));
  89.  
  90. $this->model->add ($product);
  91.  
  92. $this->view->setVar($this->request->getParam('title'), $this->request->getParam('price'));
  93. $this->view->display();
  94. }
  95. }
  96.  
  97. $title, $price 
  98.  
  99. /**
  100. * Tu powinien byc jakis front controller ktory wywola akurat kontroler produktow
     ale do tego jeszcze nie doszedlem
  101. * Front controller nie powinien wiedziec jakie parametry bedzie posiadal nowy pr
    odukt, nie powinien rowniez wiedziec nic o 
  102. * jakichkolwiek produktach dane do produktu mozesz zebrac z GET albo POST
  103. */
  104. $o = new ProductController ($request, $response);
  105. $o->addproductAction ();
  106.  
  107. ?>
Helios
Chce zrobic sobie jakos ladnie lancuchy akcji i wymyslilem takie oto rozwiazanie.

Stworze klase abstrakcyjna AppQuery, ktora bedzie podstawa dla klas z niej korzystajacych.
Na jej podstawie utworze dwie klasy: AppAction i AppView. Chce, aby kazda wywolana akcja zwracala do kontrolera obiekt klasy AppAction lub AppView ustawiajac w skladowych nazwe akcji do odpalenia i ewentualne argumentu a w AppView nazwe szablonu do zaladowania. Kontroler chce utworzyc w ten sposob, aby dostawal z zewnatrz np. z klasy Router dane, wybieral akcje i wykonywal je dalej o ile zwracane obiekty sa instancja klasy AppAction, jezeli akcja zwroci AppView to wywolam odpowiedni widok. Co myslicie o takim rozwiazaniu? Wydaje mi sie calkiem okej, tylko aktualnie mam problem jak powiazac komunikacje miedzy widokiem a akcjami, gdyz akcje zwracaja mi obiekty AppQuery a chcialbym np. zwrocic rowniez liste wynikow danego zapytania. Macie jakies pomysly? Moze wykorzystac zwracany obiekt AppAction?

Wyglada to mniej wiecej tak:

Router->Front Controller->RunAction(action) tu obsluga lanuchow akcji az do momentu kiedy jakas akcja zwroci AppView.

  1. <?php
  2. public function run(AppQuery $objAppQuery){
  3. if($objAppQuery instanceof AppAction){
  4. $this->runAction($objAppQuery);
  5. }elseif($objAppQuery instanceof AppView){
  6. $this->runView($objAppQuery);
  7. }
  8. }
  9.  
  10. public function runAction(AppAction $objAppAction){
  11. $this->run(call_user_func_array(array('jakismodul', $objAppAction->getName()), $objAppAction->getArgs()));
  12. }
  13.  
  14. public function runView(AppView $objAppView){
  15. }
  16. ?>
Cysiaczek
Możesz też poczytać tutaj. Może się przyda ;]

Pozdrawiam.
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.