Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

3 Stron V   1 2 3 >  
Reply to this topicStart new topic
> Zalążek frameworka z MVC, Proszę, zweryfikujcie moje podejście
Prph
post 4.03.2006, 16:02:14
Post #1





Grupa: Zarejestrowani
Postów: 338
Pomógł: 2
Dołączył: 4.03.2006
Skąd: Łódź

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


Witam wszystkich,

Ostatnio zacząłem czytać o obiektowym php5, MVC, frameworkach i postanowiłem zacząć pisać kod, który byłby dla mnie wygodny oraz co ważne - nadawał się do powtórnego wykorzystania.

Opiszę to co do tej pory zrobiłem. Proszę Was, znaczniej bardziej doświadczonych programistów, o uwagi na temat mojego podejścia.

Zaznacze, że swoją pracę oparłem do tej pory na artykule Frameworki z php.pl, framework CakePHP oraz o wypowiedzi forumowiczach w topikach MVC.

Charakterystyka ogólna:
Drzewo projektu

Kod
|- actions/ (tu wrzucam kontrolery w postaci class.NazwaKontrolera.php)
|- conf/
|- models/ (tu będą modele, do tej pory nic tam nie mam)
|- lib/
|  +-- core/ - tu są moje pliki wykorzystywane w całej aplikacji
|        +-- class.Dispatcher.php
|        +-- class.Controller.php
|- templates/ - szablony Smarty  
|
|- index.php


Oczywiście nie jest to finalny widok drzewa projektu. Ale nie to jest ważne.

Jak działa mój framework?
index.php uruchamia Dispatcher, który parsuje URL. Jeżeli następuje zgłoszenie index.php/Akcja1/Parametr1/Parametr2/, to dispatcher załącza kontroler Akcja1, a następnie kontroler tej akcji wywołuje na sobie (w zasadzie na potomku) metodę Parametr1 z parametrem Parametr2.

Przykład: strona.pl/index.php/Uzytkownik/Pokaz/1234. Dispatcher przekaże kontrolę do kontrolera Uzytkownik. Ten natomiast włączy metodę Pokaz(1234);

Generalnie wygląda to właśnie tak. Z tego co czytałem, to chyba całkiem logiczne rozwiązanie. Oczywiście mogę się mylić...

