Přepisování persitentních proměnných – částí pole

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

Mám v presenteru property:

<?php

	/** @persistent array */
	public $filters = array(
		'gender' => NULL,
		'age' => NULL,
	);

?>

Pokud naplním jen klíč gender, Nette ignoruje původní obsah pole a natvrdo jej přepíše tím, co dostalo v requestu.

Zatím to řeším tíhle škaredým workaroundem:

<?php

	public function startup()
	{
		$classVars = get_class_vars(get_class($this));
		$this->filters = $this->filters + $classVars['filters'];
	}

?>
Jan Tvrdík
Nette guru | 2567
+
0
-

To není bug, ale feature.

jtousek
Člen | 951
+
0
-

Nebylo by lepší mít to jako samostatné perzistentní parametry?

enlilcz
Člen | 7
+
0
-

@jtousek: Mnohem lépe se mi s tím pracuje v poli v rámci aplikace. Když přidám vlastnost, stačí to upravit na jednom místě. Data pak v modelu sanitizuji, takže mi nikdo nemůže ani nic podstrčit.

@Jan Tvrdík: Feature? Pokud to pole je definované ve třídě, tak mi nikdo zvenku nemůže do defaultu nic podstrčit a očekávatelné chování je, že se přepíšou klíče pole, co přišly v requestu a zbytek se sloučí. Úplně stejně jako kdybych se třídou pracoval zevnitř.

Filip Procházka
Moderator | 4668
+
0
-

@**enlilcz**: to je ale tvoje chyba, že to očekáváš ;) Nikdy nevěř vstupu od uživatele. Tohle je jeden parametr, tedy jeho hodnotu může ovlivnit uživatel a může i smazat co v něm je. Pokud ti to vadí, udělej dva parametry.

Naopak tvůj požadavek je hloupost, protože se to příčí chování jazyka. Nekonzistence je špatná. Nikdo ti samozřejmě nebrání si to hacknout, ale to už jde na tvé triko ;)

Správně bys to měl dělat takto, pokud tam chceš vždy všechny klíče.

/** @persistent array */
public $filters = array();

/** @var array */
static $filterDefaults = array(
	'gender' => NULL,
	'age' => NULL,
);

public function startup()
{
	$this->filters = $this->filters + static::$filterDefaults;
}
jtousek
Člen | 951
+
0
-

@HosipLan: Jestli jsem to dobře pochopil tak mu jde o změnu pouze jednoho parametru, např. odkazem. Správné řešení je tedy v šabloně předávat ne jen ten upravený filtr ale původní parametr $filters + pole s upraveným filtrem.

@enlilcz: A to je tak těžké si z těch několika perzistentních parametrů v metodě startup poskládat pole a dále pracovat s nim?

Editoval jtousek (24. 5. 2012 13:43)

Ascaria
Člen | 187
+
0
-

Mít persistentní jen jeden parametr považuju za velké plus (pracuji na svém datagridu, který na všechno potřebuje jen jeden argument), lehko se přenáší a nemusí se kontrolovat přítomnost nepovinných parametrů. Takže HosipLan ti to shrnul přesně, jen namísto něj bych ale udělal:

/** @persistent */
public $filters;
// a nebo
public $filters = null;

Protože se pak líp ta hodnota vyruší, nemusíš tápat v kódu jakou to má výchozí hodnotu, jen napíšeš = null a máš jistotu že ti to z adresy zmizí.

Editoval Ascaria (24. 5. 2012 14:48)

Filip Procházka
Moderator | 4668
+
0
-

@**Ascaria**: což je hloupost, protože Nette ti automaticky vynucuje datový typ. Tedy array() tam není jen tak, aby to vypadalo pěkně ;)

Ascaria
Člen | 187
+
0
-

HosipLan napsal(a):

@**Ascaria**: což je hloupost, protože Nette ti automaticky vynucuje datový typ. Tedy array() tam není jen tak, aby to vypadalo pěkně ;)

V tom případě pak něco jako:

/** @persistent Array */
public $filters = null;

Podle pravidel PHP se pak hodnota null přidá do výčtu akceptovaných hodnot. Ověřit si to lze třeba na metodě function(Array $a) versus function(Array $a = null).

Filip Procházka
Moderator | 4668
+
0
-

@**Ascaria**: opět hloupost. PHP nativně neumí annotace, umí ovšem nativně říct, jaký je výchozí datový typ. A NULL je vždycky výchozí hodnota, pokud žádnou neuvedeš ⇒ zbytečnost.

Editoval HosipLan (24. 5. 2012 16:05)