数据库和教义ORM
编辑该页面警告:你浏览的文档欧宝官网下载appob娱乐下载Symfony 2.8,不再维护。
读这个页面的更新版本Symfob娱乐下载ony 6.2(当前的稳定版本)。
< /div>数据库和教义ORM
最常见的和具有挑战性的任务对于任何应用程序包括持久化和阅读信息和从数据库。尽管Symfony框架不整ob娱乐下载合处理数据库的任何组件,它提供与第三方库称为紧密集成学说。原则的唯一目标是给你强大的工具使数据库交互简单、灵活。
在这一章,你将学习如何开始利用教义在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
# app / config / parameters.yml参数:database_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:司机:pdo_mysql主持人:“% database_host %”dbname:“% database_name %”用户:“% database_user %”密码:“% database_password %”
通过将数据库信息到一个单独的文件中,您可以很容易地保持在每个服务器上文件的不同版本。您还可以方便地存储数据库配置(或任何敏感信息)以外的项目,比如在Apache配置。有关更多信息,请参见服务容器外部参数如何设置。
< /div>现在学说可以连接到数据库,下面的命令可以自动生成一个空test_project
数据库:
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
创建一个实体类
假设您要构建一个应用程序,需要显示的产品。没想学说或数据库中,你已经知道你需要一个产品
对象来表示这些产品。创建这个类里面实体
你的AppBundle目录:
1 2 3 4 5 6 7 8 9
/ / src / AppBundle /实体/ Product.php名称空间AppBundle\实体;类产品{私人美元的名字;私人美元价格;私人美元描述;}
类——通常被称为一个“实体”的意思一个基本类,保存数据——很简单,帮助满足需要的产品在您的应用程序的业务需求。这个类不能被持久化到数据库——这只是一个简单的PHP类。
提示
一旦你学习原则背后的概念,你可以有教义为您创建简单的实体类。这将问你互动问题帮助你建立任何实体:
1
美元php应用程序/控制台学说:生成:实体
添加映射信息
教义允许您工作与数据库更加有趣的方式不仅仅是获取行标量数据到一个数组中。相反,教义允许您获取整个对象从数据库中,将整个对象持久化到数据库中。的学说能够做到这一点,你必须地图具体的PHP类,你的数据库表和列在这些表必须映射到特定属性对应的PHP类。
你会提供这种映射信息的形式“元数据”的规则的集合告诉学说如何产品
类及其属性映射到一个特定的数据库表中。此元数据可以指定在许多不同的格式,包括YAML、XML或直接在产品
类通过DocBlock注释:
- 注释
- 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 / AppBundle /实体/ Product.php名称空间AppBundle\实体;使用学说\ORM\映射作为ORM;/ * * *@ORM* \实体@ORM\表(name = "产品")* /类产品{/ * * *@ORM\列(type =“整数”)*@ORM\ Id *@ORM\ GeneratedValue(策略=“汽车”)* /私人美元id;/ * * *@ORM\列(类型=“字符串”,长度= 100)* /私人美元的名字;/ * * *@ORM\列(type =“小数”,规模= 2)* /私人美元价格;/ * * *@ORM\列(type = " text ") * /私人美元描述;}
请注意
一捆只能接受一个元数据定义格式。例如,它是不可能的混合YAML的元数据定义与注释PHP实体类定义。
< /div>提示
表名是可选的,如果省略,将自动确定基于实体类的名称。
< /div>教义允许您选择各种不同的字段类型,每个都有自己的选择。有关可用的字段类型的信息,请参阅数据库和教义ORM部分。
另请参阅
你也可以看看学说基本的映射文档欧宝官网下载app对所有细节映射信息。如果你使用注释,需要预先考虑所有注释ORM \
(如。ORM \列(…)
所示),这不是教条的文档。欧宝官网下载app你还需要包括使用原则\ ORM \ ORM映射;
声明,进口的ORM
注释前缀。
谨慎
小心如果你的实体类的名称(或属性)也保留SQL关键字集团
或用户
。例如,如果您的实体的类名集团
默认情况下,对应的表名集团
。这将导致一个SQL错误在某些数据库引擎。看到学说的保留SQL关键字的文档欧宝官网下载app有关如何正确逃脱这些名字。另外,如果你自由选择数据库模式,简单地映射到不同的表名或列名。看到学说的创建数据库的类和属性映射欧宝官网下载app文档。
请注意
当使用另一个库或程序(例如Doxygen),使用注释,你应该把@IgnoreAnnotation
注释的类来表示注释Symfony应该忽略。ob娱乐下载
例如,为了防止@fn
注释从抛出异常,添加以下:
1 2 3 4 5
/ * * *@IgnoreAnnotation(fn) * /类产品/ /……
提示
在创建您的实体应该验证映射使用下面的命令:
1
美元php应用程序/控制台学说:模式:验证
生成getter和setter方法
尽管学说现在知道如何坚持产品
对象到数据库,类本身还没有真正有用的。自产品
只是一个普通的PHP类私人
属性,您需要创建公共
(例如getter和setter方法。getName ()
,setName(名称)
)为了访问其属性在应用程序的其余部分的代码。手动添加这些方法或与自己的IDE。
创建数据库表/模式
你现在有一个可用的产品
类映射信息,以便教义确切地知道如何坚持。当然,你还没有相应的产品
表在数据库中。幸运的是,教义可以自动创建所需的所有数据库表为每一个已知的实体在您的应用程序。要做到这一点,运行:
1
美元php应用程序/控制台学说:模式:更新——力量
提示
实际上,这个命令是非常强大的。比较你的数据库应该看起来像(基于实体的映射信息)与它实际上看起来,并执行所需的SQL语句更新数据库模式在它应该在的地方。换句话说,如果你添加一个新的属性映射元数据产品
运行这个命令,它将执行“ALTER TABLE语句需要添加新列的现有产品
表。
一个更好的方法是通过利用这个功能迁移,它允许您生成这些SQL语句和存储他们移民类,可以生产服务器上运行系统,以更新和安全可靠地跟踪更改数据库模式。
你是否利用迁移,原则:模式:更新
命令应该只在开发期间使用。它不应该在生产环境中使用。
数据库现在有一个全功能产品
表和列匹配你指定的元数据。
持久化对象到数据库
现在您已经绘制了产品
实体对应的产品
表,就可以持续下去产品
对象到数据库。在一个控制器,这是非常容易的。添加以下方法DefaultController
包:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21日22日23日24
/ / src / AppBundle /控制器/ DefaultController.php/ /……使用AppBundle\实体\产品;使用ob娱乐下载\组件\HttpFoundation\响应;/ /……公共函数createAction(){美元产品=新产品();美元产品- >setName (“键盘”);美元产品- >setPrice (19.99);美元产品- >setDescription (的人体工学和时尚!);美元entityManager=美元这- >getDoctrine ()- >getManager ();/ /告诉学说你想(最终)保存产品(没有查询)美元entityManager- >persist (美元产品);/ /实际执行查询(即插入查询)美元entityManager- >冲洗();返回新响应(“保存新产品id”。美元产品- >getId ());}
请注意
如果你按照这个例子中,您需要创建一个指向这个动作路线工作。
< /div>提示
本文展示了处理原则从控制器使用getDoctrine ()控制器的方法。这是一个快捷的方法学说
服务。你可以在任何地方使用原则通过注入服务的其他服务。看到服务容器在创建自己的服务。
更详细地看一看前面的示例:
- 第10 - 13行在本节中,您实例化和工作
美元的产品
像其他普通PHP对象。 - 第15行这条线获取学说实体管理器对象,负责持久化对象的过程中,和抓取对象从数据库中。
- 第18行的
坚持(产品)
打电话告诉学说“管理”美元的产品
对象。这并不导致一个查询的数据库。 - 第21行当
冲洗()
方法被调用,原则通过的所有对象的管理,看看他们是否需要被持久化到数据库中。在这个例子中,美元的产品
对象的数据在数据库中不存在,所以实体管理器执行一个插入
查询,创建一个新行产品
表。
请注意
事实上,由于教义意识到你所有的管理实体,当你调用冲洗()
方法,它计算一个整体变更集和执行查询以正确的顺序。它利用缓存准备语句稍微提高性能。例如,如果您坚持共有100产品
然后随后调用对象冲洗()
,100年学说将执行插入
使用一个事先准备好的声明中对象的查询。
请注意
如果冲洗()
调用失败,学说\ ORM \ ORMException
异常。看到事务和并发性。
是否创建或更新对象,工作流总是相同的。在下一节中,您将看到如何学说是一个足够聪明来自动问题更新
数据库中查询如果实体已经存在。
提示
学说提供了一个库,允许您以编程方式测试数据加载到您的项目(即。“固定数据”)。信息,请参阅“DoctrineFixturesBundle _”文档。欧宝官网下载app
< /div>从数据库中获取对象
获取一个对象的数据库更容易。例如,假设您已经配置了一个显示一个特定的路线产品
基于其id
值:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
公共函数showAction(美元productId){美元产品=美元这- >getDoctrine ()- >getRepository(产品::类)- >找到(美元productId);如果(!美元产品){扔美元这- >createNotFoundException (“没有发现产品id”。美元productId);}/ /……做点什么,比如通过美元产品对象到一个模板}
提示
可以达到相当于这个没有编写任何代码通过使用@ParamConverter
快捷方式。看到FrameworkExtraBundle文欧宝官网下载app档为更多的细节。
查询一个特定类型的对象时,你总是用所谓的“仓库”。你可以认为一个存储库是一个PHP类唯一的工作就是帮助你获取某个类的实体。您可以访问存储库对象为一个实体类通过:
1 2
美元存储库=美元这- >getDoctrine ()- >getRepository(产品::类);
请注意
您还可以使用AppBundle:产品
语法。这个字符串是一个快捷方式可以使用任何学说,而不是实体的完整类名(即。AppBundle \ \实体产品
)。只要你的实体下的生活实体
你的包名称空间,这将工作。
一旦你有了一个存储库对象,您可以访问各种各样的有用的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
美元存储库=美元这- >getDoctrine ()- >getRepository(产品::类);/ /查找单个产品的主键(通常是“id”)美元产品=美元存储库- >找到(美元productId);/ /动态方法名来找到一个单一产品基于列值美元产品=美元存储库- >findOneById (美元productId);美元产品=美元存储库- >findOneByName (“键盘”);/ /动态方法名称查找一组产品基于列值美元产品=美元存储库- >findByPrice (19.99);/ /找到* *所有产品美元产品=美元存储库- >findAll ();
请注意
当然,你也可以问题复杂的查询,你会了解更多的数据库和教义ORM部分。
< /div>你也可以利用有用的findBy ()
和findOneBy ()
方法方便地获取对象根据多个条件:
1 2 3 4 5 6 7 8 9 10 11 12
美元存储库=美元这- >getDoctrine ()- >getRepository(产品::类);/ /查找单个产品匹配给定的名称和价格美元产品=美元存储库- >findOneBy (数组(“名字”= >“键盘”,“价格”= >19.99));/ /查找多个产品匹配给定的名称、订购价格美元产品=美元存储库- >findBy (数组(“名字”= >“键盘”),数组(“价格”= >“ASC”));
提示
在呈现页面时需要做一些数据库调用、网络调试工具栏底部的页面显示查询的数量和执行它们的时间:
如果数据库查询的数量过高,图标会变黄,表明一些可能不是正确的。点击图标打开Symfony分析器,看看具体执行的查询。ob娱乐下载
< /div>更新一个对象
一旦你获取一个对象从教义,更新很容易。假设您有一个路线,产品id映射到一个更新控制器中的动作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
使用AppBundle\实体\产品;/ /……公共函数updateAction(美元productId){美元entityManager=美元这- >getDoctrine ()- >getManager ();美元产品=美元entityManager- >getRepository(产品::类)- >找到(美元productId);如果(!美元产品){扔美元这- >createNotFoundException (“没有发现产品id”。美元productId);}美元产品- >setName (“新产品的名字!”);美元entityManager- >冲洗();返回美元这- >redirectToRoute (“主页”);}
更新对象包括三个步骤:
- 获取对象从教义;
- 修改对象;
- 调用
冲洗()
实体管理器。
注意,调用(entityManager - >保存美元产品)
是没有必要的。回想一下,这个方法简单告诉原则管理或“观察”美元的产品
对象。在这种情况下,因为你把美元的产品
对象从教义,它已经成功。
删除一个对象
删除一个对象非常相似,但需要调用remove ()
实体管理器的方法:
1 2
美元entityManager- >remove (美元产品);美元entityManager- >冲洗();
如您所料,remove ()
方法通知学说,你想从数据库中删除给定对象。实际的删除
查询,但是,并不是实际执行,直到冲洗()
方法被调用。
查询对象
您已经看到如何存储库对象允许您运行基本查询没有任何工作:
1 2 3 4
美元存储库=美元这- >getDoctrine ()- >getRepository(产品::类);美元产品=美元存储库- >找到(美元productId);美元产品=美元存储库- >findOneByName (“键盘”);
当然,教义也允许您编写更复杂的查询使用查询语言(DQL)原则。DQL类似于SQL除外,你应该想象你查询一个或多个对象的一个实体类(如。产品
)而不是桌子上(如查询行。产品
)。
在教义查询时,你有两种选择:写纯DQL查询或使用原则的查询生成器。
查询与DQL对象
想象一下你想查询的产品成本比19.99
,从最小订购最昂贵的。您可以使用DQL,教义的原生sql语言,构造一个查询的方法对于这个场景:
1 2 3 4 5 6 7 8 9
美元entityManager=美元这- >getDoctrine ()- >getManager ();美元查询=美元entityManager- >createQuery (“从AppBundle选择p:产品p, p。价格>:价格按p。ASC的价格)- >setParameter (“价格”,19.99);美元产品=美元查询- >getResult ();
如果您熟悉SQL,那么DQL应该感到很自然。最大的区别是,你需要考虑选择PHP对象,而不是数据库中的行。出于这个原因,你选择从的AppBundle:产品
实体(一个可选的快捷方式AppBundle \ \实体产品
这类),然后别名p
。
提示
注意的setParameter ()
方法。在处理原则时,它总是一个好主意任何外部值设置为“占位符”(:价格
在上面的示例中),因为它可以防止SQL注入攻击。
的getResult ()
方法返回一个数组的结果。只有一个结果,您可以使用getOneOrNullResult ()
:
1
美元产品=美元查询- >setMaxResults (1)- >getOneOrNullResult ();
DQL语法是非常强大的,允许您轻松地加入实体之间的话题关系稍后将介绍)、组等。有关更多信息,看到官方的吗教义的查询语言欧宝官网下载app文档。
< /div>查询对象使用原则的查询生成器
而不是写一个DQL字符串,您可以使用一个称为有用的对象QueryBuilder
为你构建字符串。这是有用,当实际的查询取决于动态条件下,随着代码很快就变得难以阅读与DQL你开始连接字符串:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
美元存储库=美元这- >getDoctrine ()- >getRepository(产品::类);/ / createQueryBuilder()自动从AppBundle:选择产品/ /,别名“p”美元查询=美元存储库- >createQueryBuilder (“p”)- >(在哪里“p。price > :price'< /span>)- >setParameter (“价格”,“19.99”)- >orderBy (“p.price”,“ASC”)- >getQuery ();美元产品=美元查询- >getResult ();/ /得到只有一个结果:/ /产品=美元查询- > setMaxResults (1) - > getOneOrNullResult ();
的QueryBuilder
对象包含每个方法需要建立你的查询。通过调用getQuery ()
方法,查询构建器返回正常查询
对象,该对象可以用来获取查询的结果。
教义的查询构建器的更多信息,参考原则查询构建器欧宝官网下载app文档。
< /div>教义字段类型引用
教义有很多可用的字段类型。这些PHP数据类型映射到一个特定的列类型无论你使用数据库。对于每个字段类型,列
进一步可以配置,设置长度
,可以为空
的行为,的名字
和其他选项。看到所有可用的列表类型和更多信息,参见学说映射类型的文档欧宝官网下载app。
关系和联系
学说提供了所有你需要的功能来管理数据库(也称为协会)的关系。信息,请参阅如何使用主义协会/关系。
< /div>最终的想法
原则,你可以专注于你对象如何在您的应用程序中使用它们,担心数据库持久性。这是因为教义允许您使用任何PHP对象保存数据和依赖映射元数据信息对象的数据映射到一个特定的数据库表。
学习教义有很多更复杂的功能,如人际关系,复杂的查询,和事件监听器。
< /div>