Wiki
Clone wikishake/database / Home
Shake \ Databáze & ORM
Shake\Database
přináší do Nette aplikací hned několik výhod. Za prvé je to ORM, díky kterému můžete výsledky z databáze rozšířit o další metody. Za druhé pak jednoduchá podpora vnořených transakcí, a to i u databází, které vnořené transakce nepodporují (MySQL).
ORM
Shake automaticky mapuje výsledky z databáze do vašich vlastních tříd, které reprezentují dané entity z databáze, případně kolekce entit. A pokud tyto třídy nemáte napsané? Nic se neděje, pak dostanete místo entit instance ActiveRow, přesně jak jste zvyklí z klasického Nette :-)
-
Entity
Vezměme si obyčejné získání jednoho záznamu z databáze. Třeba posledního vloženého článku z tabulky
articles
.<?php namespace App\Model; use Shake\Scaffolding\Repository; class ArticleRepository extends Repository { public function findLast() { return $this->select() ->order('created DESC') ->fetch(); } }
Pokud neexistuje žádná entita s názvem
ArticleEntity
, vrátí tato metoda instanci třídy Nette\Database\Table\ActiveRow.Entity jsou v pojetí Shake frameworku třídy, které se vždy nazývají podle názvu tabulky, ze které pochází, plus přívlastek Entity. Tedy např. tabulka article -> entita ArticleEntity, tabulka article_category -> entita ArticleCategoryEntity.
Entity vždy dědí z Shake\Database\Orm\Entity.<?php namespace App\Model; use Shake\Database\Orm\Entity; class ArticleEntity extends Entity { }
Poté, co napíšeme tuto entitu a uložíme jí třeba do app/model/ArticleEntity.php, začnou všechny dotazy do databáze vracet místo ActiveRow instanci této entity.
Ta se chová úplně stejně jako ActiveRow. Můžete nad ní volat metody ->related(), získávat data atd. Navíc ji ale můžete rozšířit o vlastní funkce, což je přesně její účel.
<?php namespace App\Model; use Shake\Database\Orm\Entity; class ArticleEntity extends Entity { public function getPosts() { return $this->related('article_post') ->order('date DESC'); } }
Entity podporují gettery, stejně jako array-access. K příspěvkům daného článku se tak můžete dostat kterýmkoli z následujících způsobů:
<?php $article = $articleRepository->findLast(); $article->getPosts(); $article['posts'] $article->posts;
což se hodí zejména v šablonách
{foreach $article->posts as $post} ... {/foreach}
-
Table
Table fungují úplně stejně, jako Entity, jen se týkají kolekce záznamů, místo jednoho konkrétního záznamu.
Při získávání více řádků z databázové tabulky vrací Shake (stejně jako Nette) instanci Nette\Database\Table\Selection. Pokud ale existuje *Table třída, je místo Selection vrácena tato *Table třída.
<?php namespace App\Model; use Shake\Database\Orm\Table; class ArticleTable extends Table { }
Všechny *Table třídy dědí z Shake\Database\Orm\Table a díky tomu mají stejnou funkčnost, jako klasický Selection z Nette. A stejně jako Entity je můžeme o další chování rozšířit.
Vnořené transakce
Vnořené transakce jsou prostě transakce v transakci :-) Klasické MySQL je nepodporuje, Shake\Database ale tento nedostatek obchází, takže je ve výsledku pouźít můžete.
Hlavní transakce je závislá na svých vnořených transakcích. Pokud se jen jedna sub-transakce nepovede, jsou zrušeny i všechny ostatní metody transakce i jejich potomků.
<?php
namespace App\Model;
use Shake\Scaffolding\Repository;
class ArticleRepository extends Repository
{
public function doSomethingFunny()
{
try {
$this->connection->beginTransaction();
...
$this->connection->beginTransaction();
...
$this->connection->commit();
$this->connection->beginTransaction();
...
$this->connection->commit();
...
$this->connection->commit();
} catch (Exception $e) {
$this->connection->rollBack();
}
}
}
Updated