Bug – parametr typu pole v presenteru nebo controlu se zpřehází podle abecedy
- Honza Marek
- Člen | 1664
Zkoušel jsem implementovat jQuery UI sortable a narazil jsem na toto:
class TestPresenter extends Presenter
{
public function actionDefault($param)
{
Debug::dump($param);
Debug::dump($_GET["param"]);
$this->terminate();
}
}
Pak jsem to zavolal na adrese typu
adresa?param[]=b¶m[]=a
nebo
adresa?param[]=2¶m[]=1
a výsledkem bylo, že dumpy oproti
očekávání nejsou stejné.
array(2) {
0 => string(1) "a"
1 => string(1) "b"
}
array(2) {
0 => string(1) "b"
1 => string(1) "a"
}
Pokud podle toho potom chci řadit, tak je to docela problém…
- Honza Marek
- Člen | 1664
To řazení se mění javascriptem. Důvodem, proč to mít v parametru je metoda
$(".sortable").sortable("serialize");
která právě vyrobí string typu param[]=a¶m[]=b
.
- vlki
- Člen | 218
Jo, vím, že když jsem si s jQuery UI sortable hrál, tak jsem něco jako
var order = $('.sortable').sortable('serialize');
$.post('nejaka-adresa', order);
používal a fungovalo bez problému. Jen to jede ještě na nějaké staré,
snad 0.7 vývojové verzi Nette, tak je možné, že se od té doby něco
změnilo. Zkusím se podívat, jestli mi to taky dělá rozdíl mezi
$_GET['order']
a $this->getParam('order')
.
- Honza Marek
- Člen | 1664
vlki napsal(a):
var order = $('.sortable').sortable('serialize'); $.post('nejaka-adresa', order);
Tohle vůbec nevím co má dělat. „Metoda“ serialize vrací string a to mi moc nesedí do toho dalšího řádku. Jestli sis poslal celý string a sám sis ho naparsoval, tak to určitě mohlo fungovat.
Jen to jede ještě na nějaké staré, snad 0.7 vývojové verzi Nette, tak je možné, že se od té doby něco změnilo.
Mezi 0.7 a 0.9 se změnilo velmi mnoho věcí…
- vlki
- Člen | 218
Hm… nevidím v tom žádný problém. Ať to pošlu POSTem nebo GETem, ať to je jako povinný parametr nebo získávám přes getParam(), tak mi to $_GET/$_POST vs param vrací stejné pole.
Chtělo by to se podívat do metod zpracovávajících parametry, jestli tam náhodou nějaký sort není…
UPDATE 12:00:
Honza M. napsal(a):
Tohle vůbec nevím co má dělat. „Metoda“ serialize vrací string a to mi moc nesedí do toho dalšího řádku. Jestli sis poslal celý string a sám sis ho naparsoval, tak to určitě mohlo fungovat.
Viz jQuery UI serialize method API:
Serializes the sortable's item id's into a form/ajax submittable string. Calling this method produces a hash that can be appended to any url to easily submit a new item order back to the server.
Mezi 0.7 a 0.9 se změnilo velmi mnoho věcí…
To určitě, ale nevím, nakolik zrovna parsování parametrů.
Editoval vlki (23. 9. 2009 11:57)
- Tomik
- Nette Evangelist | 485
Teď jsem to taky řešil… :) (BTW http://code.google.com/…edsortables/ … to samé, ale i pro vnořování…)
Mám to řešené takto:
JS:
$(document).ready(function() {
// schováme ovládací prvky, které jsou tam jen proto, aby fungovalo řazení i bez JS
$(".jshide").hide();
// naopak zobrazíme ty, které tam jsou jen kvůli tomu řazení s JS
$(".jsshow").show();
// "sortedMenu" je ID toho seznamu, který se řadí
$('#sortedMenu').NestedSortable(
{
accept: 'sortable', // třída prvku, který je možné řadit
opacity: .8,
onChange: function(serialized) {
// odkaz s ID "moveUrl" má v šabloně definované href jako {link move!} - tedy adresu pro handler pro přesunutí položek
url = $("#moveUrl").attr("href");
// adresu si vezmu, zparsuju a přidám za ní pořadí z jQuery UI
if ((url+'').indexOf('?') === -1) url = url + "?";
else url = url + "&";
url = url + serialized[0].hash;
$.get(url);
// $("#info").html(url); // just for debug
},
autoScroll: true,
});
});
Handler pro přesunutí:
<?php
/**
* Move handler
*
*/
public function handleMove()
{
$params = $this->parent->params['sortedMenu'];
MenuModel::moveItemsInMenu($params);
$this->invalidateControl();
}
?>
A ještě ta fce moveItemsInMenu
z modelu:
<?php
/**
* Move menu items in structure
*
* @param array $params
* @param int $parentId
* @param int $deep
* @return bool
*/
public static function moveItemsInMenu($params, $parentId = 0, $deep = 0) {
$position = 0;
foreach ($params AS $param) {
self::getDb()->query('UPDATE [:cms:menu_items] SET %a WHERE id = %i', array('position' => $position,
'parentId' => $parentId,
'deep' => $deep),
$param['id']);
// pro vnořené položky použijeme rekurzi...
if (isset($param['children'])) self::moveItemsInMenu($param['children'], $param['id'], $deep + 1);
$position++;
}
return TRUE;
}
?>
Snad je to pochopitelné… :)
P.S.: České komentáře jsem doplnil teď, jinak používám vždy a všude angličtinu… :)
- Honza Kuchař
- Člen | 1662
Narazil jsem na to taky v TabControlu: https://guest@svn.mujserver.net:8443/…bControl.php metoda
;handleSaveTabsOrder(); – někde ke konci. SOubor je v UTF-8. Řeším to
tam takhle: $order = $_GET[$this->getUniqueId()."-order"];
i když je to prasárna :)
- Honza Marek
- Člen | 1664
No tak dělá to funkce parse_str tady. Nechápu, proč se get parametry nenačítají rovnou z pole $_GET.
- David Grudl
- Nette Core | 8227
Měl jsem vždycky za to, že při porovnávání dvou URL nezáleží na pořadí parametrů, tj. že adresy
http://example.com?a=10&b=33
http://example.com?b=33&a=10
jsou totožné. Mýlil jsem se, ve specifikaci nic takového není. Omlouvám se, že prozření mi tak dlouho trvalo, už je to opravené.