Bug – parametr typu pole v presenteru nebo controlu se zpřehází podle abecedy

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

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&param[]=a nebo adresa?param[]=2&param[]=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…

vlki
Člen | 218
+
0
-

Hm, myslím, že tak moc úzká závislost na parametrech by tam ani snad nemusela být.

Nebo je důvod, proč si to pole nedát do session a nepředávat si jen nějaký hash, přes který se budou ty data v session identifikovat?

Honza Marek
Člen | 1664
+
0
-

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&param[]=b.

http://jqueryui.com/demos/sortable/

vlki
Člen | 218
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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 :)

Sámo
Člen | 1
+
0
-

Pěkné, jen při předávání parametrů metodou get by se mohlo stát, že se překročí maximální povolená délka uri (HTTP Error 414 – Request URI too long). Bývá nastavena na 2048 nebo 4096 znaků.

Honza Marek
Člen | 1664
+
0
-

No tak dělá to funkce parse_str tady. Nechápu, proč se get parametry nenačítají rovnou z pole $_GET.

Honza Kuchař
Člen | 1662
+
0
-

Tak to mi tedy taky není jasné. Davide, má to nějaký důvod?

David Grudl
Nette Core | 8110
+
0
-

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é.