User Warning: Form was submitted but there are no associated handlers

David Grudl
Nette Core | 8108
+
+3
-

Formuláře od verze 3.1.4 kontrolují, zda mají nějaký obslužný handler, tj. je zavěšené volání metody pro onSuccess, onSubmit nebo onClick na tlačítku:

$form->onSuccess[] = [$this, 'formSucceeded'];

Pokud chybí, vyhodí varování Form was submitted but there are no associated handlers.

Důvod je ten, že se stává, že programátor, zejména začátečník, zapomene asociovat obslužný handler a pak složitě pátrá, proč odesílání formuláře nefunguje. Tohle by mu mělo usnadnit vývoj.

Marek Bartoš
Nette Blogger | 1165
+
0
-

Upozornění je to fajn, ale myslím že začátečník si bude pořád říkat, co má být ten associated handler a bude muset sám zjistit, jak problém vyřešit. Moc by se mi líbilo, kdyby Nette v chybách vysvětlovalo jaká událost nastala, co je v ná za problém a jak ji vyřešit. Momentálně je třeba si řešení domyslet.

Context: Form with ID product-form was submitted.
Problem: Form has no handler to process it on success.
Solution: Add callback to Form->onSuccess[] or Form->onSubmit[] to process sent data.

Editoval Marek Bartoš (29. 8. 2021 15:01)

David Grudl
Nette Core | 8108
+
+4
-

Ono to vysvětlení obvykle nejde udělat jednou větou, proto jsem vlastně založil tohle vlákno, aby se hláška dala vygooglit a tam najít řešení.

Polki
Člen | 553
+
0
-

Hm i když jsem začátečník od roku 2014, tak se mi zrovna minulý týden podařilo přesně tuhle botu udělat.
Konkrétně jsem měl strukturu takovou, že jsem dělal formulář jako komponentu a tedy jsem měl více navěšených onSuccess metod.
Jednu, která se v komponentě starala o zpracování dat a jednu, která se v Presenteru starala o přesměrování po úspěšném dokončení.

Problém byl, že jsem navěštil tu událost z Presenteru, ale zapomněl jsem navěštit zpracování dat, takže redirect s flashMessage proběhl v pohodě, ale data se nezpracovala. Divil jsem se a docela dlouho na můj vkus jsem hledal kde je chyba a proč se mi nevolá update nad databází.

Když jsem si všiml, že mi tam chybí navěšení události, tak jsem se sám divil, že po takové době, kdy jsou formy denní chleba jsem udělal takovou chybu. A to, že to formuláře tvořím často přispělo taky k tomu, že jsem tuto konkrétní chybu nehledal.

Za mě rozhodně +.
Můj problém to sice neřeší, jelikož by to bralo, že mám vše ok, jelikož by to bralo jako navěšenou událost z presenteru starající se o přesměrování, ale i tak si myslím, že to je dobrý nápad.

Michal Kumžák
Člen | 106
+
0
-

Problém byl, že jsem navěštil tu událost z Presenteru, ale zapomněl jsem navěštit zpracování dat, takže redirect s flashMessage proběhl v pohodě, ale data se nezpracovala. Divil jsem se a docela dlouho na můj vkus jsem hledal kde je chyba a proč se mi nevolá update nad databází.

To by ti v tomto případě, ale tato úprava nepomohla, jestli sem to pochopil správně.

Polki
Člen | 553
+
+1
-

Michal Kumžák napsal(a):

Problém byl, že jsem navěštil tu událost z Presenteru, ale zapomněl jsem navěštit zpracování dat, takže redirect s flashMessage proběhl v pohodě, ale data se nezpracovala. Divil jsem se a docela dlouho na můj vkus jsem hledal kde je chyba a proč se mi nevolá update nad databází.

To by ti v tomto případě, ale tato úprava nepomohla, jestli sem to pochopil správně.

Nepomohla. Proto jsem taky psal:

Můj problém to sice neřeší, …

Jen jsem chtěl poukázat na to, že to je dobrý nápad, jelikož když se to může stát někomu, kdo s Nette pracuje 7 let, tak se to určitě stává nováčkům.

Editoval Polki (30. 8. 2021 16:37)

finwe
Člen | 58
+
0
-

