Bezbolestná integrace Doctrine 2 ORM do Nette – Kdyby/Doctrine
- David Matějka
- Moderator | 6445
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)
- Tomáš Votruba
- Moderator | 1114
@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í.
- noodle
- Člen | 9
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
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
@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
- Jiří Nápravník
- Člen | 710
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
@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
@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)
- Tomáš Votruba
- Moderator | 1114
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)
- Tomáš Votruba
- Moderator | 1114
@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
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)
- Jiří Nápravník
- Člen | 710
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
@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
@Ripper, @Jiří Nápravník – A co požít DoctrineModule – Hydrator? :)
Editoval David Zadražil (17. 3. 2014 20:01)
- Tomáš Votruba
- Moderator | 1114
@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
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
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)
- Martin Vágovszký
- Člen | 14
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
- Tomáš Votruba
- Moderator | 1114
@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
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
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
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
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
@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
@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
- Climber007
- Člen | 105
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
Diskriminátor může být pouze jeden sloupec, ideálně nějaký string/int. Moc nechápu jak myslíš.
- Climber007
- Člen | 105
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].
- Climber007
- Člen | 105
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.