Využívání vlastních atributů v ActiveRow bez chyby při update()

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

Pokud si do AktiveRow přidám nějakou svoji vlastní hodnotu XYZ (což není problém, můžu si tam přidat co se mi zachce) tak ji můžu používat kdekoliv v kódu dál. Problém nastane v okamžiku, kdy zavolám nad daným ActiveRow::update(). Bude to řvát, že sloupec XYZ v DB neexistuje, což je sice v pořádku, ale pak je to takto nepoužitelný.

Jde mi o to částečně využívat ActiveRow jako vlastní entitu a ta kromě properties mapovaných na DB může mít i další properties, který jen přidávají funkcionalitu. Např. mám tabulku Obrázky, kde je název souboru, titulek a popis. A pak třídu File, která realizuje fyzický ukládní a mazání souboru na disku a třeba vrací cestu k danýmu obrázku. Pokud si vytáhnu všechny obrázky z DB a ke každýmu bych si chtěl vytvořit instanci třídy File, mám dvě možnosti:

  • mít zvlášt pole s File instancema, kde klíčem bude třeba ID obrázku v DB a zvlášť Selection s obrázky,
  • každou instanci File přidat do ActiveRow$image->file = new File($image->fileName);

První řešení je hnusný a druhý selže v okamžiku, když zavolám $image->file, jelikož sloupec file v DB neexistuje. Otázka zní jak z toho ven? Samozřejmně, že vím, že to není úplně košér řešení a že by to chtělo mít vlastní entity, na druhou stranu chci pracovat čistě s Nette\Database.

mkoubik
Člen | 728
+
0
-

Ještě existuje třetí řešení: vytvořit si dekorátor pro ActiveRow – třída entity, která bude obsahovat active row. Na ActiveRow pak nemusíš sahat a svoje data si budeš ukládat do té entity.

hAssassin
Člen | 293
+
0
-

Aha, díky, asi chápu jak to myslíš, ale přeci jen, mohl bys to trochu rozvést? Třeba na ten příklad s File a ActiveRow pro tabulku obrázků? Díky.

mkoubik
Člen | 728
+
0
-

Něco jako

class Entity extends \Nette\Object
{
	private $row;

	public $file;	// například

	public __construct(\Nette\Database\Table\ActiveRow $row)
	{
		$this->row = $row;
	}

	public function &__get($name)
	{
		if (isset($this->row[$name])) {
			return $this->row[$name];
		} else {
			return parent::__get($name);
		}
	}

	// podobně __set()
}
Píšu to z hlavy, takže to nejspíš nebude fungovat. Myšlenka je ale snad jasní
hAssassin
Člen | 293
+
0
-

Super díky, tak nějak sem si to asi i představoval sám a přemýšlel jsem že to tam udělám. A asi to tak předělám. Ale trápí mě trochu ještě jiná věc a to jak to pak používat v repozitářích? Momentálně mám repozitáře podobně jako v quickstartu, čili tam mám metodu:

public function findById($id)
{
	$e = $this->getTable()->get($id);
	return ($e) ? $e : NULL;
}

Takže předpokládám, že s použitím entity by se to změnilo nepatrně na

public function findById($id)
{
	$e = $this->getTable()->get($id);
	return ($e) ? new Entity($e) : NULL;
}

Co když by ale entit bylo víc a každý model by měl vlastní entitu? Pak by asi nezbývalo, než přetížit metodu findById() v každým repoziráři, případně odvodit magicky název třídy entity z názvu repozitáře, že? Jen se ujišťuju, jestli jsem na správný cestě.

P.S. Jo a jak tento postup aplikovat na Selection a jeho průchod ve foreach třeba v šabloně?

David Ďurika
Člen | 328
+
0
-

skus sa pozriet na toto https://github.com/fabik/database