Možnost náhrady třídy TableRow

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

Zdravím,
celkem by se mi hodila možnost přidat do table selection metodu pro vytvoření instance třídy řádku. V podstatě funkci createRow, která by šla přepsat v potomcích selection a daly se tak vytvářet vlastní třídy mimo TableRow? Hodí se to např pokud je potřeba rozšířit řádek o rozhraní IResource, rozšíření chování při delete atp. Co vy na to?

Klidně se do toho pustím sám, pokud se nenajdou nějaké důvody proč by to bylo špatné…

hrach
Člen | 1838
+
0
-

Takové snahy tu byli. zatím neprůchodné. prý je to špatný návrh…

David Grudl
Nette Core | 8218
+
0
-

Aleš napsal(a):
rozšíření chování při delete atp. Co vy na to?

Co tím myslíš?

hrach
Člen | 1838
+
0
-

Osobně si pod tím představuji třeba přesunutí záznamu do archivní tabulky, či nějaký „programový“ trigger.

Aleš
Člen | 30
+
0
-

David Grudl napsal(a):

Co tím myslíš?

Měl jsem na mysli např smazání souboru z disku a podobné věci které se nedají udělat pomocí závislostí v DB.

Pročetl jsem si linky zmíněné hrachem. Nedokázal jsem vyčíst proč v tomto případě je dědění horší než kompozice. Chápu že z hlediska 5vrstého modelu je potřeba oddělit tohle chování od úložiště, nicméně důvod proč to nelze podědit mi uniká.

Vyki
Člen | 388
+
0
-

Aleš napsal(a):
Měl jsem na mysli např smazání souboru z disku a podobné věci které se nedají udělat pomocí závislostí v DB.

Myslím, že mazání souborů a podobné operace sem rozhodně nepatří. To bych umístil do nějaké samostatné servisní vrstvy, která bude pracovat jak s DB tabulkou tak s filesystémem. Nebudeš pak mazat prvek pouze smazáním řádku v DB pomocí Nette\Database, ale vytvoříš si vlastní service, do které pomocí DI předáš Nette\Database a nějaký svůj FileSystemService. Potom např. v metodě delete získáš z DB cestu k souboru, odstraníš jej z DB a disku.

Aleš
Člen | 30
+
0
-

Jak jsem psal, vrstvu navíc chápu, ale nechápu proč bych měl kvůli vytvářet další třídu, v ní implementovat array_access, iterator atp jenom proto abych je naplnil přímým voláním TableRow.

Editoval Aleš (9. 2. 2012 10:44)

Filip Procházka
Moderator | 4668
+
0
-

@**Aleš**: Proč je tohle problém? Nemusí to mít přeci stejný interface jako ActiveRow.

$photo = new Photo($table->get('id'));
$photo->delete();

Editoval HosipLan (9. 2. 2012 10:51)

hrach
Člen | 1838
+
0
-

@HosipLan: fuj, co to tady děláš za pseukody: $row->id nebo $db->table->get($id) :P :D

Aleš
Člen | 30
+
0
-

HosipLan napsal(a):

@**Aleš**: Proč je tohle problém? Nemusí to mít přeci stejný interface jako ActiveRow.

Protože když budu chtít možnost ukládat do Photo z tvého příkladu stejně pohodlně jako do ActiveRow tak musím. Navíc pokud budu chtít vytvořit nějakou PhotoCollection která mi bude vracet Photo, tak abych jí mohl ovládat stejně pohodlně jako Selection, budu muset implementovat iterátor, order, get metody, které budu zase jenom přímým voláním :-/

Filip Procházka
Moderator | 4668
+
0
-

Já to tedy rozepíšu…

use Nette\Forms\Controls\UploadControl;
use Nette\Database\Table\ActiveRow;
use Nette\Database\Table\Selection;

class PhotoFile extends Nette\Object
{
	private $photo;
	public function __construct(ActiveRow $photo)
	{
		$this->photo = $photo;
	}

	public function delete()
	{
		if (!@unlink($f = $this->photo->realpath)) {
			throw new Nette\IOException("Error while removing file '$f'.");
		}
		$this->photo->delete();
		return TRUE;
	}

	public static function fromUpload(UploadControl $form, Selection $table)
	{
		// ...
		return new static($table->insert($data));
	}

	public function __get($name)
	{
		return $this->photo->$name;
	}
}

Proč by to mělo umět víc, než co zrovna teď potřebuješ? Nepíšeš přeci framework, ne? :)

$table = $connection->table('photos');

smažu

$photo = new PhotoFile($table->get('id'));
$photo->delete();

a nebo nahraju

$photo = PhotoFile::fromUpload($form['upload'], $table);

Nepotřebuješ to dědit ;)

Editoval HosipLan (9. 2. 2012 15:13)

Aleš
Člen | 30
+
0
-

No jenže když budu chtít smazat např vše z kolekce tak

<?php
$photos = new PhotoCollection($location);
foreach($photos as $photoRow){
	$photo = new Photo($photoRow); //proč musím mi tuhle řádku navíc :-/
	$photo->detele();

}
?>

photoRow by se podle mě neměl v presenteru vůbec vyskytnout. Mám model Photo a nezajímá mě uložení v db a že potřebuju vytáhnout row abych mohl model naplnit datama. To mi přijde větší porušení vrstev než podědění.

Další příklad – oprávnění v template

<?php
presenter:
$template->photos = Array();

$photos = new PhotoCollection($location);
foreach($photos as $photoRow){
	template->photos[] = new Photo($photoRow);
}

template:
foreach($photos as $photo)
	$user->isAllowed($photo,"delete)
?>

Stejný problém, plus musím materializovat celou kolekci, což, jak psal Šaman jinde, může být paměťově náročné.

O vytváření instance Photo až v template se radši ani nebudu zmiňovat.

Momentálně jsem skončil u kompozice se selection které využívá MapIterator nad výsledkem a zpřístupňuje všechny metody selection. Jako vedlejší efekt to sice znamená vytváření nových položek přes kolekci, místo vytvoření nové položky a zavolání save, ale nakonec je to asi nejmenší zlo.

Jinak framework nepíšu, ale většina modelů používá identický přístup (insert, delete), takže to po společném předkovi volá.