EN | CS | Přihlásit | Registrovat

Ormion

ORM pro Nette a dibi.

Zdrojové kódy (github) http://github.com/janmarek/Ormion
Autor Jan Marek
Licence MIT

Ormion vyžaduje PHP 5.3 a aktuální vývojovou verzi dibi.

Instalace

Zkopírujte do adresáře libs složku Ormion. Vytvořte složku %appDir%/models/config, do které se budou ukládat konfigurační soubory. Před jejich prvním vygenerováním v této složce musí být povolen zápis.

Připojení k databázi

Ormion\Ormion::connect(Nette\Environment::getConfig("database"));

Funkce Ormion::connect pouze zavolá funkci dibi::connect. Jen nastavuje výchozí jméno připojení na ormion. Jméno lze ovlivnit volitelným druhým parametrem.

Vytvoření modelu

Pro základní funkčnost modelu je potřeba jen nastavit jméno tabulky.

class Article extends Ormion\Record
{
protected static $table = "articles";
}

Alternativně lze název tabulky zadat pomocí anotace.

/**
* Article record
*
* @table articles
*/

class Article extends Ormion\Record
{

}

Model bude načítat údaje o databázi z cache (např. typy sloupců, jména klíčů, …). Typ tinyint(1) v databázi je považován za boolean.

Práce se záznamem

Vytvoření záznamu:

$article = new Article;

$article = Article::create();

// s přednastavenými daty
$article = Article::create(array(
"id" => 4,
"name" => "Nový článek",
"text" => "Text článku",
// ...
));

// s přednastaveným primárním klíčem
$article = Article::create(4);

Nastavování a čtení dat záznamu:

// nastavení hodnoty name
$article->name = "Název";

// lze použít ArrayAccess
$article["name"] = "Název";

// čtení
echo $article->name;

// hodnoty jsou automaticky přetypovány
$article->id = "4";
is_int($article->id); // true

// je hodnota nastavena?
isset($article->name);

// je hodnota nastavena nebo je alespoň null?
$article->hasValue("name");

// Čtení nenastavené hodnoty vyvolá výjimku.

// zrušení hodnoty
unset($article->name);

// Hromadný getter a setter lze najít pod metodami getValues, setValues.

Uložení záznamu – jestli je záznam vkládán nebo upravován ovlivňuje stav nastavitelný pomocí metody setState, případně přítomnost či nepřítomnost primárního klíče. V případě úpravy záznamu jsou ukládány jen změněné hodnoty.

$article->save();

Smazání záznamu z databáze:

$article->delete();

Hodnoty záznamu lze procházet pomocí cyklu, takže je možné nastavit záznam jako výchozí hodnoty formuláře. $form->setDefaults($article);

Výběr dat

Výběr jednoho záznamu:

// vyhledání pomocí primárního klíče
$article = Article::find(123);

// vyhledání podle jiných hodnot
$article = Article::find(array(
"author" => 4,
"allowed" => true,
));

// nebo alternativně
$article = Article::findByAuthorAndAllowed(4, true);

// také lze využít lazy loadingu, kdy nenačtené hodnoty jsou v případě potřeby doplněny z databáze
$article = Article::create($id);
echo $article->name;

Výběr kolekce záznamů:

// získání všech záznamů
$articles = Article::findAll();

// vyhledání záznamů podle určitých hodnot
$articles = Article::findAll(array(
"author" => 4,
"allowed" => true,
));

// nebo alternativně
$articles = Article::findAllByAuthorAndAllowed(4, true);

Vyhledání více záznamů vrací objekt třídy OrmionCollection. Ten zatím nemá data načtená (načte je až budou potřeba), protože umožňuje s kolekcí dále pracovat podobně jako lze upravovat třídu DibiFluent.

$articles = Article::findAll()->where("[author] = %i", 4)->orderBy("[date] DESC")->limit(10)->offset(0);

Získání počtu záznamů:

$count = count($articles);

Pokud záznamy již nejsou načteny, zavolá se dotaz typu select count(*) from ....

Třída OrmionCollection také implementuje řadu fetchovacích funkcí, jaké znáte z dibi.

$collection = Article::findAll();

$articles = $collection->fetchAll();

$limit = 10;
$offset = 0;
$firstTenArticles = $collection->fetchAll($limit, $offset);

$firstArticle = $collection->fetch();

$firstArticleName = $collection->fetchSingle("name");

