Reputation: 2908
so I am fairly new to Symfony and Doctrine. I would like to know if there's a way to ask doctrine what foreign keys are in place, but without having to map relationships in the model.
For example, say you have CoreBundle:Company
which is ALWAYS going to be present, and then you have OptionalBundle:Client
which will extend Company with a @OneToOne
mapping relationship, adding a few more fields in itself. The thing is, that since OptionalBundle
may not be present, I don't want explicit mapping from CoreBundle
to OptionalBundle
.
Now say a user comes along and attempts to delete Company(5)
. If the entity was fully mapped it would delete both with cascading, but since the bundle is not going to be aware of a mapped relationship it would end up deleting the Company only - I want to produce an error rather than cascading the deletion.
If this is possible quite easily, then I would also want to take it another step further and say, what entities (class and id) have foreign keys that I can show the data to the user, like
@CoreBundle:Company(5) ->
has @OptionalBundle:Client(3) linked, and
has @AnotherOptionalBundle:Supplier(12) linked
My first instinct is to do a custom INFORMATION_SCHEMA lookup for the foreign keys but that will only give me table names...
PS I REALLY prefer not to have to use any third party vendors as I like to try and keep the dependencies down, even if it means reinventing the wheel
Upvotes: 3
Views: 1006
Reputation: 1598
Question 1
You could set the Client
as the owner of the 1-to-1 relationship. However, depending on your use-case it might not be ideal, but if that works for you it would really be the simplest solution, as pointed out by ABM_Dan.
Barring that, the best option for you is probably to use Doctrine event subscribers and to hook on the preDelete
event, where you would remove the associated Client
, before the Company
itself is removed - if cascading the deletion is really what you want.
By default both deletion will be in the same Doctrine transaction, meaning that if something goes wrong when deleting the Company
, the Client
deletion will be cancelled.
If you really want to trigger an error instead of this "manual cascading" of sorts, it is also possible in the preDelete
method of the Doctrine subscriber.
The subscriber class can reside in your optional bundle even though it will act on an event associated to Company
.
Doctrine event subscribers are separate from the regular Symfony event system. Newcomers often are not aware of its existence, but it can achieve a lot of interesting things.
Question 2
Still in your event subscribers, it is possible to hook on the postLoad
event. This would allow you to request the database and load related entities directly into Company
. You can create an event subscriber for Company
in each bundle that requires it.
Although this is possible I really wonder if there might not be a better way. Using decorators might be a better solution. I found a Doctrine cookbook article about it.
Upvotes: 1
Reputation: 238
Have you considered defining the relationship as owned by the OptionalBundle side?
Upvotes: 1
Reputation: 1507
The only idea I come across is to pre-create class-mapping during Compiler Pass with some fallback type when secondary bundle is absent.
In compiler pass, check whether container has a secondary bundle loaded and use DoctrineOrmMappingsPass::createXmlMappingDriver
with adjusted path. If found - map with secondary bundle's entity, if not - map it to null (for example).
Upvotes: 0