Bezbolestná integrace Doctrine 2 ORM do Nette – Kdyby/Doctrine

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
David Matějka
Moderator | 6445
+
0
-

proc mas v config.local.neon konfiguraci nette/database?

a config.local.neon ma vyssi prioritu nez config.neon. takze kdyz mas v config.local.neon user: root, tak se to bude snazit prihlasit pod rootem

edit: ruzne udaje k databazi atd. davej do config.local.neon, v config.neon davej jen obecne platne konfiguracni veci pro aplikaci

Editoval matej21 (8. 3. 2014 22:12)

tivvit
Člen | 36
+
0
-

@matej21 nette/database jsem smazal. Pokud v config.neon budu mít jen obecně platné konfigurace musím vytvořit ještě něco jako config.production.neon a v boostrap ho nastavit?

David Matějka
Moderator | 6445
+
0
-

ne – jak pisu, dej to do config.local.neon

tivvit
Člen | 36
+
0
-
Tomáš Votruba
Moderator | 1114
+
0
-

@akadlec: Ad Gedmo, díky. Máš nějaký fční příklad (create, read, update)? Moc nechápu ukázku v repu. To samé by šlo i bez rozšíření.

akadlec
Člen | 1326
+
0
-

@Tomáš Votruba: no zatím nic veřejného ne, ale pracuješ s tím jako by tam translation nebyl. A automaticky ti to vytahuje ty překlady co máš nastaveno jako locale. ale asi se to dá snadno realizovat i bez rozšíření.

one-two
Člen | 80
+
0
-

Ad Gedmo: též bych ocenil, kdyby někdo zveřejnil nějakou ukázku nebo demo

noodle
Člen | 9
+
0
-

Ahoj, chtěl bych se zeptat, jestli existuje něco jako sandbox nebo demo aplikace Kdyby/Doctrine?
Jsem docela zmatený, snažil jsem se inspirovat v tomto tématu https://forum.nette.org/…est-practice, ale zatím bez pokroku.
Díky za odpověď

Filip Procházka
Moderator | 4668
+
0
-

Ohledně gedma, existuje balíček který kompatibilitu řeší. Já gedmo nepoužívám protože se mi nelíbí jak interně funguje a jak je implementované. Škoda že je autor línej balík rozdělit.

akadlec
Člen | 1326
+
0
-

@Tomáš Votruba: ok tak se něco pokusím. Používám balíček rixiho jak už uvedl Filip. Konfigurace v neonu je jednoduchá, jako jakákoliv jiná extension:

gedmo:
	translatableLocale	: en_US
	defaultLocale		: en_US
	# Enabled extensions
	loggable		: on
	sluggable		: on
	softDeleteable	: on
	sortable		: on
	timestampable	: on
	translatable	: on
	tree			: on
	uploadable		: on
	blameable		: on

pozn: já si rixxiho balík upravil abych zapínal/vypínal konkrétní doplňky gedma

K nastavení doctrine je asi potřeba přidat ještě filtr pokud chceš využívat SoftDeletable

doctrine:
	....
	....
	filters:
		# without this softDeleteable won't work......probably
		soft-deleteable	: Gedmo\SoftDeleteable\Filter\SoftDeleteableFilter

No a pak pokud chceš dělat entity s překlady tak stačí nějak takto: https://gist.github.com/akadlec/9505625
Máš tedy dvě entity, jedna je hlavní a to co v ní chceš přeložit doplníš o anotaci @Gedmo\Translatable (popřípadě podle toho jak si připojiš namespace gedma) a druhou entitu která ti bude shromaždovat jednotlivé překlady.

když děláš save klasicky, tj. nic nepřidáš tak ti to uloží ve výchozím locale jaké máš pro gedmo nastavené (v tomto příkladu en_US)

$widget= new Entities\Widgets\Widget;
$widget->setName('my name in en');
$em->persist($widget);
$em->flush();

pokud chceš uložit v jiné jazykové mutaci tak jen si přidáš konkrétní locale dané entitě:

$widget= new Entities\Widgets\Widget;
$widget->setName('my name in de');
$widget->setLocale('de_de'); // zmena locale entity
$em->persist($widget);
$em->flush();

