Nette\Image a ztracená obrazová data při cachování

honza.kopecky
Člen | 2
+
0
-

Ahoj,

mám třídu Contact, jejíž atribut ProfilePhoto je typu Nette\Utils\Image. Pole objektů Contact získávám pomocí parsování XML a výsledky si kešuji. Problém je, že při serializaci je výstupem atributu ProfilePhoto toto: O:17:"Nette\\Utils\\Image":1:{s:24:"\x00Nette\\Utils\\Image\x00image";i:0;}

Ano, zkontroloval jsem, zda atribut opravdu není prázdný a není. Před serializací je v proměnné image (objektu Image) uložen gd resource. Zdá se ale, že během serializace tohle úplně zmizí a data obrázku se ztratí. Pro kešování používám klasickou notaci $cache->save() na objekty typu Contact. Všechny ostatní atributy (včetně vnořených objektů) fungují bez problémů, problém se projevuje jen u Image.

Koukal jsem do zdrojových kódů třídy Nette\Utils\Image a nevšiml jsem si, že by někde byla serializace definovaná. Znamená to, že tato třída serializaci nepodporuje a je třeba ji rozšířit? Existuje už někde hotové řešení?

Předem díky za odpověď.

Jan Tvrdík
Nette guru | 2595
+
0
-

@honza.kopecky Datový typ resource AFAIK vůbec cachovat nejde.

Jan Tvrdík
Nette guru | 2595
+
+4
-

mám třídu Contact, jejíž atribut ProfilePhoto je typu Nette\Utils\Image

To vypadá jako velmi špatný nápad. Obrázek patří na disk / na S3. GD image struktura je vhodná akorát na zpracování obrázku, ne na jejich dlouhodobé uchovávání.

David Grudl
Nette Core | 8082
+
+5
-

Ale mohlo by to vyhodit výjimku…

honza.kopecky
Člen | 2
+
-3
-

Asi to nebude úplně nejlepší řešení, ale když už data kešuji na disk, tak mi to nepřipadá až takový rozdíl, jestli ten obrázek budu mít v odděleném souboru nebo společně s objektem. Obzvlášť pokud vezmu v potaz tu práci, kterou mi to šetří.

Každopádně jsem to vyřešil poděděním třídy Nette\Utils\Image následovně:

use Nette\Utils\Image;

class SerializableImage extends Image implements \Serializable
{
	public function serialize()
	{
		return \serialize(['data' => (string)$this]);
	}

	public function unserialize($serialized)
	{
		$unserializedArray = \unserialize($serialized);
		$this->setImageResource((SerializableImage::fromString($unserializedArray['data']))->getImageResource());
	}
}
Jan Tvrdík
Nette guru | 2595
+
+2
-

když už data kešuji na disk, tak mi to nepřipadá až takový rozdíl, jestli ten obrázek budu mít v odděleném souboru nebo společně s objektem

Je to obrovský rozdíl, co se spotřebované paměti a CPU týče. Kešuješ, abys šetřil výkon, ale implementoval jsi to způsobem, který je extrémně (!) neefektivní.