Jak tohle funguje u GET formulářů? Protože tam můžu chtít prostě načíst stránku s GET parametrama a handler mi tam nacpe get parametr, kterej nechci. A přesměrovat z handleru mi přijde zbytečná práce a request navíc.

David Grudl
Nette Core | 8108
+
0
-

U GET formulářů by se to asi kontrolovat nemuselo. Proč tam handler cpe parametr?

finwe
Člen | 58
+
0
-

To já nevim, proč :) Ale v url je &do=searchForm-submit

MajklNajt
Člen | 471
+
0
-

nazdar, už dlší čas pozorujem tento warning na jednom webe, kde handlery sú zavesené, bolo to ale len sporadicky, no dnes som po tom začal pátrať a zistil som, že mi tento warning generuje asi iba jeden návštevník (jeden typ návštevníka), ktorý má User-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 – môže to s tým nejako súvisieť? v priebehu 3 dní to bolo z 50 prihlásení 8×, z toho 2× z jednej IP, 6× z druhej IP, pričom obe IP sú od rovnakého providera, takže považujem za možné sa domnievať, že ide o jednu osobu…

EDIT: project mám cez git nasadený na 10+ weboch, avšak robí mi to iba na jednom

Editoval MajklNajt (20. 1. 2023 8:02)

Milo
Nette Core | 1283
+
0
-

Mně se to také stávalo a nechápal jsem. Nakonec jsem zjistil, že jsem navěšoval událost moc pozdě a podmíněně a nějaký bot mohl form submitnout přes _do parametr.

MajklNajt
Člen | 471
+
0
-

Podľa logov webservera však tu ide o bežného človeka, ktorý klikne na prihlásenie a formulár odošle. Udalosť vešiam priamo v komponente, nie je však navesená na Form::onSuccess ale SubmitButton::onClick, no to sa tiež kontroluje, tak nechápem :/

EDIT:

92.249.*.* - - [20/Jan/2023:07:03:43 +0100] "GET /catalog HTTP/2.0" 200 7134 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
92.249.*.* - - [20/Jan/2023:07:03:43 +0100] "GET /favicon.ico HTTP/2.0" 404 247 "https://***.hu/catalog" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
92.249.*.* - - [20/Jan/2023:07:03:46 +0100] "GET /sign/in HTTP/2.0" 200 4361 "https://***.hu/catalog" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
92.249.*.* - - [20/Jan/2023:07:03:47 +0100] "POST /sign/in HTTP/2.0" 200 4379 "https://***.hu/sign/in" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
92.249.*.* - - [20/Jan/2023:07:03:49 +0100] "POST /sign/in HTTP/2.0" 200 316 "https://***.hu/sign/in" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
92.249.*.* - - [20/Jan/2023:07:03:49 +0100] "GET /sign?_fid=uypu HTTP/2.0" 200 5585 "https://***.hu/sign/in" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
92.249.*.* - - [20/Jan/2023:07:04:00 +0100] "GET /catalog HTTP/2.0" 200 7441 "https://***.hu/sign?_fid=uypu" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
92.249.*.* - - [20/Jan/2023:07:04:35 +0100] "GET /catalog HTTP/2.0" 200 7444 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"

Editoval MajklNajt (20. 1. 2023 10:54)

MajklNajt
Člen | 471
+
+2
-

dá sa toto chovanie nejako vypnúť alebo obísť? začínajú sa mi množiť tieto falošné hlášky niekoľkokrát denne a prestáva ma to baviť…

Ozzrel
Generous Backer | 51
+
+2
-

Taky bych to potřeboval vypnout. Při použití metody Formulář pro vytvoření i editaci záznamu tak to právě nefunguje.

m.brecher
Generous Backer | 735
+
0
-

@MajklNajt

Udalosť vešiam priamo v komponente, nie je však navesená na Form::onSuccess ale SubmitButton::onClick, no to sa tiež kontroluje

To vypadá na robot, který posílá nestandardní request a proto se ten handler nezavolá. Máš tam asi nějakou skulinku v kódu. Zkus do kódu komponenty přidat navíc handler onSuccess, který zachytí vše, otestovat, kudy tam ten robot chodí.

$this->onSuccess[] = fn() => $this->logger->log('komplet info o requestu');