co se pak týká načtení překladu tak je to stejné, v základu se ti načte entita s locale co máš nastaveno, ale máš možnost si z tentity vytáhnout všechny překlady:

$translations ´$widget->getTranslations();
/* $translations contains:
Array (
    [de_de] => Array
        (
            [name] => my title in de
        )

    [en_us] => Array
        (
            [name] => my title in en
        )
)*/

Nastavení výchozího locale podle toho v jaké jazykové verzi jsou stránky přepnuty provádím zatím dost nešikovně v presenteru v metodě startup:

// Modify GEDMO listeners
$this->context->getService('gedmo.gedmo.translatable')->setTranslatableLocale("cs_CZ"); // nebo en_US atd

Já z GEDMO ještě používám blameable co loguje editora/autora entity automaticky při akci a loggable co mě verzuje vybrané entity, takže ve startupu ještě upravím tyto listenery:

// User is logged in...
if ( $this->user->isLoggedIn() ) {
	// Set user for blameable interface
	$this->context->getService('gedmo.gedmo.blameable')->setUserValue($this->user->getIdentity());
	// Set username for loggable interface
	$this->context->getService('gedmo.gedmo.loggable')->setUsername($this->user->getIdentity()->getUsername());
}

pozn: vím že je to v presenteru/startup prasárna, ale nevím jak jinak ty data do gedma předat.

A v podastě je to vše pro základní využití GEDMO extension. Ono samotná práce s entitama (vytažení, filtrování atd. je závislá na tom jak s nima pracuješ ale v podstatě pokud ti stačí tahat překlady podle aktuálního locale tak ti stačí vždy nastavovat ten listener a ten zajistí že ti z DB příjde požadovaný překlad.

Jinak GEDMO má sice asi trochu chaoticky popsanou ale snad pochipitelnou dokumentaci v repu

akadlec
Člen | 1326
+
0
-

@Filip Procházka: hele taky se mě některá řešení v GEDMO nelíbí, už sem si říkal že bych to celé přepsal aby to integrovalo Kdyby mnohem čistěji ale holt nejsem takový killer abych to teď udělal dobře ;)

Jiří Nápravník
Člen | 710
+
0
-

akadlec když tu řešíte Gedmo, jak vám funguje Gedmo\Tree, je pořád třeba upravovat zdroják gedma? Jako píšeš tady? ale mco se mi to nelíbí… + si tam vždy pro pohodlnost přepisuju na EntityDao

enumag
Člen | 2118
+
0
-

@Jiří Nápravník: Ještě stále ano, ale řešení je zdá se na cestě: https://github.com/…ts/issues/22.

Tomáš Votruba
Moderator | 1114
+
0
-

@akadlec: Díky tvým spiskům jsem implementoval možnost předání locale translatorem (v mém případě Kdyby\Translation). Překopal jsem rixxi extension (pull pošlu zítra).
Vše co stačí: https://gist.github.com/…ruba/9509314

Tím pádem není potřeba nic řešit v presenteru.

Pak ještě nastavit správně název služby translatoru zde (v mém případě $this->getService('translation.default')->getLocale()).

(Pozn.: Řeším pouze rozšíření translatable).

Editoval Tomáš Votruba (12. 3. 2014 19:26)

mishak
Člen | 94
+
0
-

Mohl bys poslat pull? Fix pro listenery teď hosiplan testuje.

akadlec
Člen | 1326
+
0
-

@Tomáš Votruba: zajímavý hint, díky. Já to chtěl původně taky vyřešit v extension, včetně předání těch useru pro blameable a loggable, ale narážel jsem na problémy s cirkulací. Zkusim znova nějak pořešit.

Tomáš Votruba
Moderator | 1114
+
0
-

Vytvořil jsem balíček Zenify/DoctrineExtensions pro jednoduchou a rychlou integraci DoctrineExtensions.

extensions:
    - Zenify\DoctrineExtensions\DI\Extension

@akadlec: To by pak vypadalo nějak takto (sic nevím, kde se bere služba gedmo.gedmo.loggable).
Takto to by to ok pro tebe?

Editoval Tomáš Votruba (18. 3. 2014 11:16)

akadlec
Člen | 1326
+
0
-

