konstruktor v modelu

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

Dík za reakci. Pokud by se to mělo za běhu číst z databáze, určitá režie by tam byla. Tuto variantu jsem uvedl spíš proto, že se podobným způsobem v dibi volitelně detekuje typ položek výsledku. Řešení má výhodu, že není potřeba dodržovat moc konvencí v názvech, a pokud by se výsledek kešoval, bylo by možná nejlepší. Potom bych zvážil, jestli informace o tabulkách skutečně nekešovat. Využilo by se to také třeba právě pro změnu typů položek výsledku, což je užitečná věc.

Řešení, které jsem původně zamýšlel, ale mělo vycházet jen z použitých konvencí v názvech, to podle mě lépe odpovídá filozofii dibi. Zjistit, jestli je v seznamu sloupců položka Tabulka.sloupec (s určenou tabulkou) a pomocí class_exists detekovat typ vztahu by nemuselo být tak pomalé. Kdyby existovala třída spojovací tabulky, považoval by se vztah za M : N, v ostatních případech by se mohlo zohlednit, jestli se v názvu tabulky používá plurál nebo singulár. Někdy by to ušetřilo dost psaní.

David Grudl
Nette Core | 8228
+
0
-

Teď jsem si pročetl fórum a omlouvám se za uvedení ve zmatek. Příklad použítí a bug v DibiDataSource jsem opravil.

Metoda count() počítá finální počet prvků (jsem toho názoru, že pokud nějaký objekt implementuje Iterator a Countable, mělo by obojí vracet stejný počet). Pokud je nastavena podmínka nebo limit, lze vstupní počet prvků získat přes getTotalCount().

David Grudl
Nette Core | 8228
+
0
-

ad DibiTable feature requests: nápady jsou to zajímavé, ale DibiTable je ve slepé uličce vývoje a pokračovat v něm nechci. Spíš si říkám, že bych jej z distribuce úplně vyčlenil a dal ke stažení extra. Pokud bys měl chuť, a vylepšil jej, rád dám tvou verzi na dibiphp.com ke stažení.

pmg
Člen | 372
+
0
-

Tvé rozhodnutí DibiTable z distribuce vyčlenit se mi líbí: myslím, že nechceš jít cestou definice tabulek pomocí třídy, a DibiTable by toto nejspíš časem vyžadovala. Chtělo by to ale vymezit, co všechno by měla a neměla umět.

Pokud má dibi zůstat univerzální jednoduchou knihovnou pro přístup k databázi, možná by se právě DibiTable mohla proměnit v takový menší ORM, který by využíval součástí Nette:

  1. Vlastnosti polí by měly jít převést na validační pravidla pro formuláře, stejně tak chyby vzniklé při vkládání záznamu by mělo být možné předat zpět.
  2. Není dobré vytvářet nový systém pro popis sloupců tabulek, ale na druhou stranu když mám v aplikaci třídy s modely, měly by vědět s jakou strukturou pracují. Definice tabulky by šla importovat z databáze.
pmg
Člen | 372
+
0
-

Jak se bez DibiTable budou provádět jednoduché dotazy insert, update, delete? Chceš se vrátit k tomuto?

$connection->query('DELETE FROM `table` WHERE `id` = %u', $id);

$connection->delete('table')->where('id = %u', $id)->execute();

Uvědomuji si celkem značnou provázanost jednotlivých knihoven. Myslím, že z mé strany nemá moc cenu se do něčeho pouštět, než bude jasnější, jak bude všechno fungovat.

Ola
Člen | 385
+
0
-

Zdravím, zkouším si hrát s tím příkladem co tu uvedl David, konkrétně do něj doplnit kešování pomocí {cache} .. {/cache}, narazím ale na tom, že keš je popsána pozicí v souboru? a nikoliv tím tagem, takže, při stránkování mám:

	{cache "list-page-$paginator->page"}
			{foreach $posts as $post}
				<div class="post">
					<div class="post_title"><h2>{$post->title}</div>
					<div class="post_body">
						<p>{$post->content}</p>
					</div>
				</div>
				<br />
			{/foreach}
	{/cache}

což ale nefunguje – asi kvůli tomu co jsem psal na začátku (a si nejsem jistý) – na stránce 2+ mám stejný obsah jako na 1 pokud první načtu stránku 1 (pokud ne tak tam mam obsah stránky kterou sem načetl jako 1.)

Najde se nějaká dobrá duše?

Díky

Editoval Ola (15. 2. 2009 14:07)

pmg
Člen | 372
+
0
-

Myslím, že tady zatím šablonová keš použít nepůjde. Současnou implementaci lze použít třeba při vkládání statického obsahu z jiného serveru nebo když se v šabloně používá Texy.

Přednastavená doba expirace je 4 až 7 dní, což je pro obsah z databáze dost. Když už potom člověk použije tagy, je to zase zbytečně málo. Tagy navíc není snadné invalidovat. Berme to tak, že je šablonová cache stále předmětem vývoje.

Tvůj problém by se vyřešil, pokud by bylo možné nastavit vlastní klíč keše. Asi bude nejlepší počkat a zatím keš nepoužívat.

