1) Forwardowanie akcji.
Forwardowanie akcji, jest bardzo przydatną rzeczą w każdym frameworku, ale nie spotkałem się jeszcze z forwardowaniem na kilka akcji 'z góry', a myśle że to jest dośc przydatne, bo możemy poprzez jedną akcje zaplanować co i jak sie stanie. Wiadomo, że jeśli mamy akcje 'dodajNewsa' to rzeby zrobić 'dodajNewsaiPokaz' musimy tworzyć nową akcję, tak samo 'dodajiWyloguj' , a co bedzie jak zrobimy 'dodajWylogujPrzejdznaStroneGlowna' ? to jest tworzenie akcji, które już mamy(np. wyloguj) i dodawanie do nich jednej linijki (stare proceduralne kopiowanie kodu?). A jak mamy forwarodwanie na kilka akcji z 'góry' to jest super bo tworzymy sobie tylko 'Dodaj' 'Wyswietl' 'Wyloguj' 'PrzejdzNaStroneGlowna'. (Może przykład wyłuskany, ale nie umiem na szbyko wymyśleć innego). Ja rozwiązałem to sobie w taki sposób, że mam klase 'ActionCollectioner', która implementuje sobie Iterator :
<?php class ActionCollectioner implements Iterator { private $_aActions; private $_bValidIterationPointer = true; public function __construct(){ } { } { } { } { $this->_bValidIterationPointer = false; else $this->_bValidIterationPointer = true; } public function valid() { return $this->_bValidIterationPointer; } public function pushAct(DispatcherToken $oDispatcherToken) { if(!($oDispatcherToken instanceof DispatcherToken)) { throw new ActionCollectionerException('Parameter You given to pushObj must be instance of DispatcherToken.'); } } } ?>
w Routerze umieściłem sobie pętlę foreach(), do której podaje mój ActionCollectioner:
<?php class Router Implements IRouter { private $_sURI = null; private $_aParams = null; private $_sCtrlName = null; private $_sActName = null; private $_oDispatcher = null; private $_oActionCollectioner = null; public function __construct(Dispatcher $oDispatcher, ActionCollectioner $oActionCollectioner) { $this->_sURI = $this->_formatQuery(); $this->_oDispatcher = $oDispatcher; $this->_oActionCollectioner = $oActionCollectioner; } private function _formatQuery(){ } public function route() { } $this->_sCtrlName = $this->_aParams[0]; { $this->_sCtrlName = _DEFAULT_CTRL_NAME; $this->_sActName = _DEFAULT_ACT_NAME; } for ($i=2; $i<sizeof($this->_aParams); $i=$i+2) { } $oCurrentAction = new DispatcherToken($this->_sCtrlName, $this->_sActName, $aActParams); //----------------------------------------------------------tutaj klade pierwsza akcje do mojego kontenera $this->_oActionCollectioner->pushAct($oCurrentAction); foreach ($this->_oActionCollectioner as $iKey => $oActionToken) { $oCurrentAction = $oActionToken; if (!$this->_oDispatcher->isDispatchable($oCurrentAction)) { $oCurrentAction = new DispatcherToken('Error404', _DEFAULT_ACT_NAME, $aActParams); } if (!$this->_oDispatcher->isDispatchable($oCurrentAction)) { throw new RouterException('Request could not be mapped to a route and Error404 Controller has not been crea
ted.'); } $this->_oDispatcher->executeAction($oCurrentAction); } return $oCurrentAction; } } ?>
Dispatcher odpala kontroller akcji, a w nim możemy skorzystać z metody rodzica pushNextAction, która odwołuje sie do FrontController'a (który jedyny we frameworku jest singletonem) trzymającego dostęp do ActionCollectioner:
<?php class DoSmth extends Controller { public function _index(){ $oView = $this->getView('DoSmth'); $oModel = $this->getModel('DoSmth'); $oView->setAttribute('all',$oModel->showMeAll()); $oView->setAttribute('imie', $this->imie); $this->pushNextAction('SaveNews'); $this->pushNextAction('Logout'); return($oView); } ?>
oczywiście pokusiło mnie żeby sprawdzić, co się dzieje jeśli przekieruje akcje z widowkiem, na akcje z widokiem - i co wyświetla sie tylko pierwsza akcja z widowkiem - czemu - zastosowanie funkcji require_once() w systemie, który przetwarza widok (pokazuje tylko raz, a że mam Template i i subTemplate - czyli główny szablon www i 'srodkowa tresc' zasysa raz Main.php i już dalej nie). Dodam, że korzystam z szablonów php. Jedyne co pozostaje to stworzyć MAX_FORWARDS, aby akcje bez widoku sie nie zapętlały.
2) Kolejna sprawa - Model.
Zauważyłem, że w niektórych frameworkach Baze danych rejestruje się we FrontControllerze... Pyanie po co, to chyba gryzie się z ideologią MVC (może jest wygodne dla programisty, który tworzy aplikacje na tym frameworku, ale mało elastyczne). Ja postanowiłem problem rozwiązać w inny sposób, a mianowicie:
mam rodzica dla każdego modelu:
<?php abstract class Model { protected $_oDataSource; { if(!NyssSystem::getLibraryPath($sSourceClassName)){ if(!NyssSystem::fileIsReadable($sPath)) throw new ModelException('File '.$sPath.' is not readable'); require_once($sSourceFile); if(!class_exists($sSourceClassName)) throw new ModelException('Can not create DataSource, class does not exist'); $this->_oDataSource = new $sSourceClassName($aParameters); } else $this->_oDataSource = new $sSourceClassName($aParameters); } protected function getDataSourceParameters() { require_once(_DIR_APPLICATION.'_configure.php'); return($aDataSourceParameters); } } } ?>
dodam iż funkcja setDataSource wygląda takowo iż używam magicznego __autoload() więc nie trzeba podawać ścieżki do DataSource, aby działało - wystarczy umieścić go w katalogu core, który na początku jest skanowany (proszę mi nie mówić, że spowalnia to aplikacje, bo czas wykonania różni sie o okolo 0.005 s, a jest bardzo wygodne) No dobra, ale do rzeczy teraz mam model :
<?php class DoSmthModel extends Model { public function __construct() { $this->setDataSource('DatabaseMySQL',$this->getDataSourceParameters()); } public function showMeAll() { $oMysql = $this->_oDataSource; $oMysql->query('SELECT * from costam WHERE option_id=1'); return($oMysql->fetch()); } } ?>
i myśle, że to jest rozwiązanie optymalne, bo jak zeche korzystać z pliku, a nie z bazy to robie:
<?php $this->setDataSource('FileReader',$this->getDataSourceParameters()); ?>
No tak więc to by było na tyle, proszę o komentarze do moich pomysłów i z góry dziękuję za pomoc. Pozdrawiam... Kamil