@Tomáš Votruba díky ušetřil si mi práci ;) Služba gedmo.gedmo.loggable se brala přímo z gedma, resp jeho extension. Já jsem si tu extension napsal trochu jinak než ji měl @mishak

Tomáš Votruba
Moderator | 1114
+
0
-

@akadlec: Rádo se stalo, je to vzájemné. Kdybys ještě něco potřeboval přepsat do extension (obvykle věci, které se opakují v presenteru nebo používající context), dej vědět.

Ripper
Člen | 56
+
0
-

Zdravím,

jak řešíte ukládání dat z formuláře? Já jsem to v mém UserManageru vyřešil následovně –

public function updateUser(App\Entity\User $user, $values)
	{
		foreach ($values as $name => $value)
		{
			$user->$name = $value;
		}

		$this->userDao->save($user);
	}

Má někdo lepší řešení? Nechce se mi to dělat pole po poli.

Editoval Ripper (17. 3. 2014 13:51)

akadlec
Člen | 1326
+
0
-

entitycrud manažerem což zjednodušeně dělá to co tvoje funkce jen má pár featurek navíc.

Ripper
Člen | 56
+
0
-

A to vezmu kde?

akadlec
Člen | 1326
+
0
-

napíšeš si ho ;)

Jiří Nápravník
Člen | 710
+
0
-

Filip připravuje Kdyby\DoctrineForms, které by mělo tyhle věci mapovat automaticky. Jinak já osobně používám Zend\StdLib\Hydrator…

akadlec
Člen | 1326
+
0
-

@Tomáš Votruba: tak asi něco dělám v té extension špatně. Nevím proč ale zprvu se to chovalo ok, po vikendu k tomu sednu a opět klasicka hláška:

Circular reference detected for services: user, authenticator, authentication.system, accountModule.userFacade, accountModule.userDao, gedmo.blameable

David Zadražil
Člen | 62
+
0
-

@Ripper, @Jiří Nápravník – A co požít DoctrineModule – Hydrator? :)

Editoval David Zadražil (17. 3. 2014 20:01)

Tomáš Votruba
Moderator | 1114
+
0
-

@akadlec: Bylo by fajn zjistit, co přesně je s čím zacyklené. Pro náš případ je důležité zřejmě gedmo.blameable.
Kdyby sis s tím nevěděl rady, tak mi to můžeš poslat a zkusím se na to podívat.

Martin Vágovszký
Člen | 14
+
0
-

Ahoj, hraju si s tímhle doplňkem.. Je super vše mi funguje až na jednu drobnost a to je cli rozhraní. Když dám v rootu projectu:

php www/index.php hodí mi to:

ERROR: the server encountered an internal error and was unable to complete your request.

Nikde jsem nenašel jak zprovoznit a používat cli rozhraní s tímto doplňkem. Prosím poraďte, díky.

leninzprahy
Člen | 150
+
0
-

Koukni do logu aplikace (adresář log na stejné úrovni jako www, měla by tam být uložená laděnka), cli nepozná vývojový režim a tak výjimky loguje, jako v produkčním.

Editoval leninzprahy (19. 3. 2014 14:31)

Tomáš Votruba
Moderator | 1114
+
0
-

Ahoj, zkus se kouknout do logs na ladenku.

Martin Vágovszký
Člen | 14
+
0
-

Chyba na mém přijímači.. Špatná práva na složky v tempu. Pro apache ok, ale pro uživatele špatné. Nyní už šlape jako hodinky.. Díky

akadlec
Člen | 1326
+
0
-

@Tomáš Votruba no tipuju to na problém s tím že kde chce dostat uživatele, ten se má získat z identity, identita bere uživatele z jeho fasady a uživatelská fasada se inicializuje až po gedmo ;)

Tomáš Votruba
Moderator | 1114
+
0
-

@akadlec: Potřeboval bych sandbox, blameable sám nepoužívám, nevím jak funguje.
Od boku bych zkusil jej přesunout do afterCompile()

Helda
Člen | 10
+
0
-

Ahoj, mohu porosit o drobné nakopnutí? Lze si nějak při použití Gedmo Tree sáhnout na childrenHierarchy(), abych nemusel vytvářet vlastní výpis stromu kategorií?

