如何处理教义协会/关系
编辑本页警告:您正在浏览的文档欧宝官网下载appob娱乐下载Symfony 3.4,现已不再维护。
读本页的更新版本用于Syob娱乐下载mfony 6.2(当前稳定版本)。
如何处理教义协会/关系
截屏视频
你更喜欢视频教程吗?请查看掌握教义关系视频系列。
假设应用程序中的每个产品都只属于一个类别。在这种情况下,你需要一个类别
类,以及一种关联产品
对象的类别
对象。
首先创建类别
实体。因为您知道您最终需要通过Doctrine持久化类别对象,所以您可以让Doctrine为您创建类。
1 2 3
$PHP bin/控制台原则:generate:entity——no-interaction \——entity=“AppBundle:类别”\——字段=“名字:字符串(255)”
此命令生成类别
实体为你,用一个id
场,的名字
字段和相关的getter和setter函数。
关系映射元数据
在本例中,每个类别都可以与许多产品,而每个产品只能与一个类别。这种关系可以概括为:许多产品一个类别(或等价地,一个类别许多产品)。
从这个角度来看产品
实体,这是一个多对一关系。从这个角度来看类别
实体,这是一个一对多的关系。这很重要,因为关系的相对性质决定了使用哪个映射元数据。它还决定了哪个类必须持有对另一个类的引用。
联系产品
而且类别
实体,只需创建一个类别
的属性产品
类,注释如下:
- 注释
- YAML
- XML
12 3 4 5 6 7 8 9 10 11 12 13
/ / src / AppBundle /实体/ Product.php/ /……类产品{/ /……/ * * *@ORM\ManyToOne(targetEntity="Category", inversedBy="products") *@ORM\JoinColumn(name="category_id", referencedColumnName="id") */私人$类别;}
这种多对一映射非常关键。它告诉教义使用category_id添加
列关于产品
表中关联该表中的每个记录与类别
表格
接下来,自单类别
对象会涉及到很多产品
对象,产品
属性可以添加到类别
类来保存这些关联对象。
- 注释
- YAML
- XML
12 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="Product", mappedBy="category") */私人$产品;公共函数__construct(){$这->产品=新ArrayCollection ();}}
虽然前面显示的多对一映射是强制性的,但这个一对多映射是可选的。这里包含它是为了帮助演示Doctrine的关系管理功能范围。另外,在这个应用程序的上下文中,这可能对每个人都很方便类别
对象自动拥有与其相关的集合产品
对象。
请注意
构造函数中的代码很重要。而不是被实例化为传统的数组
,美元的产品
属性必须是实现Doctrine的类型集合
接口。在这种情况下,anArrayCollection
对象。这个物体的样子和作用几乎是一样的完全类似于数组,但有一些额外的灵活性。如果这让你不舒服,别担心。想象一下这是一个数组
你的身材会很好。
另请参阅
要理解inversedBy
而且的mappedBy
用法,见教义协会更新欧宝官网下载app文档。
提示
的targetEntity
上面使用的元数据中的值可以引用具有有效名称空间的任何实体,而不仅仅是同一名称空间中定义的实体。要关联在不同类或包中定义的实体,请输入完整的名称空间作为targetEntity
.
现在,您已经向两个产品
而且类别
类,您必须手动或使用您自己的IDE生成缺少的getter和setter方法。
暂时忽略Doctrine元数据。你现在有两个类产品
而且类别
,具有自然的多对一关系。的产品
类持有一个单类别
对象,而类别
类持有一个集合的产品
对象。换句话说,您已经以对应用程序有意义的方式构建了类。数据需要持久化到数据库始终是次要的。
现在,回顾上面的元数据产品
实体的美元的类别
财产。它告诉Doctrine相关的类是类别
,而且id
的相关类别记录应存储在一个category_id添加
字段上的产品
表格
换句话说,是相关的类别
对象将存储在美元的类别
属性,但在幕后,Doctrine将通过将类别的id存储在category_id添加
的列产品
表格
上面的元数据类别
实体的美元的产品
财产没有那么复杂。它只是告诉教义去看Product.category
属性来确定如何映射关系。
在继续之前,请务必告诉Doctrine添加新的类别
表,新product.category_id
列和新的外键:
1
$PHP bin/控制台原则:schema:update——force
保存相关实体
现在您可以看到这个新代码的实际运行!假设你在一个控制器中:
12 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
属于新类别。教条为你管理这种关系的持久性。
获取相关对象
当您需要获取关联对象时,您的工作流看起来就像以前一样。首先,获取美元的产品
对象,然后访问其相关类别
对象:
12 3 4 5 6 7 8 9 10 11 12 13
使用AppBundle\实体\产品;/ /……公共函数showAction($productId){$产品=$这->getDoctrine ()->getRepository(产品::类)->找到($productId);$categoryName=$产品->getCategory ()->getName ();/ /……}
在本例中,首先查询a产品
对象基于产品的id
.的查询只是该产品的数据和补水美元的产品
对象使用该数据。等会儿,等你打电话的时候产品- > getCategory()——> getName ()
,教义默默地进行第二次查询,以找到类别
这和这个有关产品
.它准备美元的类别
对象并将它返回给你。
重要的是,您可以很容易地访问产品的相关类别,但直到您请求类别时,类别数据才会实际检索到(即它是“惰性加载”)。
您也可以向其他方向查询:
1 2 3 4 5 6 7 8 9 10
公共函数showProductsAction($被标记){$类别=$这->getDoctrine ()->getRepository(类别::类)->找到($被标记);$产品=$类别->getProducts ();/ /……}
在这种情况下,会发生相同的情况:首先查询单个类别
对象,然后Doctrine执行第二个查询以检索相关的产品
对象,但只有一次/如果你要求他们(即当你调用getProducts ()
).的美元的产品
Variable是all的数组产品
与给定对象相关的对象类别
对象通过category_id添加
价值。
加入相关记录
在上面的例子中,进行了两个查询——一个是原始对象(例如a类别
)和一个用于相关对象(例如产品
对象)。
提示
请记住,您可以通过web调试工具栏查看请求期间进行的所有查询。
如果您事先知道需要访问这两个对象,则可以通过在原始查询中发出连接来避免第二个查询。属性中添加以下方法ProductRepository
类:
12 3 4 5 6 7 8 9 10 11 12
/ / src / AppBundle /仓库/ ProductRepository.php公共函数findOneByIdJoinedToCategory($productId){$查询=$这->getEntityManager ()->createQuery ('SELECT p, c FROM AppBundle:Product p JOIN p.category c WHERE p.id =:id')->setParameter (“id”,$productId);返回$查询->getOneOrNullResult ();}
现在,你可以在控制器中使用这个方法来查询产品
对象及其相关对象类别
只有一个问题:
1 2 3 4 5 6 7 8 9 10
公共函数showAction($productId){$产品=$这->getDoctrine ()->getRepository(产品::类)->findOneByIdJoinedToCategory ($productId);$类别=$产品->getCategory ();/ /……}
更多有关关联的资料
本节介绍了一种常见的实体关系类型,即一对多关系。有关如何使用其他类型关系(例如,一对一,多对多)的更高级细节和示例,请参阅Doctrine关联映射文档欧宝官网下载app.
请注意
如果使用注释,则需要在所有注释前加上@ORM \
(如。@ORM \ OneToMany
),并没有反映在Doctrine的文档中。欧宝官网下载app您还需要包括使用Doctrine\ORM\Mapping作为ORM;
声明,进口的ORM
注释前缀。