Closed TiSiE closed 7 years ago
A concrete example would be custom and editable job categories which would be embedded in an organization entity to be available to all jobs created for this organization. Managable by the organization owner (or any employment with the correspondent right). Speaking of that, customizable employee rights are just another example of such embedded entities.
I can take a look at it on Monday. I will let you know my thoughts.
I went over the description above and the concept in the gist and I did not grasp it. Please provide an example of a client code. I think this could help me to understand the concept easier.
We want to create a mechanism to let modules embed their own documents into an entity of another module. This is to allow to access this document through the other modules' entity.
If a module is disabled however, its embedded documents in the entities of the other module MUST NOT affect the functionality of YAWIK. Therefor we CAN NOT use Doctrine, as its implementation relies on the classes of embedded documents to be available (and they are not, if a module is not loaded.)
Example client code:
$moduleA_entity->embed($moduleB_entity);
$moduleB_entity = $moduleA_entity->getEmbedded('moduleB\Entity\moduleB_entity');
/* or define own key */
$moduleA_entity->embed($moduleB_entity, 'moduleB.custom');
$moduleB_entity = $moduleA_entity->getEmbedded('moduleB.custom');
/* If not embedded or module is disabled getEmbedded returns null */
$moduleB_entity = $moduleA_entity->getEmbbeded('nonExistentKey');
var_dump($moduleB_entity); // => null
var_dump($moduleA_entity->getEmbedded('moduleB.custom')); // null, if ModuleB is disabled
I assume the $moduleB_entity
will not be managed by an ODM and embeds inside the $moduleA_entity
will be stored in @ODM\Hash
(we will be responsible for correct hydrating/extracting). Am I right?
Yes, and that's is exactly the point where it gets dirty. I'm not so sure anymore that embedding is the way to go.
What if we just store references and require a dedicated collection for moduleB_entities. That way we just have to implement the logic to fetch/store the referenced entity from the ODM.
{
"moduleB.custom": {
"repository": "ModuleB/EmbeddedEntities",
"entitiy": "<objectId>"
}
}
in a custom "Referenced Entity Collection":
function loadEmbedded($key)
{
$ref = $this->getEmbeddedRef($key);
return $this
->repositories
->get($ref->getRepository())
->find($ref->getEntityId())
;
}
I thought of it the same way! I think it would be more sensible solution ;)
Do you want me to sketch a use case with a custom "Referenced Entity Collection"?
I created a new gist reflecting the reference idea..
The only thing I didn't figure out is how to inject the dependencies in the custom collection (which will further on be wrapped in a PersistentCollection once loaded from the ODM). Although I did read the documentation.
Dependencies can be injected via AbstractPersistentCollectionFactory described in http://docs.doctrine-project.org/projects/doctrine-mongodb-odm/en/latest/reference/custom-collections.html#taking-control-of-the-collection-s-constructor
I went over the new gist and it looks good.
I noticed the new gist does not support storing/retrieving arrays of entities (e.g. mentioned categories).
You would store the reference (=>attach) [to] an entity which holds the categories in an array....
Dependencies can be injected via AbstractPersistentCollectionFactory
I've read this, but as I understand this factory is then used to create ALL persistent collections, so we would need a control statement (as in the example outlined). Also the factory is only used when entities are fetched from the database and not, if an entity is created.
When entity is created AttachedEntitiesCollection could be passed via entity constructor.
I remembered, we once created a RepositoryEventSubscriber which injects the entity prototype into a repository. That's where the dependencies can be injected. I updated the gist accordingly.
Nice one
@fedys If you don't mind, go ahead and code it! :smile:
@TiSiE I am working on it.
We need the ability to have entites from one module be embedded in entites from other modules. e.g. The Applications module embeds a document to an organization entitiy.
This mechanism must be independent from Doctrine, because disabling one module should not break the other - we must come up with an own strategy. But maybe we could use Doctrines "Custom Collection Classes" in combination with postLoad Events....
Concept sketch in this gist