Předem díky za Vaše rady

akadlec
Člen | 1326
+
0
-

tak máš tam getChildren. Co přesně chceš?

Helda
Člen | 10
+
0
-

Přesně chci docílit tohoto https://github.com/…/doc/tree.md#…

Ale ať se k tomu snažím přistoupit jakkoliv, tak stále Call to undefined method.

//EDIT: Vyřešeno vlastním vykreslením stromu v HTML

//EDIT 2:
Tak jsem zjistil, že nelze volat žadné pomocné funkce z Gedmo tree. Konkrétně mi jde o https://github.com/…/doc/tree.md#…, konkrétně funkce moveUp a moveDown. Při pokusu jí volat přes DAO mi píše Call to undefined method Kdyby\Doctrine\EntityDao::moveUp(). Pokud si tam předám EntityManager,

/**
 * Je jedno jestli předám
 * @var Kdyby\Doctrine\EntityManager
 * nebo
 * @var Doctrine\ORM\EntityManager
 */
public $em;

public function __construct(EntityManager $em)
{
	$this->em = $em
}

Tak mi to stále vyhazuje chybu Call to undefined method Kdyby\Doctrine\EntityDao::moveUp()

Pokud u DAO nebo u EntityManageru použiji ještě funkci findAll(), tak se začne tvářit, že uvedené funkce existují, ale hodí následující chybu Call to a member function moveUp() on a non-object. Má někdo nějaký nápad jak to vyřešit?

Děkuji za případné rady.

Editoval Helda (22. 3. 2014 2:58)

Climber007
Člen | 105
+
0
-

Je to dotaz mírně mimo vlákno, nicméně nevím kam jinam s ním,

Kam je vhodné umístit ošetření integrity? Do entity nebo do modelové třídy (obdoba zmiňovaných \App\Articles)?

Díky!

Jan Mikeš
Člen | 771
+
0
-

Ahoj, rad bych zacal pouzivat Kdyby\Doctrine, o Doctrine toho mam spoustu nacteno, par veci je mi ale nejasnych – jeste jsem ani nezacal a nez zacnu tak bych mel rad jasno.

Nekde jsem se docetl, ze lze vygenerovat entity na zaklade hotove db a tak stejne lze vygenerovat db z entit, strasne rad bych chtel videt o priklad obou vyuziti, zaroven uvest co je lepsi, zda vytvorit db a z db vygenerovat entity, nebo vytvorit entity a nechat si vygenerovat db, co je doporucovany zpusob a proc?

Jak resit, pokud jsem zvykly mit v kazde tabulce sloupce nesouci info o tom kdo kdy a jak je vlozil (ins_dt, ins_user_id, ins_process, upd_dt, upd_user_id, upd_process), lze to udelat vlozenim traity do kazde entity, ktera by obsahovala properties s prislusnymi anotacemi?

Jak se resi default hodnoty, napr. pro vyse zmineny sloupec ins_user_id, jsem v NDB resil extendovanim Nette\Database\Table\Selection, ktera byla rozsirena o Nette\Security\User, jak vyresit default hodnotu CURRENT_TIMESTAMP pro datetime/timestamp sloupce?

Snad nejsou me otazky uplne stupidni, predem dekuji za odpovedi a objasneni.

mkoubik
Člen | 728
+
0
-

Lexi napsal(a):
Nekde jsem se docetl, ze lze vygenerovat entity na zaklade hotove db a tak stejne lze vygenerovat db z entit, strasne rad bych chtel videt o priklad obou vyuziti, zaroven uvest co je lepsi, zda vytvorit db a z db vygenerovat entity, nebo vytvorit entity a nechat si vygenerovat db, co je doporucovany zpusob a proc?

Pokud píšeš novou aplikaci bez existující db tak rozhodně piš entity a db generuj.

Jak resit, pokud jsem zvykly mit v kazde tabulce sloupce nesouci info o tom kdo kdy a jak je vlozil (ins_dt, ins_user_id, ins_process, upd_dt, upd_user_id, upd_process), lze to udelat vlozenim traity do kazde entity, ktera by obsahovala properties s prislusnymi anotacemi?

