Rozuzlení ORM v Nelle

Patrik Votoček

V předešlém článku jsem sepsal své strasti při hledání vhodného “ORM”((Object-relational mapping)) pro Nellu . Popsal jsem v něm hrubé požadavky, které by měl kandidát splňovat. Popsal jsem, proč jsem nezvolil Ormion, dibi-ActiveRecord, Propel, Doctrine 1.2 a ani Doctrine 2.0.

Nedávno se na scéně objevila nová vlaštovka od Jakuba Vrány . “ORM” “NeORM” jménem NotORM je super a inspirující nicméně také není dokonalé. NotORM spoléha na načtení struktury databáze z databáze. Což je pro Nellu nevyhovující z důvodu že Nellu plánuji vydat s podporou více databází. A bude obsahovat instalačního průvodce, který databázi vygeneruje. No a generovat databázi z prázdné databáze jaksi nejde. Navíc NotORM se mě zdá zase až příliš jednoduché.

Finální volba

Najít vhodné “ORM”((Object-relational mapping)), které by nebylo ani velké ani malé. Nebylo by ošklivé, snadno se používalo a zároveň bylo postavené nad dibi. Je nemožné. Proto jsem zvolil snad nejhorší možnou variantu “udělej si sám”. Naplněn informacemi z průzkumu již hotových řešení. Jsem začal přemýšlet a zkoumat jak to teda vlastně udělat aby to nebylo přeplácané a zároveň aby to umělo vše co potřebuji. No a tak vzniká ActiveMapper. Další a určitě né poslední “ORM”((Object-relational mapping)) postavené nad dibi .

Ukázkový příklad

Mějme asi takovouto strukturu databáze: alt text Pokud vám při prvním pohledu nejsou jasené relace tak jsou následující: Authors 1:1 Profiles , Authors 1:N Articles , Articles N:M Tags

Struktura dat

<?php
namespace App\Models;

/**
 * @OneToMany(App\Models\Article)
 * @OneToOne(App\Models\Profile)
 */
class Author extends \ActiveMapper\Entity
{
	/**
	 * @column(Int)
	 * @autoincrement
	 * @primary
	 */
	protected $id;
	/**
	 * @column(String, 100)
	 * @unique
	 */
	protected $name;
}

/**
 * @OneToOne(App\Models\Author, mapped = FALSE)
 */
class Profile extends \ActiveMapper\Entity
{
	/**
	 * @column(String, 255)
	 */
	private $web;
}

/**
 * @ManyToOne(App\Models\Author)
 * @ManyToMany(App\Models\Tag)
 */
class Article extends \ActiveMapper\Entity
{
	/**
	 * @column(Int)
	 * @autoincrement
	 * @primary
	 */
	private $id;
	/**
	 * @column(String, 255)
	 */
	private $title;
	/**
	 * @column(Text)
	 */
	private $content;
	/**
	 * @column(Date)
	 * @default NOW()
	 */
	private $create;
	/**
	 * @column(Float)
	 * @null
	 */
	private $price;
	/**
	 * @column(Bool)
	 * @default false
	 */
	private $public;
}

/**
 * @ManyToMany(App\Models\Article, mapped = FALSE)
 */
class Tag extends \ActiveMapper\Entity
{
	/**
	 * @column(Int)
	 * @autoincrement
	 * @primary
	 */
	private $id;
	/**
	 * @column(String, 255)
	 */
	private $name;
}

Jak je z ukázky patrné mapuje se pomocí “Entit”, které hojně využívají anotací. Pokud se ptáte co je dalšího potřeba? Tak říkám že nic! Můžete to začít používat.

PHP 5.3

Další věc která je z ukázky patrná je že se používají namespace tudíž je nutné PHP 5.3. Máte-li vůči PHP 5.3 averzi a nehodláte to překousnou dále snad ani nečtěte. A nebo se podívejte že nutnost PHP 5.3 je čím dál více potřeba. Stačí se podívat na budoucí Doctrine 2.0, Zend Framework 2.0, Symfony 2.0 a spoustu dalších knihoven a frameworků. Zkrátka čím dříve začleníte PHP 5.3 do svého života tím lépe pro vás. PS: Zatím každý koho znám a zkusil PHP 5.3 u něj taky zůstal!

Získávání dat

Jak definovat strukturu dat jsme si už ukázaly. Ale jak data získat? Jednoduše takto:

$article = \ActiveMapper\Repository::find('App\Models\Article', 1); //načti článek s ID 2
echo $article->title; //vypíše titulek článku
echo $article->author()->name; //vypíše jméno autora
foreach ($article->tags() as $tag)
{
		echo $tag->name; //vypíše název štítku
}
echo $article->author()->profile()->web; //vypíše web autora

To musím pokaždé psát ActiveMapper\Repository::find('App\Models\Article',...)? Ne! Stačí při definování struktury dat dědit od ActiveMapper\ServiceEntity místo ActiveMapper\Entity a můžete používat App\Models\Article::find(2).

Pět vrstev ActiveMapperu

Pokud jste četli Pět vrstev modelu od Honzy Tichého . Ptáte se asi jestli něco takového ActiveMapper má. Ano má a aktuálně to je asi takto: alt text

Pokud se ptáte kde je UnitOfWork a podobné části zabývající se zápisem tak ty si ukážeme příště, až budu ActiveMapper uvolňovat pro širokou veřejnost.

« »