Doctrine 2 ORM & Migrations extension a sandbox pro Nette 2.0.x

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Patrik Votoček
Člen | 2221
+
0
-

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
bazo
Člen | 620
+
0
-

dal by sa spravit taky sandbox aj pre mongo ODM?

newPOPE
Člen | 648
+
0
-

bazo napsal(a):

Hi, nieco mam rozrobene. Akurat je to pre verziu ktora je v /download (vyhradne pouzivam len tie :-))

Mohol by som to v dohladnom case dat von aspon v akom takom stave :-D. Ostatni to pomocou pull-requestov doladia :-)

mbskot
Člen | 42
+
0
-

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
+
0
-

@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
+
0
-

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
+
0
-

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
+
0
-

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..

bazo
Člen | 620
+
0
-

za help treba napisat meno prikazu, zoznam prikazov sa zobrazi index.php list

Dalibor
Člen | 26
+
0
-

bazo napsal(a):

za help treba napisat meno prikazu, zoznam prikazov sa zobrazi index.php list

Jo, ale když napíšeš jen „php index.php help“ tak, jak to je v readme, tak ti vyjedou jen příkazy pro Symfony..

Quinix
Člen | 108
+
0
-

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
+
0
-

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
+
0
-

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)

Jan Endel
Člen | 1016
+
0
-

nemáš náhodou přístupové údaje k databázi v development/production? při přístupu přes konzoli se berou data ze sekce console

Tomáš Kolinger
Člen | 136
+
0
-

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
+
0
-

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).

knyttl
Člen | 196
+
0
-

Ahoj,

možná jsem trochu natvrdlej, ale kde a jak získáváš entityManager? :-) V tomhle příkladu, jak to běží celé v pozadí Usera, tak to úplně zřejmé není.

Tomáš Kolinger
Člen | 136
+
0
-

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
+
0
-

@knyttl: $container->doctrine->entityManager->default resp delam si alias https://github.com/…/config.neon#L43 $container->database

@Tomáš Kolinger: bug opraveno

hapi
Člen | 35
+
0
-

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
+
0
-

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.

hapi
Člen | 35
+
0
-

to jsem si taky myslel, bohužel pokud zkusím vypsat
die(var_export($container->findByTag(‚doctrineListener‘), true));
v Nella\NetteAddons\Doctrine\Config\Extension::createEventManager
vrací se mi prázné pole…

llook
Člen | 407
+
0
-

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
+
0
-

diky za odpoved, ted mam jinou praci, ale az to vyzkousim, dam vedet :)

hapi
Člen | 35
+
0
-

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

Morlok
Člen | 26
+
0
-

Uvazujem, nebolo by lepsie mat toto rozsirenie pre nette v adresary „libs/Doctrine/Nette“? Mi pride ze by to bolo „logickejsie“ a nebola by tam zavyslost na Nelle.

Editoval Morlok (5. 6. 2012 11:38)

Patrik Votoček
Člen | 2221
+
0
-

Žá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
+
0
-

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
+
0
-

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
+
0
-

@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
+
0
-

protože to je složka jednotlivých migrací nikoli knihovna na práci s nimi…

Azim
Člen | 41
+
0
-

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
+
0
-

@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.

Azim
Člen | 41
+
0
-

ok, diky

hapi
Člen | 35
+
0
-

Patriku, prosím, změň si v dokumentaci, že tag pro listenery již není doctrineListener, ale doctrineEvent :) trošku si mě tím pozlobil, když se mi roze***** prefixy tabulek :)

Patrik Votoček
Člen | 2221
+
0
-

dík fixnuto… Příště můžeš rovnou poslat pull https://github.com/…/nellafw.org :-)

hapi
Člen | 35
+
0
-

ajo, vidis to, sem si nevsim, ze tam mas i dokumentaci :)

Azim
Člen | 41
+
0
-

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
+
0
-

pravděpodobně máš na serveru eAccelerator který ti mrví komentáře. doporučuju ho vypnout

Azim
Člen | 41
+
0
-

Patrik Votoček napsal(a):

pravděpodobně máš na serveru eAccelerator který ti mrví komentáře. doporučuju ho vypnout

bylo to tim, vyreseno a diky

Nutelac
Člen | 58
+
0
-

Je možné přidávat vlastní datové typy, dědící od Doctrine\DBAL\Types\Type?

Patrik Votoček
Člen | 2221
+
0
-

@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.

Nutelac
Člen | 58
+
0
-

Chtěl jsem si vytvořit typ, který by se mi automaticky staral o hashování a porovnávání hesla. Není to sice nic důležitého, ale život by mi to zpříjemnilo :).

Patrik Votoček
Člen | 2221
+
0
-

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
+
0
-

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 :)

Patrik Votoček
Člen | 2221
+
0
-

jde to… ale jinak… zaregistruješ si to rozšíření znova s jiným názvem

leninzprahy
Člen | 150
+
0
-

Nojo, to mě vůbec nenapadlo, díky.

krucinal
Člen | 38
+
0
-

Existuje nekde nejaky polopaticky navod jak to zprovoznit? Tento sandbox samostatne nefunguje. Zrejme je do nej potreba sehnat nejake dalsi soucasti ktere na gitu chybi.

Patrik Votoček
Člen | 2221
+
0
-

a co třeba trochu víc rozepsat to „nefunguje“?

krucinal
Člen | 38
+
0
-

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);