nejlepší konstrukce pro formulář „výběr dat->úprava dat->uložení dat a zobrazení úspěchu“
- Ofi
- Člen | 13
Mohl by mi někdo poradit jak nejlépe sestavit tuto konstrukci/v čem je
špatná moje verze?:
1.formulář – výběr řádku z databáze, který chci upravit (řádku
odpovídá objekt Description)
2.následuje další formulář obsahuje data z vybraného řádku volné
k editaci
3.následuje uložení
já to udělal takto(a moc se mi to nelíbí):
šablona description při načtení zobrazí widget selectForm (bod 1), po jeho
odeslání se v redirectu té samé šabloně předá seoUrl vybraného řádku
v db… vzhledem k tomu, že po redirectu se nevolá action, tak v render si
šáhnu do db pro potřebný řádek, pošlu ho dál do šablony + uložím do
proměnné $this->activeItem.
šablona pokud dostane objekt, zobrazí widget editDescriptionForm (bod 2) ..
createComponentEditDescriptionForm si vezme data z $this->activeItem a
použije je jako hodnoty do formuláře, pole které se neupravují jsou
hidden.. celé to musí být ošetřeno jestli $this->activeObject je
object.
Po odeslání vytáhnu data z formuláře a vytvořím objekt Description a
zavolám metodu save() která už se postará o update, opět přesměruji na
tu samou šablonu, která zobrazí flash message a opět úvodní výběr
řádku z db..
toto řešení se mi zdá těžkopádné, zkoušel jsem to vyřešit tak, aby byl ten objekt v presenteru stále a já jen u něj pomocí formulářů změním jeden parametr a uložím, jenže se mi vždycky po submitu smazal a vyhodilo mi to hlášku „caling bla bla of a non-object…“ zkoušel jsem i static i persistent.. bez úspěchu..
- Ani
- Člen | 226
To moc nechápu, ale tak udělej si dvě view (něco jako selectrow a editrow) prvně zobrazíš ten select se selectForm, po provedení provedeš redirect na ten editrow, jako parametr předáš id toho řádku. V tom editrow si to vytáhneš z DB, zedituješ a přesměruješ s flash message. Můžeš tam dát dvě tlačítka a podle těch to přesměruješ na danej view.
- Ofi
- Člen | 13
v podstatě mi na tom nevoní fakt, že dvakrát budu tahat jeden a ten samý řádek z databáze a tříkrát budu dělat stejný objekt… poprvé při načtení dat do selectu a podruhé při načtení dat pro edit a třetí vytvoření objektu bude při převedení dat z formuláře pro uložení… a to bych vlastně tahal třikrát z db, kdybych si neudělal v presenteru tu pomocnou proměnnou…
já vím, že časové to je nula k nule, ale není to „čisté“, není to „chytré“… prostě mi to nesedí a nevím jak jinak to řešit…
nechápu proč mi nefungovalo použití statické proměnné presenteru…
Editoval Ofi (8. 9. 2010 23:33)
- Patrik Votoček
- Člen | 2221
Obávám se že tohle ani jinak řešít nebude… PHP „neumí“ mezi jednotlivímy požadavky přenášet oběkty…
Můžeš to buď „kešovat“ nebo ukládat do session a nebo se smířít s tím že 3 různé požadavky šahaní 3× do DB…
- Ofi
- Člen | 13
keš je v nette souborová nemýlím-li se, takže je to buď db nebo file, sessions mě napadly také, k jejich vyzkoušení jsem se ještě nedostal…
já si ve všech případech tahám všechno, protože to má 4 sloupce a
z tech bych vždycky tahal 2–4…
takhle vypadá příslušný presenter..
class Admin_DefaultPresenter extends Admin_SecuredPresenter {
private $contentManager = NULL;
private $activeItem = NULL;
public function actionLogout() {
Environment::getUser()->logout();
$this->flashMessage('Právě jste sa odlásili z administrace.');
$this->redirect('Auth:login');
}
public function actionDescrtiption() {
}
public function renderDescription($itemSelected = NULL) {
$this->activeItem = $this->model->getDescription($itemSelected);
$this->template->description = $this->activeItem;
$this->template->itemSelected = $itemSelected;
}
public function createComponentEditDescriptionForm() {
$form = new AppForm();
$form->addHidden("id");
$form->addHidden("menuItem");
$form->addHidden("seoUrl");
$form->addTextArea("description", "Popis: ");
$form->addSubmit("send", "Změnit popis");
if(is_object($this->activeItem)) {
$form->setValues(array('description'=>$this->activeItem->description,
'id'=>$this->activeItem->id,
'menuItem'=>$this->activeItem->menuItem,
'seoUrl'=>$this->activeItem->seoUrl
));
}
$form->onSubmit[] = callback($this, 'processEditDescriptionForm');
return $form;
}
public function processEditDescriptionForm(Appform $form) {
if($form['send']->isSubmittedBy()) {
$values = $form->getValues();
$properties = array();
foreach($values as $key=>$val) {
$properties[$key]=$val;
}
$updatedItem = new Description($properties);
$updatedItem->save();
$this->flashMessage('Popis byl úspěšně změněn.');
$this->redirect('Default:description');
}
}
public function createComponentSelectDescription() {
$form = new AppForm();
$descriptions = $this->model->getDescriptions();
$items = array();
foreach ($descriptions as $d) {
$items[$d->seoUrl] = $d->menuItem;
}
$form->addSelect('description', 'Položka: ', $items);
$form->addSubmit('send', 'Vybrat');
$form->onSubmit[] = callback($this, 'processSelectDescription');
return $form;
}
public function processSelectDescription($form) {
if($form['send']->isSubmittedBy()) {
$values = $form->getValues();
$this->redirect('description', $values['description']);
}
}
public function getModel() {
if(!isset($this->contentManager))
$this->contentManager = new ContentManager;
return $this->contentManager;
}
}
a takhle příslušná šablona:
{block content}
<h3>Vyberte, pro kterou položku si přejete změnit popis:</h3>
{widget selectDescription}
{if isset($itemSelected) && $itemSelected != NULL}
<h3>
Úprava popisu:
</h3>
{widget editDescriptionForm}
{/if}
{/block}
čtení flash message mám v @layout takže o to se v téhle šabloně nestarám..
- Ani
- Člen | 226
Přijde mi to celý zbytečně komplikovaně řešený.
- Za cenu úspory dotazu do db, tam děláš různý iterace přes celý pole (ta v processEditDescriptionForm mi přijde obzvlášť nelogická).
- V těch process metodách nemusíš dělat $form[‚send‘]->isSubmittedBy(), když to máš jako appform s jedním tlačítkem (raději koukni do dokumentace).
- Stejně tak předávání těch hidden polí je pěkně kostrbaté a kromě id, nejspíš zbytečné.
- V renderDescription předáváš do šablony ten objekt, ale v ní ho pak nepoužíváš.
<?php
public function renderDescription($itemSelected = NULL) {
$activeItem = $this->model->getDescription($itemSelected);
$this->template->description = $activeItem; // to tam potrebujes?
$this->template->itemSelected = $itemSelected;
if ($itemSelected != null)
$this['editDescriptionForm']->setDefaults($activeItem); //tady to mozna bude chtit upravit na array(id => $activeItem->id, description => $activeItem->description)
}
public function createComponentEditDescriptionForm() {
$form = new AppForm();
$form->addHidden("id");
$form->addTextArea("description", "Popis: ");
$form->addSubmit("send", "Změnit popis");
$form->onSubmit[] = callback($this, 'processEditDescriptionForm');
return $form;
}
public function processEditDescriptionForm(Appform $form) {
$values = $form->getValues();
$updatedItem = new Description($values);
$updatedItem->save();
$this->flashMessage('Popis byl úspěšně změněn.');
$this->redirect('Default:description');
}
}
public function createComponentSelectDescription() {
$form = new AppForm();
$descriptions = $this->model->getDescriptionsPairs();
$form->addSelect('description', 'Položka: ', $descriptions);
$form->addSubmit('send', 'Vybrat');
$form->onSubmit[] = callback($this, 'processSelectDescription');
return $form;
}
public function processSelectDescription($form) {
$values = $form->getValues();
$this->redirect('description', $values['description']);
}
}
?>
Takhle potřebuješ dva dotazy (celý jeden řádek) a pak druhý jako všechny řádky…
Editoval Ani (9. 9. 2010 19:25)
- Ofi
- Člen | 13
dnes dopoledne jsem refaktoroval frontend a:
Ani napsal(a):
Přijde mi to celý zbytečně komplikovaně řešený.
- Za cenu úspory dotazu do db, tam děláš různý iterace přes celý pole (ta v processEditDescriptionForm mi přijde obzvlášť nelogická).
už není – nevím proč jsem jí tam dával :D
- V těch process metodách nemusíš dělat $form[‚send‘]->isSubmittedBy(), když to máš jako appform s jedním tlačítkem (raději koukni do dokumentace).
to jsem nevěděl… čili to ještě změním
- Stejně tak předávání těch hidden polí je pěkně kostrbaté a kromě id, nejspíš zbytečné.
ano to už tam také nemám krom toho id…
- V renderDescription předáváš do šablony ten objekt, ale v ní ho pak nepoužíváš.
také už je minulost, všiml jsem si toho…
nakonec jsem to zjednodušil, ale i tak.. teď mě to trápí, protože až přijde nějaký projekt kde si budu muset znovu a znovu sahat pro daleko větí objem dat tak si s tím nebudu vědět rady…