OnSuccess se volá až po onClick, takže by se teoreticky neměl zavolat nikdy, jedině v případě toho robota. Jednak Ti to pomůže najít chybu v kódu, jednak to můžeš použít pro potlačení té falešné hlášky:

$this->onSuccess[] = fn() => 'foo';
m.brecher
Generous Backer | 735
+
+1
-

@Ozzrel

Taky bych to potřeboval vypnout.

Já mám občas formuláře, kde tlačítkem přidávám do formuláře dynamicky nějaký prvek. Toto tlačítko má vypnutou validaci a nemá handler, protože jeho úkolem není provést na serveru nějakou akci, ale pouze změnit stav formuláře (např. počet položek faktury). Abych potlačil warning o chybějícím handleru, musím přidat do formuláře zbytečný handler, který nic nedělá, jenom odstraní ten warning. Čistší řešení by bylo mít možnost tento warning v konfiguraci vypnout.

mskocik
Člen | 52
+
0
-

m.brecher napsal(a):

Já mám občas formuláře, kde tlačítkem přidávám do formuláře dynamicky nějaký prvek. Toto tlačítko má vypnutou validaci a nemá handler, protože jeho úkolem není provést na serveru nějakou akci, ale pouze změnit stav formuláře (např. počet položek faktury). Abych potlačil warning o chybějícím handleru, musím přidat do formuláře zbytečný handler, který nic nedělá, jenom odstraní ten warning. Čistší řešení by bylo mít možnost tento warning v konfiguraci vypnout.

A nestačilo by ti len nastaviť pre ten button type=button? Ten nesubmituje formulár

m.brecher
Generous Backer | 735
+
0
-

@mskocik

A nestačilo by ti len nastaviť pre ten button type=button? Ten nesubmituje formulár

V mém případě to není vhodné řešení. Potřebuji, aby formFactory měla hned na začátku když formulář sestavuje informace jak má formulář vypadat. Přesněji, kolik položek faktury má vykreslit. Formulář se sestavuje na serveru, proto když chci, aby klik na tlačítko přidal prvek do formuláře, musím to prohnat POST přes server, aby se současně neztratily data ve formuláři.

Kdybych přidal prvek do formuláře v prohlížeči javascriptem pomocí type=button, tak po odeslání dat nebude při zpracování na serveru formFactory vědět, že tam nějaký prvek/ky přibyl. Musely by se analyzovat odeslaná data POST a to vede na komplikované a nepřehledné řešení. Proto preferuji submit button, formulář si udržuje v pomocném input hidden stav a ten řídí sestavování formuláře ve form Factory.

Při přidávání nových feature do frameworku, je potřeba dát pozor, aby dobře míněná funkce nezpůsobila nezamýšlené potíže. Protože lidi framework používají různými způsoby. V případě upozornění na chybějící handler by bylo vhodné mít možnost tuto hlášku vypnout.

MajklNajt
Člen | 471
+
0
-

Idem skúsiť pridať prázdny onSuccess, že ma toto nenapadlo 🙈

BuMoRi
Člen | 109
+
0
-

Ahoj, také používám formuláře podobným způsobem jako m.brecher. Řešení je tedy přidat všude prázdný onSuccess? Jiné potlačení warningů není možné?

David Grudl
Nette Core | 8108
+
0
-

Napadá tě nějaký jednodušší způsob?

BuMoRi
Člen | 109
+
0
-

Mě ne. Bohužel mám v aplikaci stovky různých formulářů, tak jsem chtěl zkusit, jestli někoho zkušenějšího nenapadlo jednodušší řešení…

elnathan
Člen | 6
+
+1
-

