Kdyby\Doctrine – vlastní typ sloupce a předání parametru/závislosti
- Gappa
- Nette Blogger | 208
Ahoj,
mám vytvořený vlastní typ sloupce (custom mapping), který je zaregistrovaný takto:
doctrine:
types:
- NejakyNamespace\FileType
V tom FileType je toto (mimo jiné, dědí od klasického StringType):
public function convertToPHPValue($value, AbstractPlatform $platform)
{
return new File($value);
}
Jde o to, že bych v entitě chtěl mít pro sloupce, kde bude soubor (typicky nějaká příloha, obrázek) rovnou instanci té třídy File, která by měla metody pro snazší práci – např. by šlo vrátit cestu na serveru, URL na webu atp.
Jenže aby to fungovalo, tak potřebuji nějak předat cestu, kde jsou ony soubory uložené – buď jako cestu, nebo nějakou instanci třídy, ze které to půjde získat:
public function convertToPHPValue($value, AbstractPlatform $platform)
{
return new File($value, $storage);
}
Ve $value
je reálný obsah z DB, tedy název souboru.
Jde to nějak řešit? Nebo na to jdu úplně špatně? :)
Editoval Gappa (21. 4. 2017 14:48)
- Svaťa Šimara
- Člen | 98
Ahoj,
super problém. Původně jsem chtěl odpovědět: Použij konstruktor pro FileType a je to.
Bohužel instanci vlastního typu vytváří Doctrine sama, a konstruktor volá vždy prázdný, takže problém. Do Doctrine lze registrovat pouze název typu, nikoliv instanci samotnou :-/
Řešení naštěstí je – použít statiku, např. singleton…
public function convertToPHPValue($value, AbstractPlatform $platform)
{
return new File($value, Storage::getInstance());
}
Anebo krkolomější bez statiky, zato se setter injection…
class FileType {
/**
* @var Storage
*/
private $storage;
public function setStorage(Storage $storage) {
$this->storage = $storage;
}
public function convertToPHPValue($value, AbstractPlatform $platform)
{
return new File($value, $this->storage);
}
}
Registraci do doctrine budeš mít pořád stejnou, a teď ta finta. Po inicializaci DI kontejneru je potřeba vykonat následující kód. Nejrychlej to můžeš vyzkoušet v bootstrap.php
$container = ...
$fileType = \Doctrine\DBAL\Types\Type::getType(FileType::class);
$storage = $container->getByType(Storage::class);
$fileType->setStorage($storage);
Jak se na to dívám, tak i druhá možnost je se statikou, ale toto je vlastnost Doctrine.
Pokud bude kód z bootstrapu, bude velice vhodné pro něj vytvořit extension.
- F.Vesely
- Člen | 369
Ja bych to resil jinak, naopak. Mel bych Storage
, ktera by na
zaklade File
vratila cestu na serveru, atd. Takhle by sis zachvili
mohl rict, ze chces mit v databazi ulozenou url ve tvaru
Presenter:action
a chtel bys vracet jiz hotovou url, tak tam
soupnes Presenter
. Osobne si myslim, ze by Service
mela pracovat s Entity
, Type
, atd. a ne naopak.
@SvaťaŠimara V tvem prvnim pripade s
Storage::getInstance()
, jak by vypadala implementace, kdybych mel
v konstruktoru zavislosti na jine sluzby nebo parametry z kofigurace?
- Svaťa Šimara
- Člen | 98
@F.Vesely Implementace by vypadala hodně blbě. Spousta problémů k řešení právě díky chybějícímu konstruktoru :-) Ne, že by řešit nešly, ale proč se trápit :-D
- Gappa
- Nette Blogger | 208
@SvaťaŠimara Díky, zatím jsem to udělal „na test“ přes
bootstrap řešení, pak uvidím o dál – tam je akorát chybička v
getType
– nedává se tam ::class
, ale jen název
typu, tedy file
(v mém případě), jinak funkční :)
@F.Vesely Chápu – uvidím, jestli v praxi tohle řešení bude spíše přínosem, nebo budoucím problémem :)