AppForm a metoda GET – kde je chyba

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
BigCharlie
Člen | 284
+
0
-

Ahoj,

prokousávám se těmi nejjednoduššími základy a narazil jsem na tohle. Jednoduchý příklad, přepsaný de facto z dokumentace. Pokud ho použiju tak, jak je napsaný, vše funguje jak má. Pokud formuláři nastavím metodu get (odstraněním komentáře), obslužné handlery jako by nebyly. PHP 5.2.6, Nette revize 181.

Kde je chyba? Zřejmě očekávám něco, co bych neměl? Díky za (obrazné) nakopnutí…

<?php
class DefaultPresenter extends BasePresenter
{
	/** @var Form */
	public $form;


	public function actionDefault()
	{
		$form = new AppForm($this, 'formSearch');
		//$form->setMethod('get');
		$form->addText('q', 'Hledaný výraz:');
		$form->addSubmit('search', 'Hledej')
				->onClick[] = array($this, 'SearchClicked');

		$form->onSubmit[] = array($this, 'FormSubmitted');
		$this->form = $this->template->form = $form;
	}


	// obslužné handlery:
	public function SearchClicked(SubmitButton $button)
	{
		echo "odesláno použitím search";
	}

	public function FormSubmitted(Form $form)
	{
		echo "odesláno";
	}
}
?>
phx
Člen | 651
+
0
-

