Doctrine 2 ORM & Migrations extension a sandbox pro Nette 2.0.x
- Patrik Votoček
- Člen | 2221
Celé toto řešení je trvořeno jako extension pro nový Dependency Injection Container.
Dokumentace
http://doc.nellafw.org/cs/doctrine
Sandbox
Hotový a připravený sandbox najdete na GitHubu a na packagistu.
Nějáké nápady na změnu / vylepšení?
Changelog
v1.0
init
v2.0
- config sections
- Nette 2.0 stable
- Doctrine 2.2.0
v2.1
- Nette 2.0.1 stable
- Doctrine 2.2.1
- namespace Addons → NetteAddons
v2.2
- Nette 2.0.2
- Symfony Console 2.0.12
- new config
v2.3
- Nette 2.0.3
- Doctrine 2.2.2
- Symfony Console 2.0.14
- latest Nella
- latest Doctrine Migrations
v3.0
- Nette 2.0.5
- Doctrine 2.3.0
- Symfony Console 2.1.2
- latest Nella
- latest Doctrine Migrations
- mbskot
- Člen | 42
Patrik Votoček: sorry ak sa sprosto pýtam, ale prečo je pre entity
východzie miesto [%appDir%]?
Ja som ich mal doteraz v App\Model\Entities a podobne som mal Repositories. Je
to zlé? Ak hej, aká je doporučená adresárová štruktúra pre súbory
Doctrine a kde by mala byť umiestnená?
- Patrik Votoček
- Člen | 2221
@mbskot: rozhodně není špatně to co používáš ale právě kvůli tomu že každý používá jinou adresářovou strukturu je výchozí místo nastaveno tak jak je. Doctrine totiž neprochází jenom složku kterou jí zadáš ale i všechny její podsložky.
Já třeba vzhledem k modularitě systému nemám pouze jednu složku se všemy entitamy. Ale mám je roztroušené po celém projektu tak aby byly součástí celku kterého se týkají.
- StiFF.cz
- Člen | 8
Zkouším zprovoznit Doctrine2 na tomto sandboxu. Mám definované entity
i anotace na nich, ale stále mi to hlásí při pokusu o vytvoření
schématu tuto hlášku „No Metadata Classes To Process“. Přitom cesty
k entitám jsem si upravil podle své vlastní struktury.
Věděl by někdo, čím to může být?
EDIT: namespace :)
Editoval StiFF.cz (31. 1. 2012 16:51)
- llook
- Člen | 407
Edit: Tak už jsem na to přišel. Neinvaliduje se to samo, protože to
v CLI nerozpozná vývojový režim.
$configurator->isProductionMode()
vrací true.
Přidal jsem si tedy do bootstrapu tohle:
if (PHP_SAPI == 'cli') {
$configurator->setProductionMode(false);
}
Editoval llook (11. 2. 2012 14:58)
- Dalibor
- Člen | 26
kdyby někdo jako já zatuhnul na tom, že Console při zadání
php www/index.php help
nevypisuje volby pro ORM a další (orm:generate-proxies apod.), tak stačí volat bez help ;-)
php www/index.php
a já dvě hodiny hledám, proč se mi neregistrují extensions :-(
Patrik: díky za tento sandbox..
- Quinix
- Člen | 108
nakonfiguroval jsem si rozšíření podle návodu, ale když teď zkusím app spustit, dostanu:
Doctrine\Common\Annotations\AnnotationException
[Semantical Error] The annotation „@MappedSuperClass" in class
BaseEntity was never imported. Did you maybe forget to add a "use“ statement
for this annotation
config.neon:
common:
parameters:
database:
driver: pdo_mysql
dbname: app
host: localhost
user: root
password:
charset: utf8
collation: utf8_czech_ci
doctrine:
connections:
default: %database%
entityManagers:
default:
entityDir: %appDir%
proxyDir: %tempDir%
proxyNamespace: Model\Proxies
connection: default
console:
entityManager: default
services:
console: @doctrine.console
entityManager: @doctrine.entityManagers.default
Předtím jsem na vytvoření entity managera používal:
<?php
public static function createEntityManager($doctrine) {
$config = new Configuration();
$config->setProxyDir($doctrine['proxyDir']);
$config->setProxyNamespace($doctrine['proxyNamespace']);
$metadataDriver = $config->newDefaultAnnotationDriver($doctrine['entityDir']);
$config->setMetadataDriverImpl($metadataDriver);
$cache = new ArrayCache();
$config->setMetadataCacheImpl($cache);
$config->setQueryCacheImpl($cache);
$eventManager = new EventManager();
$eventManager->addEventSubscriber(new CacheSubscriber());
// Vytvoření samotného EntityManageru
$entityManager = EntityManager::create((array) $doctrine['connection'], $config, $eventManager);
$config->setSQLLogger(Doctrine2Panel::getAndRegister($entityManager));
return $entityManager;
}
?>
Kde může být chyba?
- Patrik Votoček
- Člen | 2221
Ve výchozím nastavení je tento sandbox nastaven na prefix Doctrine
anotací viz:
https://github.com/…els/User.php
Pokud chceš používat anotace bez prefixu mělo by stačit přidat:
common:
doctrine:
useSimleAnnotation: true
- Tomáš Kolinger
- Člen | 136
Stáhnul jsem si sandbox ale bohužel nemůžu rozchodit CLI rozhraní. Jak jsem dohledal, tak se údaje z neonu neberou a jsou tam nastaveny na výchozí hodnoty (prázdné heslo, prázdné jméno, …). Výchozí připojení (doctrine.connections.default) se předá ale pole %database% se ignoruje, nevím proč.
Samotná aplikace přes HTTP funguje a na server se připojí.
Editoval Tomáš Kolinger (29. 2. 2012 12:36)
- Tomáš Kolinger
- Člen | 136
Dával jsem údaje přímo do „common“ sekce a zkusil jí importovat/podědit do „console“ (console < common) ale nepomohlo.
Editoval Tomáš Kolinger (29. 2. 2012 17:24)
- Patrik Votoček
- Člen | 2221
od nette 2.0.x sekce „console“ neexistuje. Musíš „natvrdo“
definovat prostředí při
$configurator->addConfig(..., 'production');
(jedná se
o vlastnost Nette nikoliv tohoto pluginu).
- Tomáš Kolinger
- Člen | 136
Chybějící registrace existujících migrací (registerMigrationsFromDirectory()) u konfigurace pro migrace je úmyslná? Pracuji s migracemi poprvé, jak bez tohoto zaregistrování použiji vytvořenou migraci?
- Patrik Votoček
- Člen | 2221
@knyttl:
$container->doctrine->entityManager->default
resp delam si
alias https://github.com/…/config.neon#L43 $container->database
@Tomáš Kolinger: bug opraveno
- hapi
- Člen | 35
Dobrý večer,
začínám s nette a doctrine 2, potřeboval bych globálně nastavit prefixy
tabulek.
V doctrine 2 to lze pomocí listeneru viz. dokumentace, v dokumentaci nella je informace o možnosti nastavení tagu
doctrineListener.
Bohužel je to pro začátek relativně dost informací. Mohl by mi, prosím, někdo mi poradit, jak globální prefixy nejlépe nastavit?
Předem děkuji
Editoval hapi (30. 4. 2012 23:46)
- Acnnair
- Člen | 34
Myslím, že takéto niečo by mohlo fungovať (neskúšal som).
config.php
parameters:
tablePrefix: myprefix_
services:
doctrineTablePrefixListener:
class: DoctrineExtensions\TablePrefix
arguments: [%tablePrefix%]
tags: [doctrineListener]
S tým, že nezabudni nakopírovať triedu
DoctrineExtensions\TablePrefix
niekam kde ti to tvoj
autoloader nájde.
- llook
- Člen | 407
Ta třída musí implementovat \Doctrine\Common\EventSubscriber
.
Když vezmeš ten příklad z dokumentace a takhle ho upravíš, tak by to
mělo fungovat:
namespace DoctrineExtensions;
use \Doctrine\ORM\Event\LoadClassMetadataEventArgs;
class TablePrefix implements EventSubscriber
{
protected $prefix = '';
public function __construct($prefix)
{
$this->prefix = (string) $prefix;
}
public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
{
$classMetadata = $eventArgs->getClassMetadata();
$classMetadata->setTableName($this->prefix . $classMetadata->getTableName());
foreach ($classMetadata->getAssociationMappings() as $fieldName => $mapping) {
if ($mapping['type'] == \Doctrine\ORM\Mapping\ClassMetadataInfo::MANY_TO_MANY) {
$mappedTableName = $classMetadata->associationMappings[$fieldName]['joinTable']['name'];
$classMetadata->associationMappings[$fieldName]['joinTable']['name'] = $this->prefix . $mappedTableName;
}
}
}
/**
*
* @return array
*/
public function getSubscribedEvents()
{
return array(\Doctrine\ORM\Events::loadClassMetadata);
}
}
Config:
services:
doctrineListener_identifiersEnvelope:
class: DoctrineExtensions\TablePrefix('haf_')
tags: [ doctrineListener ]
- hapi
- Člen | 35
Tak jsem se konecne dostal k tomu, to vyzkouset a funguje to skvele :)
v prikladu v dokumentaci doctrine neni implementovano rozhrani, to byl ten problem :)
Dekuju za rady
- Patrik Votoček
- Člen | 2221
Žádná závyslost na Nelle tam není jen to má ten namespace, protože je to součástí NellaFW, který to využívá. Ale je to použitelně samostatně. Nezávisle na Nelle :-)
- Tomáš Jablonický
- Člen | 115
Ahoj,
snažil jsem se rozchodit Doctrine 2 podle zmiňovaného sandboxu a narazil jsem na chybu, kterou nemohu vyřešit. Po zasunutí Sandboxu se objevuje následující chybka:
Fatal error: Class ‚Nella\NetteAddons\Doctrine\Config\Extension‘ not found in /var/www/CMS/app/bootstrap.php on line 51
Tedy třída nebyla načtena Nette Loaderem.
- Patrik Votoček
- Člen | 2221
Aktualizováno
v3.0
- Nette 2.0.5
- Doctrine 2.3.0
- Symfony Console 2.1.2
- latest Nella
- latest Doctrine Migrations
jablon napsal(a):
Ahoj,
snažil jsem se rozchodit Doctrine 2 podle zmiňovaného sandboxu a narazil jsem na chybu, kterou nemohu vyřešit. Po zasunutí Sandboxu se objevuje následující chybka:
Fatal error: Class ‚Nella\NetteAddons\Doctrine\Config\Extension‘ not found in /var/www/CMS/app/bootstrap.php on line 51
Koukni na aktualizovaný sandbox a dokumentaci :-)
- Tomáš Jablonický
- Člen | 115
@Patrik Votoček: Díky, teď už to funguje velmi dobře (ve smyslu, že jsem to zatím rozběhl). Jinak ten Sandbox je výborná práce od skvělého programátora :-).
Edit:
Proč je Migrations v app/migrations a ne v libs? Trochu mě to
v app vadí.
Editoval jablon (25. 9. 2012 15:21)
- Patrik Votoček
- Člen | 2221
protože to je složka jednotlivých migrací nikoli knihovna na práci s nimi…
- Azim
- Člen | 41
Dobry den.
Potrebuji pridat eventSubscriber konkretni tride, inspiroval jsem se tady :https://forum.nette.org/…-nette-2-0-x#… , tzn. v configu mam
doctrineListener_getZakaznikSvatek:
class: ZakaznikGetSvatekSubscriber
tags: [ doctrineListener ]
ale takto nastavene sto vypada, ze se to vola pro kazdou entitu. Jak toto specifikovat? Dekuji za rady.
- Patrik Votoček
- Člen | 2221
@Azim: nevím o tom že by něco takového Doctrine umožňovala. Musíš si to ošetřit přímo v onom listeneru.
- Patrik Votoček
- Člen | 2221
dík fixnuto… Příště můžeš rovnou poslat pull https://github.com/…/nellafw.org :-)
- Azim
- Člen | 41
Zdravim.
Pouzivam aktualni versi sandboxu, na localhostu mi vse funguje tak jak ma, ale
pri nasazeni na produkcni server mi Doctrine vyhazuje vyjimku (DB vygenerovanou
orm:schema-tool importuju na server pres phpMyAdmin export/import do SQL)
Doctrine\Common\Annotations\AnnotationException:
[Semantical Error] The class „Doctrine\ORM\Mapping\Entity“ is not annotated with @Annotation. Are you sure this class can be used as annotation? If so, then you need to add @Annotation to the _class_ doc comment of „Doctrine\ORM\Mapping\Entity“. If it is indeed no annotation, then you need to add @IgnoreAnnotation("ORM\Entity") to the _class_ doc comment of class User.
Po refreshi vsak zacne vyhazovat jinou vyjimku:
Doctrine\ORM\Mapping\MappingException
Class „Obchodnik“ sub class of „Nette\Object“ is not a valid entity or mapped super class.
Nesetkal jste se s tim nekdo? google mi s tim moc nepomohl.
Diky za rady
Editoval Azim (9. 10. 2012 14:43)
- Patrik Votoček
- Člen | 2221
pravděpodobně máš na serveru eAccelerator který ti mrví komentáře. doporučuju ho vypnout
- Patrik Votoček
- Člen | 2221
@Nutelac: aktuálně ne – nenarazil jsem totiž na opodstatněnou potřebu vlastních typů. Až mě někdo nebo já sám dokáže přesvědčit že to dává smysl není problém ji přidat.
- Patrik Votoček
- Člen | 2221
Resp. abych byl přesnější. Tohle rozšíření umí všechno co umí Doctrine už z podstaty. Nicméně pro některé věci nemá syntax-sugar (tj možnost snadné definice v configu).
To znamená že svůj vlastní typ si stále můžeš přidat ale nepůjde to tak jednoduše jak by to šlo kdyby mělo toto rozšíření přímou podporu.
- leninzprahy
- Člen | 150
Chtěl bych se zeptat, jestli je pomocí toho rozšíření možné nastavit připojení k více databázím? Něco jako
doctrine:
connections:
default: %database.default%
other: %database.other%
entityManagers:
default:
entityDir: %appDir%/model/app
connection: connections.default
other:
entityDir: %appDir%/model/other
connection: connections.other
Při prohlížení zdrojáků se skoro bojím že ne.
Jinak zatím vše ostatní funguje jak má, díky za dobrou práci :)
- krucinal
- Člen | 38
Fatal Error
Class ‚Nella\Console\Config\Extension‘ not found
V bootstrapu je registrace trid, ktere v sandboxu vubec nejsou.
\Nella\Console\Config\Extension::register($configurator);
\Nella\Doctrine\Config\Extension::register($configurator);
\Nella\Doctrine\Config\MigrationsExtension::register($configurator);