Doctrine 2 Symfony 2获取没有映射的外键实体

时间:2021-11-26 06:45:52

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(例如)。