$articleIds = $collection->fetchColumn("id");

$articleIdNameMap = $collection->fetchPairs("id", "name");

$articlesInGroupsByParent = $collection->fetchAssoc("parent,#");

Kolekce také podporují čtyři agregační funkce (min, max, avg a sum).

// nejvyšší počet návštěv u článku
$value = Article::findAll()->getMax("visits");

// průměrný počet návštěv u článku
$value = Article::findAll()->getAvg("visits");

// nejmenší počet návštěv u článku
$value = Article::findAll()->getMin("visits");

// součet počtů návštěv u článků
$value = Article::findAll()->getSum("visits");

Přizpůsobení OrmionRecordu

Přepsáním metody init lze upravit chování OrmionRecordu.

/**
* @table articles
*/

class Article extends Ormion\Record
{
protected function init()
{
// nastavení výchozích dat
$this->setDefaultValue("text", "Lorem Ipsum, Dorot Sir Ahmed");
// (lze nastavit pouze v této metodě,
// na pozdější nastavování nebude brán zřetel :)


// nastavení aliasů sloupců
$this->setAlias("content", "text");


// nastavení filtrů (callbacky, které berou vstup, upraví ho a vrátí)
$this->addOutputFilter("name", "Nette\String::lower");
// jméno bude při čtení převedeno na malá písmenka

// $this->addInputFilter("name", "Nette\String::lower");


// nastavení komplexních callbacků
$record = $this;
$this->registerGetter("url", function () use ($record) {
return $record->id . "-" . Nette\String::webalize($record->name);
});
// $this->registerSetter(..., ...);
// i pro tyto callbacky jsou zohledněny filtry a konvertování hodnot na správný typ


// nastavení událostí
$this->onBeforeDelete[] = array($this, "deleteComments");
// Existují ještě onAfterDelete, onBeforeInsert, onAfterInsert, onBeforeUpdate, onAfterUpdate
}


public function deleteComments()
{
foreach (Comments::findAllByParent($this->id) as $comment) {
$comment->delete();
}
}

}

Behaviors

Podrobné nastavování modelu lze vyčlenit do třídy implementující rozhranní IBehavior a poté používat opakovaně.

V distribuci již některé příklady jsou:

Timestampable při vytvoření nastaví aktuální čas na sloupci (např.) created, při úpravě aktualizuje čas na sloupci (např.) updated.

/**
* @table articles
*/

class Article extends Ormion\Record
{
protected function init()
{
$this->addBehavior(new Ormion\Behavior\Timestampable("created", "updated"));
}
}

Sortable udržuje sloupec (např.) order seřazený hezky lineárně 1, 2, 3, 4, … i při mazání, změně pořadí, vkládání nových záznamů a podobně. Lze rozkategorizovat podle další hodnoty (např. parent).

/**
* @table articles
*/

class Article extends Ormion\Record
{
protected function init()
{
$this->addBehavior(new Ormion\Behavior\Sortable("order", "parent"));
}
}

$article1 = Article::create()->save();
$article2 = Article::create()->save();
$article3 = Article::create()->save();
$article4 = Article::create()->save();

echo $article1->order . " " . $article2->order . " " . $article3->order . " " . $article4->order;
// vypíše 1 2 3 4

$article4->order = 2;
$article4->save();

echo $article1->order . " " . $article2->order . " " . $article3->order . " " . $article4->order;
// vypíše 1 3 4 2

Texy umožňuje získávat pod hodnotou (např.) htmlText cachovaný výstup hodnoty ze zdrojového sloupce (např.) text.

/**
* @table articles
*/

class Article extends Ormion\Record
{
protected function init()
{
$this->addBehavior(new Ormion\Behavior\Texy("htmlText", "text", "MyTexyClass"));
}
}

Hashable dokáže zahashovat při vkládání hodnoty a při změně hodnoty zvolený sloupec, např. password.


Komentáře Comments feed

dj.kure | 15. 7. 2010, 19:10 | bug

// nastavení komplexních callbacků
$record = $this;
$this->registerGetter(„ur­l“, function () {
return $record->id . „-“ . Nette\String::we­balize($record->name);
});

do závorek ve function se musí vložit proměnná $record;

jxp | 13. 8. 2010, 14:07 | comment

Je možné používat Ormion v Ne MVC aplikaci?

Honza Marek | 30. 8. 2010, 23:08 | comment

Nevidím důvod, proč by to nešlo.

Login to submit a comment