$cache = Environment::getCache('Nette.Template.Curly');

$cache->clean(array(
	Cache::TAGS => 'tag'
));

Takto bys mohl ze šablonové keše odstranit položku podle tagu, ale nepomůžeš si tím.

Jan Tvrdík
Nette guru | 2595
+
0
-

Najde se nějaká dobrá duše?

Osobně jsem si před pár dny napsal vysoce experimentální verzi tagu xcache, protože Davidova verze tagu cache mi nevyhovuje (ze stejného důvodu jako tobě).

// Registrace
$this->template->registerHelper('xcache', 'XCachingHelper::create');
CurlyBracketsFilter::$macros['xcache'] = '<?php if ($_cb->foo = $template->xcache(%TplFilters::macroCache%, $template->getFile())) { $_cb->caches[] = $_cb->foo; ?>';
CurlyBracketsFilter::$macros['/xcache'] = '<?php array_pop($_cb->caches)->save(); } if (!empty($_cb->caches)) end($_cb->caches)->addItem($_cb->key); ?>';

class TplFilters
{
	// nejvíc stupidní implementace makra :)
	public static function macroCache($var)
	{
		$var = explode(' ', $var);

		$ns = array_shift($var);
		$key = array_shift($var);

		$var = implode(' ', $var);

		return "\"$ns\", \$_cb->key = \"$key\", array($var)";
	}
}

// Přepis současného caching helperu
class XCachingHelper extends Object
{
	/** @var string */
	private $namespace;

	/** @var array */
	private $frame;

	/** @var string */
	private $key;



	/**
	 * Starts the output cache. Returns CachingHelper object if buffering was started.
	 * @param  string
	 * @param  string
	 * @param  string
	 * @param  array
	 * @return CachingHelper
	 */
	public static function create($namespace, $key, $tags, $file)
	{
		$cache = Environment::getCache($namespace);

		if (isset($cache[$key])) {
			echo $cache[$key];
			return FALSE;

		} else {
			$obj = new self;
			$obj->namespace = $namespace;
			$obj->key = $key;
			$obj->frame = array(
				Cache::FILES => array($file),
				Cache::TAGS => $tags,
				Cache::EXPIRE => rand(86400 * 4, 86400 * 7),
			);
			ob_start();
			return $obj;
		}
	}



	/**
	 * Stops and saves the cache.
	 * @return void
	 */
	public function save()
	{
		$this->getCache()->save($this->key, ob_get_flush(), $this->frame);
		$this->key = $this->frame = NULL;
	}



	/**
	 * Adds the file dependency.
	 * @param  string
	 * @return void
	 */
	public function addFile($file)
	{
		$this->frame[Cache::FILES][] = $file;
	}



	/**
	 * Adds the cached item dependency.
	 * @param  string
	 * @return void
	 */
	public function addItem($item)
	{
		$this->frame[Cache::ITEMS][] = $item;
	}



	/********************* backend ****************d*g**/



	/**
	 * @return Cache
	 */
	protected function getCache()
	{
		return Environment::getCache($this->namespace);
	}

}

EDIT: Příklad použití

{xcache MyWeb.Articles $article->id 'tag1', 'tag2'}
	{!$article->content|texy}
{/xcache}

Editoval Jan Tvrdík (15. 2. 2009 15:36)

Ola
Člen | 385
+
0
-

Díky moc! Funguje to parádně!

Editoval Ola (15. 2. 2009 19:32)

knyttl
Člen | 196
+
0
-

XCache se tváří výborně – jen se mi nedaří přijít na nějaké elegantní řešení, jak v závislosti na

Environment::getVariable(‚cache‘) :: Boolean

cache používat, nebo nepoužívat.

Díky.

knyttl
Člen | 196
+
0
-

Byl bych pro to, aby tahle cache byla oficiální součástí distribuce – je mnohem použitelnější.

Majkl578
Moderator | 1364
+
0
-

knyttr napsal(a):

Byl bych pro to, aby tahle cache byla oficiální součástí distribuce – je mnohem použitelnější.

Tak to budu proti, Xcache nepoužívám. (Tím chci říct, že bych uvítal něco univerzálního – momentálně používám Memcache).

Jan Tvrdík
Nette guru | 2595
+
0
-

A výš, v jakém významu je zde XCache myšlená?

Osobně jsem pro přepracování makra {cache}, ale ne tak, jak jsem to udělal já. Tady je to napsané hodně mizerně.

Ondrej
Člen | 110
+
0
-

Majkl578 napsal(a):>
Tak to budu proti, Xcache nepoužívám. (Tím chci říct, že bych uvítal něco univerzálního – momentálně používám Memcache).

Pokud mas zaregistrovany service ICacheStorage jako MemcachedStorage, tak prece muzes Xcache pouzivat s Memcache.

Jsem taky pro prepracovani {cache} necemu podobnemu jako {xcache}, aby to zvladalo parametrizovat i cas expirace.

Patrik Votoček
Člen | 2221
+
0
-

Ano může používat Memcache a Xcache zároveň ale já se ptám proč bych to dělal? Chci používat Memcache tak proč bych měl být nucen používat i Xcache?

