Nette + Doctrine2 + Gedmo
- akadlec
- Člen | 1326
Zkoušel někdo z vás už připojit Gedmo extension k Doctrine2? Potřebuju nějak vyřešit načtení kategorií do stromu a co se mě podařilo vygooglit tak pomocí gedmo by to mělo jít.
Doctrine normálně inituju pomocí neonu takto:
services:
doctrineConfig:
class: Doctrine\ORM\Configuration
setup:
- setProxyDir(%doctrine.proxyDir%)
- setProxyNamespace(%doctrine.proxyNamespace%)
- setAutoGenerateProxyClasses(%doctrine.autoGenerateProxyClasses%)
- setMetadataCacheImpl
- setQueryCacheImpl
- setMetadataDriverImpl
_doctrineDummyConfig:
class: Doctrine\ORM\Configuration
autowired: no
doctrineChainDriver:
class: Doctrine\ORM\Mapping\Driver\DriverChain
setup:
- addDriver(@_doctrineDummyConfig::newDefaultAnnotationDriver(%doctrine.entityDir%), 'Entities')
doctrineEventManager:
class: Doctrine\Common\EventManager
setup:
- addEventSubscriber(Doctrine\DBAL\Event\Listeners\MysqlSessionInit('utf8', 'utf8_czech_ci'))
doctrineCache:
class: Doctrine\Common\Cache\ArrayCache
entityManager:
class: Doctrine\ORM\EntityManager
create: Doctrine\ORM\EntityManager::create(%doctrine.connection%)
Vše funguje, ale když přidám rozšíření o Gedmo tak je konec. Do doctrineEventManager přidám
- addEventSubscriber(\Gedmo\Timestampable\TimestampableListener())
a laděnka začne řvát že mám špatně anotace. Takže v entitě kde to řve upravím anotace z @id na @ORM\id, @column na @ORM\Column atd. Ale pak mi začne řvát že ta entita není validní classa. Je potřeba ještě někde něco jiného nastavit?
Doctrine2 mám v2.3.2 a Gedmo čerstvě z gitu v2.3.5
- akadlec
- Člen | 1326
Ještě teda doplním tu hlášku na které končím
Class System is not a valid entity or mapped super class
System je první entita se kterou se pracuje při zpracovávání, je extendována globální entitou která má definované společné vlastnosti. Pokud tuto extenzi odstraním tak stále stejný problém :(
- Michal Vyšinský
- Člen | 608
Myslím, že je chyba jen v entitě, nechceš ji ukázat? A hodila by se i ona globální entita.
EDIT: První věc co mě napadla: Změnil jsi i anotaci @Entity na @ORM\Entity?
Editoval CherryBoss (15. 3. 2013 10:07)
- akadlec
- Člen | 1326
jj anotace jsem změni, pokud je necham bez ORM\ tak to řve že je chyba v anotaci, pokud tam všude nahážu to ORM\ tak to právě skončí na té hlášce nevalidní entity.
No entita ma cca takovýto tvar (momentálně nemám kod u sebe)
/**
* @Entity(repositoryClass="SystemRepository")
*/
class System
{
/**
* @GeneratedValue
*/
protected $id;
/**
* @Column(type="string", length=100, unique=true)
*/
protected $name;
/**
* @Column(type="string", length=250)
*/
protected $description;
....
}
ono pokud to do toho setupu nepřidám tak to jede bez problému, jakmile tam to GEDMO přidám začne to blbnout :(
Editoval akadlec (15. 3. 2013 10:13)
- David Matějka
- Moderator | 6445
takhle nějak používám gedmo:
<?php
namespace Foo\Bar;
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\ORM\Mapping as ORM;
/**
* @Gedmo\Tree(type="nested")
* @ORM\Table(name="directory_entry")
* @ORM\Entity(repositoryClass="EntryRepository")
*/
class EntryEntity
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
* @var int
*/
private $id;
/**
* @ORM\Column(name="name", type="string", length=64)
*/
private $name;
/**
* @Gedmo\TreeLeft
* @ORM\Column(name="lft", type="integer")
*/
private $lft;
/**
* @Gedmo\TreeLevel
* @ORM\Column(name="lvl", type="integer")
*/
private $lvl;
/**
* @Gedmo\TreeRight
* @ORM\Column(name="rgt", type="integer")
*/
private $rgt;
/**
* @Gedmo\TreeParent
* @ORM\ManyToOne(targetEntity="EntryEntity", inversedBy="children")
* @ORM\JoinColumn(name="parent_id", referencedColumnName="id", onDelete="SET NULL")
*/
private $parent;
/**
* @ORM\OneToMany(targetEntity="EntryEntity", mappedBy="parent")
* @ORM\OrderBy({"lft" = "ASC"})
*/
private $children;
/**
* @Gedmo\TreeRoot
* @ORM\Column(name="root_id")
*/
private $root;
....
}
- David Matějka
- Moderator | 6445
koukni na https://github.com/…xtension.php
a koukni jestli ti tam neco nechybi, pripadne si rovnou nainstaluj z https://github.com/nella doctrine a gedmo
extensions a mas po problemech :)
(pokud jedes na dev verzi nette, tak mrkni na moje https://github.com/…/nette-gedmo
a https://github.com/…tte-doctrine
jsou to jen forky s kompatibilitou na dev verzi
- akadlec
- Člen | 1326
Takže beru zpět, neshazuje to gedmo ale orm mapping
Vyhozená exception:
Doctrine\ORM\Mapping\MappingException
Class "IPub\CMS\Models\System\Systems\System" sub class of "IPub\Doctrine\Entity" is not a valid entity or mapped super class.
Entita:
namespace IPub\CMS\Models\System\Systems;
use \Doctrine\ORM\Mapping as ORM,
\Doctrine\Common\Collections\ArrayCollection;
/**
* @ORM\Entity(repositoryClass="SystemRepository")
* @ORM\Table(name="system_systems")
*/
class System extends \IPub\Doctrine\Entity
{
/**
* @ORM\Id
* @ORM\Column(type="integer", name="system_id")
* @ORM\GeneratedValue
*/
protected $id;
/**
* @OneToMany(targetEntity="\IPub\CMS\Models\System\Systems\System", mappedBy="parent")
**/
private $children;
/**
* @ManyToOne(targetEntity="\IPub\CMS\Models\System\Systems\System", inversedBy="children")
* @JoinColumn(name="parent_id", referencedColumnName="system_id")
**/
private $parent;
/**
* @ManyToOne(targetEntity="\IPub\CMS\Models\Users\Users\User")
* @JoinColumn(name="user_id", referencedColumnName="user_id")
*/
protected $owner;
/**
* @OneToOne(targetEntity="\IPub\CMS\Models\System\Resellers\Reseller", inversedBy="system")
* @JoinColumn(name="reseller_id", referencedColumnName="reseller_id")
**/
protected $reseller;
/** @ORM\Column(type="integer", name="package_id", nullable=false) */
protected $package;
/** @ORM\Column(type="string", name="system_name", nullable=false) */
protected $name;
....
}
Abstraktní entita:
namespace IPub\Doctrine;
use \Doctrine\ORM\Mapping as ORM;
/**
* Basic entity with ID
*
* @ORM\MappedSuperclass
*
* @property-read int $id
*/
abstract class Entity extends \Nette\Object
{
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* @return array
*/
public function toArray()
{
return get_object_vars($this);
}
/**
* @return string
*/
public function __toString()
{
if ( isset($this->name) && $this->name !== null )
return $this->name;
else
return (string) $this->id;
}
public function __construct()
{
}
}
Nastavení a init doctrine2 v neonu:
common:
parameters:
doctrine:
prefix: smart_
entityDir: %appDir%/models
proxyDir: %tempDir%/temp/proxies
proxyNamespace: Entities\Proxies
autoGenerateProxyClasses: true
connection:
driver: pdo_mysql
user: root
password: root
dbname: nette_smartstart
host: localhost
services:
# DATABASE SERVICES
sqlLogger: IPub\Doctrine\Diagnostics\ConnectionPanel::register
mappingStrategy: \Doctrine\ORM\Mapping\UnderscoreNamingStrategy
tablePrefix:
class: IPub\Doctrine\TablePrefix
arguments: [%doctrine.prefix%]
doctrineConfig:
class: Doctrine\ORM\Configuration
create: Doctrine\ORM\Tools\Setup::createAnnotationMetadataConfiguration(%entityDirs%, true)
setup:
- setNamingStrategy(@mappingStrategy)
- setSQLLogger(@sqlLogger)
- setProxyDir(%doctrine.proxyDir%)
doctrineDummyConfig:
class: Doctrine\ORM\Configuration
autowired: no
doctrineChainDriver:
class: Doctrine\ORM\Mapping\Driver\DriverChain
setup:
- addDriver(@doctrineDummyConfig::newDefaultAnnotationDriver(%doctrine.entityDir%), 'Entities')
doctrineEventManager:
class: Doctrine\Common\EventManager
setup:
- addEventListener('loadClassMetadata', @tablePrefix)
- addEventSubscriber(Doctrine\DBAL\Event\Listeners\MysqlSessionInit('utf8', 'utf8_general_ci'))
doctrineCache:
class: Doctrine\Common\Cache\ArrayCache
entityManager:
class: Doctrine\ORM\EntityManager
create: Doctrine\ORM\EntityManager::create(%doctrine.connection%)
- akadlec
- Člen | 1326
Takže problém se mě podařilo na 99% odhalit, jen zatím nevím jak jej vyřešit. Problém je v tom že se používá simpleAnotationReader, když jej natvrdo vypnu tak to projde dále. Ten simple anotationreader pak špatně skládá názvy tříd.
jak tedy aktivovat tu extension co je v nellaframeworku?
class Extension extends \Nette\Config\CompilerExtension {}
a následně gedmo
class GedmoExtension extends \Nette\Config\CompilerExtension {}
edit:
předpokládám tedy nějak takto v bootstrapu:
$configurator->onCompile[] = function ($configurator, $compiler) {
$compiler->addExtension('doctrine', new Nella\Doctrine\Config\Extension);
};
Editoval akadlec (15. 3. 2013 21:59)
- akadlec
- Člen | 1326
Tak zase update ;)
Tu extension jsem vyhodil protože se mi ji nepodařilo spojit s configem, a
padala na tom že chybí driver a vrátil jsem se k definici přes neon a tam
stačilo upravit jeden řádek služby:
doctrineChainDriver:
class: Doctrine\ORM\Mapping\Driver\DriverChain
setup:
- addDriver(@doctrineDummyConfig::newDefaultAnnotationDriver(%doctrine.entityDir%, false), 'IPub\CMS\Models')
do metody newDefaultAnnotationDriver jsem přidal za entity dirs false čímže se deaktivuje simpleAnotationDriver.
Doufám že toto vyřešení problému je korektní.
Editoval akadlec (16. 3. 2013 15:10)
- akadlec
- Člen | 1326
Super, zatím mi tedy vše funguje jen jsem narazil na další problém ;) Snažím se použít extension Blameable. V anotaci je vše ok, při krokování jsem zjistil že tenhle listener funguje ok, ale problém je ten že v tom listeneru není přiřazen user který by se uložil do DB.
Potřeboval bych nějak zavolat něco takového:
$listener->setUserValue($user);
otaázkou tedy je jak se dostat k tomu konkrétnímu listeneru? Je definovaný v service doctrineEventManager pomocí addEventSubscriber
doctrineEventManager:
class: Doctrine\Common\EventManager
setup:
- addEventListener('loadClassMetadata', @tablePrefix)
- addEventSubscriber(Doctrine\DBAL\Event\Listeners\MysqlSessionInit('utf8', 'utf8_general_ci'))
- addEventSubscriber(Gedmo\Timestampable\TimestampableListener())
- addEventSubscriber(Gedmo\Blameable\BlameableListener())
- addEventSubscriber(Gedmo\Loggable\LoggableListener())
- addEventSubscriber(Gedmo\Sluggable\SluggableListener())
- addEventSubscriber(Gedmo\Tree\TreeListener())
- stefi023
- Člen | 71
Necetl jsem cely thread, doctrine2 + gedmo vesele pouzivam (ala Nella), ale tvuj problem bych asi resil vyclenenim listeneru jako sluzby:
blameableListener:
class: Gedmo\Blameable\BlameableListener
setup:
- setUser(@user) //nebo kde mas toho uzivatele
doctrineEventManager:
class: Doctrine\Common\EventManager
setup:
- addEventListener('loadClassMetadata', @tablePrefix)
- addEventSubscriber(Doctrine\DBAL\Event\Listeners\MysqlSessionInit('utf8', 'utf8_general_ci'))
- addEventSubscriber(Gedmo\Timestampable\TimestampableListener())
- addEventSubscriber(Gedmo\Loggable\LoggableListener())
- addEventSubscriber(Gedmo\Sluggable\SluggableListener())
- addEventSubscriber(Gedmo\Tree\TreeListener())
- addEventSubscriber(@blameableListener)
ale doporucuji jeste jednou zvazit tu extension z Nella FW, je to tam hezky vyresene a napr Event listenery se pridavaji jen otagovanim sluzby, etc…
- akadlec
- Člen | 1326
No tu bych i rád použil bohužel se mi jí nedaří zprovoznit :( a
sandbox nebo nějaké příklady jsem nenašel :(
No chvíli zkoušení a laborování a podařilo se mi nella extenze rozjet. Hodím to sem kdyby náhodou někdo stejně tápal jako já.
Extensions sem zaregistroval v bootstrapu
$configurator->onCompile[] = function ($configurator, $compiler) {
$compiler->addExtension('doctrine', new Nella\Doctrine\Config\Extension);
$compiler->addExtension('gedmo', new Nella\Doctrine\Config\GedmoExtension);
};
$container = $configurator->createContainer();
A v neonu jsem upravil konfigurace. Původně byly v sekci parameters, nyní je to pro každou extension zválšť
common:
doctrine:
entityDirs: ['%libsDir%/IPub/CMS/Models']
proxy:
dir : %tempDir%/proxies
namespace : 'App\Model\Proxies'
autogenerate : true
connection:
prefix: smart_
driver: pdo_mysql
user: root
password: root
dbname: nette_smartstart
host: localhost
charset: utf8
collation: utf8_general_ci
gedmo:
orm:
em : @doctrine.entityManager
loggable : true
sluggable : true
softDeleteable : true
sortable : true
timestampable : true
translatable : true
tree : true
uploadable : true
Snad jsem to realizoval správně. Gedmo extenze již funguji tak jak mají, ještě tedy musím dodělat tu Blameable která v nella není.
Editoval akadlec (16. 3. 2013 18:01)
- akadlec
- Člen | 1326
Takže znova jsem se pokusil o dokončení implementace Blameable od gedma za pomocí nella extension z gitu: https://github.com/…xtension.php s tím že jsem tam dodělal to blameable. Listener je regnuty bez problému. Jediné na co jsem narazil je to jak předat tomu listeneru Entitu přihlášeného uživatele.
Do té extension sem mimo jiné přidal tento registrator:
public static function registerBlameable(ObjectManager $om, EventSubscriber $listener)
{
$listener->setUserValue(\Nette\Environment::getUser()->getId());
if ($om instanceof \Doctrine\ORM\EntityManager || $om instanceof \Doctrine\ODM\MongoDB\DocumentManager) {
$om->getEventManager()->addEventSubscriber($listener);
}
}
a právě ta metoda $listener->setUserValue() provede uložení uživatele do listeneru který se pak použije při update v databázi. Když tam před environment předám ID tak je to málo, protože když se to ukládá tak je pořeba vazba na entitu uživatele. Když si tam předám službu fasády na uživatele tak to neprojde jelikož ta zas má vazbu na doctrine takže na tomhle to umře. Nenapadá někoho jak tam tu entitu uživatele dostat?
- stefi023
- Člen | 71
Tenhle zacarovany kruh jsem take resil (psal jsem si sve vlastni
Blameable
rozsireni) ale potreboval jsem to vyresit asap takze
nakonec jsem to udelal tak, ze jsem mel vlastni tridu User
(uz jsem
ji stejne mel z jinych duvodu), ktera mela metodu
getUserEntity(EntityManager $em)
, takze v tom listeneru jsem ji
toho entity managera predal (ten je v tech EventArgs $args
)…
rozhodne na to nejsem pysny, ale fungovalo to… to ale asi neni tvuj pripad,
pac bys ten BlameableListener
musel trochu prepsat…
Ale napada me, k cemu je vlastne
CompilerExtension::afterCompile(Nette\Utils\PhpGenerator\ClassType $class)
,
nedala by se zneuzit k donastaveni sluzby po jejich vytvoreni? fakt
netusim…
- akadlec
- Člen | 1326
No ja už přemýšlel nad tím že bych udělal vlastní \Security\User co by podědil \Nette\Security\User ale měl by k dispozici navíc fasádu pro usera, takže bych si do toho listeneru mohl předat toho usera jak mám teď tj. $listener->setUserValue(\Nette\Environment::getUser()); a pak upravit samotný listener kde se zpracovává user a udělat tam vytažení entity. Bylo by to sice takové přiohnutí a hrabání do samotného Gedmo rozšíření ale zatím mě jiná cesta nenapadla.
Nad tou metodou afterCompile jsem taky přemýšlel ale nedopátral jsem se zatím nikde jak to tam rozumně vyřešit.
- stefi023
- Člen | 71
Problem je v tom ze to „circular reference detected“ bys tam mel porad:
LISTENER needs USER needs FACADE needs ENTITY_MANAGER needs LISTENER :)
jestli jsem ti teda porozumel… presne tak jsem to chtel take udelat, ale pak mi nezbylo nic jineho, nez tomu USEROVI rict o ENTITY_MANAGER az kdyz se jsem se ho na tu entitu ptal
- akadlec
- Člen | 1326
No ten error circular reference detected jsem tam měl teď když jsem se pokusil předat přímo fasádu usera protože se udělal ten kruh že. Právě to co jsem popsal výše by fungovalo tak že by se předal jen ten user co by měl v sobě injectovanou fasádu a ta by se použila až při volání dané operace. Zatím jsem to nezkusil takže nevím zda se mi tam taky udělá ten kruh.
- Filip Procházka
- Moderator | 4668
Kdybys použil kdyby/events tak se ti container zkompiluje tak, že ti tuhle circural reference přeruší (platí pouze na listenery) ;)
Jenom jsem nezkoušel, jestli je kdyby/events
kompatibilní
s Nellou (myslím že není) :)
- Filip Procházka
- Moderator | 4668
Předpokládám, že článek si četl, takže rozvedu pouze to s tím fixováním circural reference.
Protože listenery mívají různé závislosti a né vždy se pustí
všechny, tak je kdyby/events
optimalizují takovým způsobem, že
všechny je zanalyzuje, vytvoří mapu ve které je popsané jaký listener
pouslouchá jakou událost a pak zruší jejich přímé provázání
s EventManagerem (zahodí všechny metody setup
které
přidávají listenery). Tahle mapa společně s DI Containerem se předá do
EventManageru a on si pak vytahuje listenery podle jména služby až když jsou
volány.
Příklad jak to vypadá fyzicky, když se to zkompiluje, můžeš vidět v testech.
- akadlec
- Člen | 1326
@Filip Procházka
Tak sem si na to zkusil sednout a pochopit. A pokud jsem pochopil
správně tak:
1. V bootsrapu si zaregistruji EventsExtension
$configurator->onCompile[] = function ($configurator, $compiler) {
$compiler->addExtension('events', new Kdyby\Events\DI\EventsExtension);
.....
};
2. Vytvořím si svůj listener kde zadefinuji jednolivé eventy
onNěco
3. Tento listener zaregistruji v configu, např. ten tvuj newRelic:
services:
# LISTENERS
newRelicListener:
class: Addons\Events\Listeners\NewRelic\NewRelicProfilingListener
tags: [kdyby.subscriber]
a mám z půle vyhráno? Abych to pak mohl aplikovat na to GEDMO tak musím vzít ty listenery gedma a upravit je aby je volala ta tva extension?
Editoval akadlec (11. 4. 2013 20:15)
- Filip Procházka
- Moderator | 4668
Listenery gedma zaregistruješ do DIC s libovolným jménem a nastavíš
jim tags: [kdyby.subscriber]
- Filip Procházka
- Moderator | 4668
Mělo by to stačit. Zkoušel jsi to? :) Já Gedmo nepoužívám, ale fungovat by to mělo.
- akadlec
- Člen | 1326
Takže zkusil jsem to a nefachči :(
services:
# LISTENERS
timestampableListener:
class: Gedmo\Timestampable\TimestampableListener
tags: [kdyby.subscriber]
upravil sem i ten listener:
class TimestampableListener extends MappedEventSubscriber implements Kdyby\Events\Subscriber
{
....
}
Je to tento listener: https://github.com/…Listener.php
Doplnění:
když to Gedmo rozšíření Timestampable vyhodím
z inicializace dle Nella a udělám to pomocí Kdyby tak to přestane
zavěšovat ty události, v tom listeneru je událost onFlush
která se nespustí a když se dívam do zaregistrovaných listenerů tak tam
není. Zkoušel jsem i upravit listener takto:
namespace Gedmo\Timestampable;
use Kdyby;
use Doctrine\Common\EventArgs,
Gedmo\Mapping\MappedEventSubscriber,
Doctrine\Common\NotifyPropertyChanged,
Gedmo\Exception\UnexpectedValueException;
class TimestampableListener extends MappedEventSubscriber implements Kdyby\Events\Subscriber
{
/**
* Specifies the list of events to listen
*
* @return array
*/
public function getSubscribedEvents()
{
return array(
'\\Doctrine\\ORM\\Events::prePersist',
'\\Doctrine\\ORM\\Events::onFlush',
'\\Doctrine\\ORM\\Events::loadClassMetadata'
);
}
Editoval akadlec (12. 4. 2013 21:35)
- Filip Procházka
- Moderator | 4668
@solution to upravoval, aby mu to jelo s
Kdyby/Doctrine
, koukni: https://gist.github.com/…tion/5389050
- Solution
- Člen | 50
Já jsem upravoval pouze NS, jelikož ten, co používalo gedmo v hintu
u metody pro registraci extensiony, tak byla deprecated: https://github.com/…verChain.php#L27
Ale jinak jsem v podstatě nic z funkčního kódu upravovat nemusel :-).
- akadlec
- Člen | 1326
@Filip Procházka Tak jsem se opět dostal k tomu rozchodit GEDMO podle výše uvedených postupů, měl jsem za to že se mě to podařilo již vyřešit, ale jak se zdá tak ne. Eventy se zaregistrují, projdou i optimalizaci listenerů ale při ukládaní entity se prostě metody onFlush či prePersist apod které mají listenery GEDMa nespustí. Nemohl bys pls nakopnout správným směrem?
- stefi023
- Člen | 71
Tak vcera jsem zrovna integroval blameable via Nella\Doctrine
a
Kdyby\Events
a zjistil jsem par postrehu, ktere by ti mohly pomoci.
Do Nella\Doctrine
muzes predat tvuj EventManager
(https://github.com/…xtension.php#L46).
Ten logicky musi byt pro celou aplikaci (nebo alepson souvisejici cast) pouze
jeden, v pripade Kdyby\Events
je to
@events.manager
:
doctrine:
eventManager: @events.manager
pak se ti zacnou ty eventy spoustet spravne…
Nicmene ale i po teto integraci jsem stale zasekly na
Circular reference detected...
Tentokrat ale tak, ze
blameableListener
je zavisly sam na sobe (?!). Po hlubsim zkoumani
fce DI\Container::getService($name)
jsem zjistil, ze je to asi tim,
ze v pripade blameable se ten blameableListener vola dvakrat
(createdBy
a updatedBy
) a snazi se nejak
nakonfigurovat… pri odstraneni jedne z techto akci to jiz funguje…
Debugovanim jsem dosel k tomu, ze pri inicializaci listeneru v
LazyEventManager
u (https://github.com/…tManager.php#L94)
se zavola v urcite zavislosti DI\Container::getService($name)
vicekrat (v pripade blameable 2x), a pokazde se snazi inicializovat, na podruhe
asi uz v zavislosti na tom prvnim… Uplne presne nevim, co se tam deje, uz
byla pozdni nocni hodina, ja chtel jit spat a tak jsem provedl pouze to, ze jsem
si v tom EventManager
u udelal registr nainicializovanych sluzeb a
spoustel to jen pro ty nove:
/** @var array already inicialized listeners */
private $inicialized = array();
/**
* @param string $eventName
*/
private function initializeListener($eventName)
{
foreach ($this->listenerIds[$eventName] as $serviceName) {
if(!array_key_exists($serviceName,$this->initialized)) {
$this->initialized[$serviceName] = true;
$subscriber = $this->container->getService($serviceName);
/** @var Doctrine\Common\EventSubscriber $subscriber */
$this->addEventSubscriber($subscriber);
}
}
unset($this->listenerIds[$eventName]);
}
Ted nedokazu rict, zda jsem delal nekde neco spatne pri definici/registraci listeneru, ale zdalo se mi to vse OK… tak nevim :( Nenapada vas nekoho neco?
Diky
- akadlec
- Člen | 1326
@stefi023: Takže jestli sem tě dobře pochopil tak doctrině předat ten vlastní event manager což se snažím používat ten layz od Filipa Procházky
$configurator->onCompile[] = function ($configurator, $compiler) {
$compiler->addExtension('events', new Kdyby\Events\DI\EventsExtension);
};
a pak v neonu:
doctrine:
eventManager: @events.manager
je tak?
- stefi023
- Člen | 71
jen jsem to tak zkousel, tzn nejdriv jsem zkousel vytvorit service:
userEntity
, ktera dostane Nette\Security\User
a
UserRepository
a ma fci getEntity
a vysledek teto fce
jsem predal do blameableListener
u.
Z patra (nemam to ted u sebe, jde o princip)
services:
userRepository: @doctrine::getRepository('User')
userEntity:
class: UserEntity
setup:
- setUser(@user)
- setUserRepository(@userRepository)
blameableListener:
class: Gedmo\BlameableListener
setup:
- setUserValue(@userEntity::getEntity())
tags: ['kdyby.subscriber']
pak jsem zkousel to predavat i ruzne jinak, ale porad jsem tam mel circular… Ovsem z ladenky bylo videt, ze se vytvareni teto sluzby inicializuje opravdu az on-demand (tzn vsechny zavislosti uz mely existovat)
- akadlec
- Člen | 1326
Hmmm zkusím si s tím ještě pohrát.
Jinak já dneska opět zapínal TREE a narazil jsem na problém v initu repository pro TREE.
public function __construct(EntityManager $em, ClassMetadata $class)
{
parent::__construct($em, $class);
$treeListener = null;
foreach ($em->getEventManager()->getListeners() as $listeners) {
foreach ($listeners as $listener) {
if ($listener instanceof \Gedmo\Tree\TreeListener) {
$treeListener = $listener;
break;
}
}
if ($treeListener) {
break;
}
}
}
V tomto konstruktoru to počítá s tím že tam je pole listenerů, jenže kdyby když se použije kdyby events tak je to mix objektů a polí, takže jsem ten kontruktor upravil:
public function __construct(EntityManager $em, ClassMetadata $class)
{
parent::__construct($em, $class);
$treeListener = null;
foreach ($em->getEventManager()->getListeners() as $listeners) {
if ( is_array($listeners) ) {
foreach ($listeners as $listener) {
if ($listener instanceof \Gedmo\Tree\TreeListener) {
$treeListener = $listener;
break;
}
}
} else if ($listeners instanceof \Gedmo\Tree\TreeListener) {
$treeListener = $listeners;
break;
}
if ($treeListener) {
break;
}
}
}
a vypadá že to šlape.
- mishak
- Člen | 94
Kompatibilita s Kdyby/Events bude opravena viz. report. Příště to rovnou nahlaš :)
Na integraci Kdyby/Doctrine a Gedmo budu průběžně pracovat tento měsíc, zatím mám chuť to přepsat nebo rovnou vzdát s Kdyby návrhem se to trochu bije (Tree) :).
Balík je Rixxi/Gedmo kód tradičně na github, kdyby někdo chtěl pomoci budu rád!
- mishak
- Člen | 94
V Kdyby/Events je stále ten bug AFAIK takže je třeba pro tree úprava listeneru jinak to funguje ± samozřejmě stromy mají vlastní repozitáře nekompatibilní s Kdyby\Doctrine\EntityDao tak se na to musí dávat bacha aby je člověk netahal přímo přes Dao (háže vyjímku). Soft-deleteable se musí registrovat ručně a to je nejspíš všechno :)
- mishak
- Člen | 94
Kolik máš času? Hosiplan chtěl napsat closure tree, by možná bylo lepší napsat vlastní stromy, zbytek jsou celkem jednoduche chování/vlastnosti, které by šli přepsat aby se zachovala kompatibilita s Kdyby\Doctrine. (vykašlat se úplně na Gedmo)
Editoval mishak (3. 10. 2013 17:56)
- akadlec
- Člen | 1326
mishak: no na tomhle projektu dělám po večerech a o chvílích volna. Jinak ale s mými znalostni nemám šanci to rozšíření napsat tak aby jej posvětil hosiplan :-)
Dočasně sem si to tedy vyřešil v startupu v base presenteru:
$this->context->getService('gedmo.gedmo.blameable')->setUserValue($this->userEntity);
$this->context->getService('gedmo.gedmo.translatable')->setTranslatableLocale($this->languageEntity->locale);
Editoval akadlec (3. 10. 2013 20:02)
- mishak
- Člen | 94
Se zkušenostmi si starost nedělej cokoli je lepší než nic. Když se navrhne základ ostatní můžou doladit a přispět.
I kdyby šlo ze začátku jen o hacky jak gedmo rozjet s doctrine stalo by to za to.
O dočasném fixu pro gedmo tree listener víš? viz. https://github.com/…ts/issues/22 je to poslední master + můj fix.
Editoval mishak (4. 10. 2013 2:12)