数据库和原则
编辑该页面警告:你浏览的文档欧宝官网下载appob娱乐下载Symfony 2.1,不再维护。
读这个页面的更新版本Symfob娱乐下载ony 6.2(当前的稳定版本)。
< /div>数据库和原则
最常见的和具有挑战性的任务对于任何应用程序包括持久化和阅读信息和从数据库。幸运的是,Symfony会ob娱乐下载结合学说、一个图书馆,它的唯一目的是给你强大的工具非常容易。在本章中,您将了解背后的基本哲学学说,看看容易使用数据库。
请注意
原则是完全脱离Symfony和使用它是可选的。ob娱乐下载这一章都是关于教义ORM,旨在让您将对象映射到关系数据库(如MySQL,PostgreSQL或Microsoft SQL)。如果你喜欢用原始的数据库查询,这是很容易的,并解释了在“如何使用原则的DBAL层“食谱条目。
你也可以保存数据MongoDB使用原则ODM图书馆。更多的信息,阅读DoctrineMongoDBBundle文档。欧宝官网下载app
< /div>一个简单的例子:一个产品
理解教义是如何工作的最简单的方法就是看它的实际应用。在本节中,您将配置数据库,创建一个产品
对象持久化到数据库并获取它。
配置数据库
在你真正开始之前,您需要配置您的数据库连接信息。按照惯例,这些信息通常是在一个配置应用程序/配置/ parameters.yml
文件:
1 2 3 4 5 6 7 8 9
# app / config / parameters.yml参数:database_driver:pdo_mysqldatabase_host:本地主机database_name:test_projectdatabase_user:根database_password:密码#……
请注意
通过定义配置parameters.yml
只是一个惯例。该文件中定义的参数引用的主要配置文件设置原则时:
- YAML
- XML
- PHP
1 2 3 4 5 6 7 8
# app / config / config.yml原则:dbal:司机:“% database_driver %”主持人:“% database_host %”dbname:“% database_name %”用户:“% database_user %”密码:“% database_password %”
通过将数据库信息到一个单独的文件中,您可以很容易地保持在每个服务器上文件的不同版本。您还可以方便地存储数据库配置(或任何敏感信息)以外的项目,比如在Apache配置。有关更多信息,请参见服务容器外部参数如何设置。
< /div>现在主义知道您的数据库,您可以创建数据库:
1
$ php应用程序/控制台学说:数据库:创建
请注意
如果你想使用SQLite作为您的数据库,您需要设置应该存储在数据库文件的路径:
- YAML
- XML
- PHP
1 2 3 4 5 6
# app / config / config.yml原则:dbal:司机:pdo_sqlite路径:“% kernel.root_dir % / sqlite.db”字符集:use UTF8
创建一个实体类
假设您要构建一个应用程序,需要显示的产品。没想学说或数据库中,你已经知道你需要一个产品
对象来表示这些产品。创建这个类里面实体
你的目录AcmeStoreBundle
:
1 2 3 4 5 6 7 8 9 10 11
/ / src / Acme / / Product.php StoreBundle /实体名称空间Acme\StoreBundle\实体;类产品{受保护的美元的名字;受保护的美元价格;受保护的美元描述;}
类——通常被称为一个“实体”的意思一个基本类,保存数据——很简单,帮助满足需要的产品在您的应用程序的业务需求。这个类不能被持久化到数据库——这只是一个简单的PHP类。
提示
一旦你学习原则背后的概念,你可以有教义为您创建简单的实体类:
1
美元的php应用程序/控制台学说:生成:实体,实体=“AcmeStoreBundle:产品”——字段=“名字:字符串(255)价格:描述:浮动文本”
添加映射信息
教义允许您工作与数据库更加有趣的方式不仅仅是获取基于列的表的行到一个数组中。相反,教义允许您保存整个对象到数据库,从数据库中获取整个对象。这是一个PHP类映射到数据库表,和PHP类的属性列在表:
的学说能够做到这一点,你只需要创建“元数据”,或告诉学说如何配置产品
类及其属性映射到数据库。此元数据可以指定在许多不同的格式包括YAML、XML或直接在产品
类通过注释:
- 注释
- YAML
- XML
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 33
/ / src / Acme / / Product.php StoreBundle /实体名称空间Acme\StoreBundle\实体;使用学说\ORM\映射作为ORM;/ * * *@ORM* \实体@ORM\表(name = "产品")* /类产品{/ * * *@ORM\ Id *@ORM\列(type =“整数”)*@ORM\ GeneratedValue(策略=“汽车”)* /受保护的美元id;/ * * *@ORM\列(类型=“字符串”,长度= 100)* /受保护的美元的名字;/ * * *@ORM\列(type =“小数”,规模= 2)* /受保护的美元价格;/ * * *@ORM\列(type = " text ") * /受保护的美元描述;}
请注意
一捆只能接受一个元数据定义格式。例如,它是不可能的混合YAML的元数据定义与注释PHP实体类定义。
< /div>提示
表名是可选的,如果省略,将自动确定基于实体类的名称。
< /div>教义允许您选择各种不同的字段类型,每个都有自己的选择。有关可用的字段类型的信息,请参阅数据库和原则部分。
另请参阅
你也可以看看学说基本的映射文档欧宝官网下载app对所有细节映射信息。如果你使用注释,需要预先考虑所有注释ORM \
(如。ORM \列(. .)
所示),这不是教条的文档。欧宝官网下载app你还需要包括使用原则\ ORM \ ORM映射;
声明,进口的ORM
注释前缀。
谨慎
不小心,你的类名和属性映射到SQL关键字(如保护集团
或用户
)。例如,如果您的实体类的名字集团
那么,在默认情况下,你的表名集团
,这将导致一个SQL错误在某些引擎。看到学说的保留SQL关键字的文档欧宝官网下载app如何正确地逃避这些名字。另外,如果你自由选择数据库模式,简单地映射到不同的表名或列名。看到学说的持久化类和属性映射欧宝官网下载app文档。
请注意
当使用或程序(即另一个图书馆。Doxygen),使用注释,你应该把@IgnoreAnnotation
注释的类来表示注释Symfony应该忽略。ob娱乐下载
例如,为了防止@fn
注释从抛出异常,添加以下:
1 2 3 4 5
/ * * *@IgnoreAnnotation(fn) * /类产品/ /……
生成getter和setter方法
尽管学说现在知道如何坚持产品
对象到数据库,类本身还没有真正有用的。自产品
只是一个常规的PHP类,您需要创建getter和setter方法(如。getName ()
,setName ()
)来访问其属性(自属性受保护的
)。幸运的是,教义为您可以通过运行:
1
$ php应用程序/控制台学说:生成:实体/ Acme / StoreBundle /实体产品
这个命令确保生成的所有的getter和setter产品
类。这是一个安全的命令,您可以运行它一遍又一遍:它只生成getter和setter方法,不存在(即它不会取代你现有的方法)。
谨慎
记住,教义的实体发生器产生简单的getter / setter。您应该检查生成的实体和getter / setter逻辑来自己的需要进行调整。
< /div>你也可以生成所有已知的实体(即任何教条的PHP类映射信息)的包或整个命名空间:
1 2
$ php应用程序/控制台学说:生成:实体AcmeStoreBundle美元php应用程序/控制台学说:Acme生成:实体
请注意
教义并不关心你的属性受保护的
或私人
,或者你是否有一个属性的getter或setter函数。这里的生成getter和setter只是因为你需要他们与PHP对象进行交互。
创建数据库表/模式
你现在有一个可用的产品
类映射信息,以便教义确切地知道如何坚持。当然,你还没有相应的产品
表在数据库中。幸运的是,教义可以自动创建所需的所有数据库表为每一个已知的实体在您的应用程序。要做到这一点,运行:
1
php应用程序/控制台学说:美元模式:更新——力量
提示
实际上,这个命令是非常强大的。比较你的数据库应该看起来像(基于实体的映射信息)与它实际上看起来,并生成所需的SQL语句更新数据库在它应该在的地方。换句话说,如果你添加一个新的属性映射元数据产品
再次运行这个任务,它将生成“alter table语句需要添加新列的现有产品
表。
一个更好的方法通过DoctrineMigrationsBundle利用这一功能,它允许您生成这些SQL语句并将它们存储在迁移类,可以生产服务器上运行系统为了安全可靠地跟踪和迁移数据库模式。
< /div>数据库现在有一个全功能产品
表和列匹配你指定的元数据。
持久化对象到数据库
现在,您已经有了一个映射产品
实体和相应的产品
表,你准备保存数据到数据库中。在一个控制器,这是非常容易的。添加以下方法DefaultController
包:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/ / src / Acme / StoreBundle /控制器/ DefaultController.php/ /……使用Acme\StoreBundle\实体\产品;使用ob娱乐下载\组件\HttpFoundation\响应;公共函数createAction(){美元产品=新产品();美元产品- >setName (“Foo酒吧”);美元产品- >setPrice (“19.99”);美元产品- >setDescription (“Lorem ipsum悲哀”);美元新兴市场=美元这- >getDoctrine ()- >getManager ();美元新兴市场- >persist (美元产品);美元新兴市场- >冲洗();返回新响应(“创建产品id”。美元产品- >getId ());}
请注意
如果你按照这个例子中,您需要创建一个指向这个动作路线工作。
< /div>更详细地看一看前面的示例:
- 行9 - 12在本节中,您实例化和工作
美元的产品
像任何其他对象,正常的PHP对象。 - 第14行这条线获取学说实体管理器对象,它负责处理的过程中坚持和抓取对象数据库。
- 第15行的
persist ()
方法告诉学说“管理”美元的产品
对象。这并不会导致查询到数据库(还)。 - 线16当
冲洗()
方法被调用,原则通过的所有对象的管理,看看他们是否需要被持久化到数据库中。在这个例子中,美元的产品
对象尚未保存,所以实体管理器执行一个插入
查询和创建一个行产品
表。
请注意
事实上,由于教义意识到你所有的管理实体,当你调用冲洗()
方法,它计算一个整体变更集和执行最有效的查询/查询。例如,如果您坚持共有100产品
然后随后调用对象冲洗()
,学说将创建一个单为每个插入准备好的语句和重用它。此模式被称为工作单元,它的使用,因为它是快速和高效。
在创建或更新对象,工作流总是相同的。在下一节中,您将看到如何学说是一个足够聪明来自动问题更新
数据库中查询如果记录已经存在。
提示
学说提供了一个库,允许您以编程方式测试数据加载到您的项目(即。“固定数据”)。信息,请参阅DoctrineFixturesBundle /索引。
< /div>从数据库中获取对象
获取一个对象的数据库更容易。例如,假设您已经配置了一个显示一个特定的路线产品
基于其id
值:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
公共函数showAction(美元id){美元产品=美元这- >getDoctrine ()- >getRepository (“AcmeStoreBundle:产品”)- >找到(美元id);如果(!美元产品){扔美元这- >createNotFoundException (“没有发现产品id”。美元id);}/ /……做点什么,比如通过美元产品对象到一个模板}
提示
可以达到相当于这个没有编写任何代码通过使用@ParamConverter
快捷方式。看到FrameworkExtraBundle为更多的细节。
查询一个特定类型的对象时,你总是用所谓的“仓库”。你可以认为一个存储库是一个PHP类唯一的工作就是帮助你获取某个类的实体。您可以访问存储库对象为一个实体类通过:
1 2
美元存储库=美元这- >getDoctrine ()- >getRepository (“AcmeStoreBundle:产品”);
请注意
的AcmeStoreBundle:产品
字符串是一个快捷方式可以使用任何学说,而不是实体的完整类名(即。Acme \ \ StoreBundle \实体产品
)。只要你的实体下的生活实体
你的包名称空间,这将工作。
一旦您的存储库,你可以访问各种各样的有用的方法:
1 2 3 4 5 6 7 8 9 10 11 12
/ /主键查询的(通常是“id”)美元产品=美元存储库- >找到(美元id);/ /动态方法名称找到基于列值美元产品=美元存储库- >findOneById (美元id);美元产品=美元存储库- >findOneByName (“foo”);/ /找到* *所有产品美元产品=美元存储库- >findAll ();/ /找到一群产品基于任意列值美元产品=美元存储库- >findByPrice (19.99);
请注意
当然,你也可以问题复杂的查询,你会了解更多的数据库和原则部分。
< /div>你也可以利用有用的findBy
和findOneBy
方法方便地获取对象根据多个条件:
1 2 3 4 5 6 7 8
/ /查询一个产品匹配的名称和价格美元产品=美元存储库- >findOneBy (数组(“名字”= >“foo”,“价格”= >19.99));/ /查询所有产品匹配的名称、订购价格美元产品=美元存储库- >findBy (数组(“名字”= >“foo”),数组(“价格”= >“ASC”));
提示
当你渲染任何页面中,您可以看到有多少查询在网络调试工具栏的右下角。
如果你单击图标,分析器会打开,显示你的查询。
< /div>更新一个对象
一旦你获取一个对象从教义,更新很容易。假设您有一个路线,产品id映射到一个更新控制器中的动作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
公共函数updateAction(美元id){美元新兴市场=美元这- >getDoctrine ()- >getManager ();美元产品=美元新兴市场- >getRepository (“AcmeStoreBundle:产品”)- >找到(美元id);如果(!美元产品){扔美元这- >createNotFoundException (“没有发现产品id”。美元id);}美元产品- >setName (“新产品的名字!”);美元新兴市场- >冲洗();返回美元这- >重定向(美元这- >generateUrl (“主页”));}
更新对象包括三个步骤:
- 获取对象从教义;
- 修改对象;
- 调用
冲洗()
在实体管理器
注意,调用(em - >坚持美元产品)
是没有必要的。回想一下,这个方法简单告诉原则管理或“观察”美元的产品
对象。在这种情况下,因为你把美元的产品
对象从教义,它已经成功。
删除一个对象
删除一个对象非常相似,但需要调用remove ()
实体管理器的方法:
1 2
美元新兴市场- >remove (美元产品);美元新兴市场- >冲洗();
如您所料,remove ()
方法通知学说,你想从数据库中删除给定的实体。实际的删除
查询,但是,并不是实际执行,直到冲洗()
方法被调用。
查询对象
您已经看到如何存储库对象允许您运行基本查询没有任何工作:
1 2 3
美元存储库- >找到(美元id);美元存储库- >findOneByName (“Foo”);
当然,教义也允许您编写更复杂的查询使用查询语言(DQL)原则。DQL类似于SQL除外,你应该想象你查询一个或多个对象的一个实体类(如。产品
)而不是桌子上(如查询行。产品
)。
教义查询时,你有两种选择:写作纯粹主义查询或使用原则的查询生成器。
查询与DQL对象
想象一下你想要查询产品,但只返回产品,超过成本19.99
命令从便宜的到最昂贵的。在一个控制器,请执行以下操作:
1 2 3 4 5 6
美元新兴市场=美元这- >getDoctrine ()- >getManager ();美元查询=美元新兴市场- >createQuery (“从AcmeStoreBundle选择p:产品p, p。价格>:价格按p。ASC的价格)- >setParameter (“价格”,“19.99”);美元产品=美元查询- >getResult ();
如果您熟悉SQL,那么DQL应该感到很自然。最大的区别是,你需要考虑“对象”而不是数据库中的行。出于这个原因,你选择从AcmeStoreBundle:产品
然后别名p
。
的getResult ()
方法返回一个数组的结果。如果你查询一个对象,您可以使用getSingleResult ()
方法:
1
美元产品=美元查询- >getSingleResult ();
谨慎
的getSingleResult ()
方法抛出一个学说\ ORM \ NoResultException
如果没有返回结果,异常学说\ ORM \ NonUniqueResultException
如果更多的返回一个结果。如果您使用这种方法,您可能需要包装在一个try - catch块,确保只有一个返回结果(如果你查询的东西能轻松返回多个结果):
1 2 3 4 5 6 7 8 9
美元查询=美元新兴市场- >createQuery (“选择…”)- >setMaxResults (1);试一试{美元产品=美元查询- >getSingleResult ();}抓(\ \ Orm \ NoResultException教义美元e){美元产品=零;}/ /……
DQL语法是非常强大的,允许您轻松地加入实体之间的话题关系稍后将介绍)、组等。有关更多信息,看到官方教义教义的查询语言欧宝官网下载app文档。
使用原则的查询生成器
而不是直接写查询,或者可以使用原则QueryBuilder
使用一个很好的做同样的工作,面向对象的接口。如果你使用一个IDE,您还可以利用自动完成输入方法名称。在一个控制器:
1 2 3 4 5 6 7 8 9 10
美元存储库=美元这- >getDoctrine ()- >getRepository (“AcmeStoreBundle:产品”);美元查询=美元存储库- >createQueryBuilder (“p”)- >(在哪里“p。price > :price'< /span>)- >setParameter (“价格”,“19.99”)- >orderBy (“p.price”,“ASC”)- >getQuery ();美元产品=美元查询- >getResult ();
的QueryBuilder
对象包含每个方法需要建立你的查询。通过调用getQuery ()
方法,查询构建器返回正常查询
对象,它是相同的对象你直接建在前一节中。
教义的查询构建器的更多信息,参考原则查询构建器欧宝官网下载app文档。
< /div>自定义库类
在前面的章节中,您开始从内部构造和使用更复杂的查询控制器。为了隔离,测试和重用这些查询,这是一个好主意为你创建一个自定义存储库类与您的查询逻辑实体和添加方法。
要做到这一点,将存储库类的名称添加到你的映射定义。
- 注释
- YAML
- XML
1 2 3 4 5 6 7 8 9 10 11 12
/ / src / Acme / / Product.php StoreBundle /实体名称空间Acme\StoreBundle\实体;使用学说\ORM\映射作为ORM;/ * * *@ORMAcme \ StoreBundle \ \实体(repositoryClass = "实体\ ProductRepository ") * /类产品{/ /……}
原则可以为您生成存储库类通过运行相同的命令使用生成早些时候失踪的getter和setter方法:
1
$ php应用程序/控制台学说:生成:Acme的实体
接下来,添加一个新方法findAllOrderedByName ()
新生成的库类。该方法将为所有的查询产品
实体,命令按字母顺序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/ / src / Acme / / ProductRepository.php StoreBundle /实体名称空间Acme\StoreBundle\实体;使用学说\ORM\EntityRepository;类ProductRepository扩展EntityRepository{公共函数findAllOrderedByName(){返回美元这- >getEntityManager ()- >createQuery (“从AcmeStoreBundle选择p:产品p p.name ASC的顺序)- >getResult ();}}
提示
实体管理器可以通过访问$ this - > getEntityManager ()
在存储库中。
您可以使用此新方法就像默认查找器方法的存储库:
1 2 3
美元新兴市场=美元这- >getDoctrine ()- >getManager ();美元产品=美元新兴市场- >getRepository (“AcmeStoreBundle:产品”)- >findAllOrderedByName ();
请注意
当使用一个自定义存储库类,你仍然可以访问默认查找器方法等find ()
和findAll ()
。
实体关系/协会
假设应用程序中的产品都属于一个“类别”。在这种情况下,您将需要一个类别
与一个对象和一个方法产品
对象一个类别
对象。首先创建的类别
实体。既然你知道你最终会通过原则需要持久化类,你可以让学说为你创建类。
1
美元的php应用程序/控制台学说:生成:实体,实体=“AcmeStoreBundle:类别”——字段=“名字:字符串(255)”
这个任务生成类别
为你的实体,一个id
场,的名字
领域和相关的getter和setter函数。
关系映射元数据
联系到一起类别
和产品
实体,首先创建一个产品
财产的类别
类:
- 注释
- YAML
- XML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/ / src / Acme / / Category.php StoreBundle /实体/ /……使用学说\常见的\集合\ArrayCollection;类类别{/ /……/ * * *@ORM\ OneToMany (targetEntity =“产品”的mappedBy =“类别”)* /受保护的美元产品;公共函数__construct(){美元这- >产品=新ArrayCollection ();}}
首先,自类别
对象将与许多产品
对象,产品
数组属性添加到保存产品
对象。再一次,这不是因为原则需要它,而是因为它是有意义的应用程序中类别
的数组产品
对象。
请注意
中的代码__construct ()
方法很重要,因为理论要求美元的产品
房地产是一个ArrayCollection
对象。几乎这个对象的外观和行为完全像一个数组,但有一些增加了灵活性。如果这让你不舒服,不要担心。想象一下,这是一个数组
你会处于良好状态。
提示
targetEntity值在上面使用的装饰可以引用任何实体与一个有效名称空间,不仅实体在同一个类中定义。与一个不同的类中定义一个实体或包,输入一个完整的名称空间作为targetEntity。
< /div>接下来,因为每个产品
类可以关联到一个类别
对象,您需要添加一个美元的类别
财产产品
类:
- 注释
- YAML
- XML
1 2 3 4 5 6 7 8 9 10 11 12 13
/ / src / Acme / / Product.php StoreBundle /实体/ /……类产品{/ /……/ * * *@ORM\ ManyToOne (targetEntity =“类别”,inversedBy = "产品")*@ORM\ JoinColumn (name = " category_id添加",referencedColumnName = " id ") * /受保护的美元类别;}
最后,现在您已经添加了一个新的属性的类别
和产品
类,告诉学说为您生成失踪的getter和setter方法:
1
$ php应用程序/控制台学说:生成:Acme的实体
忽略教义的元数据。你现在有两类类别
和产品
与自然的一对多关系。的类别
类的数组产品
对象和产品
对象可以容纳一个类别
对象。换句话说,你建造类的方式适合您的需要。这一事实的数据需要被持久化到数据库总是次要的。
现在,看看上面的元数据美元的类别
财产的产品
类。这里的信息告诉学说相关的类类别
和存储id
类别的记录上category_id添加
领域的生活产品
表。换句话说,相关的类别
将存储在对象美元的类别
属性,但在幕后,学说将持续这种关系通过存储类别的id值category_id添加
列的产品
表。
上面的元数据美元的产品
财产的类别
对象不是那么重要,只是告诉学说看Product.category
属性如何映射的关系。
在您继续之前,一定要告诉添加新的学说类别
表,product.category_id
列,和新外键:
1
php应用程序/控制台学说:美元模式:更新——力量
请注意
这个任务只能在开发过程中使用。一种更健壮的方法系统地更新你的生产数据库,了解DoctrineMigrationsBundle。
< /div>保存相关的实体
现在你可以看到这个新代码在行动!想象一下你在一个控制器:
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
/ /……使用Acme\StoreBundle\实体\类别;使用Acme\StoreBundle\实体\产品;使用ob娱乐下载\组件\HttpFoundation\响应;类DefaultController扩展控制器{公共函数createProductAction(){美元类别=新类别();美元类别- >setName (主要产品的);美元产品=新产品();美元产品- >setName (“Foo”);美元产品- >setPrice (19.99);/ /与本产品类别美元产品- >setCategory (美元类别);美元新兴市场=美元这- >getDoctrine ()- >getManager ();美元新兴市场- >persist (美元类别);美元新兴市场- >persist (美元产品);美元新兴市场- >冲洗();返回新响应(“创造了产品id:”。美元产品- >getId ()。和类别id:。美元类别- >getId ());}}
现在,添加一行到类别
和产品
表。的product.category_id
列新产品将不管id
是新类别的。原则管理这种关系的持久性。
获取相关对象
当您需要获取相关的对象,你的工作流看起来就像以前一样。首先,拿一个美元的产品
对象,然后访问相关类别
:
1 2 3 4 5 6 7 8 9 10
公共函数showAction(美元id){美元产品=美元这- >getDoctrine ()- >getRepository (“AcmeStoreBundle:产品”)- >找到(美元id);美元categoryName=美元产品- >getCategory ()- >getName ();/ /……}
在这个例子中,首先查询产品
基于产品的对象id
。这问题一个查询只是产品数据和水合物美元的产品
对象的数据。之后,当你调用产品- > getCategory () - > getName ()
,默默地教义使得第二个查询来找到类别
这是与此相关产品
。它准备美元的类别
对象,并返回给你。
重要的是你有容易获得相关产品的类别,但类别数据并不是直到你要求类别检索(即“延迟加载”)。
你也可以查询另一个方向:
1 2 3 4 5 6 7 8 9 10
公共函数showProductAction(美元id){美元类别=美元这- >getDoctrine ()- >getRepository (“AcmeStoreBundle:类别”)- >找到(美元id);美元产品=美元类别- >getProducts ();/ /……}
在这种情况下,同样的事情发生了:你第一次查询单类别
对象,然后教义使得第二个查询来检索相关产品
对象,但只有当/如果你问他们(即当你调用- > getProducts ()
)。的美元的产品
变量是一个数组产品
与给定的对象类别
通过他们的对象category_id添加
价值。
加入相关的记录
在上面的例子中,两个查询了—一个用于原来的对象(例如一个类别
),一个用于相关对象(s)(如产品
对象)。
提示
记住,你可以看到所有的查询在一个请求通过网络调试工具栏。
< /div>当然,如果你预先知道你需要访问两个对象,你可以避免第二个查询发出加入原始查询。添加以下方法ProductRepository
类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/ / src / Acme / / ProductRepository.php StoreBundle /实体公共函数findOneByIdJoinedToCategory(美元id){美元查询=美元这- >getEntityManager ()- >createQuery (“选择p c AcmeStoreBundle:产品p加入p。类别c p。id =: id ')- >setParameter (“id”,美元id);试一试{返回美元查询- >getSingleResult ();}抓(\ \ ORM \ NoResultException教义美元e){返回零;}}
现在,您可以使用这种方法在你的控制器查询产品
对象及其相关类别
只有一个查询:
1 2 3 4 5 6 7 8 9 10
公共函数showAction(美元id){美元产品=美元这- >getDoctrine ()- >getRepository (“AcmeStoreBundle:产品”)- >findOneByIdJoinedToCategory (美元id);美元类别=美元产品- >getCategory ();/ /……}
更多信息协会
本节介绍了一个常见的实体关系,一对多的关系。为更先进的细节和例子(如如何使用其他类型的关系。一对一的
,多对多
),看到学说协会映射文档欧宝官网下载app。
请注意
如果你使用注释,需要预先考虑所有注释ORM \
(如。ORM \ OneToMany
),这不是反映在教义的文档。欧宝官网下载app你还需要包括使用原则\ ORM \ ORM映射;
声明,进口的ORM
注释前缀。
配置
教义是高度可配置的,虽然你可能不会需要担心的大多数选项。找到更多关于配置原则,看到的理论部分参考手册。
< /div>生命周期回调
有时,您需要执行一个动作之前或之后插入一个实体,更新或删除。这些类型的行为被称为“生命周期”回调,作为他们回调方法,您需要执行在一个实体的生命周期的不同阶段(如实体插入、更新、删除等)。
如果你使用元数据注释,首先使生命周期回调。这不是必要的,如果你使用YAML或XML映射:
1 2 3 4 5 6 7 8
/ * * *@ORM()* \实体@ORM\ HasLifecycleCallbacks () * /类产品{/ /……}
现在,你可以告诉原则来执行一个方法在任何可用的生命周期事件。例如,假设您想要设置一个创建
日期列当前日期,只有当首先坚持实体(即插入):
- 注释
- YAML
- XML
1 2 3 4 5 6 7
/ * * *@ORM\ PrePersist * /公共函数setCreatedValue(){美元这- >创建了=新\ DateTime ();}
请注意
上面的示例假设您已经创建了映射创建
财产(这里没有显示)。
首先在实体是坚持,教义将自动调用这个方法,创建
字段将被设置为当前日期。
这对其他生命周期可以重复事件,其中包括:
preRemove
postRemove
prePersist
postPersist
preUpdate
postUpdate
postLoad
loadClassMetadata
有关这些生命周期事件是什么意思的更多信息和生命周期回调,看到教义的生命周期事件文档欧宝官网下载app
主义扩展:Timestampable Sluggable等等。
教义很灵活,和许多第三方扩展,使您可以轻松地执行重复和常见任务的实体。这些包括等Sluggable,Timestampable,Loggable,可翻译,树。
为更多的信息关于如何找到并使用这些扩展,看到食谱篇有关使用共同的原则扩展。
教义字段类型引用
教义有大量可用的字段类型。这些PHP数据类型映射到一个特定的列类型无论你使用数据库。在教义支持以下类型:
字符串
字符串
(用于较短的字符串)文本
(用于较大的字符串)
数字
整数
短整型
长整型数字
小数
浮动
日期和时间(使用一个DateTime用PHP对象为这些字段)
日期
时间
datetime
其他类型
布尔
对象
(序列化和存储在一个CLOB
字段)数组
(序列化和存储在一个CLOB
字段)
有关更多信息,请参见学说映射类型的文档欧宝官网下载app。
场的选择
每个字段可以应用一组选项。可用的选项包括类型
(默认为字符串
),的名字
,长度
,独特的
和可以为空
。一些例子:
- 注释
- YAML
- XML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/ * * *不能为空的字符串字段长度为255 *(反映默认值“类型”,“长度”*和* nullable *选项)* *@ORM\列()* /受保护的美元的名字;/ * * *的字符串字段长度为150,坚持一个“email_address”列*,唯一索引。* *@ORM\列(name = " email_address "独特= true,长度= 150)* /受保护的美元电子邮件;
请注意
这里有几个选项未列出。更多细节,请参阅原则属性映射文档欧宝官网下载app
控制台命令
Doctrine2 ORM集成提供了几下控制台命令学说
名称空间。查看命令列表您可以运行控制台没有任何参数:
1
$ php应用程序/控制台
可用命令将打印出的列表,其中很多开始原则:
前缀。你可以找到更多的信息关于这些命令(或任何Symfony命令)通过运行ob娱乐下载帮助
命令。例如,要获取详细信息原则:数据库:创建
任务,运行:
1
$ php应用程序/控制台帮助原则:数据库:创建
一些著名的或有趣的任务包括:
原则:ensure-production-settings
——检查当前环境配置高效生产。这应该是在运行刺激
环境:1
php应用程序/控制台学说:美元ensure-production-settings - env =刺激
原则:映射:导入
——允许学说一个现有的数据库并创建映射信息。有关更多信息,请参见如何从一个现有的数据库生成实体。原则:映射信息
——告诉你所有的实体学说是意识到,是否有任何基本的错误映射。原则:查询:dql
和原则:查询:sql
——允许您直接从命令行执行DQL或SQL查询。
请注意
能够加载数据设备到您的数据库,您将需要DoctrineFixturesBundle
包安装。学习如何做,阅读文档的“DoctrineFixturesBundle”条目。欧宝官网下载app
提示
这个页面显示在控制器处理原则。您可能还希望使用原则在您的应用程序。的getDoctrine ()控制器返回的方法学说
服务,您可以使用这个同样其他注射到您自己的服务。看到服务容器在创建自己的服务。