konstruktor v modelu
- pmg
- Člen | 372
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
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
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
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:
- 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.
- 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
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
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
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
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)
- Jan Tvrdík
- Nette guru | 2595
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
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
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
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
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
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
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}
- Jan Tvrdík
- Nette guru | 2595
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
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í
- poslední mně známá reakce
Davida na problematiku
{cache}
- zajímavé řešení od jansfabik (vhodné pro jednodušší situace)
- knyttl
- Člen | 196
Jan Tvrdík napsal(a):
V tom případě máš dojem mylný. Detekovat změnu šablony není problém, protože toCache
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
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
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)