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.
所以我对Symfony和Doctrine来说还是个新手。我想知道是否有一种方法可以向教义询问外键是什么,但无需在模型中映射关系。
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
.
例如,假设您有CoreBundle:公司总是会出现,然后您有OptionalBundle:Client将使用@OneToOne映射关系扩展Company,并在其中添加更多字段。问题是,由于OptionalBundle可能不存在,我不希望从CoreBundle到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.
现在说用户出现并试图删除Company(5)。如果实体已完全映射,它将使用级联删除两者,但由于捆绑包不会意识到映射关系,它最终将仅删除公司 - 我想产生错误而不是级联删除。
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
如果这很容易,那么我还想进一步说一下,哪些实体(class和id)有外键我可以向用户显示数据,比如
@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...
我的第一直觉是为外键执行自定义INFORMATION_SCHEMA查找,但这只会给我表名...
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
PS我真的不想使用任何第三方供应商,因为我喜欢尝试保持依赖关系,即使它意味着重新发明*
3 个解决方案
#1
1
Question 1
问题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.
您可以将客户端设置为1对1关系的所有者。但是,根据您的用例,它可能并不理想,但如果这对您有用,那么它将是最简单的解决方案,正如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.
除此之外,最好的选择可能是使用Doctrine事件订阅者并挂钩preDelete事件,在删除公司本身之前删除关联的客户端 - 如果级联删除确实是您想要的。
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.
默认情况下,删除都将在同一个Doctrine事务中,这意味着如果在删除公司时出现问题,将删除客户端删除。
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.
如果你真的想要触发错误而不是这种“手动级联”的类型,那么也可以在Doctrine订阅者的preDelete方法中使用。
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.
Doctrine事件订阅者与常规Symfony事件系统是分开的。新手常常不知道它的存在,但它可以实现很多有趣的事情。
Question 2
问题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.
仍然在您的活动订阅者中,可以挂钩postLoad事件。这将允许您直接向公司请求数据库和加载相关实体。您可以在需要它的每个捆绑中为Company创建一个事件订阅者。
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.
虽然这是可能的,但我真的很想知道是否有更好的方法。使用装饰器可能是更好的解决方案。我找到了一篇关于它的Doctrine cookbook文章。
#2
1
Have you considered defining the relationship as owned by the OptionalBundle side?
您是否考虑过将OptionalBundle所拥有的关系定义为?
#3
0
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).
在编译器传递中,检查容器是否已加载辅助包,并使用带调整路径的DoctrineOrmMappingsPass :: createXmlMappingDriver。如果找到 - 映射与辅助包的实体,如果不是 - 将其映射为null(例如)。
#1
1
Question 1
问题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.
您可以将客户端设置为1对1关系的所有者。但是,根据您的用例,它可能并不理想,但如果这对您有用,那么它将是最简单的解决方案,正如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.
除此之外,最好的选择可能是使用Doctrine事件订阅者并挂钩preDelete事件,在删除公司本身之前删除关联的客户端 - 如果级联删除确实是您想要的。
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.
默认情况下,删除都将在同一个Doctrine事务中,这意味着如果在删除公司时出现问题,将删除客户端删除。
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.
如果你真的想要触发错误而不是这种“手动级联”的类型,那么也可以在Doctrine订阅者的preDelete方法中使用。
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.
Doctrine事件订阅者与常规Symfony事件系统是分开的。新手常常不知道它的存在,但它可以实现很多有趣的事情。
Question 2
问题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.
仍然在您的活动订阅者中,可以挂钩postLoad事件。这将允许您直接向公司请求数据库和加载相关实体。您可以在需要它的每个捆绑中为Company创建一个事件订阅者。
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.
虽然这是可能的,但我真的很想知道是否有更好的方法。使用装饰器可能是更好的解决方案。我找到了一篇关于它的Doctrine cookbook文章。
#2
1
Have you considered defining the relationship as owned by the OptionalBundle side?
您是否考虑过将OptionalBundle所拥有的关系定义为?
#3
0
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).
在编译器传递中,检查容器是否已加载辅助包,并使用带调整路径的DoctrineOrmMappingsPass :: createXmlMappingDriver。如果找到 - 映射与辅助包的实体,如果不是 - 将其映射为null(例如)。