|
15 Červen 2010
Posted in
Dokumentace -
Komponenty
Minule jsme skončili u zobrazení seznamu zadaných dat, jenomže jsme ještě v něm neměli co zobrazit. Toto dneska hned napravíme, protože si něco povíme o tvorbě formuláře pro zadávání dat a skončíme vytvořením instalačního balíčku, abychom si mohli všechno pohromadě hezky vyzkoušet. V příkladu opět použijeme sekce našeho fóra.
Controller
Začít musíme úpravou controlleru, který jsme vytvořili v předchozím dílu. Tento dostane následující podobu
jimport('joomla.application.component.controller'); class simpleForumControllersections extends JController { private $_url=null; private $_model=null; parent::__construct($config); $this->_url='index.php?option=com_simpleforum&controller=sections'; $this->_model=$this->getModel('section'); } function display() { JRequest::setVar('view','sections'); parent::display(); } function edit() { JRequest::setVar('view','section'); JRequest::setVar('layout','form'); JRequest::setVar('hidemainmenu',1); parent::display(); } function save() { JRequest::checkToken() or jexit('Invalid token'); $error=""; if(!$this->_model->store(JRequest::get('post'))) { $msg=$this->_model->getError(); $error='error'; } else { } $this->_model->checkin(); $this->setRedirect($this->_url,$msg,$error); } function cancel() { $this->_model->checkin(); $this->setRedirect($this->_url); } function remove() { JRequest::checkToken() or jexit('Invalid token'); $msg=""; $error=""; if(!$this->_model->delete()) { $msg=$this->_model->getError(); $error='error'; } $this->setRedirect($this->_url,$msg,$error); } }
Do konstruktoru třídy jsme nejprve připravili dvě proměnné a to adresu kam se má provést přesměrování po uložení, stornování, nebo vymazání sekce(proměnná _url) a také objekt modelu, který budeme dále potřebovat(proměnná _model). První novou funkcí je funkce edit, kterou si připravíme editaci článku. V podstatě je podobná funkci display z minulého dílu, jenom v ní nastavujeme o něco více proměnných. Mimo proměnné view nastavené na section se jedná o typ zobrazení, které je pro editaci je formulář - tedy form. Jako poslední si nastavením proměnné hidemainmenu na hodnotu 1, zablokujeme horní menu, aby uživatel nemohl během editace položky odejít bez jejího uložení, nebo stornování. Následně opět zavoláme funkcí předka pro zobrazení dat.
Pokračujeme funkcí pro uložení editované sekce. Na začátku si otestujeme jestli se nejedná a CSRF podvrh pomocí funkce checkToken() třídy JRequest. Tato metoda kontroluje token, který vkládáme do formuláře, jak si později ukážeme. V případě nesouhlasu tokenu zpracování dat ukončíme se zprávou Invalid token, jinak pokračujeme zavoláním metody modelu, kterou si vytvoříme za chvíli. Jako parametr jí předáme POST data formuláře, které získáme pomocí metody JRequest::get(), která přijímá jako parametr typ požadavku, tedy GET, POST, FILES, COOKIE, ENV a SERVER psané malými písmeny jako textový řetězec tedy v uvozovkách. Pokud nezadáte žádný typ, použije se jako výchozí REQUEST. V případě chyby si do proměnné msg uložíme chybové hlášení, které si v modelu vytvoříme. V opačném případě proběhlo uložení dat v pořádku a oznámíme to uživateli.
Před přesměrováním na zobrazení seznamu metodou setRedirect() controlleru ještě provedeme odemčení záznamu(metoda checkin() modelu). Opačná operace - zamykání - se řeší v zobrazení modelu. Do metody pro přesměrování přijdou jako parametry adresa, na kterou se má přesměrování provést a také zpráva, která se má uživateli zobrazit. V případě chyby je zde ještě třetí parametr(řetězec error), který indikuje, že se má text zobrazit červeně jako upozornění, že se něco nepovedlo.
V případě stornování editace článku se zavolá metoda cancel(), ve které stačí pouze provést odemčení záznamu a přesměrování na tabulku s daty.
Poslední metoda(remove()) se týká vymazání záznamu. Zde pouze zavoláme metodu modelu pro vymazání dat a v případě chyby nastavíme odpovídající proměnné a provedeme přesměrování.
Model
Tímto bychom měli to jednodušší hotové a teď přichází na řadu opět model, kde uvaříme to hlavní.
jimport('joomla.application.component.model'); class simpleforumModelsection extends JModel { private $_cid=null; private $_id=null; private $_user=null; private $_table=null; function __construct() { parent::__construct(); $this->_id=$this->_cid[0]; $this->_user=JFactory::getUser(); $this->_table=$this->getTable('section'); } function getData() { $this->_table->load($this->_id); return $this->_table; } function store($datas) { $this->_table->bind($datas); $this->_table->id=$this->_id; if(!$this->_table->store()) { $this->setError($this->_db->stderr(true)); return false; } return true; } function delete() { $query="DELETE FROM ".$this->_table->getTableName()." \n"; $this->_db->setQuery($query); if(!$this->_db->query()) { $this->setError($this->_db->stderr(true)); return false; } return true; } function checkout() { if(!$this->_table->checkout($this->_user->get('id'),$this->_id)) { $this->setError($this->_db->stderr(true)); return false; } return true; } function checkin() { if(!$this->_table->checkin($this->_id)) { $this->setError($this->_db->stderr(true)); return false; } return true; } }
V modelu si pro začátek v konstruktoru po volání konstruktoru předka(je důležité jako první zavolat konstruktor předka) připravíme čtyři proměnné, které budeme později potřebovat. Jedná se i _cid, do které uložíme seznam vybraných položek(ty které byly zaškrtnuté v tabulce s daty). Toto pole získáme metodou JRequest::getVar(), což je obecná metoda pro získání proměnné, která potřebuje čtyři parametry a to popořadě jméno proměnné, výchozí hodnota, typ požadavku(stejný jako v metodě JRequest::get()) a požadovaný typ proměnné v tomto případě array jelikož chceme pole. Mimo varianty pro získání pole existují zkratkové metody jako getInt(), getString(), ..., atd, které pochopitelně přijímají pouze 3 parametry. Jelikož více zaškrtnutých položek využijeme pouze u mazání položek, uložíme si do _id první položku z pole zaškrtnutých položek. Následně získáme aktuálně přihlášeného uživatele a objekt tabulky sekcí.
Všechno máme připravené, takže se můžeme pustit do hlavní práce. Začneme získáním dat pro formulář pomocí metody getData(). U těchto metod je nutné dodržet syntaxi pojmenování, které musí vypadat getNeco(), kdy pak data získáme v pohledu pomocí metody get('neco') v tomto případě get('data'). V tomto jednoduchém případě nic složitého řešit nemusíme, pouze načteme vybraný záznam tabulky(metoda load()) a celou tabulku použijeme jako návratovou hodnotu metody. Rovněž si všimněte metody checkout(), kde provádíme zamčení záznamu. Metoda tabulky potřebuje dvě proměnné a to id uživatele editujícího položku a id položky. Velmi podobná je i odemykací metoda checkin(), která potřebuje pouze id editovaného záznamu.
Zbývá vyřešit pouze uložení a vymazání záznamů. O uložení dat se stará metoda store(). Namapování dat na objekt tabulky za nás zařídí metoda bind() s parametrem výsledků požadavku. Následující řádek možná považujete za zbytečný, ale všimněte si, že v administraci Joomly se pro identifikaci záznamů používá pole cid[], takže i ve formuláři je číslo upravovaného záznamu uloženo právě v této proměnné. Proto musíme id záznamu přiřadit ručně. Data uložíme pomocí store(), která v případě neúspěchu vrací false(stejně jako metody checkout() a checkin() objektu _table). Čehož využijeme a v případě chyby si hlášku databáze uložíme do modelu, ze kterého jí, díky tomu, že je v Joomle použit návrhový vzor Singleton(vždy existuje pouze jedna instance objektu), můžeme získat v controlleru, jak jsme si dříve ukázali a rovněž vrátíme hodnotu false.
Na mazání záznamů si ukážeme použití SQL dotazu v Joomle. V textu dotazu si můžete pouze všimnout, že pomocí funkce PHP implode získáme všechny zaškrtnuté položky. Samotný text SQL dotazu předáme pomocí objektu databáze _db, který nám třída JModel, ze které dědíme předpřipravila. V případě neúspěchu dotazu si opět uložíme chybový výstup databáze, který nám vypíše metoda stderr(), kde si parametrem true zajistíme, že se ve výpisu objeví také prováděný SQL dotaz.
Pohled
jimport('joomla.application.component.view'); class simpleforumViewsection extends JView { function display($tpl=null) { $data=$this->get('data'); if(JTable::isCheckedOut(JFactory::getUser()->get('id'),$data->checked_out)) { JFactory::getApplication()->redirect('index.php?option=com_simpleforum&controller=sections',JText::_('This item is currently being edited by another user')); return false; } $this->getModel()->checkout(); $this->assignRef('data',$data); JToolbarHElper::save(); JtoolbarHelper::cancel(); parent::display($tpl); } }
Pohled zařídíme jak víme z minula implementací metody display(). V ní si získáme data editovaného záznamu(proměnná data), aktuálně přihlášeného uživatele a uložíme je do proměnné, abychom v následující podmínce mohli použít hodnotu pole checked_out, ve které máme uložené id uživatele aktuálně editujícího záznam. Toto společně s id přihlášeného uživatele předáme do metody JTable::isChechedOut(), který neprovádí pouze jednoduché porovnání obou čísel, nýbrž také zjišťuje věci jako jestli je uživatel uložený v checked_out přihlášený. Jestliže je zjišťěno, že je daný záznam upravován, provedeme pomocí metody redirect, který získáme z objektu aplikace(který pro změnu získáme z užitečné třídy Továrny - JFactory), přesměrování na tabulku dat se zprávou, že je záznam právě editován jiným uživatelem.
Jinak provedeme zamčení záznamu(neboli uložíme id aktuálního uživatele do pole checked_out) a následně přířadíme data do pohledu(metoda assignRef()). Zbývá ještě vytvořit titulek a ikonky pro uložení a stornování editace položky.
Zobrazení
Již nám nic nebrání, abychom zpracovaná data konečně zobrazili uživateli - vytvoříme formulář.
<form action="index.php" method="post" name="adminForm" id="adminForm">
<fieldset class="adminform">
<legend><?php echo JText::_('Details'); ?></legend>
<table class="adminform">
<tr>
<td>
<?php echo JText::_('Title'); ?>
</td>
<td>
<input type="text" class="textarea" name="title" id="title" value="<?php echo $this->data->title; ?>" />
</td>
</tr>
</table>
</fieldset>
<input type="hidden" name="option" value="com_simpleforum" />
<input type="hidden" name="controller" value="sections" />
<input type="hidden" name="task" value="" />
<input type="hidden" name="hidemainmenu" value="1" />
<input type="hidden" name="cid[]" value="<?php echo $this->data->id; ?>" />
<?php echo JHTML::_('form.token'); ?>
</form>
Formulář se musí jmenovat adminForm, protože jinak by nefungoval js skript zajišťující odeslání dat po stisknutí tlačítek. Další povinnou věcí jsou skrytá pole option, controller a task kam popořadě uložíme název komponenty, název controlleru a pole task necháme prázdné. O jeho vyplnění se postará js Joomly při odeslání formuláře. Pole hidemainmenu je zde rovněž z důvodu js Joomly. O hodnotě cid[] jsem se již zmiňoval při popisu modelu. Úplně vespod najdeme kód starající se o vygenerování klíče proti CSRF, který je oveřeován v controlleru. V hlavní části se nachází hlavní tabulka pro zadávání dat. Do parametru value inputu zadáváme hodnotu uloženého záznamu. V případě, že se jedná o nový záznam, tak je hodnota artibutu $this->data->title prázná, takže toto nemusíme řešit a máme jeden typ formuláře jak pro editaci existujícího záznamu, tak pro zadání nového. Poslední věc, která zde stojí za zmínku je, že pokud chceme využívat automatického napojení dat formuláře na tabulku (metoda bind() tabulky), tak samozřejmě musejí názvy vstupních polí odpovídat názvu polí v databázi
Příště
Tak tentokrát se na instalaci nedostalo, ale příště už si skutečně instalační balíček vytvoříme včetně české lokalizace naší komponenty.
Články