Pliki
  1. Plik index.php
  2. <?php
  3. require_once('conf/conf.Core.php');
  4. require_once('lib/core/Logger/class.Logger.php'); // to nas nie interesuje - zwyklu silnik logowania
  5. require_once('lib/core/class.Dispatcher.php');
  6.  
  7. try
  8. {
  9. Logger::register('file:///tmp/log.core.txt');
  10.  
  11. $objDispatcher = new Dispatcher();
  12. $objDispatcher->handle();
  13. }
  14. catch (Exception $exception)
  15. {
  16. echo $exception->getMessage();
  17. }
  18.  
  19. ?>



  1.  Plik class.Dispatcher.php
  2.  
  3. <?php
  4.  
  5. require_once('lib/core/class.Controller.php');
  6. require_once('Smarty.class.php');
  7.  
  8. class Dispatcher
  9. {
  10.  
  11. private $_strUrlParameters; // zawiera parametry url, np: dla strona.pl/index/a/b/c/d zawiera a/b/c/d/
  12. private $_arrUrlParameters; // tutaj parametry juz są w tablicy 
  13.  
  14. public function __construct()
  15. {
  16. $strUrlParameters = $_SERVER['PATH_INFO'];
  17. $this->_strUrlParameters = substr($strUrlParameters, 1);
  18. }
  19.  
  20. public function handle()
  21. {
  22. $this->_parsePath(); // zapusuje parametry url do tablicy
  23.  
  24. $strControllerName = $this->_getControllerName(); // zwroci pierwszy elementy w tablicy parametrow (indeks w tablicy oczywiscie 0)
  25. //Następnie tworzy kontroler na podstawie nazwy akcji i go uruchamia
  26. $strControllerFile = 'actions/class.'.$this->_getControllerName().'Controller.php'; 
  27. if(file_exists($strControllerFile))
  28. {
  29. require_once($strControllerFile);
  30. $strControllerClasName = $this->_getControllerName().'Controller';
  31. $objController = new $strControllerClasName($this->_getParametersForController());
  32. $objController->run();
  33.  
  34. $objSmarty = new Smarty();
  35. $objSmarty->tempalte_dir = 'templates';
  36. $objSmarty->compile_dir = 'var';
  37.  
  38. $objSmarty->assign($objController->getModelData()); // kontroler powinien zwrocic dane dla Smarty.
  39. $objSmarty->display($objController->getView());
  40. }
  41. else
  42. {
  43. throw new Exception('Core, dispatcher: Action '.$strActionToRun.' does not exist');
  44. }
  45. }
  46.  
  47. private function _parsePath() // rozbija parametry url na tablice
  48. {
  49.  $arrParameters = explode('/', $this->_strUrlParameters);
  50.  if($arrParameters[count($arrParameters) - 1] == '')
  51.  array_pop($arrParameters);
  52.  
  53.  $this->_arrUrlParameters = $arrParameters;
  54. }
  55.  
  56. private function _getControllerName() // zwraca nazwe akcji ktora nalezy wykonac - tutaj to pierwsza pozycja w tablicy zawierajacej parametry url
  57. {
  58. $strControllerName = $this->_arrUrlParameters[0];
  59.  
  60. if(strlen($strControllerName))
  61. return $strControllerName;
  62. else
  63. throw new Exception('Core, dispatcher: There is not action to run');
  64. }
  65.  
  66. private function _getParametersForController()
  67. {
  68. $intNumOfPathParameters = count($this->_arrUrlParameters);
  69. $arrPrametersForController = array();
  70.  
  71. for($i = 1; $i < $intNumOfPathParameters; $i++)
  72. $arrPrametersForController[] = $this->_arrUrlParameters[$i];
  73.  
  74. return $arrPrametersForController;
  75. }
  76. }
  77.  
  78. ?>


  1. Plik class.Controller.php
  2. <?php
  3.  
  4. require_once('Collection/class.Collection.php');
  5.  
  6. class Controller
  7. {
  8. private $_strControllerName = null; // nazwa kontrolera - wyorzystuje sie do wybrania widoku i modelu
  9. private $_arrControllerParameters = array(); // parametry dla kontrolera. jezeli url wygladal nastepujaco: strona.pl/index.php/Uzytkownik/Pokaz/12345 to zawiera tablice [Pokaz][1234]
  10.  
  11. protected $_strPageName; // tytul strony (dla htmla)
  12.  
  13. private $_objModelsCollection; // kolekcja modeli, dziala jak tablica asocjacyjna - malo wazne
  14. private $_strView; // widok - tutaj to nazwa szablonu smarty
  15.  
  16. private $_arrViewVars = array();
  17.  
  18. public function __construct($arrParameters = null)
  19. {
  20. if(!isset($this->_strControllerName)) // pobiera nazwe swojej klasy - wykorzystuje sie to do wyboru widoku oraz modelu
  21. {
  22. $arrResults = array();
  23.  
  24. if(!preg_match('/(.*)Controller/i', get_class($this), $arrResults))
  25. {
  26. die('Controller: Can not get my class name');
  27. }
  28.  
  29. $this->_strControllerName = $arrResults[1];
  30. }
  31.  
  32. if(count($arrParameters))
  33. $this->_arrControllerParameters = $arrParameters;
  34.  
  35. $this->_objModelsCollection = new Collection();
  36.  
  37. $this->_objModelsCollection->addItem($this->_strControllerName.'Model');
  38. $this->_strView = $this->_toLowerCase($this->_strControllerName).'.tpl';
  39. }
  40.  
  41. public function getModelData() // zwraca tablice dla Smarty->assign()
  42. {
  43. if(count($this->_arrViewVars))
  44. return $this->_arrViewVars;
  45. }
  46.  
  47. public function getView() // zwraca szablon dla smarty->display();
  48. {
  49. return $this->_strView;
  50. }
  51.  
  52. public function run() // sedno kontrolera. Jezeli przekazano dodatkowy parametr w url, np: strona.pl/index.php/Uzytkownik/Pokaz to wywola sie funkcja Pokaz, jezeli nie wywola funckje domysla, ktora defi
    niuje juz potomek tej klasy
  53. {
  54. if($this->_getMethodToRun())
  55. {
  56. if(is_callable(array($this, $this->_getMethodToRun()), $this->_getParameterForMethod()))
  57. call_user_func_array(array($this, $this->_getMethodToRun()), $this->_getParameterForMethod());
  58. }
  59. else
  60. $this->runDefaultMethod();
  61. }
  62.  
  63. protected function _setPageTitle($strTitle)
  64. {
  65. $this->_strPageTitle = $strTitle;
  66. $this->_setVar('TITLE', $strTitle);
  67. }
  68.  
  69. protected function _setVar($strVarName, $mixValue)
  70. {
  71. $this->_arrViewVars[$strVarName] = $mixValue;
  72. }
  73.  
  74. private function _toLowerCase($strString)
  75. {
  76. return strtolower(substr($strString, 0, 1)).substr($strString, 1);
  77. }
  78.  
  79. private function _getMethodToRun() // sprawdza parametr url, czy ma wykonac jakas metode - patrz wyzej
  80. {
  81. if(isset($this->_arrControllerParameters))
  82. {
  83. if(method_exists($this, $this->_arrControllerParameters[0]))
  84. return($this->_arrControllerParameters[0]);
  85. }
  86. return false;
  87. }
  88.  
  89. private function _getParameterForMethod() // zwraca tablice parametrow dla metody ktora nalezy wykonac. Jezeli url wygldal: 
    strona.pl/index.php/uzytkownik/pokaz/12345 to wykona metode pokaz kontrolera uzytkownik przekazujac do pokaz() 12345.
  90. {
  91. if(isset($this->_arrControllerParameters))
  92. {
  93. if(count($this->_arrControllerParameters) > 1)
  94. {
  95. $intNumOfParameters = count($this->_arrControllerParameters);
  96. $arrPrametersForMethod = array();
  97.  
  98. for($i = 1; $i < $intNumOfParameters; $i++)
  99. $arrPrametersForMethod[] = $this->_arrControllerParameters[$i];
  100.  
  101. return $arrPrametersForMethod;
  102. }
  103. }
  104. }
  105. }
  106.  
  107. ?>


  1. Plik class.HelloController.php - przykładowy kontroler dla akcji Hello
  2. <?php
  3.  
  4. // To jest przykladowy kontroler. Jak widac mozna wywolac strone tak: strona.pl/index.php/Hello/Hi albo Hello/Bye. Mozna przekazac argument: Hello/Bye/Adrian przez co akcja porzegna Adriana.
  5.  
  6. class HelloController extends Controller
  7. {
  8. public function hi()
  9. {
  10. $this->_setPageTitle('Witamy Cię');
  11. $this->_setVar('HEADER', 'Witaj, to działa!');
  12. }
  13.  
  14. public function bye($strName)
  15. {
  16. $this->_setPageTitle('Pa pa pa');
  17. $this->_setVar('HEADER', 'Pa pa '.$strName.', do następnego razu!');
  18. }
  19.  
  20. public function runDefaultMethod()
  21. {
  22. $this->hi();
  23. }
  24. }
  25.  
  26. ?>


