Možnost náhrady třídy TableRow
- Aleš
- Člen | 30
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
Takové snahy tu byli. zatím neprůchodné. prý je to špatný návrh…
- https://github.com/…tte/pull/431
- https://forum.nette.org/…map-myslenky#… a následující komentáře… bohužel nikdo zatím žádné jiné řešení nenabízí…
- David Grudl
- Nette Core | 8218
Aleš napsal(a):
rozšíření chování při delete atp. Co vy na to?
Co tím myslíš?
- Aleš
- Člen | 30
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
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.
- Filip Procházka
- Moderator | 4668
@**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)
- Aleš
- Člen | 30
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
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
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á.