Napiš si třídu s danými atributy od které všechny entity dědí. Datumy created/updated použij postup z timestampable tady, zbytek pomocí eventů.

Jak se resi default hodnoty, napr. pro vyse zmineny sloupec ins_user_id, jsem v NDB resil extendovanim Nette\Database\Table\Selection, ktera byla rozsirena o Nette\Security\User, jak vyresit default hodnotu CURRENT_TIMESTAMP pro datetime/timestamp sloupce?

V konstruktoru $this->createdAt = new DateTime().

David Matějka
Moderator | 6445
+
0
-

@Lexi:
generovani entit/databaze – viz http://docs.doctrine-project.org/…e/tools.html#…, s kdyby/console se ti ty commandy registrujou a budou dostupny v cli

s traitama by to melo byt OK

propojeni s User – tady casto pomuzou kdyby/events a napojeni se na nejakou z udalosti

akadlec
Člen | 1326
+
0
-

@Lexi:
2. Pokud to máš opravdu v každé tabulce tak bych to asi řešil base entitou, pokud jen v některých (jak to mám já) tak traitama. Mám to takto na několika entitach a zatím no problemo.

3. Default hodnoty si nadefinuješ v constructoru dané entity. Pokud chceš některé vyplňování zautomatizovat (autor, čas) tak můžeš využít gedmo a rixxiho extension pro nette, ale jak už tady jinde zaznělo, pár lidem se toto rozšíření nelíbí. Dalo by se nahradit pomocí kdyby\events

elevate
Člen | 31
+
0
-

Ahoj,

je velice omezující, že Kdyby\EventsManager neni kompatibilní s Doctrine\EventsManager – metoda getEventListeners vrací jinak indexované pole. Tudíž nefungují některé doctrine behavioral extensions.

Nedalo by se stím něco do budoucna dělat?

Michal Vyšinský
Člen | 608
+
0
-

To už je dva měsíce opraveno: https://github.com/…ents/pull/34

elevate
Člen | 31
+
0
-

Omlouvam se za flame :-) Díky!

Climber007
Člen | 105
+
0
-

Ahoj,
využívám dědičnosti a potřebuji mít jednu hlavní entitu a s více potomky, kde z každé třídy potomka může vést reference na toho samého rodiče. Do teď jsem měl jednoho potomka doufal, že v ‚discriminator column‘ lze uchovávat více hodnot, bohužel Doctrine tuhle hodnotu vezme a nacpe přímo jako index do pole a nemůžu najít jestli tomu někde Kdyby\Doctrine nepomáhá, resp. jestli to vůbec jde.

Díky za rychlé odpovědi
Martin

Filip Procházka
Moderator | 4668
+
0
-

Diskriminátor může být pouze jeden sloupec, ideálně nějaký string/int. Moc nechápu jak myslíš.

Climber007
Člen | 105
+
0
-

Filip Procházka napsal(a):

Diskriminátor může být pouze jeden sloupec, ideálně nějaký string/int. Moc nechápu jak myslíš.

Chtěl jsem k jednomu rodiči dva potomky. Rodič je ‚user‘ a ke každé roli jsem chtěl data navíc v jiných entitách jako potomcích. Momentálně jediné co mě napadlo je OneToOne ať už uni. nebo bi.
Původně jsem čekal, že diskriminátor může být něco jako [user,admin,customer].

akadlec
Člen | 1326
+
0
-

V discriminitaoru si určíš čím má doctrine rozlišit jednotlivé entity.

mkoubik
Člen | 728
+
0
-

A jak jinak než kompozicí bys to chtěl reprezentovat v php, když nemá vícenásobnou dědíčnost?

Climber007
Člen | 105
+
0
-

mkoubik napsal(a):

A jak jinak než kompozicí bys to chtěl reprezentovat v php, když nemá vícenásobnou dědíčnost?

Vícenásobná dědičnost není potřeba. Vždycky chci buď rodiče nebo potomky s atributy rodiče. Jde o to, že v tom discriminátoru nejde ukázat na více entit. On je to asi můj problém vnímat to zase jako objekty a ne jako tabulky. V relační databázi není problém mít v tabulce rodičů data, která potom načtu buď z prvního nebo z druhýho potomka, ale v objektech to nejde.