如何使用主义协会/关系
编辑该页面警告:你浏览的文档欧宝官网下载appob娱乐下载Symfony 2.8,不再维护。
读这个页面的更新版本Symfob娱乐下载ony 6.3(当前的稳定版本)。
如何使用主义协会/关系
假设在应用程序中每个产品属于一个类别。在这种情况下,您将需要一个类别
类,和联系方式产品
对象一个类别
对象。
首先创建的类别
实体。既然你知道你最终需要持久化类对象通过原则,你可以让学说为你创建类。
1 2 3
美元php应用程序/控制台学说:生成:实体——没有交互\实体=“AppBundle:类别”\——字段=“名字:字符串(255)”
这个命令生成类别
为你的实体,一个id
场,的名字
领域和相关的getter和setter函数。
关系映射元数据
在这个例子中,每个类别可以联系在一起许多产品,每个产品只能联系在一起一个类别。这种关系可以概括为:许多产品一个类别(或等价,一个类别许多产品)。
从的角度产品
实体,这是一个多对一的关系。从的角度类别
实体,这是一对多的关系。这很重要,因为相对关系的性质决定使用哪个映射元数据。这也决定了哪些类必须其他类的引用。
联系到一起产品
和类别
实体,简单地创建一个类别
财产的产品
类,注释如下:
1 2 3 4 5 6 7 8 9 10 11 12 13
/ / src / AppBundle /实体/ Product.php/ /……类产品{/ /……/ * * *@ORM\ ManyToOne (targetEntity =“类别”,inversedBy = "产品")*@ORM\ JoinColumn (name = " category_id添加",referencedColumnName = " id ") * /私人美元类别;}
1 2 3 4 5 6 7 8 9 10 11
# src / AppBundle /资源/ config /理论/ Product.orm.ymlAppBundle \实体\产品:类型:实体#……manyToOne:类别:targetEntity:类别inversedBy:产品joinColumn:名称:category_id添加referencedColumnName:id
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
< !——src / AppBundle /资源/ config /理论/ Product.orm。xml - - >< ?xml version = " 1.0 " encoding = " utf - 8 " ? ><doctrine-mappingxmlns=“http://doctrine-project.org/schemas/orm/doctrine-mapping”xmlns: xsi=“http://www.w3.org/2001/XMLSchema-instance”xsi: schemaLocation=“http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd”><实体的名字=“AppBundle \实体\产品”>< !——……- - ><多对一场=“类别”目标实体=“类别”用=“产品”连接列=“类别”><连接列的名字=“category_id添加”referenced-column-name=“id”/ >< /多对一>< /实体>< /doctrine-mapping>
这种多对一的映射是至关重要的。它告诉原则使用category_id添加
列在产品
表与该表中的每条记录的记录类别
表。
接下来,因为一个单一的类别
对象将与许多产品
对象,产品
可以添加到属性类别
类来保存这些关联对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/ / src / AppBundle /实体/ Category.php/ /……使用学说\常见的\集合\ArrayCollection;类类别{/ /……/ * * *@ORM\ OneToMany (targetEntity =“产品”的mappedBy =“类别”)* /私人美元产品;公共函数__construct(){美元这- >产品=新ArrayCollection ();}}
1 2 3 4 5 6 7 8 9 10
# src / AppBundle /资源/ config /理论/ Category.orm.ymlAppBundle \ \实体类别:类型:实体#……对:产品:targetEntity:产品的mappedBy:类别#别忘了初始化集合# __construct()方法的实体
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
< !——src / AppBundle /资源/ config /理论/ Category.orm。xml - - >< ?xml version = " 1.0 " encoding = " utf - 8 " ? ><doctrine-mappingxmlns=“http://doctrine-project.org/schemas/orm/doctrine-mapping”xmlns: xsi=“http://www.w3.org/2001/XMLSchema-instance”xsi: schemaLocation=“http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd”><实体的名字=“AppBundle \实体\类别”>< !——……- - ><一对多场=“产品”目标实体=“产品”所绘制=“类别”/ >< !——别忘了init __construct()方法的实体集合- - >< /实体>< /doctrine-mapping>
虽然早些时候显示的多对一的映射是强制性的,但这一对多映射是可选的。这里包括帮助演示教义的一系列关系管理能力。另外,这个应用程序的上下文中,它可能会方便类别
对象自动自己相关的集合产品
对象。
请注意
构造函数中的代码是很重要的。作为一个传统而不是被实例化数组
,美元的产品
属性的类型必须实现原则集合
接口。在这种情况下,一个ArrayCollection
使用对象。几乎这个对象的外观和行为完全像一个数组,但有一些增加了灵活性。如果这让你不舒服,不要担心。想象一下,这是一个数组
你会处于良好状态。
另请参阅
要理解inversedBy
和的mappedBy
使用,看到学说协会更新欧宝官网下载app文档。
提示
上述targetEntity价值所使用的元数据可以参考任何实体与一个有效名称空间,不仅仅是相同的名称空间中定义的实体。与一个不同的类中定义一个实体或包,输入一个完整的名称空间作为targetEntity。
现在您已经添加新属性的产品
和类别
类,您必须手动生成失踪的getter和setter方法或使用自己的IDE。
忽略教义的元数据。你现在有两类产品
和类别
,自然多对一的关系。的产品
班级中有单类别
对象,类别
班级中有集合的产品
对象。换句话说,你建造类的方式为您的应用程序是有意义的。这一事实的数据需要被持久化到数据库总是次要的。
现在,回顾上面的元数据产品
实体的美元的类别
财产。它告诉学说相关的类类别
,id
相关的记录应该存储在一个类别category_id添加
场的产品
表。
换句话说,相关的类别
将存储在对象美元的类别
属性,但在幕后,学说将持续这种关系通过存储类别的idcategory_id添加
列的产品
表。
上面的元数据类别
实体的美元的产品
房地产不太复杂。它只是告诉学说看Product.category
属性如何映射的关系。
在您继续之前,一定要告诉添加新的学说类别
表,新product.category_id
列,新外键:
1
美元php应用程序/控制台学说:模式:更新——力量
保存相关的实体
现在你可以看到这个新代码在行动!想象一下你在一个控制器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29 30 31 32
/ /……使用AppBundle\实体\类别;使用AppBundle\实体\产品;使用ob娱乐下载\组件\HttpFoundation\响应;类DefaultController扩展控制器{公共函数createProductAction(){美元类别=新类别();美元类别- >setName (“电脑外围设备”);美元产品=新产品();美元产品- >setName (“键盘”);美元产品- >setPrice (19.99);美元产品- >setDescription (的人体工学和时尚!);/ /该产品涉及的范畴美元产品- >setCategory (美元类别);美元entityManager=美元这- >getDoctrine ()- >getManager ();美元entityManager- >persist (美元类别);美元entityManager- >persist (美元产品);美元entityManager- >冲洗();返回新响应(“保存新产品id:”。美元产品- >getId ()。“和新类别id:”。美元类别- >getId ());}}
现在,添加一行到类别
和产品
表。的product.category_id
列新产品将不管id
是新类别的。原则管理这种关系的持久性。
获取相关对象
当您需要获取相关的对象,你的工作流看起来就像以前一样。首先,拿一个美元的产品
对象,然后访问相关类别
对象:
1 2 3 4 5 6 7 8 9 10 11 12 13
使用AppBundle\实体\产品;/ /……公共函数showAction(美元productId){美元产品=美元这- >getDoctrine ()- >getRepository(产品::类)- >找到(美元productId);美元categoryName=美元产品- >getCategory ()- >getName ();/ /……}
在这个例子中,首先查询产品
基于产品的对象id
。这问题一个查询只是产品数据和水合物美元的产品
对象的数据。之后,当你调用产品- > getCategory () - > getName ()
,默默地教义使得第二个查询来找到类别
这是与此相关产品
。它准备美元的类别
对象,并返回给你。
重要的是你有容易获得相关产品的类别,但类别数据并不是直到你要求类别检索(即“延迟加载”)。
你也可以查询另一个方向:
1 2 3 4 5 6 7 8 9 10
公共函数showProductsAction(美元被标记){美元类别=美元这- >getDoctrine ()- >getRepository(类别::类)- >找到(美元被标记);美元产品=美元类别- >getProducts ();/ /……}
在这种情况下,同样的事情发生:首先查询单类别
对象,然后教义使得第二个查询来检索相关产品
对象,但只有当/如果你问他们(即当你调用getProducts ()
)。的美元的产品
变量是一个数组产品
与给定的对象类别
通过他们的对象category_id添加
价值。
关系和代理类
这个“延迟加载”是可能的,因为,在必要的时候,教义返回一个“代理”对象的真正对象。再看看上面的例子:
1 2 3 4 5 6 7 8 9
美元产品=美元这- >getDoctrine ()- >getRepository(产品::类)- >找到(美元productId);美元类别=美元产品- >getCategory ();/ /打印“代理\ AppBundleEntityCategoryProxy”转储(get_class (美元类别));死();
这个代理对象扩展了真的类别
对象,外表和行为完全一样。不同的是,通过使用一个代理对象,教义可以为真正的延迟查询类别
直到你真正需要的数据(例如,直到你的电话$分类- > getName ()
)。
生成的代理类学说并存储在缓存目录。虽然你可能从未注意到你美元的类别
对象实际上是一个代理对象,重要的是要记住的。
在下一节中,当你检索的产品和类别数据(通过加入),原则将返回真正的类别
对象,因为不需要延迟加载。
加入相关记录
在上面的例子中,两个查询了—一个用于原来的对象(例如一个类别
),一个用于相关对象(s)(如产品
对象)。
提示
记住,你可以看到所有的查询在一个请求通过网络调试工具栏。
当然,如果你预先知道你需要访问两个对象,你可以避免第二个查询发出加入原始查询。添加以下方法ProductRepository
类:
1 2 3 4 5 6 7 8 9 10 11 12
/ / src / AppBundle /仓库/ ProductRepository.php公共函数findOneByIdJoinedToCategory(美元productId){美元查询=美元这- >getEntityManager ()- >createQuery (“选择p c AppBundle:产品p加入p。类别c p。id =: id ')- >setParameter (“id”,美元productId);返回美元查询- >getOneOrNullResult ();}
现在,您可以使用这种方法在你的控制器查询产品
对象及其相关类别
只有一个查询:
1 2 3 4 5 6 7 8 9 10
公共函数showAction(美元productId){美元产品=美元这- >getDoctrine ()- >getRepository(产品::类)- >findOneByIdJoinedToCategory (美元productId);美元类别=美元产品- >getCategory ();/ /……}
更多信息协会
本节介绍了一个常见的实体关系,一对多的关系。对于更高级的细节和例子如何使用其他类型的关系(例如一对一、多对多),看到教义的协会映射文档欧宝官网下载app。
请注意
如果你使用注释,需要预先考虑所有注释@ORM \
(如。@ORM \ OneToMany
),这不是反映在教义的文档。欧宝官网下载app你还需要包括使用原则\ ORM \ ORM映射;
声明,进口的ORM
注释前缀。