Nextras\ORM je lehko použitelná knihovna, vhodná i pro malé projekty. Hlavní maintener není nikdo jiný než databázový mág Jan hrach
Škrášek.
Knihovna má svůj balíček, takže instalace je úplně jednoduchá.
composer require nextras/orm
Aktuálně je stable verze 1.0.0, ale brzo vyjde verze 1.1.0, která se nyní nachází ve stavu Release Candidate 1.
Nextras\ORM je střední knihovna pro jednoduchou práci s databází (MySQL, PostreSQL).
Je rozdělena na jednotlivé logické bloky.
Storage ---(DBAL)---> Mapper -> Repository -> Entity
Mapper vykonává dotazy nad Nextras\Dbal, což je knihovna pro práci s databázemi, napsaná taktéž Honzou Škráškem a Honzou Tvrdíkem.
Repository nám skrz mapper připravuje data a vytváří z nich Entity případně kolekce. Nelze nad ním volat jednotlivé SQL dotazy, na to slouží mapper.
Entita je obálka nad daty. Která nemusí být úplně hloupá, to záleží na vás, jak to pojmete. Entity v Nextras\Orm podporují tzv. inject*
metody, takže si tam můžete vstříknout, co potřebujete.
Základní stavební jednotkou Nextras\ORM je samozřejmě entita.
Entity se definují pomocí anotací, a ty jsou velmi vyčerpávající, pojďme si to rozebrat na příkladu.
/**
* @property string $name
* @property DateTime $born
* @property string|NULL $web
* @property-read int $year
* @property-read int $age {virtual}
* @property Address $address {1:1d Address primary}
* @property DateTime $createdAt {default now}
* @property int $gender {enum self::GENDER_*}
*/
class Member extends Nextras\Orm\Entity\Entity
{
const GENDER_MALE = 1;
const GENDER_VELKE = 2;
protected function getterAge()
{
return date('Y') - $this->born->format('Y');
}
}
Property se definují klíčovým slovem @property
nebo @property-read
. Pokud jde o @property-read
nelze do ní zapisovat a ORM to přísně kontroluje.
Poté se definuje typ fieldu, např. string
, int
, float
, bool
apod. Zvládno to však i DateTime
. Pokud doplníme typ kouzelným |NULL
, říkáme tím, že tento field může být null
ový.
Následuje název fieldu ve stylu camelCase. Pokud máte radši underscore, myslím, že se to dá nějak donastavit. Ale řekl bych, že camelCase je taková klasika.
V základu vám Nextras\ORM samo mapuje sloupečky na fieldy v entitě. Pokud si ale chcete nějaký sloupeček přece jenom upravit, lze použít metod getter<field>
a setter<field>
. Například getterAge
.
Občas se to velmi hodí.
Opatrně s pojmenováním, pokud by jste použili getAge
, tak při použítí magie typu $member->age
se vám tato metoda nezavolá. To je rozdíl od magického Nette\Object.
Virtual je specialní typ, kterým si sami definujete jednotlivý field. Poté vám funguje magie, viz příklad a field $age
.
Skvělá vecička při práci s datumem.
@property DateTime $createdAt {default now}
Pakliže nenasetuje nic do $member->createAt
, knihovna vám tam vloží aktualní čas/datum.
Je skvělé, že je zabudovaná podpora pro výčtové typy - jako je enum.
/**
* @property int $gender {enum self::GENDER_*}
*/
class Member extends Nextras\Orm\Entity\Entity
{
const GENDER_MALE = 1;
const GENDER_VELKE = 2;
}
ORM si na začátku sestaví mapu všech možností pro enum, a poté vám vstup krásně validuje.
ORM nabízí plnou podporu pro všechny možné relace.
1:1d
Tato relace se řídí postfixem primary, který určuje jaká entita je hlavní a která nese referenci (in storage).
/**
* @property Author {1:1d Author primary}
*/
class Book extends Nextras\Orm\Entity\Entity {
}
V této entitě máme uloženého autora.
Skrze repozitáře/kolekce můžeme data filtrovat, řadit, omezova apod.
Obecně se dá říci, že metody get*
nám vrací právě jednu entitu a find*
nám vrací kolekci, nad kterou pak můžeme vykonávat další dotazy.
Metody nad kolekcemi:
findBy(array $conds)
- filtruje podle hodnotgetBy(array $conds)
- stejná jako findBy, ale vratí 1. řádek (entitu)orderBy($column, $direction)
- seřadí pole entity podle soupečku/ůlimitBy($limit, $offset)
- vratí část polefetch()
- vrací 1. řádek (entitu)fetchAll()
- vrací všechny řádky (entity)fetchPairs($key, $value)
- vrací pole, kde je klíč $key
například ID a hodnota $value
například NAMEVýhody podle mého nazoru:
Někdo by mohl namítat, že už tu existuje Doctrina. Ano, ale na můj vkus je velká a použítí není uplně jednoduché, pokud člověk není tak zkušený nebo nemá připravený dev-stack.
Za to Nextras\ORM se hodí i na malé projekty (od 2-3 provázaných entit), přes střední až po velké aplikace.
Podle mě je jeden větší nedostatek (možná, že už není, protože vývoj neustále probíhá a nové verze se jen hrnou) a to, že programátor musí definovat relace na obou stranách.
Jedná se konkrétně o nextras/orm#29, kde se můžete zapojit směle do diskuze.
Lépe na příkladu..
/**
* @property OneHasMany|Image[] $images {1:m Image}
*/
class Book {
}
/**
* @property Book $book {m:1 Book}
*/
class Image {
}
Vždy se musí uvést i závislost u druhé entity (Image), což může trochu vadit. Ne vždy se totiž potřebuji dotazovat na knihu jako $image->book->..
. Ale na tohle se dá zvyknout.
Dle statusu na twitteru, Honza pracuje na nějakém rozšíření do PhpStormu, kterou všichni určitě rádi uvítáme (tweet).
Nedávno jsem jeden projekt převáděl na Nextras\ORM a u toho mě napadla myšlenka vytvořit generátor, který by mi s tím pomohl. A tak vznikl contributte/nextras-orm-generator.
Stačí mu dát přístupy do databáze a on vám vytvoří entity, repozitáře, mappery a případně fasády dle vašich tabulek.
Umí správně nakonfigurovat typy sloupečků, DateTime
, enum
a základní vazby. Bohužel nepozná, o jakou vazbu se jedná, zda-li o 1:1, 1:m, m:1, m:n nebo 1:1d. To už si musíte dodefinovat sami.
Každopádné vám ušetří spoustu času.
Do budoucna plánuji i konvertor z Doctrine ---> Nextras\ORM
a také z LeanMapperu ---> Nextras\ORM
.
Na Githubu je k dispozici základní example, jak generátor funguje. Mam v plánu dodělat základní popisek ke configu a také one-phar-file, aby se to dalo jednoduše spouštět.
Budu rád, když mi necháte komentář, jesti se vám to líbí nebo případně, zda-li vám to fungovalo/nefungovalo dle očekávání.
Závěrem bych rád poděkoval Honzovi Škráškovi za práci na ORM a DBAL, celkově na Nextras
. Má to vše hlavu a patu. Dokumentace je velmi zdařilá a mě osobně se v ní dobře orientuje.
Díky ti.. :-)