Będę Wam ogromnie wdzięczny za uwagi. Pozdrawiam serdecznie,
Adrian.

Ten post edytował Prph 4.03.2006, 19:40:41
Go to the top of the page
+Quote Post
sf
post 4.03.2006, 18:07:56
Post #2





Grupa: Zarejestrowani
Postów: 1 597
Pomógł: 30
Dołączył: 19.02.2003
Skąd: Tychy

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


Brak komentarzy, miales jakis pomysl, ale nie kazdy rozumie/nie ma czasu analizowac co dana metoda robi - toteż analiza ogólna pomysłu jest dość trudna.

Pozatym nie bardzo rozumiem Twoje nazewnictwo, z ktorego wynika, ze kontroler i akcja to jest to samo... wg. mnie kontroler powinien byc jeden i to on wywoluje odpowiednia akcje. Dla mnie tutaj kontrolerem jest klasa Dispatcher.

Co do wyjątki w index.php, tutaj mi się wydaje, że lepiej zarejestrować globalny ( http://php.net/set_exception_handler ) .

Pozatym zamiast count + for lepiej uzyc foreach winksmiley.jpg

Po co dajesz die? Skoro używasz wyjątków to się tego trzymaj.

Wielu można funkcji użyc do sprawdzenia czy string jest pusty... ale wydaje mi się, że lepiej używać funkcji, które do tego służą.. czyli empty, a nie strlen.


--------------------
Zapraszam na mój php blog, tworzenie stron.
Go to the top of the page
+Quote Post
matid
post 4.03.2006, 18:56:02
Post #3





Grupa: Zarejestrowani
Postów: 362
Pomógł: 0
Dołączył: 18.02.2004
Skąd: Knurów

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


Cytat(sf @ 2006-03-04 18:07:56)
Pozatym nie bardzo rozumiem Twoje nazewnictwo, z ktorego wynika, ze kontroler i akcja to jest to samo... wg. mnie kontroler powinien byc jeden i to on wywoluje odpowiednia akcje. Dla mnie tutaj kontrolerem jest klasa Dispatcher.

Akcja przy zastosowaniu wzorca MVC jest częścią kontrolera, natomiast sam Dispatcher jest częścią wzorca Front Controller (przynajmniej w tym kodzie, bo generalnie Front Controller powinien korzystać z Dispatchera w celu obsługi żądania, ale założenia są podobne).
Go to the top of the page
+Quote Post
Prph
post 4.03.2006, 19:52:05
Post #4





Grupa: Zarejestrowani
Postów: 338
Pomógł: 2
Dołączył: 4.03.2006
Skąd: Łódź

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


Diękują za uwagi.

Co do die() - faktycznie nie powinno go tam być. To dlatego, że wzorowałem się na CakePHP a tam było die() winksmiley.jpg

Wydaje mi się, że Kontroler to klasa danej akcji. To tak jakby moduł naszej aplikacji. Tzn jeżeli mamy akcję Użytkownik to wydaje mi się, że (nazwijmy je) podakcje typu PokażProfil, Usuń, Edytuj powinny być w tym kontrolerze Użytkownik, np:

  1. <?php
  2.  
  3. class Użytkownik
  4. {
  5. PokażProfil();
  6. Usuń();
  7. Edytuj();
  8. }
  9. ?>


Dlaczego Dispatcher? Dlatego, że był obecny w CakePHP. Nie wiem - nazwać go FrontController? Może faktycznie jest to lepszy pomysł. Z drugiej strony - przecież on rozbija URL i na podstawie tego odpala kontroler danej akcji.

Czekam na dalsze uwagi. Pozdrawiam serdecznie, Adrian.
Go to the top of the page
+Quote Post
Fipaj
post 4.03.2006, 19:58:25
Post #5





Grupa: Zarejestrowani
Postów: 691
Pomógł: 0
Dołączył: 19.01.2005
Skąd: Warszawa

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


Ten pomysł z Dispatcherem mi się nie podoba.

Czemu nie zrobić tak, jak w większości frameworków? index.php/Kontroler/Akcja/Parametr/Parametr/...?


--------------------
Go to the top of the page
+Quote Post
Prph
post 4.03.2006, 20:26:36
Post #6





Grupa: Zarejestrowani
Postów: 338
Pomógł: 2
Dołączył: 4.03.2006
Skąd: Łódź

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


Ale przeciez w praktyce to tak działa winksmiley.jpg

Ale chyba źle rozumiem pojęcie akcji i kontrolera. Może mi ktoś powiedzieć, co powinienem zmienić w swoim toku myślenia?

Pozdrawiam, Adrian.
Go to the top of the page
+Quote Post
matid
post 4.03.2006, 20:51:50
Post #7





Grupa: Zarejestrowani
Postów: 362
Pomógł: 0
Dołączył: 18.02.2004
Skąd: Knurów

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


We wzorcu MVC kontroler to część aplikacji odpowiedzialna za modyfikacje danych, pobiera on dane wprowadzane przez użytkownika, modyfikuje model i wymusza aktualizację widoku. Nie należy mylić kontrolera we wzorcu MVC z wzorcem Application Controller, bo ten drugi umiejscawia kontroler między modelem a widokiem, co nie jest zgodne z założeniami MVC.

Implementując kontroler w MVC mamy dwie drogi do wyboru: wzorzec Page Controller i Front Controller.

Page Controller - dla każdej strony należącej do witryny tworzymy osobny kontroler. Dekoduje on dane wprowadzane przez użytkownika, tworzy obiekty modelu i wywołuje operacje na modelu, a następnie określa, którego widoku należy użyć i przekazuje mu informacje modelu. Raczej stosowany w aplikacjach o prostej logice działania.

Front Controller - obsługuje wszystkie żądania przesyłane do witryny, a następnie tworzy obiekt polecenia abstrakcyjnego, który następnie wykonuje (można je nazwać akcjami). Traktuje on polecenia jako klasy, a nie strony jak to jest w przypadku wzorca Page Controller. Często łączony z wzorecem Intercepting Filter, bardziej złożony od wzorca Page Controller, ale również bardziej elastyczny.

Pozostaje jeszcze wzorzec Application Controller, ale to już nieco inna bajka winksmiley.jpg

Jaki wzorzec zastosujesz - to zależy od ciebie. Ja mogę polecić lekturę PoEAA i POSA
Go to the top of the page
+Quote Post
Ociu
post 5.03.2006, 09:12:40
Post #8





Grupa: Moderatorzy
Postów: 1 566
Pomógł: 37
Dołączył: 14.05.2003
Skąd: Kraków




Ja sobie podzieliłem to tak:
Kod
framework
     - Web
            - Services
            - ActionChain
            - Controller
            - FrontController
            - Sockets
            - Request


Idzie to tak:
Request pobiera dane z urla o akcji. Odpalany jest Controller, który ładuje bloki menu. Controller odpala FrontController, który znowu korzysta z ActionChain. ActionChain ładuje plik xml z dostępnymi akcjami. Co do parsowania urla. Stwórz obsługę filtrów, i tam wsadź sobie URLFilter.

pozdrawiam
Go to the top of the page
+Quote Post
Prph
post 5.03.2006, 10:14:11
Post #9





Grupa: Zarejestrowani
Postów: 338
Pomógł: 2
Dołączył: 4.03.2006
Skąd: Łódź

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


Teraz raz jeszcze przeczytalem Wprowadzenie do MVC z portalu. Patrzac na Twoje rozwiazanie i idee przedstawione w artykule stwierdzam, ze juz zupelnie mvc nie rozumiem winksmiley.jpg

Mozesz przedstawic zarys Twojej aplikacji - napisz jakie klasy, metody i co robia. Kodu nie potrzebuje.

Kolejna sprawa... Przeczytalem ze Kontroler wlacza widok a on wywoluje model. Jakos nie rozumiem :/ Jak widok ma wywylac metode? Widok to obiekt? A jak na koncu wyswietlane sa dane?

Pozdrawiam, Adrian.
Go to the top of the page
+Quote Post
hwao
post 5.03.2006, 10:24:42
Post #10


Developer


Grupa: Moderatorzy
Postów: 2 844
Pomógł: 20
Dołączył: 25.11.2003
Skąd: Olkusz




W ogole brak Ci widoku w tym frameworku.

Glupio jest troche to wszytko skladac w php poniewaz calosc nie dziala w trybie "ciaglym" tylko jest odpalana po requestach, wiec moze sie okazac ze czesc zalozen MVC wogole nie pasuje do zastosowana WEB'owych.

Dlatego ciezko moim zdaniem jest znalesc kompromis miedzy paroma czynnikami, ilosc klas, modele, akcje, kontroler, widok i szybkosc pisania(ze nie pisze sie 'nie potrzebnych klas' - chociaz roznie z tym nie potrzebnym jest, to zalezy od tego jakiego framework'a potrzebujesz)
Go to the top of the page
+Quote Post
matid
post 5.03.2006, 10:51:08
Post #11





Grupa: Zarejestrowani
Postów: 362
Pomógł: 0
Dołączył: 18.02.2004
Skąd: Knurów

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


U mnie to wygląda tak:

index.php:
W tym pliku tworzone są obiekty HttpRequest i HttpResponse (ktore następnie dodaje do kontenera HttpContext dla ułatwienia). Następnie tworzony jest obiekt FrontController i wywoływana jest jego metoda processRequest( iHttpRequest $Request, iHttpResponse $Response);
Oczywiście wszystkie metody tutaj zawarte można umieścić w obiekcie ApplicationBootstrap, albo czymś podobnym.

FrontController.class.php:
Metoda processRequest tworzy obiekt RequestHelper (patrz niżej). Po pobraniu od RequestHelpera polecenia, FrontController wywołuje metodę processCommand( iCommand $Command). Metoda ta tworzy nowy obiekt FilterManager. A następnie rejestruje w nim kolejne filtry, jednym z nich jest ExecutionFilter, który przyjmuje jako parametr polecenia do wykonania.

RequestHelper.class.php:
Klasa ta udostępnia metodę getCommand. Tworzony jest obiekt CommandFactory i RequestDispatcher. Wywoływana jest metoda CommandFactory->createCommand, która przyjmuje zwracane przez RequestDispatcher nazwę modułu i nazwę polecenia.

ExecutionFilter.class.php:
Klasa ta jest wykonywana przez FilterManager. Wywołuję na poleceniu (Command) metodę execute(), następnie tworzy obiekt ViewFactory, który na podstawie danych dostarczonych przez obiekt Command tworzy nowy widok. Operacje zawarte w obiekcie widoku są wykonywane, następnie dane zwrócone przez widok przekazywane są obiektowy HttpResponse.

Sama przykładowe polecenie wygląda tak:
  1. <?php
  2.  
  3. class IndexCommand extends BaseCommand
  4. {
  5. public function execute()
  6. {
  7. $Title = new String( 'Blank Index Page' );
  8. $Body = new String( 'Lorem ipsum <span class="red">dolor</span> sit amet, consectetuer adipiscing elit. Praesent in eros egestas velit congu
    e elementum. Morbi varius ante non nibh. Mauris urna ipsum, ultricies vitae, inte
    rdum egestas, molestie ac, mauris. Maecenas fermentum mollis arcu. Integer alique
    t nulla et velit. Suspendisse nibh urna, egestas faucibus, ullamcorper sit amet, 
    volutpat id, nibh. Ut arcu lorem, dignissim et, auctor et, suscipit sed, sapien. 
    Praesent sollicitudin, mauris in auctor adipiscing, diam orci ullamcorper turpis,
     non gravida augue mi vitae ante. Cras accumsan risus eget est. Maecenas iaculis,
     ligula at consequat adipiscing, ante urna eleifend velit, non tincidunt lacus ma
    uris at nulla. Nulla semper dictum felis. Fusce feugiat. Sed consequat mauris ut 
    libero gravida adipiscing. Aliquam et eros non tellus auctor euismod. Maecenas ti
    ncidunt massa nec dolor. Suspendisse potenti. Suspendisse tincidunt, tortor in po
    suere tempor, risus sapien pellentesque massa, eget ultrices ante nibh a eros. Et
    iam quis risus a turpis viverra mattis. Mauris a wisi.'
     );
  9. $Message = new Message( $Title, $Body );
  10.  
  11. $this->addModel( new String( 'Message' ), $Message );
  12.  
  13. $this->setViewHandle( new ViewHandle( new String( 'MessageView' ) ) );
  14. }
  15. }
  16.  
  17. ?>


A widok MessageView tak:
  1. <?php
  2.  
  3. class MessageView extends XHTMLView
  4. {
  5. public function execute()
  6. {
  7. $XML = new MessageXMLHelper( $this->getModel( new String( 'Message' ) ) );
  8.  
  9. $XSL = new DOMDocument;
  10. $XSL->load( OF_TEMPLATE_DIR . 'Message.xsl' );
  11.  
  12. $XSLTProcessor = new XSLTProcessor;
  13. $XSLTProcessor->importStylesheet( $XSL );
  14.  
  15. $XHTML = $XSLTProcessor->transformToDoc( $XML->execute() );
  16. $XHTML->formatOutput = true;
  17.  
  18. $this->addDocument( $XHTML );
  19. }
  20. }
  21.  
  22. ?>


Nie jest to może najprostsze rozwiązanie, ale myślę, że jest poprawne w duchu MVC.

Ten post edytował matid 5.03.2006, 10:52:21
Go to the top of the page
+Quote Post
Prph
post 5.03.2006, 16:47:05
Post #12





Grupa: Zarejestrowani
Postów: 338
Pomógł: 2
Dołączył: 4.03.2006
Skąd: Łódź

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


Witam winksmiley.jpg

Widzę, że niechętnie podchodzicie do mojej prośby winksmiley.jpg Ok, to spróbuję inaczej.

Znalazłem pewnien artykuł o budowie frameworka z wykorzystaniem MVC. Troche z niego wyciągnąłem winksmiley.jpg

Prosze mi jednak opisać, co powinno wydarzyć się w przypadku zgłoszenia rządania HTTP. Proszę podać co jest klasą, co zwykłą metodą. Co klasa robi itp winksmiley.jpg

Np:

Rządanie obsługuje Kontroler (klasa). Rozbija URI, mapuje (domyślam się, że chodzi tu kojarzenie akcji z URI z klasą akcji) itd...

Pozdrawiam,
Adrian.

Ten post edytował Prph 6.03.2006, 15:59:08
Go to the top of the page
+Quote Post
Ociu
post 7.03.2006, 14:59:34
Post #13





Grupa: Moderatorzy
Postów: 1 566
Pomógł: 37
Dołączył: 14.05.2003
Skąd: Kraków




Widze, że czekasz aż ktoś rzuci kodem.
  1. <?php
  2. public class Context {
  3. public $module;
  4. public $parameters = array();
  5. public $action;
  6.  
  7. # inne metody
  8. }
  9.  
  10. public class URLFilter {
  11. public function perform( Context $context ) {
  12. $path = explode('/', $_SERVER['PATH_INFO']);
  13.  
  14. $context->module = $path[0];
  15. $context->action = $path[1];
  16. unset($path[0]);
  17. unset($path[1]);
  18. $context->parameters = array_values($path);
  19. }
  20. }
  21.  
  22. public class FrontController {
  23. public function __construct() {}
  24. public function runApplication( Context $context ) {
  25. # uruchamianie aplikacji
  26. }
  27. }
  28. ?>
To jak zbudowana jest aplikcja, zależy od Ciebie.
Możesz mieć tak:
  1. <?php
  2. public class DeleteModel {
  3. public function news() { /* Usuwanie newsa */ }
  4. public function article() { /* Usuwanie artykułu */ }
  5. }
  6. ?>

Możesz mieć jeszcze inaczej...
Go to the top of the page
+Quote Post
Prph
post 9.03.2006, 23:24:05
Post #14





Grupa: Zarejestrowani
Postów: 338
Pomógł: 2
Dołączył: 4.03.2006
Skąd: Łódź

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


Przejrzałem kod Phienda, poczytałem dokumentacje, znowu przejrzałem pół Internetu i napisalem zupełnie od nowa framework. Ma jeszcze kupe błędów, jest mało spójny, ale mam wrażenie, że ogólne założenie udało mi się zrealizować.



Ale zastanawiam się teraz, jak zrealizować łańcuchy akcji. Może jakieś sugestie?
Go to the top of the page
+Quote Post
hwao
post 10.03.2006, 06:48:18
Post #15


Developer


Grupa: Moderatorzy
Postów: 2 844
Pomógł: 20
Dołączył: 25.11.2003
Skąd: Olkusz




czemu u Ciebie akcja wlacza Model i Widok? ohmy.gif ph34r.gif

Przy takim zalozeniu nie potrzebny Ci chyba lancuch ackji
Go to the top of the page
+Quote Post
Prph
post 10.03.2006, 07:54:17
Post #16





Grupa: Zarejestrowani
Postów: 338
Pomógł: 2
Dołączył: 4.03.2006
Skąd: Łódź

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


Yyyyy? A to co ma włączać model i widok?
Ludzie czym do ... jest akcja? Bo dla mnie to ona jest jak kontroler - zwyczajnie steruje.

  1. <?php
  2.  
  3. class SayHelloAction extends Action
  4. {
  5.  
  6. public function __construct()
  7. {
  8. $this->_setModel('HelloModelDao'); // z rodzica Action, metoda "odnajduje model i towrzy jeg obiekt
  9. $this->_setView('SayHelloHtmlView'); // j.w.
  10.  
  11. parent::__construct();
  12. }
  13.  
  14. public function run()
  15. {
  16. $arrAnswer = $this->_getModel()->getMessageForUser(); // wykonuje metode na tym modelu
  17. $this->_getView()->display($arrAnswer); // i w zasadzie przekazuje dane dla widoku
  18. }
  19. }
  20.  
  21. ?>


To nie jest poprawne rozwiązanie? I czy ono kłuci się z MVC?
Go to the top of the page
+Quote Post
sf
post 10.03.2006, 09:03:36
Post #17





Grupa: Zarejestrowani
Postów: 1 597
Pomógł: 30
Dołączył: 19.02.2003
Skąd: Tychy

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


Hyh, w ostatnim php Solutions jest fajnie napisane o frameworku. Wladowali tam kupe przykladowych wzorcow. Polecam.


--------------------
Zapraszam na mój php blog, tworzenie stron.
Go to the top of the page
+Quote Post
mike
post 10.03.2006, 09:09:42
Post #18





Grupa: Przyjaciele php.pl
Postów: 7 494
Pomógł: 302
Dołączył: 31.03.2004

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


Cytat(Prph @ 2006-03-10 07:54:17)
Yyyyy? A to co ma włączać model i widok?
Ludzie czym do ... jest akcja? Bo dla mnie to ona jest jak kontroler - zwyczajnie steruje.

Błąd.

Mylisz pojęcia i znaczenia. Do sterowania jest kontroler, to on na podstawie żądania uruchamia akcję.
A ona ma za zadanie tylko i wyłącznie wykonać jakąś operację i kropka. Akcja niczym nie steruje.
Go to the top of the page
+Quote Post
Martio
post 10.03.2006, 12:28:05
Post #19





Grupa: Zablokowani
Postów: 167
Pomógł: 2
Dołączył: 15.02.2004

Ostrzeżenie: (30%)
XX---


Cytat(mike_mech @ 2006-03-10 10:09:42)
Hyh, w ostatnim php Solutions jest fajnie napisane o frameworku. Wladowali tam kupe przykladowych wzorcow.

(...)

Mylisz pojęcia i znaczenia. Do sterowania jest kontroler, to on na podstawie żądania uruchamia akcję.

Mam ten artykuł z php Solutions. Jest dobry, ale nic nie mówi o najważniejszym dla nas w tym przypadku wzorcu: MVC.

Ja również w innym wątku nie mogłem się doprosić wyjaśnienia co to jest akcja i za co opowiada!

Wzorzec MVC mówi o modelu, widoku i kontrolerze. Teoretycznie w tym wzorcu nie ma mowy o akcji...

Kod
$kontroler = new KontrolerMVC();
$model = new ModelMVC();
$widok = new WidokMVC();

$kontroler->wybierzModel($_GET['model']);
$widok->dane($model->pobierz());
$widok->wyswietl($model->widok());


To rozwiązanie jest dobre dla jednej operacji (akcji). Jednak jak powinna wyglądać implementacja tego wzorca w przypadku wielu akcji do realizacji?

Taki przykład. Do realizacji jest:
- zapisanie danych z formularza
- wyświetlenie właściwego komunikatu (czy powiodło się?)
- pobranie danych do wyświetlenia na stronie

Mamy 3 operacje. Jak powinna teraz wyglądać implementacja tego wzorca. Tylko proszę nie odsyłać mnie do żadnego frameworka. Widziałem już dziesiątki przykładów, jednak żaden nie trzymał się zasad wzorca MVC.
Go to the top of the page
+Quote Post
hawk
post 10.03.2006, 14:51:59
Post #20





Grupa: Zarejestrowani
Postów: 521
Pomógł: 0
Dołączył: 3.11.2003
Skąd: 3city

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


Żaden nie trzymał się zasad wzorca MVC? Bo to zależy, jak autor danego frameworka interpretuje te zasady. Jakby było to takie oczywiste, to by był tylko jeden framework i koniec dyskusji. Zamiast tego masz wiele frameworków, i jeszcze więcej koncepcji implementacji tego wzorca. Więc nie pytaj "czy to jest zgodne z MVC", tylko "dlaczego to jest zrobione tak, a nie inaczej". I dlaczego to, że jakiś framework nie trzyma się zasad MVC, jest wadą?

Ale wracając do twojego przykładu:
1. Na początku będzie jakaś implementacja kontrolera, pewnie FrontController, która w jakiś sposób dojdzie do wniosku, którą akcję chce wykonać.
2. Akcja pobierze dane z formularza (albo bezpośrednio z $_POST, albo z jakiegoś HttpRequesta, albo jeszcze inaczej), stworzy odpowiedni obiekt warstwy modelu i za jego pomocą wykona update
3. Teraz albo akcja oddaje sterowanie do kontrolera, który dochodzi do wniosku, że należy wykonać odpowiedni widok, lub akcja sama odpala potrzebny widok.
4. Widok wypluwa HTMLa.

Muszę się też przyczepić do modelu. Po prostu szał mnie bierze, kiedy widzę $model = new Model(). Model to jest warstwa, a nie klasa. Rysujesz sobie, co aplikacja ma robić, i tworzysz z tego ładny diagram klas, bez żadnego HTTP, HTML, kontrolerów, akcji i całego tego balastu.
Go to the top of the page
+Quote Post

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

 



RSS Wersja Lo-Fi Aktualny czas: 16.04.2024 - 07:17