Na toto jsem narazil jiz davno. Problem je ze se v URL nepredava parametr do=submit nebo tak nejak (jukni v post do skrytych poli). FOrmulare s GET mi akorat zlobi. Resil jsem to rucne pridanim onoho parametru do hidden pole, ale neni to systemove. Dalsi neblaha vec je, ze get formulare znici aktualni GET parametry stranky. Proste to prelpeskne tim co je ve formulari a tim co je aktualne v URL se nezabyva:( Tusim ze jsem na to jiz nekdy upozornoval, ale zatim bez efektu. Asi to upadlo v zapomneni.

Priklad:

  • pozadavek na stranka.php?param=bagr
  • na ni je form odeslinany GET metodou (napr ten od BigCharlie)
  • vysledny dotaz je stranka.php?q=neco&search=Hledej
  • parametr param je znicen:(
blacksun
Člen | 177
+
0
-

To je přece běžné chování, které nijak nesouvisí s Nette. Když mám stránku neco.php?novyrok=1 a na ni odkaz na neco.php?auto=bmw, tak je jasné, že po přechodu tím odkazem se mi nepředá parametr novyrok. Odkazy a formuláře s metodou GET funguji stejně. Takže pokud chcete, aby se původní parametry předávaly, musí se nastrkat do hidden polí a nebo do action parametru formuláře.

paranoiq
Člen | 392
+
0
-

úplně běžné to není a vlastně mě to dost překvapilo.
phx to špatně popisuje. jde o to, že:

  • mám stránku dejme tomu stranka.php?param=bagr (to je ošem naprosto irelevantní!)
  • formulář má definovanou method=„GET“
  • formulář má definovanou action=„stranka.php?do=form-submit“ (a to je důležité!)
  • výsledný dotaz je dejme tomu stranka.php?q=neco&search=Hledej – parametr do je znicen

při submitu bych očekával, že se ostatní parametry (z formulářových polí) dosadí za kompletní action, ale tak tomu není. místo toho prohlížeče napřed odstraní z action parametry a až poté tam dosadí hodnoty z formulářových polí. to je v rozporu s tím, že při odesílání metodou POST prohlížeče action nijak neupravují (a parametry tudíž neodstraní)

Editoval paranoiq (1. 1. 2009 20:35)

piler
Člen | 111
+
0
-

paranoiq napsal(a):

úplně běžné to není a vlastně mě to dost překvapilo.
phx to špatně popisuje. jde o to, že:

  • mám stránku dejme tomu stranka.php?param=bagr (to je ošem naprosto irelevantní!)
  • formulář má definovanou method=„GET“
  • formulář má definovanou action=„stranka.php?do=form-submit“ (a to je důležité!)
  • výsledný dotaz je dejme tomu stranka.php?q=neco&search=Hledej – parametr do je znicen

při submitu bych očekával, že se ostatní parametry (z formulářových polí) dosadí za kompletní action, ale tak tomu není. místo toho prohlížeče napřed odstraní z action parametry a až poté tam dosadí hodnoty z formulářových polí. to je v rozporu s tím, že při odesílání metodou POST prohlížeče action nijak neupravují (a parametry tudíž neodstraní)

Ale to predsa nie je chyba nette, alebo forms…alebo sa mylim? Ked pouzivam formular s metodou GET, tak vsetky get parametre musim pridat do hidden pola aj tie co by som rad preniesol v ACTION

Priklad bez NETTE:

<?
print_r($_GET);
?>
<form method="get" action="stranka.php?do=form-submit">
<input type="text" name="name" />
<input type="submit" value="SEND" />
</form>

do parameter sa neprenesie…musi byt v hidden poli, tak ako aj ostatne existujuce get parametre :(

paranoiq
Člen | 392
+
0
-

samozřejmě chyba nette to není. na vině jsou prohlížeče. nejspíše to bude ‚feature‘

Tomik
Nette Evangelist | 485
+
0
-

Už jdu spát a jen tak ze zvyku projíždím diskusi – a tudíž jsem třeba mimo mísu, ale nepomůže udělat ten parametr perzistetní? :)

BigCharlie
Člen | 284
+
0
-

Ať tak či tak, jedná se v tom případě zřejmě o chybu. Uvidím, zda se David ozve a případně objasní. Pokud ano, bylo by dobré tohle vlákno přesunout do chyb. Pokud ne, záložím tam nové a na tohle odkážu.

Zkoušel jsem také přidat hidden pole, ale nevedlo to k úspěchu, odpovědí bylo vždy BadSignalException.

Editoval BigCharlie (2. 1. 2009 10:48)

phx
Člen | 651
+
0
-

Problem jsem asi popsal nepresne. Mam stranku s persitentnim parametrem, kterou nette spravne doplni do action=„stranka.php?parametr=hodnota“, ale jelikoz je metoda=„get“ tak prohlizec parametry v action znici. Ocekaval bych chovani formularu takove, ze kdyz je metoda GET tak automaticky persistentni parametry nahazi do hiddne poli samotne nette a nemusim se o to stara. To je ta chyba co myslim.

Je to pochopitelnejsi?

David Grudl
Nette Core | 8282
+
0
-

phx napsal(a):

Ocekaval bych chovani formularu takove, ze kdyz je metoda GET tak automaticky persistentni parametry nahazi do hiddne poli samotne nette a nemusim se o to stara. To je ta chyba co myslim.

Souhlasím, AppForm by to měl udělat.

BigCharlie
Člen | 284
+
0
-

Pokud jsem to tedy pochopil správně, pokud bych chtěl nasimulovat metodu GET z uvedeného příkladu v mém prvním příspěvku, mělo by stačit do adresní řádky zadat tyto parametry „?do=formSearch-submit&q=hledane_slovo&search=Hledej“. Ovšem výsledkem nic není, resp. ani jeden z obslužných handlerů se nezavolá.

Žádné další hidden pole, o kterém psal phx, jsem neobjevil. Tedy další chyba, nebo je chyba ve mně?

BigCharlie
Člen | 284
+
0
-

Opravdu nikdo netuší? Zkusil jsem upravit presenter do této podoby:

<?php
class DefaultPresenter extends BasePresenter
{
        /** @var Form */
        public $form;


        public function actionDefault()
        {
                $form = new AppForm($this, 'formSearch');
                $form->setMethod('get');
                $form->addHidden('do')->setValue('formSearch-submit');
                $form->addText('q', 'Hledaný výraz:');
                $form->addSubmit('search', 'Hledej')
                                ->onClick[] = array($this, 'SearchClicked');

                $form->onSubmit[] = array($this, 'FormSubmitted');
                $this->form = $this->template->form = $form;
        }


        // obslužné handlery:
        public function SearchClicked(SubmitButton $button)
        {
                echo "odesláno použitím search<hr>";
        }

        public function FormSubmitted(Form $form)
        {
                echo "odesláno";
        }
?>

Výsledek po odeslání formuláře je žalostný. Nikdo na tenhle problém nenarazil? Stále netuším, zda-li je chyba v Nette, nebo na mé straně. I přes diskusi výše by mělo Nette při ručním přidání parametru zafungovat, nebo ne?

phx
Člen | 651
+
0
-

Koukam do AppForm a je tam asi bug, protoze metoda processHttpRequest() vubec nevyhodnocuje GET:(

David Grudl
Nette Core | 8282
+
0
-

Buďte trpěliví, jak jsem psal výše, AppForm by měl GET řešit jinak, v tuto chvíli na něj není připraven.

mkrause
Člen | 20
+
0
-

Davide, nevím jak AppForm, ale „obyčejný“ Form někdy od revize 100 podle mého názoru prostě GET nezpracuje, protože jeho protected atribut isPost je nastaven explicitně na true, nikdy v kódu dále se nemění a v metodě processHttpRequest je následující konstrukce:

		if ($this->isPost) {
			if (!$httpRequest->isMethod('post')) return;
			$data = self::arrayAppend($httpRequest->getPost(), $httpRequest->getFiles());

		} else {
			if (!$httpRequest->isMethod('get')) return;
			$data = $httpRequest->getQuery();
		}

Ve starších revizích se isPost nastavoval na false po zavolání setAction($url, false), v aktuální verzi by to IMHO měla udělat metoda setMethod("get").

David Grudl
Nette Core | 8282
+
0
-

ad mkrause: opraveno

mkrause
Člen | 20
+
0
-

David Grudl napsal(a):

ad mkrause: opraveno

Bezva, díky :)

Petr Daňa
Člen | 109
+
0
-

Nevím, co dělám blbě nebo v čem je problém, ale zápasím s formulářem pro filtrování seznamu, který odesílám přes GET. Formulář je coby komponenta součástí Article presenteru, takže do formuláře přidávám dvě hidden pole:

<?php
$form->setMethod('get');
$form->addHidden('do')->setValue('articleFilter-submit');
$form->addHidden('presenter')->setValue('Article');
?>

Ten presenter tam je kvůli tomu, aby se vůbec po odeslání vyvolal zpátky, jinak to jde na default presenter.

V renderDefault presenteru Article mám pak:

<?php
$form = $this->getComponent('articleFilter');
$this->template->formFilter = $form;

if ($form->isSubmitted())
{
    $form->setDefaults($form->getValues());
}
?>

To aby se ve formuláři zachovalo nastavení filtru.

Po odeslání je v url „do“ i „presenter“ parametr, ale ve formuláři je naplněn (mimo jiné „normální“ prvky) jen parametr „do“, „presenter“ je prázdný, takže při dalším odeslání filtračního formuláře se přenese pro presenter prázdná hodnota a končí to chybou.

Jak na to správně?

Petr Daňa
Člen | 109
+
0
-

Tak zatím jsem to vyřešil tak, že jsem v renderDefault za podmínku isSubmited() přidal

<?php
$form['presenter']->setValue($this->getName());
?>

Ale je to takový hnusný hack, tak jestli někdo víte, jak to napsat správně, budu rád za každou radu.

jasir
Člen | 746
+
0
-

Petr Daňa napsal(a):

Nevím, co dělám blbě nebo v čem je problém, ale zápasím s formulářem pro filtrování seznamu, který odesílám přes GET. Formulář je coby komponenta součástí Article presenteru, takže do formuláře přidávám dvě hidden pole:

<?php
$form->setMethod('get');
$form->addHidden('do')->setValue('articleFilter-submit');
$form->addHidden('presenter')->setValue('Article');
?>

Ten presenter tam je kvůli tomu, aby se vůbec po odeslání vyvolal zpátky, jinak to jde na default presenter.

V renderDefault presenteru Article mám pak:

<?php
$form = $this->getComponent('articleFilter');
$this->template->formFilter = $form;

if ($form->isSubmitted())
{
    $form->setDefaults($form->getValues());
}
?>

To aby se ve formuláři zachovalo nastavení filtru.

Po odeslání je v url „do“ i „presenter“ parametr, ale ve formuláři je naplněn (mimo jiné „normální“ prvky) jen parametr „do“, „presenter“ je prázdný, takže při dalším odeslání filtračního formuláře se přenese pro presenter prázdná hodnota a končí to chybou.

Jak na to správně?

Nejsem si vůbec jist, ale není možné, že se jména ‚presenter‘ (a možná i ‚do‘) nějak tlučou s frameworkovými parametry v url? Zkusit to nazvat jinak?

Petr Daňa
Člen | 109
+
0
-

To se ale má tlouct. Problém je s tím odesíláním formuláře přes GET – „ztratí se“ parametr pro presenter (nemám router, vše je v query string parametrech), takže ho musím dát do formuláře jako hidden.

David Grudl
Nette Core | 8282
+
0
-

Vyřešeno v poslední revizi.