Ondrej
Člen | 110
+
0
-

vrtak-cz napsal(a):

Ano může používat Memcache a Xcache zároveň ale já se ptám proč bych to dělal? Chci používat Memcache tak proč bych měl být nucen používat i Xcache?

Honza toto makro pojmenoval nevhodne, protoze se plete s aplikaci XCache, ale ve skutecnosti s XCache nema nic spolecneho…

Majkl578
Moderator | 1364
+
0
-

Ondrej napsal(a):

vrtak-cz napsal(a):

Ano může používat Memcache a Xcache zároveň ale já se ptám proč bych to dělal? Chci používat Memcache tak proč bych měl být nucen používat i Xcache?

Honza toto makro pojmenoval nevhodne, protoze se plete s aplikaci XCache, ale ve skutecnosti s XCache nema nic spolecneho…

I mě to zmátlo, proto jsem napsal to co jsem napsal.

Michalek
Člen | 211
+
0
-

Taky už rok marně doufám v předělání, používám něco jako xcache ale rád bych, aby vnitřnosti napsal někdo jiný než já a lépe :)

vrtak-cz: Jak píší výš, je to jen shoda jmen. Jde o to, že když použiju

<?php
$this->template->id = $presenter->getParam('id');

{cache}
 {$id}
{/cache}
?>

uloží se jako _21023e33958d0fd99953bb7b6da6c0a3216 a po změně ?id=X zůstává v šabloně starý obsah.

V „novém tagu“ xcache je to takhle:

<?php
$this->template->id = $presenter->getParam('id');

{xcache 'id#' . $id}
 {$id}
{/xcache}
?>

uloží se jako _id#1 a po změně ?id=X se generuje různá cache různých id.

Doteď mi není jasné, jak bez toho ostatní řeší cachování :)

Editoval Michalek (24. 8. 2010 23:08)

Jan Tvrdík
Nette guru | 2595
+
0
-

Aktuálně to mám napsané tak, aby to zvládalo takovouto syntaxi, ale pořád s tím nejsem spokojen (mizerně napsaný parser, není vázáno na číslo řádku a název souboru) a hlavně jsem nevymyslel, jak to efektivně invalidovat.

{cache
	ns => "events",
	key => "$category:$style:$startDate:$endDate:$today:$userSpecific",
	tags => array("events", "events/overview"),
	expire => "tomorrow 00:00",
}
	...
{/cache}
knyttl
Člen | 196
+
0
-

Mám dojem, že to {xcache} {/xcache} nedokáže rozpoznat změnu šablony a tak se neinvaliduje.

Jinak tedy, plný souhlas pro přepracování {cache} na něco praktičtějšího.

Editoval knyttr (25. 8. 2010 0:33)

Jan Tvrdík
Nette guru | 2595
+
0
-

knyttr napsal(a): Mám dojem, že to {xcache} {/xcache} nedokáže rozpoznat změnu šablony a tak se neinvaliduje.

V tom případě máš dojem mylný. Detekovat změnu šablony není problém, protože to Cache v Nette nativně umí.

Problém je, na jakých tazích nechat cache záviset, aby se s tím dobře pracovalo.

Jan Tvrdík
Nette guru | 2595
+
0
-

Když už se znovu otevřela diskuse v tomto vlákně, tak ještě připomenu vlákno jiné, kde se mimo jiné nachází

knyttl
Člen | 196
+
0
-

Jan Tvrdík napsal(a):
V tom případě máš dojem mylný. Detekovat změnu šablony není problém, protože to Cache v Nette nativně umí.

Problém je, na jakých tazích nechat cache záviset, aby se s tím dobře pracovalo.

Nevím, používám zhruba takovýhle formát

sablona.phtml
{xcache $presenter $id.$lang}

{/xcache}

Což funguje pěkně. Pokud ale šablonu sablona.phtml uložím, cache se neinvaliduje. Zkoušel jsem to teď jen i s {cache}{/cache} a teda taky se to neinvaliduje. Netuším proč.

Jan Tvrdík
Nette guru | 2595
+
0
-

Zvláštní. Při jakékoliv změně v souboru sablony.phtml by měla cache invalidovat a to jak s makrem {cache}, tak s makrem {xcache}. Funguje to na stejném principu jako invalidace nacachovaných šablon.

knyttl
Člen | 196
+
0
-

Experimenty jsem si ověřil, že jediná invalidace proběhne, pokud aktualizuji @layout.phtml – ta způsobí i invalidaci vnořených šablon. Pokud ale aktualizuji vnořenou šablonu, invalidace neproběhne na žádné, ani na ní samotné.

Dělal jsem to tak, že jsem do šablon naumísťoval

<?php
 echo date("H:i:s");
?>

a pozoroval, kdy se hodnota změní. Invalidace neproběhla ani v controls. Kde bych tak mohl hledat chybu?

Editoval knyttr (25. 8. 2010 9:31)

knyttl
Člen | 196
+
0
-

Vypadá to, že David v nightly builds implementoval novou verzi cache. Funguje dokonale a řeší mnou zmiňovanou nefunkčnost.

Díky.