Invalid parameter name, číslo a ajax
- leninzprahy
- Člen | 150
Nette Framework 2.0.1 (revision 94abcaa released on 2012–02–29)
PHP Version 5.3.5–1ubuntu7.7
Narazil jsem na problém ve verzi 2.0.1 (v 2.0 bylo v pořádku)
Mám formulář jehož položky jsou pojmenovány čísly (int), pokud ho odešlu normálně, není žádný problém, ale pokud je odeslán přes ajax, ukončí se chybou „Nette\Application\BadRequestException: ‚Invalid parameter name ‘2'“
Přijde mi že za to může regulární výraz v /Nette/Application/UI/Presenter.php:1275 v kombinaci s přidáním postu mezi parametry v případě ajaxu.
Editoval leninzprahy (16. 4. 2012 12:44)
- nanuqcz
- Člen | 822
Ahoj, názvy proměnných v PHP nesmí začínat číslem, tedy ani názvy polí ve formuláři.
http://www.tvorba-webu.cz/php/vars.php:
Název proměnné nesmí začínat číslem (jinak může čísla obsahovat), toto je chybné $1promenna = „hodnota“.
- leninzprahy
- Člen | 150
To je mi jasné, že proměnné nesmí začínat číslem (případně být číslo), ale proč to nejde u formulářového pole. Tam jde o název parametru a ne proměnné, je to vlastně klíč asociativního pole a ten číselný být může.
Nebo mi něco uniká?
- nanuqcz
- Člen | 822
Pokud by bylo na serveru zapnuté register_globals,
tak se automaticky všechny $_POST['1']
namapujou na
$1
a to nejde. Takže proto tohle omezení platí i pro
formulářové pole.
- leninzprahy
- Člen | 150
Díky za odpovědi, ale stále mluvíme každý o něčem jiném :)
register_globals na to dle mého názoru nemá vliv, navíc v php 5.3 je deprecated a v php 5.4 snad už nebude vůbec.
Položka formuláře je komponenta a ta žádné takové omezení na
jméno nemá (musí jen projít '#^[a-zA-Z0-9_]+$#'
).
Navíc jak jsem psal už na začátku, pokud je formulář odeslán normálně, vše je v pořádku, problém nastává až při AJAXovém požadavku.
Domnívám se, že za to může initGlobalParameters() v /Nette/Application/UI/Presenter.php
ve verzi 2.0 vypadal takto
...
$params = $this->request->getParameters();
if ($this->isAjax()) {
$params += $this->request->getPost();
}
foreach ($params as $key => $value) {
$a = strlen($key) > 2 ? strrpos($key, self::NAME_SEPARATOR, -2) : FALSE;
if (!$a) {
$selfParams[$key] = $value;
} else {
$this->globalParams[substr($key, 0, $a)][substr($key, $a + 1)] = $value;
}
}
...
zatímco ve verzi 2.0.1
...
$params = $this->request->getParameters();
if ($this->isAjax()) {
$params += $this->request->getPost();
}
foreach ($params as $key => $value) {
if (!preg_match('#^((?:[a-z0-9_]+-)*)((?!\d+$)[a-z0-9_]+)$#i', $key, $matches)) {
$this->error("'Invalid parameter name '$key'");
}
if (!$matches[1]) {
$selfParams[$key] = $value;
} else {
$this->globalParams[substr($matches[1], 0, -1)][$matches[2]] = $value;
}
}
...
- nanuqcz
- Člen | 822
Já tě chápu, ale
$form->addText('1', '1:');
vygeneruje
<input type="text" name="1"> <!-- plus nějaké ID, DATA-NETTE apod. -->
Takže pokud by někdo takový formulář odeslal na serveru s PHP 5.2 a se zapnutým register_globals, byl by průšvih (neotestováno).
Takže podle mě je chyba, že Nette nevyhodí vyjímku už při vytváření formuláře… Už ale nechám prostor i dalším lidem, tady je to evidentně jen věc názoru.
- leninzprahy
- Člen | 150
Věc názoru určitě. Každopádně děkuju za odezvu.
Já s tím třeba problém nemám, ale zase chápu že pojmenování položek
formuláře čísly není úplně normální :)
Vygeneruje to přesně:
<input id="frmForm-1" class="text" type="text" value="" name="1_">
Samozřejmě bych mohl položkám dát prefix a při zpracování ho zase zahodit, ale o to mi tu nejde.
Ten regulár dle mého názoru parsuje akci z GETu, ale při odeslání AJAXem se tam zamotá i POST a vzniká problém. V anotaci té funkce initGlobalParameters() se píše
@throws Nette\Application\BadRequestException if action name is not valid
ale mě jí to vyhodí i když se o jméno akce nejedná …
No, zatím zůstanu u verze 2.0 kde vše funguje tak jak má :)
- David Grudl
- Nette Core | 8228
Tohle s register globals nijak nesouvisí.
Je tu restrikce, aby poslední segment názvu parametru nezačínal číslem. Je to z toho důvodu, že funkce Presenter::createRequest() & argsToParams(), která se používá při canonicalizaci, převede číselné indexy na klíče dle názvů parametrů příslušné funkce. Nejspíš by bylo možné restrikci zrušit a při canonicalizaci tohle chování zakázat, ale to je jiné téma.
Při vytváření formuláře se každopádně číselné názvy doplňují
podtržítkem (čísla by způsobila problémy s JavaScriptovou validací),
takže <input type="text" name="1">
vzniknout nemůže, bude
tam name="1_"
.
Z toho důvodu by nikdy k chybě dojít nemělo.