Tahle featura je taková nedomyšlená:
Všude používám ->onClick[], což je i dle nejnovější dokumentace stále povoleno a v pořádku. Všechny formuláře jej mají korektně vyplněný, takže nepotřebuji žádné upozorňování pro začátečníky (jak tomu říkáte). Pro běžného návštěvníka vše funguje, ale pak na web přijdou roboti, kteří se snaží projít formulářem a odesílají prázdný POST případně GET ?do=form-submit (podle typu). Hádejte, co se stane? Vyhodí to tuto chybu, protože chybí informace o kliknutí na tlačítko a tudíž to hlásí, že neexistuje handler. Všechny weby, všechny formuláře po aktualizaci Nette najednou hlásí desítky/stovky errorů do logu, které mě ale vůbec nezajímají, protože to není “chyba”.
Ano, má to řešení: u jednotlačítkových přepsat $input->onClick[] na $form->onSuccess[] … u více-tlačítkových doplnit prázdný $form->onSuccess[] … ale proč mám přepisovat všechny formuláře v aplikaci, které jsou fakticky správné? Tohle chování by mělo jít globálně vypnout někde v konfiguraci projektu.

m.brecher
Generous Backer | 735
+
0
-

@elnathan

Všude používám ->onClick[], což je i dle nejnovější dokumentace stále povoleno a v pořádku.

Ve formulářích používám $form->onSuccess[] málokdy. Problém s warningem při chybějícím ovladači onSuccess[] jsem vyřešil ve vlastních abstraktních předcích FormControl a BaseForm – dvojice ze kterých dědí všechny formuláře. Tyto třídy řeší i jiné nepružnosti existující třídy Form a warning řeší nějak takhle:

if($form->onSuccess === []){
    $form->onSuccess[] = fn() => null;        // fix Nette warning
}

Tohle chování by mělo jít globálně vypnout někde v konfiguraci projektu.

Určitě by to bylo vhodné, protože warning jeden problém řeší a jiný vytváří a je otázka zda udělá více škody více než užitku? Přijít na to, že někde chybí ovladač formuláře je práce na minutu, ale přepsat po upgrade Nette všechny formuláře ve všech aplikacích může být práce na mnoho hodin.

Editoval m.brecher (5. 4. 10:31)

Martk
Člen | 652
+
0
-

Vypnout warningy jde snadno, ve FormFactory dáš toto:

$form = new Form();
$form->onSuccess[] = fn() => null;
return $form;

při nejhorším ve vlastní třídě Form. A když tvoje aplikace nepoužívá ani jedno, tak si vytvoříš php script, který automaticky vytvoří nové App\Forms\Form a nahradí v php souborech use Nette\Application\UI\Form; za use App\Forms\Form;.

elnathan
Člen | 6
+
0
-

Martk napsal(a):

Vypnout warningy jde snadno, ve FormFactory dáš toto:

$form = new Form();
$form->onSuccess[] = fn() => null;
return $form;

při nejhorším ve vlastní třídě Form. A když tvoje aplikace nepoužívá ani jedno, tak si vytvoříš php script, který automaticky vytvoří nové App\Forms\Form a nahradí v php souborech use Nette\Application\UI\Form; za use App\Forms\Form;.

Tady ale nejde o hledání toho, jak to obejít. Proč, když mám vše správně, bych měl dělat nějakou FormFactory, kterou ale k ničemu nepotřebuji? Proč bych měl nahrazovat výchozí Nette Form nějakou svojí Form třídou, když ji nepotřebuji? Jde o to, že v kódu není žádná chyba a jen “kvůli začátečníkům” to v určitých případech (popsáno v předchozím komentáři) hlásí úplně zbytečně warning. Obcházet to není správný postup (což se přesně váš FormFactory), přepisovat validní formuláře zbytečným kódem taky ne. Tato validace by prostě měla jít vypnout v konfiguraci (neon) nebo tam nebýt vůbec, jelikož bohužel nefuguje dobře s roboty.

David Grudl
Nette Core | 8108
+
+1
-

elnathan napsal(a):

Tahle featura je taková nedomyšlená:
Všude používám ->onClick[], což je i dle nejnovější dokumentace stále povoleno a v pořádku. Všechny formuláře jej mají korektně vyplněný, takže nepotřebuji žádné upozorňování pro začátečníky (jak tomu říkáte). Pro běžného návštěvníka vše funguje, ale pak na web přijdou roboti, kteří se snaží projít formulářem a odesílají prázdný POST případně GET ?do=form-submit (podle typu). Hádejte, co se stane? Vyhodí to tuto chybu, protože chybí informace o kliknutí na tlačítko a tudíž to hlásí, že neexistuje handler.

Chyby prosím hlas na GitHub, tady si jich všimnu spíš náhodou.

Opraveno