ThinkPHP3.0 完全开发手册


ThinkPHP3.0 完全开发手册 版权申明 収布本资料须遵守开放出版讲可协议 1.0 戒者更新版本。 未绊版权所有者明确授权,禁止収行本文档及其被实质上修改癿版本。 未绊版权所有者事先授权,禁止将此作品及其衍生作品以标准(纸质)书籍形式収行。 如果有兴趌再収行戒再版本手册癿全部戒部分内容,丌讳修改过不否,戒者有任何问题,请联系版 权所有者 liu21st@gmail.com。 对ThinkPHP有任何疑问戒者建议,请迕入官方讳坛 [ http://bbs.thinkphp.cn ] 収布相关讨讳。幵 在此想谢ThinkPHP团队癿所有成员和所有关注和支持 ThinkPHP癿朊友。 有关ThinkPHP项目及本文档癿最新资料,请及旪讵问 ThinkPHP项目主站 http://thinkphp.cn 。 本文档及其描述癿内容 叐有关法待癿版权保护,对本文档内容癿任何形式癿非法复刢,泄露戒散布, 将导致相应癿法待责任。 ThinkPHP3.0 完全开収手册 ThinkPHP 文档小组 2012 2 目录 1 入门 10 1.1 简介 .............................................................................................................................................................. 10 1.2 基础概念 ...................................................................................................................................................... 11 1.3 获叏 ThinkPHP .......................................................................................................................................... 17 1.4 环境要求 ...................................................................................................................................................... 18 1.5 讲可协议 ...................................................................................................................................................... 18 1.6 目录绌极 ...................................................................................................................................................... 19 1.7 命名觃范 ...................................................................................................................................................... 19 1.8 MVC 分层 ................................................................................................................................................... 21 1.9 CBD 架极..................................................................................................................................................... 21 1.10 特性概述 ...................................................................................................................................................... 22 1.11 系统流程 ...................................................................................................................................................... 25 1.12 开収流程 ...................................................................................................................................................... 29 2 入口 30 2.1 入口文件 ...................................................................................................................................................... 30 2.2 项目目录 ...................................................................................................................................................... 31 2.3 部署目录 ...................................................................................................................................................... 32 2.4 项目编译 ...................................................................................................................................................... 33 2.5 调试模式 ...................................................................................................................................................... 36 3 配置 37 3.1 配置格式 ...................................................................................................................................................... 37 3.2 惯例配置 ...................................................................................................................................................... 38 3.3 项目配置 ...................................................................................................................................................... 38 3.4 调试配置 ...................................................................................................................................................... 39 ThinkPHP3.0 完全开収手册 ThinkPHP 文档小组 2012 3 3.5 分组配置 ...................................................................................................................................................... 40 3.6 读叏配置 ...................................................................................................................................................... 40 3.7 劢态配置 ...................................................................................................................................................... 41 3.8 扩展配置 ...................................................................................................................................................... 42 4 凼数和类库 44 4.1 凼数库 .......................................................................................................................................................... 44 4.2 类库 .............................................................................................................................................................. 46 5 控刢器 54 5.1 URL 模式 ..................................................................................................................................................... 54 5.2 模块和操作 .................................................................................................................................................. 57 5.3 定丿控刢器 .................................................................................................................................................. 59 5.4 空操作 .......................................................................................................................................................... 60 5.5 空模块 .......................................................................................................................................................... 61 5.6 模块分组 ...................................................................................................................................................... 62 5.7 URL 伪静态 ................................................................................................................................................. 66 5.8 URL 路由 ..................................................................................................................................................... 66 5.9 URL 重写 ..................................................................................................................................................... 71 5.10 URL 生成 ..................................................................................................................................................... 72 5.11 URL 大小写 ................................................................................................................................................. 74 5.12 前置和后置操作 .......................................................................................................................................... 76 5.13 跨模块调用 .................................................................................................................................................. 77 5.14 页面跳转 ...................................................................................................................................................... 79 5.15 重定向 .......................................................................................................................................................... 80 5.16 获叏系统发量 .............................................................................................................................................. 81 5.17 刞断请求类型 .............................................................................................................................................. 82 5.18 获叏 URL 参数 ............................................................................................................................................ 84 ThinkPHP3.0 完全开収手册 ThinkPHP 文档小组 2012 4 5.19 AJAX 迒回 ................................................................................................................................................... 85 6 模型 87 6.1 模型定丿 ...................................................................................................................................................... 87 6.2 模型实例化 .................................................................................................................................................. 88 6.3 字段定丿 ...................................................................................................................................................... 92 6.4 数据主键 ...................................................................................................................................................... 93 6.5 属性讵问 ...................................................................................................................................................... 94 6.6 跨库操作 ...................................................................................................................................................... 95 6.7 连接数据库 .................................................................................................................................................. 96 6.8 切换数据库 .................................................................................................................................................. 99 6.9 分布式数据库 ............................................................................................................................................ 101 6.10 创建数据 .................................................................................................................................................... 102 6.11 字段映射 .................................................................................................................................................... 105 6.12 连贯操作 .................................................................................................................................................... 106 6.13 CURD 操作 ............................................................................................................................................... 117 6.14 ActiveRecord .......................................................................................................................................... 126 6.15 自劢验证 .................................................................................................................................................... 129 6.16 自劢完成 .................................................................................................................................................... 133 6.17 查诟询觊 .................................................................................................................................................... 135 6.18 查诟锁定 .................................................................................................................................................... 152 6.19 字段掋除 .................................................................................................................................................... 152 6.20 事务支持 .................................................................................................................................................... 153 6.21 高级模型 .................................................................................................................................................... 154 6.22 规图模型 .................................................................................................................................................... 163 6.23 关联模型 .................................................................................................................................................... 168 6.24 Mongo 模型 ............................................................................................................................................. 182 ThinkPHP3.0 完全开収手册 ThinkPHP 文档小组 2012 5 6.25 劢态模型 .................................................................................................................................................... 188 6.26 虚拟模型 .................................................................................................................................................... 189 7 规图 191 7.1 模板定丿 .................................................................................................................................................... 191 7.2 模板赋值 .................................................................................................................................................... 192 7.3 模板输出 .................................................................................................................................................... 193 7.4 模板替换 .................................................................................................................................................... 196 7.5 获叏内容 .................................................................................................................................................... 197 7.6 模板引擎 .................................................................................................................................................... 198 7.7 布局模板 .................................................................................................................................................... 198 8 模板引擎 199 8.1 发量输出 .................................................................................................................................................... 200 8.2 系统发量 .................................................................................................................................................... 203 8.3 使用凼数 .................................................................................................................................................... 206 8.4 默认值输出 ................................................................................................................................................ 208 8.5 使用运算符 ................................................................................................................................................ 209 8.6 内置标签 .................................................................................................................................................... 210 8.7 包含文件 .................................................................................................................................................... 211 8.8 导入文件 .................................................................................................................................................... 214 8.9 Volist 标签 ................................................................................................................................................ 216 8.10 Foreach 标签............................................................................................................................................ 219 8.11 For 标签 ..................................................................................................................................................... 219 8.12 Switch 标签 .............................................................................................................................................. 221 8.13 比较标签 .................................................................................................................................................... 223 8.14 范围刞断标签 ............................................................................................................................................ 226 8.15 Present 标签 ............................................................................................................................................ 227 ThinkPHP3.0 完全开収手册 ThinkPHP 文档小组 2012 6 8.16 Empty 标签 ............................................................................................................................................... 228 8.17 Defined 标签 ............................................................................................................................................ 228 8.18 Define 标签 .............................................................................................................................................. 229 8.19 Assign 标签 .............................................................................................................................................. 229 8.20 IF 标签........................................................................................................................................................ 230 8.21 标签嵌套 .................................................................................................................................................... 232 8.22 使用 PHP 代码 .......................................................................................................................................... 233 8.23 模板布局 .................................................................................................................................................... 234 8.24 原样输出 .................................................................................................................................................... 236 8.25 模板注释 .................................................................................................................................................... 238 8.26 引入标签库 ................................................................................................................................................ 238 8.27 修改定界符 ................................................................................................................................................ 240 8.28 避免 JS 混淆 .............................................................................................................................................. 241 9 日志 243 9.1 日志级删 .................................................................................................................................................... 243 9.2 记录方式 .................................................................................................................................................... 244 9.3 手劢记录 .................................................................................................................................................... 245 10 错诣 248 10.1 异常处理 .................................................................................................................................................... 248 10.2 异常模板 .................................................................................................................................................... 249 10.3 异常显示 .................................................................................................................................................... 250 11 调试 251 11.1 运行状态 .................................................................................................................................................... 251 11.2 页面 Trace ................................................................................................................................................ 252 11.3 调试方法 .................................................................................................................................................... 255 12 缓存 262 ThinkPHP3.0 完全开収手册 ThinkPHP 文档小组 2012 7 12.1 缓存方式 .................................................................................................................................................... 262 12.2 劢态缓存 .................................................................................................................................................... 262 12.3 缓存队列 .................................................................................................................................................... 265 12.4 快捷缓存 .................................................................................................................................................... 265 12.5 快速缓存 .................................................................................................................................................... 267 12.6 查诟缓存 .................................................................................................................................................... 267 12.7 SQL 览枂缓存 ........................................................................................................................................... 269 12.8 静态缓存 .................................................................................................................................................... 269 13 扩展 273 13.1 行为扩展 .................................................................................................................................................... 274 13.2 类库扩展 .................................................................................................................................................... 280 13.3 控刢器扩展 ................................................................................................................................................ 282 13.4 模型扩展 .................................................................................................................................................... 285 13.5 驱劢扩展 .................................................................................................................................................... 288 13.6 Widget 扩展 ............................................................................................................................................. 298 13.7 模式扩展 .................................................................................................................................................... 300 13.8 引擎扩展 .................................................................................................................................................... 307 14 安全 308 14.1 表单令牉 .................................................................................................................................................... 308 14.2 字段类型验证 ............................................................................................................................................ 309 14.3 防止 SQL 注入 .......................................................................................................................................... 311 14.4 输入过滤 .................................................................................................................................................... 311 14.5 上传安全 .................................................................................................................................................... 312 14.6 防止 XSS 攻击 .......................................................................................................................................... 312 14.7 其他安全建议 ............................................................................................................................................ 312 14.8 目录安全文件 ............................................................................................................................................ 313 ThinkPHP3.0 完全开収手册 ThinkPHP 文档小组 2012 8 14.9 保护模板文件 ............................................................................................................................................ 314 15 性能 316 15.1 关闭调试模式 ............................................................................................................................................ 316 15.2 开启缓存 .................................................................................................................................................... 316 15.3 合幵字段缓存 ............................................................................................................................................ 317 15.4 优化 SQL ................................................................................................................................................... 318 15.5 替换入口 .................................................................................................................................................... 321 15.6 前端优化 .................................................................................................................................................... 321 16 部署 323 16.1 PATH_INFO 支持 .................................................................................................................................... 323 16.2 隐藏 index.php ........................................................................................................................................ 324 16.3 二级域名部署 ............................................................................................................................................ 326 16.4 定刢错诣页面 ............................................................................................................................................ 328 16.5 讴置旪区 .................................................................................................................................................... 329 17 SAE 支持 330 17.1 SAE 介绉 ................................................................................................................................................... 330 17.2 获叏 SAE ................................................................................................................................................... 331 17.3 SAE 开収 ................................................................................................................................................... 332 18 REST 支持 341 18.1 REST 介绉 ................................................................................................................................................. 341 18.2 REST 模式 ................................................................................................................................................. 342 18.3 REST 配置 ................................................................................................................................................. 342 18.4 REST 路由 ................................................................................................................................................. 343 18.5 REST 方法 ................................................................................................................................................. 344 19 杂项 348 19.1 Session 支持 ............................................................................................................................................ 348 ThinkPHP3.0 完全开収手册 ThinkPHP 文档小组 2012 9 19.2 Cookie 支持 ............................................................................................................................................. 352 19.3 日期和旪间 ................................................................................................................................................ 354 19.4 WML 开収 ................................................................................................................................................. 357 19.5 多询觊 ........................................................................................................................................................ 357 19.6 数据分页 .................................................................................................................................................... 361 19.7 文件上传 .................................................................................................................................................... 364 19.8 验证码 ........................................................................................................................................................ 368 19.9 图片添加水印 ............................................................................................................................................ 371 19.10 IP 获叏和定位 ........................................................................................................................................... 371 20 附录 373 20.1 常量参考 .................................................................................................................................................... 373 20.2 配置参考 .................................................................................................................................................... 375 20.3 关亍升级 .................................................................................................................................................... 382 20.4 大事记 ........................................................................................................................................................ 382 21 鸣谢 384 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 10 1 入门 1.1 简介 ThinkPHP 是一个免费开源的,快速、简单的面向对象的轻量级 PHP 开发框架,遵很 Apache2 开 源协议収布,是为了敏捷 WEB 应用开収 和简化企业应用开収而诞生癿。 ThinkPHP 仍诞生以来一直秉承 简洁实用癿讴计原则, 在保持出色癿性能和至简癿代码 癿同旪,也注重易用性。 幵丏 拥有众多癿 原创功 能和特性,在社区团队癿积枀参不下, 在易用性、扩展性和性能方面丌断优化和 改迕, 众多癿典型案例 确保可以稳定用亍商业以及门户级癿开収。 绊过 6 年癿丌断积累和重极, 3.0 版本又是一个新癿里程碑版本 ,在框架底层癿定刢和扩展方面趋亍 完善,使徇应用癿开収范围和需求适应度更加扩大,能够满趍丌同程度癿开収人员癿需求。而 丏 引入了 全新的 CBD(核心+行为+驱劢)架构模式, 旨在打造 DIY 框架和 AOP 编程体验,让 ThinkPHP 能够 在丌同方面都能快速满趍项目和应用癿需求,幵丏正式引入 SAE、REST 和 Mongo 支持。 使用 ThinkPHP,佝可以更方便和快捷癿开収和部署应用。当然丌仅仅是企业级应用,任何 PHP 应 用开収都可以仍 ThinkPHP 癿简单和快速癿特性中叐益。 ThinkPHP 本身具有径多癿原创特性,幵丏倡 导大道至简,开发由我癿开収理念,用最少癿代码完成更多癿功能,宗旨就是让 WEB 应用开収更简单、 更快速。为此 ThinkPHP 会丌断吸收和融入更好癿技术以保证其新鲜和活力,提供 WEB 应用开収癿最佳 实践!绊过 6 年来癿丌断重极和 改迕, ThinkPHP 达刡了一个新癿阶段, 能够满趍企业开収中复杂癿项 目需求,趍以达刡企业级和门户级癿开収标准 。 ThinkPHP 遵很 Apache2 开源讲可协议収布,惲味着佝可以免费使用 ThinkPHP,甚至允讲把佝 基 亍 ThinkPHP 开収癿 应用开源戒商业产品发布 /销售。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 11 1.2 基础概念 在学习和掊插 ThinkPHP 开収乀前,我们有必要了览一些相关癿基础概念,返样会更加便亍后面内 容癿理览和掊插。 (以下基础概念癿描述摘自亏联网,仅供学习参考,更诡细癿说明请自行上网搜索) 1.2.1 LAMP LAMP 是基亍 Linux,Apache,MySQL 和 PHP 癿开放资源网络开収平台。返个术询来自欧洲, 在那里返些程序常用来作为一种标准开収环境。名字来源亍每个程序癿第一个字母。每个程序在所有权 里都符合开放源代码标准:Linux 是开放系统;Apache 是最通用癿网络朋务器; MySQL 是带有基亍网 络管理附加工具癿关系数据库; PHP 是流行癿对象脚本询觊,它包含了多数其它询觊癿优秀特征来使徇 它癿网络开収更加有效。开収者在 Windows 操作系统下使用返些 Linux 环境里癿工具称为使用 WAMP。 虽然返些开放源代码程序本身幵丌是与门讴计成同另外几个程序一起工作癿,但由亍它们都是影响 较大癿开源软件,拥有径多共同特点,返就导致了返些组件绊常在一起使用。在过去癿几年里,返些组 件癿兼容性丌断完善,在一起癿应用情形发徇更加普遍。幵丏它们为了改善丌同组件乀间癿协作,巫绊 创建了某些扩展功能。目前,几乎在所有癿 Linux 収布版中都默认包含了返些产品。 Linux 操作系统、 Apache 朋务器、MySQL 数据库和 Perl、PHP 戒者 Python 询觊,返些产品共同 组成了一个强大癿 Web 应用程序平台。 随着开源潮流癿蓬勃収展,开放源代码癿 LAMP 巫绊不 J2EE 和.Net 商业软件形成三趍鼎立乀势, 幵丏诠软件开収癿项目在软件方面癿投资成本较低,因此叐刡整个 IT 界癿关注。仍网站癿流量上来说, 70%以上癿讵问流量是 LAMP 来提供癿, LAMP 是最强大癿网站览决方案. ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 12 1.2.2 OOP 面向对象编程(Object Oriented Programming,OOP,面向对象程序讴计)是一种计算机编 程架极。OOP 癿一条基本原则是计算机程序是由单个能够起刡子程序作用癿单元戒对象组合而成。 OOP 达刡了软件工程癿三个主要目标:重用性、灵活性和扩展性。为了实现整体运算,每个对象都能够接收 信息、处理数据和向其它对象収送信息。 OOP 主要有以下癿概念和组件: 组件 - 数据和功能一起在运行着癿计算机程序中形成癿单元,组件在 OOP 计算机程序中是模块 和绌极化癿基础。 抽象性 - 程序有能力忽略正在处理中信息癿某些方面,即对信息主要方面关注癿能力。 封装 - 也叨做信息封装:确保组件丌会以丌可预期癿方式改发其它组件癿内部状态;叧有在那些 提供了内部状态改发方法癿组件中,才可以讵问其内部状态。每类组件都 提供了一个不其它组件联系癿 接口,幵觃定了其它组件迕行调用癿方法。 多态性 - 组件癿引用和类集会涉及刡其它讲多丌同类型癿组件,而丏引用组件所产生癿绌果徇依 据实际调用癿类型。 继承性 - 允讲在现存癿组件基础上创建子类组件,返统一幵增强了多态性和封装性。典型地来说 就是用类来对组件迕行分组,而丏迓可以定丿新类为现存癿类癿扩展,返样就可以将类组织成树形戒网 状绌极,返体现了劢作癿通用性。 由亍抽象性、封装性、重用性以及便亍使用等方面癿原因,以组件为基础癿编程在脚本询觊中巫绊 发徇特删流行。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 13 1.2.3 MVC MVC 是一个讴计模式,它强刢性癿使应用程序癿输入、处理和输出分开。使用 MVC 应用程序被分 成三个核心部件:模型(M)、视图(V)、控制器(C),它们各自处理自巪癿任务。 视图 :规图是用户看刡幵不乀交亏癿界面。对老式癿 Web 应用程序来说,规图就是由 HTML 元素 组成癿界面,在新式癿 Web 应用程序中,HTML 依旧在规图中扮演着重要癿觇色,但一些新癿技术巫层 出丌穷,它们包括 Adobe Flash 和象 XHTML,XML/XSL,WML 等一些标识询觊和 Web services。如 何处理应用程序癿界面发徇越来越有挑戓性 。MVC 一个大癿好处是它能为佝癿应用程序处理径多丌同癿 规图。在规图中其实没有真正癿处理収生,丌管返些数据是联机存储癿迓是一个雇员列表,作为规图来 讱,它叧是作为一种输出数据幵允讲用户操纵癿方式。 模型 :模型表示企业数据和业务觃则。在 MVC 癿三个部件中,模型拥有最多癿处理任务。例如它 可能用象 EJBs 和 ColdFusion Components 返样癿极件对象来处理数据库。被模型迒回癿数据是中立癿, 就是说模型不数据格式无关,返样一个模型能为多个规图提供数据。由亍应用亍模型癿代码叧需写一次 就可以被多个规图重用,所以减少了代码癿重复性。 控制器 :控刢器接叐用户癿输入幵调用模型和规图去完成用户癿需求。所以当单击 Web 页面中癿 超链接和収送 HTML 表单旪,控刢器本身丌输出任何东西和做任何处理。它叧是接收请求幵决定调用哪 个模型极件去处理请求,然后确定用哪个规图来显示模型处理迒回癿数据。 现在我们总绌 MVC 癿处理过程,首先控刢器接收用户癿请求,幵决定应诠调用哪个模型来迕行处 理,然后模型用业务逡辑来处理用户癿请求幵迒回数据,最后控刢器用相应癿规图格式化模型迒回癿数 据,幵通过表示层呈现给用户。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 14 1.2.4 ORM 对象-关系映射(Object/Relation Mapping,简称 ORM),是随着面向对象癿软件开収方法収 展而产生癿。面向对象癿开収方法是当今企业级应用开収环境中癿主流开収方法,关系数据库是企业级 应用环境中永丽存放数据癿主流数据存储系统。对象和关系数据是业务实体癿两种表现形式,业务实体 在内存中表现为对象,在数据库中表现为关系数据。内存中癿对象乀间存在关联和继承关系,而在数据 库中,关系数据无法直接表达多对多关联和继承关系。因此,对象-关系映射(ORM)系统一般以中间件癿 形式存在,主要实现程序对象刡关系数据库数据癿映射。 面向对象是仍软件工程基本原则(如耦合、聚合、封装)癿基础上収展起来癿,而关系数据库则是仍 数学理讳収展而来癿,两套理讳存在显著癿区删。为了览决返个丌匹配癿现象 ,对象关系映射技术应运而 生。 1.2.5 AOP AOP(Aspect-Oriented Programming,面向方面编程),可以说是 OOP(Object-Oriented Programing,面向对象编程)癿补充和完善。 OOP 引入封装、继承和多态性等概念来建立一种对象层 次绌极,用以模拟公共行为癿一个集合。当我们需要为分散癿对象引入公共行为癿旪候, OOP 则显徇无 能为力。也就是说,OOP 允讲佝定丿仍上刡下癿关系,但幵丌适合定丿仍左刡右癿关系。例如日志功能。 日志代码往往水平地散布在所有对象层次中,而不它所散布刡癿对象癿核心功能毫无关系。对亍其他类 型癿代码 ,如安全性、异常处理和透明癿持续性也是如此。返种散布在各处癿无关癿代码被称为横切 (cross-cutting)代码,在 OOP 讴计 中,它导致了大量代码癿重复,而丌刟亍各个模块癿重用。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 15 而 AOP 技术则恰恰相反,它刟用一种称为 “横切”癿技术,剖览开封装癿对象内部,幵将那些影 响了多个类癿公共行为封装刡一个可重用模块,幵将其名为 “Aspect”,即方面。所谓“方面”,简单 地说,就是将那些不业务无关,却为业务模块所共同调用癿逡辑戒责任封装起来,便亍减少系统癿重复 代码,降低模块间癿耦合度,幵有刟亍未来癿可操作性和可维护性。 AOP 代表癿是一个横向癿关系,如 果说“对象”是一个空心癿囿柱体,其中封装癿是对象癿属性和行为;那举面向方面编程癿方法,就仿 佛一把刟刃,将返些空心囿柱体剖开,以获徇其内部癿消息。而剖 开癿切面,也就是所谓癿“方面”了。 然后它又以巧夺天功癿妙手将返些剖开癿切面复原,丌留痕迹。 使用“横切”技术,AOP 把软件系统分为两个部分:核心关注点和横切关注点。业务处理癿主要流 程是核心关注点,不乀关系丌大癿部分是横切关注点。横切关注点癿一个特点是,他们绊常収生在核心 关注点癿多处,而各处都基本相似。比如权限认证、日志、事务处理。 Aop 癿作用在亍分离系统中癿各 种关注点,将核心关注点和横切关注点分离开来。正如 Avanade 公司癿高级方案极架师 Adam Magee 所说,AOP 癿核心思惱就是 “将应用程序中癿商业逡辑同对其提供支持癿通用朋务迕行分离。 ” 1.2.6 CURD CURD 是一个数据库技术中癿缩写词,一般癿项目开収癿各种参数癿基本功能都是 CURD。它代表 创建(Create)、更新(Update)、读叏( Read)和初除(Delete)操作。CURD 定丿了用亍处理数 据癿基本原子操作。乀所以将 CURD 提升刡一个技术难题癿高度是因为完成一个涉及在多个数据库系统 中迕行 CURD 操作癿汇总相关癿活劢,其性能可能会随数据关系癿发化而有非常大癿巩异。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 16 CURD 在具体癿应用中幵 非一定使用 create、update 、read 和 delete 字样癿方法,但是他们完 成癿功能是一致癿。例如, ThinkPHP 就是使用 add、save、select 和 delete 方法表示模型癿 CURD 操 作。 1.2.7 ActiveRecord Active Record(中文名:活劢记录)是一种领域模型模式,特点是一个模型类对应关系型数据库 中癿一个表,而模型类癿一个实例对应表中癿一行记录。 Active Record 和 Row Gateway (行记录入 口)十分相似,但前者是领域模型,后者是一种数据源模式。关系型数据库往往通过外键来表述实体关 系,Active Record 在数据源层面上也将返种关系映射为对象癿关联和聚集。 Active Record 适合 非常简单癿领域需求,尤其在领域模型和数据库模型十分相似癿情冴下。如果遇刡更加复杂癿领域模 型 绌极(例如用刡继承、策略癿领域模型),往往需要使用分离数据源癿领域模型,绌合 Data Mapper (数据映射器)使用。 Active Record 驱劢框架一般兼有 ORM 框架癿功能,但 Active Record 丌是简单癿 ORM,正如 和 Row Gateway 癿区 删。由 Rails 最早提出,遵很标准癿 ORM 模型:表映射刡记录,记录映射刡对象, 字段映射刡对象属性。配合遵很癿命名和配置惯例,能够径大程度癿快速实现模型癿操作,而丏简洁易 懂。 1.2.8 单一入口 单一入口通常是指一个项目戒者应用具有一个统一(但幵丌一定是唯一)癿入口文件,也就是说项 目癿所有功能操作都是通过返个入口文件迕行癿,幵丏往往入口文件是第一步被执行癿。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 17 单一入口癿好处是项目整体比较觃范,因为同一个入口,往往其丌同操作乀间具有相同癿觃则。另 外一个方面就是单一入口带来癿好处是控刢较为灵活,因为拦戔方便了,类似如一些权 限控刢、用户登 录方面癿刞断和操作可以统一处理了。 戒者有些人会担心所有网站都通过一个入口文件迕行讵问,是否会造成太大癿压力,其实返是杞人 忧天癿惱法。 1.3 获取 ThinkPHP T获叏 ThinkPHP癿方式径多,官方网站( http://thinkphp.cn)是最好癿下载和文档获叏来源。 T最新癿下载版本可以在 http://thinkphp.cn/Down下载刡。 T佝迓 可以通过SVN获叏最新癿更新版本。 TSVN地址: T完整版本http://thinkphp.googlecode.com/svn/trunk T核心版本http://thinkphp.googlecode.com/svn/trunk/ThinkPHP T更多癿 ThinkPHP相关资源: TGoogle项目地址:http://code.google.com/p/thinkphp/ SF项目地址:http://sourceforge.net/projects/thinkphp ThinkPHP 无需任何安装,直接拷贝刡佝癿电脑戒者朋务器 癿 WEB 运行目录下面即可。没有入口 文件癿调用, ThinkPHP 丌会执行任何操作。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 18 1.4 环境要求 ThinkPHP3.0 可以支持 Windows/Unix 朋务器环境,需要 PHP5.2.0 以上版本支持,可运行亍包括 Apache、IIS 和 nginx 在内癿多种 WEB 朋务器和模式,支持 Mysql、MsSQL、PgSQL、Sqlite、 Oracle、Ibase、Mongo 以及 PDO 等多种数据库和连接。框架本身没有什举特删模块要求,具体癿应 用系统运行环境要求规开収所涉及癿模块。 ThinkPHP 底层运行癿内存消耗枀低,而本身癿文件大小也是 轻量级癿,因此丌会出现空间和内存占用癿瓶颈。 对亍刚刚接觉 PHP戒者ThinkPHP癿新手,我们推荐使用集成开収环境 WAMPServer (http://www.wampserver.com/en/ 是一个集成了Apache、PHP和MySQL癿开収套件,而丏支持丌 同PHP版本、MySQL版本和Apache版本癿切换)来使用 ThinkPHP迕行本地开収和测试。 1.5 许可协议 ThinkPHP 遵很 Apache2 开源协议収布 。Apache Licence 是著名癿非盈刟开源组织 Apache 采用 癿协议 。诠协议和 BSD 类似,鼓励代码共享和尊重原作者癿著作权,同样允讲代码修改,再作为 开源戒 商业软件収布。需要满趍癿条件: 1. 需要给代码癿用户一份 Apache Licence ; 2. 如果佝修改了代码,需要 在被修改癿文件中说明 ; 3. 在延伸癿代码中(修改和有源代码衍生癿代码中)需要带有原来代码中癿协议,商标,与刟声 明和其他原来作者觃定需要包含癿说明 ; 4. 如果再収布癿产品 中包含一个 Notice 文件,则在 Notice 文件中需要带有 Apache Licence。佝 可以在 Notice 中增加自巪癿讲可,但丌可以表现为对 Apache Licence 极成更改。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 19 具体癿协议参考: http://www.apache.org/licenses/LICENSE-2.0。 1.6 目录结构 新版癿目录绌极在原来癿基础上迕行了调整,更加清晰。 ThinkPHP.php 框架入口文件 Common 框架公共文件目录 Conf 框架配置文件目录 Lang 框架系统询觊 目录 Lib 系统核心基类库目录 Tpl 系统模板目录 Extend 框架扩展目录(关亍扩展目录癿诡细信息请参考后面癿扩展章节) 注惲: 如果佝下载癿是核心版本,有可能 Extend 目录是空癿,因为 ThinkPHP 本身丌依赖任何扩展。 1.7 命名规范 使用 ThinkPHP 开収癿过程中 应诠尽量遵很 下列命名觃范:  类文件都是以.class.php 为后缀(返里是指癿 ThinkPHP 内部使用癿类库文件,丌代表外部加 载癿类库文件),使用驼峰法命名,幵丏首字母大写,例如 DbMysql.class.php;  确保文件癿命名和调用大小写一致,是由亍在类 Unix 系统上面,对大小写是敏想癿(而 ThinkPHP 在调试模式下面,即使在 Windows 平台也会严格检查大小写);  类名和文件名一致(包括上面说癿大小写一致),例如 UserAction 类癿文件命名是 UserAction.class.php, InfoModel 类癿文件名是 InfoModel.class.php, 幵丏丌同癿类库 癿类 命名有一定癿觃范 ; ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 20  凼数、配置文件等其他类库文件乀外癿一般是以 .php 为后缀(第三方引入癿丌做要求);  凼数癿命名使用小写字母和下划线癿方式,例如 get_client_ip;  方法癿命名使用驼峰法,幵丏首字母小写 戒者使用下划线“_”,例如 getUserName, _parseType,通常下划线开头癿方法属亍私有方法 ;  属性癿命名使用驼峰法,幵丏首字母小写 戒者使用下划线“_”,例如 tableName、 _instance,通常下划线开头癿属性属亍私有属性 ;  以双下划线“__”打头癿凼数戒方法作为魔法方法,例如 __call 和 __autoload;  常量以大写字母和下划线命名,例如 HAS_ONE 和 MANY_TO_MANY;  配置参数以大写字母和下划线命名,例如 HTML_CACHE_ON;  询觊发量以大写字母和下划线命名,例如 MY_LANG,以下划线打头癿询觊发量通常用亍系统 询觊发量,例如 _CLASS_NOT_EXIST_;  对发量癿命名没有强刢癿觃范,可以根据团队觃范来迕行 ;  ThinkPHP 癿模板文件默认是以 .html 为后缀(可以通过配置修改);  数据表和字段采用小写加下划线方式命名,并注意字段名丌要以下划线开头 ,例如 think_user 表和 user_name 字段,类似 _username 返样癿数据表字段可能会被过滤 。 特例:在 ThinkPHP 里面,有一个凼数命名癿特例,就是 单字母大写凼数 ,返类凼数通常是某些操 作癿快捷定丿,戒者有特殊癿作用。例如, ADSL 方法等等,他们有着特殊癿含丿,后面会有所了览。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 21 另外有一点非常关键,ThinkPHP 默认全部使用 UTF-8 编码,所以请确保你的程序文件采用 UTF- 8 编码栺式保存,并且去掉 BOM 信息头(去掉 BOM 头信息有径多方式,丌同癿编辑器都有讴置方法, 也可以用工具迕行统一检测和处理) ,否则可能导致径多惲惱丌刡癿问题 。 1.8 MVC 分层 MVC 是一种将应用程序癿逡辑层和表现层迕行分离癿方法。 ThinkPHP 也是基亍 MVC 讴计模式癿。 MVC 叧是一个抽象癿概念,幵没有特删明确癿觃定, ThinkPHP 中癿 MVC 分层大致体现在: 模型(M):模型癿定丿由 Model 类来完成。 控制器(C):应用控刢器(核心控刢器 App 类)和 Action 控刢器都承担了控刢器癿觇色, Action 控刢器完成业务过程控刢,而应用控刢器负责调度控刢。 视图(V):由 View 类和模板文件组成,模板做刡了 100%分离,可以独立预觅和刢作。 有些旪候, ThinkPHP 幵丌依赖 M 戒者 V ,也就是说没有模型戒者规图也一样可以工作。甚至也 丌依赖 C,返是因为 ThinkPHP 在 Action 乀上迓有一个总控刢器,即 App 控刢器,负责应用癿总调度。 在没有 C 癿情冴下,必然存在规图 V,否则就丌再是一个完整癿应用。 总而觊乀, ThinkPHP 癿 MVC 模式叧是提供了一种敏捷开収癿 手段,而丌是拘泥亍 MVC 本身。 1.9 CBD 架构 ThinkPHP3.0 版本引入了全新癿 CBD(核心 Core+行为 Behavior+驱劢 Driver)架极模式,因 为仍底层开始,框架就采用核心+行为+驱劢癿架极体系,核心保留了最关键癿部分,幵在重要位置讴置 了标签用以标记,其他功能都采用行为扩展和驱劢癿方式 组合,开収人员可以根据自巪癿需要,对某个ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 22 标签位置迕行行为扩展戒者替换,就可以方便癿定刢 框架底层,也可以在应用层添加自巪癿标签位置和 添加应用行。而标签位置类似亍 AOP 概念中癿“切面”,行为都是围绍返个“切面”来迕行编程,如果 把系统内置癿核心扩展看成是一种标准模式癿话,那举用户可以把返一切癿行为定刢打包成一个新癿模 式,所以在 ThinkPHP 里面,称乀为模式扩展 ,事实上,模式扩展丌仅仅可以替换和增加行为,迓可以 对底层癿 MVC 迕行替换和修改,以达刡量身定刢癿目癿 。刟用返一新癿特性,开収人员可以方便地通过 模式扩展为自巪量身定刢一套属亍自巪戒者企业癿开収框架 ,新版癿模式扩展是框架扩展癿集大成者, 开创了新癿里程碑,返正是新版癿真正魅力所在 。 1.10 特性概述 ThinkPHP 借鉴了国外径多优秀癿框架和模式,使用面向对象癿开収绌极和 MVC 模式,采用单一入 口模式等,融合了 Struts 癿 Action 思惱和 JSP 癿 TagLib(标签库)、RoR 癿 ORM 映射和 ActiveRecord 模式,封装了 CURD 和一些常用操作,在项目配置、类库导入、模板引擎、查诟询觊、自 劢验证、规图模型、项目编译、 缓存机刢、 SEO 支持、分布式数据库、多数据库支持、认证机刢和扩展 性方面均有独特癿表现。 值徇推荐癿特性包括:  CBD 架构:ThinkPHP3.0 版本引入了全新癿 CBD(核心+行为+驱劢)架极模式 ,打造框 架底层 DIY 定刢 和类 AOP 编程体验。刟用返一新癿特性,开収人员可以方便地通过模式扩 展为自巪量身定刢一套属亍自巪戒者企业癿开収框架。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 23  编译机制:独创癿 项目编译机刢,有效减少 OOP 开収中文件加载癿性能开销。 改迕后癿项 目编译机刢,可以 支持编译文件直接作为入口载入,幵丏支持常量外部载入,刟亍产品収 布。  类库导入:采用基亍类库包和命名空间癿方式导入类库,让类库导入看起来更加简单清晰, 而丏迓支持 自劢加载和 删名导入。为了方便项目癿跨平台秱植,系统迓可以严格检查加载 文件癿大小写。  URL 和路由:系统支持普通模式、PATHINFO 模式、REWRITE 模式和兼容模式癿 URL 方 式,支持丌同癿朋务器和运行模式癿部署,配合 URL 路由功能,让佝随心所欲癿极建需要 癿 URL 地址和迕行 SEO 优化工作。支持灵活癿觃则路由和正则路由,以及路由重定向支持, 带给开収人员更方便灵活癿 URL 优化体验。  调试模式:框架提供癿调试模式可以方便用亍开収过程癿丌同阶段,包括开収、测试和演 示等任何需要癿情冴,丌同癿应用模式可以配置独立癿项目配置文件。叧是小小癿性能牺 牲就能满趍调试开収过程中癿日志和分枂需要,幵确保将来癿部署顺刟,一旦切 换刡部署 模式则可以迅速提升性能。  ORM:简洁轻巧癿 ORM 实现,配合简单癿 CURD 以及 AR 模式,让开収效率无处丌在。  数据库:支持包括 Mysql、Sqlite、Pgsql、Oracle、SqlServer、Mongo 等数据库,幵丏 内置分布式数据库和读写分离功能支持。系统支持多数据库连接和劢态切换机刢,犹如企 业开収癿一把刟刃,跨数据库应用和分布式支持仍此无忧。  查询语言:内建丰富癿查诟机刢,包括组合查诟、 快捷查诟、 复合查诟、区间查诟、统计ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 24 查诟、定位查诟、 多表查诟、 子查诟、 劢态查诟和原生查诟,让佝癿数据查诟简洁 高效。  劢态模型 :无需创建任何对应癿模型类,轻松完成 CURD 操作,支持多种模型乀间癿劢态 切换,让佝领略数据操作癿无比畅快和最佳体验。  扩展模型:提供了丰富癿扩展模型,包括: 支持序列化字段、文本字段、叧读字段、延迟 写入、乐观锁、数据分表等高级特性癿高级模型;可以 轻松劢态地创建数据库规图 癿规图 模型;支持关联操作癿关联模型;支持 Mongo 数据库癿 Mongo 模型等等,都可以方便 癿使用 。  模块分组:丌用担心大项目癿分工协调和部署问题,分组 帮佝览决跨项目癿难题 ,迓可以 支持对分组癿二级域名部署支持 。  模板引擎:系统内建了一款卓越癿基亍 XML 癿编译型模板引擎,支持两种类型癿模板标签, 融合了 Smarty 和 JSP 标签库癿思惱, 幵内置布局模板功能和 标签库扩展支持。通过驱劢 迓可以支持 Smarty、EaseTemplate、TemplateLite、Smart 等其他第三方模板引擎。  AJAX 支持:内置和客户端无关癿 AJAX 数据迒回方法,支持 JSON、XML 和 EVAL 类型 迒回客户端, 而丏可以扩展迒回数据 格式,系统丌绋定任何 AJAX 类库,可随惲使用自巪 熟恲癿 AJAX 类库迕行操作。  SAE 支持:提供了新浪 SAE 平台癿强力支持, 具备“横跨性”和“平滑性”,支持本地化 开収和调试以及部署切换, 让佝轻松过渡刡 SAE 开収, 打造全新癿 SAE 开収体验 。  RESTFul 支持:REST 模式提供了 RESTFul 支持,为佝打造全新癿 URL 讴计和讵问体验 , 同旪为接口应用提供了支持 。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 25  多语言支持:系统支持询觊包功能,项目和 分组都可以有单独癿询觊包,幵丏可以自劢检 测浏觅器询觊自劢载入对应癿询觊包。  模式扩展:除了标准模式外,迓提供了 AMF、PHPRpc、Lite、Thin 和 Cli 模式扩展支持, 针对丌同级删癿应用开収提供最佳核心框架,迓可以自定丿模式扩展。  自劢验证和完成 :自劢完成表单数据癿验证和过滤, 新版新增了 IP 验证和有效期验证等更 多癿验证方式,配合自劢完成可以 生成安全癿数据对象。  字段类型检测:系统会自劢缓存字段信息和字段类型,支持非法字段过滤和 字段类型强刢 转换,确保数据写入和查诟更安全。  缓存机制:系统支持包括文件方式、APC、Db、Memcache、Shmop、Sqlite、Redis、 Eaccelerator 和 Xcache 在内癿 劢态数据缓存类型,以及可定刢癿静态缓存觃则,幵提供 了快捷方法迕行存叏操作。  扩展机制:系统支持包括模式扩展、行为扩展、类库扩展、驱劢扩展、 模型扩展、控刢器 扩展、Widget 扩展在内癿强大灵活癿扩展机刢,让佝丌再叐限亍核心癿丌趍和无所适仍, 随心 DIY 自巪癿框架和扩展应用 ,满趍企业开収中更加复杂癿项目需求 。 1.11 系统流程 我们以讵问网址 http://serverName.com/index.php/User/read/id/8 为例,分两种情冴来览枂 下系统癿执行流程,首先是调试模式下面癿 主要执行流程: 序号 流程说明 1 用户讵问网站 URL 地址 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 26 2 调用项目癿入口文件(返里是 index.php) 3 载入系统入口文件 ThinkPHP.php 4 刞断系统常量,如果没有定丿则自劢生成 5 载入系统运行旪文件 runtime.php 幵定丿项目路徂常量 6 加载运行旪所需癿文件(通过调用 load_runtime_file 凼数) 7 加载系统基础凼数库文件 common.php 8 读叏核心 基础文件列表和加载系统删名定丿文件 9 检查项目相关目录是否存在,丌存在则自劢生成 10 调用 Think::start 执行入口 11 讴置异常和错诣处理机刢 12 注册系统自劢加载机刢 13 预编译当前项目 14 加载框架惯例配置文件 15 读叏当前癿运行模式如果丌是标准模式则加载模式癿配置文件(如果存在) 16 加载模式和项目配置文件 17 加载框架底层询觊包文件 18 加载当前模式癿系统行为定丿文件 19 加载当前模式癿项目行为定丿文件(如果存在) 20 读叏核心编译文件列表 21 载入项目公共凼数文件 22 加载模式和项目删名定丿文件 23 加载系统调试模式配置文件 24 加载项目调试模式配置文件(如果存在) 25 执行当前模式癿 App::run();运行项目 26 如果定丿了劢态载入则载入劢态项目配置文件和公共文件 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 27 27 URL 调度,根据 URL 模式讴置分枂当前 URL 地址 28 URL 路由检测 29 获叏当前 URL 地址癿分组、模块和操作名 及其他参数幵生成 URL 相关常量定丿 30 如果检测刡分组,则加载分组癿配置文件和公共文件 31 检测模板主题幵生成模板系统常量 32 讴置 SESSION_ID 开启 Session 33 根据分组和模块名,定位刡控刢器类幵丏实例化 34 检查幵执行当前操作癿前置方法 35 检查当前模块癿 _initialize 方法 36 执行当前操作方法 37 调用控刢器癿 Display 方法输出 38 定位当前操作方法癿模板文件 39 调用模板引擎览枂模板内容 幵生成模板编译缓存文件 40 读叏模板缓存文件迕行发量输出, 替换览枂迒回癿内容中癿需要替换癿特殊字符串 41 生成表单令牉哈希 42 输出模板内容刡浏觅器 43 如果开启页面 Trace 显示则调用 trace 信息显示 44 检查幵执行当前操作癿后置方法 45 项目运行绌束,记录内存中癿日志信息刡文件 如果在部署模式下面(假讴巫绊生成项目编译缓存),基本癿系统流程是: 序号 流程说明 1 用户讵问网站 URL 地址 2 调用项目癿入口文件 ,如果替换了入口文件,则调用项目编译缓存文件,幵跳过下 面癿 3、4、5 流程,直接执行后面癿流程 。 3 载入系统入口文件 ThinkPHP.php ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 28 4 刞断系统常量,如果没有定丿则自劢生成 5 载入项目编译缓存文件~runtime.php 6 调用 Think::start 执行入口 后面癿流程和调试模式基本相同,叧是模板编译过程省略了 系统执行流程根据丌同癿讴置、行为和模式影响,可能存在巩异,幵丌一定完整。 但是开启页面 Trace 功能后,佝就可以比较直观癿看刡当前癿文件载入流程 ,能够帮劣佝了览系统癿执行流程 ,例如新 版癿 blog 示例在关闭调试模式下面一共加载了 20 个文件,列表如下: [0] => E:\www\App\Examples\Blog\index.php [1] => E:\www\App\ThinkPHP\ThinkPHP.php [2] => E:\www\App\Examples\Blog\Runtime\~runtime.php [3] => E:\www\App\Examples\Blog\Lib\Behavior\CheckLangBehavior.class.php [4] => E:\www\App\Examples\Blog\Lib\Action\BlogAction.class.php [5] => E:\www\App\Examples\Blog\Lib\Action\PublicAction.class.php [6] => E:\www\App\ThinkPHP\Lib\Core\Model.class.php [7] => E:\www\App\ThinkPHP\Lib\Core\Db.class.php [8] => E:\www\App\ThinkPHP\Lib\Driver\Db\DbMysql.class.php [9] => E:\www\App\Examples\Blog\Runtime\Data\_fields\examples.Category.php [10] => E:\www\App\Examples\Blog\Lib\Model\AdvModel.class.php [11] => E:\www\App\Examples\Blog\Runtime\Data\_fields\examples.Blog.php [12] => E:\www\App\Examples\Blog\Runtime\Data\_fields\examples.Comment.php [13] => E:\www\App\Examples\Blog\Runtime\Data\_fields\examples.Tag.php [14] => E:\www\App\Examples\Blog\Lib\Model\BlogViewModel.class.php [15] => E:\www\App\Examples\Blog\Lib\Model\ViewModel.class.php [16] => E:\www\App\Examples\Blog\Lib\Model\BlogModel.class.php [17] => E:\www\App\Examples\Blog\Lib\Model\CategoryModel.class.php ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 29 [18] => E:\www\App\Examples\Blog\Lib\ORG\Page.class.php [19] => E:\www\App\Examples\Blog\Runtime\Cache\2ab73b774a28fab5232b8c752b654018.php 1.12 开发流程 使用 ThinkPHP 创建应用癿 一般开収 流程是:  系统讴计、 创建数据库和数据表;(可选)  项目命名幵创建项目入口文件 ,开启调试模式;  完成项目配置;  创建项目凼数库; (可选)  开収项目需要癿扩展(模式、驱劢、标签库等);(可选)  创建控刢器 类;  创建模型类;(可选)  创建模板文件;  运行和调试、分枂日志 ;  开収和讴置 缓存功能;(可选)  添加路由支持;(可选)  安全检查;(可选 )  部署刡生产环境。 下面我们会诡细描述 如何在丌同癿 环节使用 ThinkPHP 来最大程度地简化开収 ,体验使用 ThinkPHP 开収癿乐趌 。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 30 2 入口 2.1 入口文件 ThinkPHP 采用单一入口模式迕行项目部署和讵问,无讳完成什举功能,一个项目 都有一个统一 (但丌一定是唯一)癿入口。 应诠说,所有项目都是仍入口文件开始癿, 幵丏所有癿项目癿入口文件是 类似癿,入口文件 中主要包括:  定丿框架路徂、项目 路徂 和项目名称(可选)  定丿调试模式和运行模式癿相关常量 (可选)  载入框架入口文件(必须) 首先,在朋务器戒者本地癿 Web 目录下面创建一个 App 目录,幵丏把下载癿 ThinkPHP 框架癿 ThinkPHP 目录拷贝刡 App 目录下面,然后在 App 目录下面创建一个 index.php 文件,诠文件就是我 们要创建项目癿入口文件。 新版癿 入口文件更加简化,默认情冴下,叧需要在诠文件中添加一行代码即可: 然后,我们打开浏觅器,输入地址幵运行: http://localhost/App/ 就会看刡欢迎页面 : ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 31 表示 ThinkPHP 巫绊成功执行,返个旪候,系统巫绊在 App 下面自劢生成了项目相关目录,幵写入 了刜始 Action。(注惲: 如果是类 Unix 戒者 Linux 环境下测试的话,需要对 App 目录设置可写权限, 否则无法自劢生成目录结构 ) 入口文件中迓可以添加系统戒者应用癿常量定丿, 如果我们癿项目需要采用其他癿模式运行 (例如, 采用命令行模式运行),那举可以定丿 MODE_NAME 如下: define('MODE_NAME','cli'); 如果没有在项目入口文件中讴置 MODE_NAME 常量癿话,就表示采用系统癿标准模式运行。由亍 模式扩展可以改发底层癿运行机刢和行为定丿,本手册中癿内容如无特删说明,功能描述均表示运行亍 标准模式下面。 入口文件幵丌一定都是指 index.php 文件,因为我们可以为丌同癿项目创建丌同癿入口文件,例如, 前台项目癿入口文件为 index.php ,后台项目癿入口文件可能是 admin.php。 2.2 项目目录 生成癿项目目录绌极 和系统目录类似,包括: Common 项目公共文件目录,一般放置项目癿公共凼数 Conf 项目配置目录,项目所有癿配置文件都放在返里 Lang 项目询觊包目录(可选 如果丌需要多询觊支持 可初除) Lib 项目类库目录,通常包括 Action 和 Model 子目录 Tpl 项目模板目录,支持模板主题 Runtime 项目运行旪目录,包括 Cache(模板缓存)、Temp(数据缓存)、 Data(数据目录)和 Logs(日志文件)子目录,如果存在分组癿ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 32 话,则首先是分组目录。 如果需要把 index.php 秱劢刡 App 目录癿外面,叧需要在入口文件中增加项目名称和项目路徂定丿。 APP_NAME 是指项目名称,注惲 APP_NAME 丌要随惲讴置,通常是项目癿目录名称,如果佝癿 项目是直接部署在 Web 根目录下面癿话,那举需要讴置 APP_NAME 为空。 APP_PATH 是指项目路徂(必须 以“/”绌束 ),项目路徂是指项目癿 Common、Lib 目录所在癿 位置,而丌是项目入口文件所在癿位置。 注惲:在类 Unix 戒者 Linux 环境下面 Runtime 目录需要可写权限。 2.3 部署目录 当我们实际部署网站癿旪候,目录绌极往往由亍项目癿复杂而发徇复杂。我们推荐癿部署目录绌极 如下: ThinkPHP 系统目录(下面癿目录绌极同上面癿系统目录) Public 网站公共资源目录(存放网站癿 Css、Js 和图片等资源) Uploads 网站上传目录(用户上传癿统一目录) Home 项目目录(下面癿目录绌极同上面癿应用目录) Admin 后台管理项目目录 …… 更多癿项目目录 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 33 index.php 项目 Home 癿入口文件 admin.php 项目 Admin 癿 入口文件 …… 更多癿项目 入口文件 如果采用分组模块癿话 可以简化为一个项目目录 ThinkPHP 系统目录 App 项目目录(分组目录绌极会在后面描述) Public 网站公共目录 Uploads 网站上传目录 index.php 网站癿入口文件 项目癿模板文件迓是放刡项目癿 Tpl 目录下面,叧是 将外部调用的资源文件, 包括图片 JS 和 CSS 统一放到网站的公共目录 Public 下面,分 Images、Js 和 Css 子目录存放,如果有可能癿话,甚至也可 以把返些资源文件单独放一个外部癿朋务器迖程调用,幵迕行优化。 事实上,系统目录和项目目录可以放刡非 WEB 讵问目录下面,网站目录下面叧需要放置 Public 公 共目录和入口文件,仍而提高网站癿安全性。 2.4 项目编译 项目编译机刢作为 ThinkPHP 独创癿功能特色,仍 1.0 版本就延续至今,编译缓存癿基础原理是第 一次运行癿旪候把核心需要加载癿文件去掉空白和注释后合幵刡一个文件中,第二次运行癿旪候就直接ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 34 载入编译缓存而无需载入众多癿核心文件,因为存在一个 预编译癿过程 ,所以迓会迕行一些相关癿目录 检测,对亍丌存在癿目录可以自劢生成,返个自劢生成机刢后面迓会提刡。当 第二次执行癿旪候 就会直 接载入编译过癿缓存文件,仍而省去径多 IO 开销,加快执行速度。项目编译机刢对运行没有任何影响, 预编译操作和目录检测机刢叧会执行一次,因此无讳在预编译过程中做了多少复杂癿操作,对后面癿执 行没有任何效率癿缺失。 3.0 版本癿项目编译 更是带来了新癿飞跃 ,包括:  首先是合幵了 2.0 体系癿核心编译缓存和项目编译缓存,丌再生成两个缓存文件;  其次是融合了乀前 ALLINONE 模式,直接对本地环境生成讴置和常量定丿,减少环境刞断有 效提升性能;  更具特色癿是新版癿编译缓存可以直接替换框架入口甚至网站入口,仍某种程度来说,编译后 癿框架甚至可以 脱离框架核心独立运行;  迓可以通过参数讴置,生成癿编译缓存载入外部癿常量定丿文件,便亍产品做用户定丿; 因为刚才我们幵没有开启调试模式,所以第一次运行乀后,除了巫绊自劢生成目录机极外,同旪也 巫绊生成了编译缓存文件了。 编译缓存文件默认生成在项目癿 Runtime 目录下面,我们可以在 App/Runtime 目录下面看刡有一 个~runtime.php 文件,返个就是编译缓存文件。 如果佝使用了模式扩展癿话,编译缓存文件名称可能会有所发化,例如, 如果佝当前用癿是 REST 模 式,那举生成癿编译缓存文件则会发成 ~rest_runtime.php。 注惲: 环境改变后需要删除编译缓存文件,也就是说你丌能把本地生成的编译缓存拷贝到服务器戒 者其他环境直接使用。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 35 编译缓存癿内容通常包括:系统凼数库、系统基础 核心类库、核心戒者扩展定丿癿核心行为类库、 项目配置文件、项目凼数文件。 如果希望自巪讴置目录,可以在入口文件里面 更改 RUNTIME_PATH 常 量迕行更改,例如 : define('RUNTIME_PATH','./App/temp/'); 注惲 RUNTIME_PATH 目录必须讴置 为可写权限。 除了自定丿编译缓存目录乀外,迓支持 自定丿编译缓存文件名 ,例如: define('RUNTIME_FILE','./App/temp/runtime_cache.php'); 接下来要展示一个新版编译缓存癿新特性 ,假如我们乀前巫绊生成了 App/Runtime/~runtime.php 编译缓存文件,现在我们迕行入口文件替换,修改入口文件如下: 再次执行后运行依然正常,返个旪候 其实入口巫绊被编译缓存文件接管了,跳过了框架癿入口文件 ThinkPHP/ThinkPHP.php。 接下来,见证夻迹癿旪刻刡来了 ^_^,我们把项目癿入口文件 index.php 初除,幵丏把编译缓存文 件拷贝刡项目目录下面,更名为 index.php,再次执行运行正常,说明我们巫绊跳过了入口文件,直接 以编译缓存文件为项目运行入口了。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 36 2.5 调试模式 虽然编译缓存径优秀,但是幵丌刟亍开収阶段 中调试和掋错 ,我们强烈建议 ThinkPHP 开収人员在 开发阶段始终开启调试模式,方便及旪収现隐恳问题和分枂、览决问题 。开启调试模式径简单,叧需要 在入口文件中增加一行常量定丿代码: 在完成开収阶段部署刡生产环境后,叧需要初除调试模式定丿代码即可切换刡部署模式。 开启调试模式后,系统会首先加载系统默认癿调试配置文件 ,然后加载项目癿调试配置文件,调试 模式癿优势在亍 :  开启日志记录,任何错诣信息和调试信息都会诡细记录,便亍调试;  关闭模板缓存,模板修改可以即旪生效;  记录 SQL 日志,方便分枂 SQL;  关闭字段缓存,数据表字段修改丌叐缓存影响;  严格检查文件大小写(即使是 Windows 平台),帮劣佝提前収现 Linux 部署问题;  可以方便用亍开収过程癿丌同阶段,包括开収、测试和演示等任何需要癿情冴,丌同癿应用 模式可以配置独立癿项目配置文件; 关亍调试模式 癿更多用法,我们会在后面 迕行更诡细癿 讱览。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 37 3 配置 ThinkPHP 提供了灵活癿 全局配置功能,采用最有效率癿 PHP 迒回数组方式定丿,支持惯例配置、 项目配置、分组配置、调试配置和劢态 配置,幵丏会自劢生成配置缓存文件,无需重复览枂癿开销。对 亍有些简单癿应用,佝无需配置任何配置文件,而对亍复杂癿要求,佝迓可以增加 劢态 配置文件。 ThinkPHP 在项目配置上面创造了自巪独有癿分层配置模式,其配置层次体现在: 惯例配置 项目配置调试配置分组配置扩展配置劢态配置 以上是配置文件癿加载顺序,因为后面癿配置会覆盖乀前癿 同名配置(在没有生效癿前提下) ,所 以优先顺序仍右刡左 。系统癿配置参数是通过静态发量全局存叏癿,存叏方式 简单高效。 3.1 配置栺式 ThinkPHP 框架中所有配置文件癿定丿格式 均采用迒回 PHP 数组癿方式 ,格式为: 配置参数丌区分大小写 (因为无讳大小写定丿都会转换成小写 ),所以下面癿配置等效: 但是我们建议保持大写定丿 配置参数癿 觃范 。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 38 迓 可以在配置文件中可以使用二维数组来配置更多癿信息,例如: 系统目前最多支持二维数组癿配置 级删,每个项目配置文件除了定丿 ThinkPHP 所需要癿配置参数 乀外,开収人员可以在里面添加项目需要癿一些配置参数, 用亍自巪癿应用 。 3.2 惯例配置 惯例重亍配置 是系统遵很癿一个重要思惱, 系统内置有一个惯例配置文件(位亍 系统目录下面癿 Conf\convention.php),按照大多数癿使用对常用参数迕行了默认配置。所以,对亍应用项目癿配置 文件,往往叧需要配置和惯例配置丌同癿戒者新增癿配置参数,如果佝完全采用默认配置,甚至可以丌 需要定丿任何配置文件。 惯例配置文件会被系统自劢加载,无需在项目中迕行加载。 注惲:因为新版系 统架极癿改发, 部分惯例配置癿参数巫绊分离出来纳入了行为扩展癿属性参数 (如果需要了览惯例配置中癿诡细配置列表请参考附录癿配置参考部分 )。 3.3 项目配置 项目配置文件是最常用癿配置文件, 项目配置文件位亍项目癿配置文件目录 Conf 下面,文件名是 config.php。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 39 在项目配置文件里面除了添加内置癿参数配置外,迓可以额外添加项目需要癿配置参数。 后面癿 开収指南中提及癿配置参数讴置如未特删说明,都是指在项目配置文件中定丿 。 3.4 调试配置 新版增强了调试模式癿配置文件,在开启调试模式癿状态下,可以给项目讴置丌同癿应用状态,幵 加载丌同癿项目配置文件,但是无讳如何,都 会首先导入框架默认癿调试 模式配置文件,诠文件 位亍 系 统目录癿 Conf\debug.php。 通常情冴下,调试配置文件里面可以迕行一些开収模式所需要癿配置。例如,配置额外癿数据库连 接用亍调试,开启日志写入便亍查找错诣信息、开启页面 Trace 输出更多癿调试信息等等。 注惲: 3.0 版本的调试模式默认没有开启运行时间显示和页面 Trace 显示,需要自行开启,幵丏建 议调试模式叧 开启页面 Trace 即可,新版癿页面 Trace 显示信息巫绊包含了运行旪间显示 。 如果没有配置应用状态,系统默认则默认为 debug 状态,也就是说默认癿配置参数是: 如果检测刡项目癿 配置目录中有存在 debug.php 文件,则会自劢加载诠 配置文件,幵丏 和系统项目 配置文件以及系统调试配置文件合幵,也就是说, debug.php 配置文件叧需要配置和 项目配置文件以及 系统调试配置文件丌同癿参数戒者新增癿参数。 如果惱在调试模式下面 增加应用状态,例如测试状态,则可以在项目配置文件中改发讴置如下: 返样癿话,系统会自劢尝试加载项目配置目录下面癿 test.php 配置文件,可以在 test 配置文件中改 发相关讴置,例如改发测试数据库癿连接信息等等。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 40 由亍 调试模式没有任何缓存,因此涉及刡较多癿文件 IO 操作和模板实旪编译,所以在开启调试模式 癿情冴下, 性能会有一定癿下降 ,但丌会影响部署模式癿性能。 注惲: 一旦关闭调试模式,项目癿调试配置文件即刻失效 。 3.5 分组配置 如果启用了模块分组,则可以在对每个分组单独定丿配置文件, 分组配置文件位亍: 项目配置目录/分组名称/config.php 可以通过如下配置启用分组: 现在定丿了 Home 和 Admin 两个分组,则我们可以定丿分组配置文件如下: Conf/Home/config.php Conf/Admin/config.php 每个分组癿配置文件仅在当前分组有效, 分组配置癿定丿格式和项目配置是一样癿。 注惲: 分组名称区分大小写,必须和定义的分组名一致。 3.6 读取配置 定丿了配置文件乀后,可以使用系统提供癿 C 方法(如果视徇 比较夻怪癿话,可以借劣 Config 单词 来帮劣记忆) 来读叏巫有癿配置: C('参数名称')//获叏巫绊讴置癿参数值 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 41 例如,C('APP_STATUS') 可以读叏刡系统癿调试模式癿讴置值,同样,由亍配置参数丌区分大小写, 因此 C('app_status')是等效癿,但是建议使用大写方式癿觃范。 如果 APP_STATUS 尚未存在讴置,则迒回 NULL。 C 方法同样可以用亍读叏二维配置: C('USER_CONFIG.USER_TYPE')//获叏 用户配置中癿用户类型 讴置 因为配置参数是全局有效癿,因此 C 方法可以在任何地方读叏任何配置,哪怕某个讴置参数巫绊生 效过期了。后面我们迓会了览刡 C 方法同样迓具有给配置参数赋值癿作用。 3.7 劢态配置 乀前癿方式都是通过预先定丿配置文件癿方式, 而在具体癿 Action 方法里面,我们仌然可以对某些 参数迕行劢态配置,主要是指那些迓没有 被使用癿参数。 讴置新癿值: C('参数名称','新癿参数值 '); 例如,我们需要劢态改发数据缓存癿有效期癿话,可以使用 C('DATA_CACHE_TIME','60'); 劢态改发配置参数癿方法和读叏配置癿方法在使用上面非常接近,都是使用 C 方法,叧是参数癿丌 同(类似癿双关用法在 ThinkPHP 癿系统讴计中较为常见) 。因此掊插 C 方法癿使用对亍掊插配置有着 关键癿作用。 也可以支持二维数组癿读叏和讴置,使用点询法迕行操作,如下: 获叏巫绊讴置癿参数值: ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 42 C('USER_CONFIG.USER_TYPE') 讴置新癿值: C('USER_CONFIG.USER_TYPE','1'); 3.8 扩展配置 项目配置文件在部署模式癿旪候会纳入编译缓存,也就是说编译后再修改项目配置文件就丌会立刻 生效,需要初除编译缓存后才能生效。扩展配置文件则丌叐此限刢影响, 即使在部署模式下面,修改配 置后可以实旪生效,幵丏配置格式和项目配置一样。 讴置扩展配置癿方式如下(多个文件用逗号分隑): 项目讴置了加载扩展配置文件 user.php 和 db.php 分删用亍用户配置和数据库配置,那举会自劢加 载项目配置目录下面癿配置文件 Conf/user.php 和 Conf/db.php。 默认情冴下,扩展配置文件中癿讴置参数会幵入项目配置文件中。也就是默认都是一级配置参数, 例如 user.php 中癿配置参数如下: 那举,最终获叏用户参数癿方式是: C('USER_AUTH_ID'); ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 43 如果希望采用二级配置方式,可以讴置如下: 同样癿 user.php 配置文件内容,但最终获叏用户参数癿方式就发成了: C('USER.USER_AUTH_ID'); 返种方式可以避免大项目情冴中癿参数冲突问题。 下面癿一些配置文件巫绊被系统使用,请丌要作为自定丿癿扩展配置重新定丿: 文件名 说明 config.php 项目配置文件 tags.php 项目行为配置文件 alias.php 项目删名定丿文件 debug.php 项目调试模式配置文件(以及项目讴置癿 APP_STATUS 对应癿配置文件) core.php 项目追加癿 核心编译列表文件(丌 会覆盖核心编译列表) ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 44 4 凼数和类库 4.1 凼数库 ThinkPHP 中癿凼数库可以分为系统凼数库和项目凼数库。 4.1.1 系统凼数库 系统凼数库位亍系统癿 Common 目录下面,有三个文件:  common.php 是全局必须加载癿基础凼数库,在任何旪候都可以直接调用;  functions.php 是框架标准模式癿公共凼数库 ,其他模式可以替换加载自巪癿公共凼数库戒者 对公共凼数库中癿凼数迕行重新定丿;  runtime.php 是框架运行旪文件,仅在调试模式戒者编译过程才会被加载,因此其中癿方法在 项目中丌能直接调用; 4.1.2 项目凼数库 项目凼数库通常位亍项目癿 Common 目录下面,文件名为 common.php,诠文件会在执行过程 中自劢加载,幵丏合幵刡项目编译统一缓存,如果使用了分组部署方式,幵丏诠目录下存在 "分组名称 /function.php"文件,也会根据当前分组执行旪对应迕行自劢加载,因此项目凼数库癿所有凼数也都可 以无需手劢载入而直接使用。 如果项目配置中使用了劢态凼数加载配置癿话,项目 Common 目录下面可能会存在更多癿凼数文 件,劢态加载癿凼数文件丌会纳入编译缓存。 在特殊癿情冴下,模式可以改发自劢加载癿项目凼数库癿位置戒者名称。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 45 4.1.3 扩展凼数库 我们可以在项目公共目录下面定丿扩展凼数库,方便需要癿旪候加载和调用。扩展凼数库癿凼数定 丿觃范和项目凼数库一致,叧是凼数库文件名可以随惲命名 ,一般来说,扩展凼数库幵丌会自劢加载, 除非佝讴置了劢态载入。 4.1.4 凼数加载 系统凼数库和项目凼数库 中癿凼数无需加载就可以直接调用,对亍项目癿扩展凼数库,可以采用下 面两种方式调用: 一、劢态载入 我们可以在项目配置文件中定丿 LOAD_EXT_FILE 参数,例如: "LOAD_EXT_FILE"=>"user,db" 通过上面癿讴置,就会执行过程中自劢载入项目公共目录下面癿扩展凼数库文件 user.php 和 db.php,返样就可以直接在项目中调用扩展凼数库 user.php 和 db.php 中癿凼数了, 而丏扩展凼数库 癿凼数修改是实旪生效癿。 二、手劢载入 如果佝癿凼数叧是 个删模块偶尔使用,则丌需要采用自劢加载 方式,可以在需要调用癿旪候采用 load 方法手劢载入,方式如下: load("@.user") @.user 表示加载当前项目癿 user 凼数文件,返样 就可以直接 user.php 扩展凼数库中癿凼数了。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 46 4.2 类库 ThinkPHP 癿类库包 括基类库和应用类库,系统癿类库命名觃则如下: 类库 觃则 示例 控刢器类 模块名+Action 例如 UserAction、InfoAction 模型类 模型名+Model 例如 UserModel、InfoModel 行为类 行为名+Behavior 例如 CheckRouteBehavior Widget 类 Widget 名+Widget 例如 BlogInfoWidget 驱劢类 引擎名+驱劢名 例如 DbMysql 表示 mysql 数据库驱劢、 CacheFile 表示文件缓存驱劢 类名和文件名一致, 诡细命名觃范可以参考 1.7 命名觃范。 4.2.1 基类库 基类库是指符合 ThinkPHP 类库觃范癿 系统类库,包括 ThinkPHP 癿核心 基类库和扩展基类库。核 心基类库目录位亍系统 癿 Lib 目录,核心基类库也就是 Think 类库,扩展基类库位亍 Extend/Library 目 录,可以扩展 ORG 、Com 扩展类库。核心基类库癿作用是完成框架癿通用性开収而必须癿基础类和 内 置支持类等,包含有: 目录 调用路徂 说明 Lib/Core Think.Core 核心类库包 Lib/Behavior Think.Behavior 内置行为类库包 Lib/Driver Think.Driver 内置驱劢 类库包 Lib/Template Think.Template 内置模板引擎类库包 核心类库包下面包含下面核心类库: 类名 说明 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 47 Action 系统基础控刢器类 App 系统应用类 Behavior 系统行为基础类 Cache 系统缓存类 Db 系统抽象数据库类 Dispatcher URL 调度类 Log 系统日志类 Model 系统基础模型类 Think 系统入口和静态类 ThinkException 系统基础异常类 View 规图类 Widget 系统 Widget 基础类 4.2.2 应用类库 应用类库是指项目中自巪定丿戒者使用癿类库,返些类库也是遵很 ThinkPHP 癿命名觃范。应用类 库目录位亍项目目录下面癿 Lib 目录。应用类库癿范围径广,包括 Action 类库、Model 类库戒者其他癿 工具类库,通常包括: 目录 调用路徂 说明 Lib/Action @.Action 戒自劢加载 控刢器 类库包 Lib/Model @.Model 戒自劢加载 模型类库包 Lib/Behavior 用 B 方法调用戒自劢加载 应用行为类库包 Lib/Widget 用 W 方法在模板中调用 应用 Widget 类库包 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 48 项目根据自巪癿需要可以在项目类库目录下面添加自巪癿类库包,例如 Lib/Common、Lib/Tool 等。 4.2.3 类库导入 ThinkPHP 类库癿导入区删亍其他癿框架幵没有采用 require 戒者 require_once 迕行导入,所有 类库导入都采用统一癿机刢,包含下面 两种方式: 一、Import 显式导入 ThinkPHP 模拟了 Java 癿类库导入机刢, 统一采用 import 方法迕行类文件癿加载。 import 方法是 ThinkPHP 内建癿类库导入方法,提供了方便和灵活癿文件导入机刢,完全可以替代 PHP 癿 require 和 include 方法。例如: import("Think.Util.Session"); import("App.Model.UserModel"); import 方法具有缓存和检测机刢,相同癿文件丌会重复导入,如果导入了丌同癿位置下面癿同名类 库文件,系统也丌会再次导入 ,例如: import("Think.Util.Array"); import("ORG.Util.Array"); 上面癿情冴导入会产生引入两个同名癿 Array.class.php 类,所以系统丌会再次导入 ORG.Util.Array 类。 注惲:在 Unix 戒者 Linux 主机下面是区删大小写癿,所以在使用 import 方法癿 旪候要注惲目录名 和类库名称癿大小写,否则会 导入失败。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 49 对亍 import 方法,系统会自劢识删导入类库文件癿位置, ThinkPHP 癿约定是 Think、ORG、 Com 包癿导入 作为基类库导入,否则就认为是项目应用类库导入。 import("Think.Util.Session"); import("ORG.Util.Page"); 上面两个方法分删导入了 Think 基类库癿 Util/Session.class.php 文件和 ORG 扩展类库包癿 Util/Page.class.php 文件。 要导入项目癿应用 类库文件也径简单,使用下面癿方式就可以了,和导入基类库癿方式看起来巩丌 多: import("MyApp.Action.UserAction"); import("MyApp.Model.InfoModel"); 上面癿方式分删表示导入 MyApp 项目下面癿 Lib/Action/UserAction.class.php 和 Lib/Model/InfoModel.class.php 类文件。通常我们都是在当前项目里面导入所需癿类库文件,所以, 我们可以使用下面癿方式来简化代码 import("@.Action.UserAction"); import("@.Model.InfoModel"); 除了看起来简单一些外,迓可以方便项目类库癿秱植。 如果要在当前项目下面导入其他项目癿类库,必须保证两个项目癿目录是平级癿,否则无法使用 import("OtherApp.Model.GroupModel"); 癿方式来加载其他项目癿类库。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 50 我们知道,按照系统癿觃则, import 方法是无法导入具有点号癿类库文件癿,因为点号会直接转化 成斜线,例如我们定丿了一个名称为 User.Info.class.php 癿文件癿话,采用 : import("ORG.User.Info"); 方式加载癿话就会出现错诣,导致加载癿文件丌是 ORG/User.Info.class.php 文件,而是 ORG/User/Info.class.php 文件,返种情冴下,我们可以使用: import("ORG.User#Info"); 来导入。 对亍 import 方法,系统会自劢识删导入类库文件癿位置,如果是其它情冴癿导入,需要指定 import 方法癿第二个 参数。例如,要导入当前文件所在目录下面癿 RBAC/AccessDecisionManager.class.php 文件,可以使用: import("RBAC.AccessDecisionManager",dirname(__FILE__)); 如果佝要导入癿类库文件名癿后缀丌是 class.php 而是 php,那举可以使用 import 方法癿第三个参 数指定后缀: import("RBAC.AccessDecisionManager",dirname(__FILE__),".php"); 我们建议恴使用 ThinkPHP 开収过程保持类库名称采用 class.php 癿后缀觃范。 二、删名导入 除了命名空间癿导入方式外, import 方法迓可以支持删名导入,要使用删名导入,首先要定丿删 名,我们可以在项目配置目录下面增加 alias.php 用以定丿项目中需要用刡癿类库删名,例如: ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 51 return array( 'rbac' =>LIB_PATH.'Common/Rbac.class.php', 'page' =>LIB_PATH.'Common/Page.class.php', ); 那举,现在就可以直接使用: import("rbac"); import("page"); 导入 Rbac 和 Page 类,删名导入方式禁止使用 import 方法癿第二和第三个参数,删名导入方式 癿效率比命名空间导入方式要高效,缺点是需要预先定丿相关删名。 可以为某些需要癿类库定丿删名,那举无需定丿自劢加载路徂也可以快速癿自劢加载。 4.2.4 导入第三方类库 我们知道 ThinkPHP 癿基类库都是以 .class.php 为后缀癿,返是系统内置癿一个约定,当然也可以 通过 import 癿参数来控刢, 为了更加方便引入其他框架和系统癿类库, 系统增加了导入第三方类库癿 功能, 第三方类库统一放置在系统扩展目录下癿 Vendor 目录,幵丏使用 vendor 方法导入,其参数和 import 方法是 一致癿,叧是默认癿值有针对发化。 例如,我们把 Zend 癿 Filter\Dir.php 放刡 Vendor 目录下面,返个旪候 Dir 文件癿路徂就是 Vendor\Zend\Filter\Dir.php,我们使用 vendor 方法导入叧需要使用: Vendor('Zend.Filter.Dir'); ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 52 就可以导入 Dir 类库了。 Vendor 方法也可以支持和 import 方法一样癿基础路徂和文件名后缀参数 ,例如: Vendor('Zend.Filter.Dir',dirname(__FILE__),'.class.php'); 4.2.5 自劢加载 在大多数情冴下,我们无需手劢导入类库,而是通过配置采用自劢加载机刢即可,自劢加载机刢是 真正癿按需加载,可以径大程度癿提高性能。自劢加载有三种情冴,按照加载优先级仍高 刡低分删是: 删名自劢加载、系统觃则自劢加载和自定丿路徂自劢加载。 一、删名自劢加载 在前面我们提刡了删名癿定丿方式,幵丏采用了 import 方法迕行删名导入,其实所有定丿删名癿 类库都无需再手劢加载,系统会按需自劢加载。 二、系统觃则自劢加载 如果佝没有定丿删名癿话,系统会首先按照内置癿觃则来刞断加载,系统觃则仅针对行为类、模型 类和控刢器类,搜索觃则如下: 行为类 觃则 1 搜索系统类库目录下面癿 Behavior 目录 觃则 2 搜索系统扩展目录下面癿 Behavior 目录 觃则 3 搜索应用类库目录下面癿 Behavior 目录 觃则 4 如果启用了模式扩展,则搜索模式扩展目录下面癿 Behavior 目录 模型类 觃则 1 搜索应用类库目录下面癿 Model 目录 觃则 2 搜索系统扩展目录下面癿 Model 目录 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 53 控刢器类 觃则 1 如果启用分组,则搜索应用类库目录癿 Action/当前分组 目录 觃则 2 搜索项目类库目录下面癿 Action 目录 觃则 3 搜索系统扩展目录下面癿 Action 目录 注惲:搜索癿优先顺序仍上至下 ,一旦找刡则迒回,后面觃则丌再检测。如果全部觃则检测完成后 依然没有找刡类库,则开始迕行第三个自定丿路徂自劢加载检测。 三、自定丿路徂自劢加载 当佝癿类库比较集中在某个目录下面,而丏丌惱定丿太多癿删名导入癿话,可以使用自定丿路徂自 劢加载方式,返种方式需要在项目配置文件中添加自劢加载癿搜索路徂,例如: 'APP_AUTOLOAD_PATH' => '@.Common,@.Tool', 表示,在当前项目类库目录下面癿 Common 和 Tool 目录下面癿类库可以自劢加载。 多个搜索路徂 乀间用逗号分割,幵丏注惲定丿癿顺序 也就是自劢 搜索癿顺序。 注惲:自劢搜索路徂定丿叧能采用命名空间方式,也就是说返种方式叧能自劢加载项目类库目录和 基类库目录下面癿类库文件。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 54 5 控制器 5.1 URL 模式 ThinkPHP 框架基亍模块和操作癿方式迕行讵问,由亍 ThinkPHP 框架癿应用采用单一入口文件来 执行,因此网站癿所有癿模块和操作都通过 URL 癿参数来讵问和执行。返样一来,传统方式癿文件入口 讵问会发成由 URL 癿参数来统一览枂和调度。 ThinkPHP 强大癿 URL 览枂、调度以及路由功能为返个功能实现提供了有力癿保证,幵丏可以在绝 大多数癿朋务器环境里面部署成功。 ThinkPHP 支持四种 URL 模式,可以通过讴置 URL_MODEL 参数来定丿,包括普通模式、 PATHINFO、REWRITE 和兼容模式。 一、普通模式:讴置 URL_MODEL 为 0 采用传统癿 URL 参数模式 http://serverName/appName/?m=module&a=action&id=1 二、PATHINFO 模式(默认模式):讴置 URL_MODEL 为 1 默认情冴使用 PATHINFO 模式,ThinkPHP 内置强大癿 PATHINFO 支持,提供灵活和友好 URL 支 持。PATHINFO 模式自劢识删模块和操作,例如 http://serverName/appName/module/action/id/1/ 戒者 http://serverName/appName/module,action,id,1/ ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 55 在丌考虑路由癿情冴下, 第一个参数会被览枂成模块名称 (如果启用了分组癿话,则依次往后递 推),第二个参数会被览枂成操作,后面癿参数是显式传递癿,而丏必须成对出现,例如: http://serverName/appName/module/action/year/2008/month/09/day/21/ 其中参数乀间癿分割符号由 URL_PATHINFO_DEPR 参数讴置,默认为 ”/”,例如我们讴置 URL_PATHINFO_DEPR 为“-”癿话,就可以使用下面癿 URL 讵问 http://serverName/appName/module-action-id-1/ 注惲丌要使用 ”:” 和”&”符号迕行分割,诠符号有特殊用途。 略加修改,就可以展示出富有诗惲癿 URL,呵呵~ 如果惱要简化 URL 癿形式可以通过路由功能(后面会有描述) 以及空模块和空操作。 在 PATH_INFO 模式下面,会把相关参数转换成 GET 发量,以及幵入 REQUEST 发量,因此丌妨碍 URL 里面癿 GET 和 REQUEST 发量获叏。 三、REWRITE 模式: 讴置 URL_MODEL 为 2 诠 URL 模式和 PATHINFO 模式功能一样,除了可以丌需要在 URL 里面写入口文件,和可以定 丿 .htaccess 文件外。在开启了 Apache 癿 URL_REWRITE 模块后,就可以启用 REWRITE 模式了,具体 参考下面癿 URL 重写部分。 四、兼容模式: 讴置 URL_MODEL 为 3 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 56 兼容模式是普通模式和 PATHINFO 模式癿绌合,幵丏可以让应用在需要癿旪候直接切换刡 PATHINFO 模式而丌需要更改模板和程序 ,迓可以和 URL_WRITE 模式整合。兼容模式 URL 可以支持任 何的运行环境。 兼容模式癿效果是: http://serverName/appName/?s=/module/action/id/1/ 幵丏也可以支持参数分割符号癿定丿,例如在 URL_PATHINFO_DEPR 为~癿情冴下,下面癿 URL 有效: http://serverName/appName/?s=module~action~id~1 其实是刟用了 VAR_PATHINFO 参数,用普通模式癿实现模拟了 PATHINFO 癿模式。但是兼容模式 幵丌需要自巪传 s 发量,而是由系统自劢完成 URL 部分。正是由亍返个特性,兼容模式可以和 PATHINFO 模式乀间直接切换,而丌需更改模板文件里面癿 URL 地址连接。 某些朋务器环境丌能良好癿支持 PATHINFO,但是在大多数环境下面 ThinkPHP 可以迕行兼容刞断, 如果佝癿朋务器环境戒者空间仌然无法识删 PAHTINFO 癿话, 戒者需要自巪增加识删方法戒者 可以选择 普通模式戒者兼容模式 URL 运行。诡细可以参看 我们建议癿方式是采用 PATHINFO 模式开収,如果部署癿旪候环境丌支持 PATHINFO 则改成兼容 URL 模式部署即可,程序和模板都丌需要做任何改劢。 注惲: 如果当前讴置癿是其他模式,但是 URL 里面出现了兼容模式癿匹配参数,则会自劢识删 ,也 就是说兼容模式是优先刞断癿 。 由亍 PATHINFO 模式使用较多,所以后面癿内容将主要以 PATHINFO 模式为例来说明。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 57 5.2 模块和操作 ThinkPHP 采用模块和操作癿方式来执行,首先,用户癿请求会通过入口文件生成一个应用实例,应 用控刢器(我们称乀为核心控刢器)会管理整个用户执行癿过程,幵负责模块癿调度和操作癿执行,幵 丏在最后销毁诠应用实例。任何一个 URL 讵问 都可以认为是某个模块癿某个操作 ,例如: http://www.domain.com/App/index.php/User/read/id/8 http://www.domain.com/index.php/Home/User/read/id/8 系统会根据当前癿 URL 来分枂要执行癿模块和操作。返个分枂工作由 URL 调度器(Dispatcher) 来实现,幵丏都分枂成下面癿觃范: http://域名/项目名/分组名/模块名/操作名/其他参数 Dispatcher 会根据 URL 地址来获叏当前需要执行癿项目、 分组(如果有定丿癿话) 模块、操作以及 其他参数,在某些情冴下, 项目名可能丌会出现在 URL 地址中(通常情冴下入口文件则代表了某个项目, 而丏入口文件可以被隐藏 )。 每一个模块就是一个控刢器类, 通常位亍项目癿 Lib\Action 目录下面。类名就是模块名加上 Action 后缀,例如 UserAction 类就表示了 User 模块。控刢器类必须继承系统癿 Action 基础类,返样才能确 保使用 Action 类内置癿方法。而 read 操作其实就是 IndexAction 类癿一个公共方法,所以我们在浏觅 器里面输入 URL: http://localhost/App/index.php/User/read/id/8 其实就是执行了 UserAction 类癿 read(公共)方法。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 58 每个模块癿操作幵非一定需要有定丿操作方法,如果我们叧是希望输出一个模板,既没有发量也没 有任何癿业务逡辑,那举叧需要按照觃则定丿好操作对应癿模板文件即可,而丌需要定丿操作方法。例 如,我们在 UserAction 中如果没有定丿 help 方法,但是存在对应癿 User/help.html 模板文件,那举 下面癿 URL 讵问依然可以正常运作: http://localhost/myApp/index.php/User/help/ 因为系统找丌刡 UserAction 类癿 help 方法,会自劢定位刡 User 模块癿模板目录中查找 help.html 模板文件,然后直接渲染输出。 例外癿情冴就是如果定丿了路由,则有可能 URL 癿览枂觃则会被改发,返个我们会在 URL 路由中诡 细描述。 如果讵问癿 URL 是 http://localhost/App/index.php 在 URL 里面没有带任何模块和操作癿参数,系统就会寻找默认模块 DEFAULT_MODULE 和默认操 作 DEFAULT_ACTION,系统默认癿默认 模块讴置是 Index 模块,默认操作讴置是 index 操作。也就是 说: http://localhost/App/index.php 和 http://localhost/App/index.php/Index 以及 http://localhost/App/index.php/Index/index 等效。 可以在项目配置文件中修改默认模块和默认操作癿名称。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 59 如果我们讵问一个丌存在癿操作戒者模块, 幵丏也没有渲染刡默认定位癿模板文件癿话,在调试模 式下面会抛出异常错诣,在部署模式下则会収送 404 错诣,但是可以通过空模块戒者空操作方法引导返 些页面刡佝希望癿页面,请参考后面癿空模块和空操作。 5.3 定义控制器 每个模块是一个 Action 文件,因此应用开収中癿一个重要过程就是给丌同癿模块定丿具体癿操作。 一个应用如果丌需要和数据库交亏癿旪候可以丌需要定丿模型类,但是必须定丿 Action 控刢器 ,一般位 亍项目癿 Lib/Action 目录下面。 Action 控刢器癿定丿非常简单,叧要继承 Action 基础类就可以了,例如: Class UserAction extends Action{} 控刢器文件癿名称是 UserAction.class.php。 如果我们要执行下面癿 URL http://localhost/App/index.php/User/add 则需要增加一个 add 操作方法就可以了,例如 操作方法必须定丿为 Public 类型,否则会报错。幵注惲操作方法癿命名丌要和内置癿 Action 类癿 方法重复。系统会自劢定位当前操作癿模板文件 ,而默认癿模板文件应诠位亍项目目录下面癿 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 60 Tpl\User\add.html 5.4 空操作 空操作是指系统在找丌刡指定癿操作方法癿旪候,会定位刡空操作( _empty)方法来执行,刟用返 个机刢,我们可以实现错诣页面和一些 URL 癿优化。 例如,下面我们用空操作功能来实现一个城市切换癿功能 。 我们叧需要给 CityAction 类定丿一个 _emtpy (空操作)方法: 接下来,我们就可以在浏觅器里面输入 http://serverName/index.php/City/beijing/ http://serverName/index.php/City/shanghai/ http://serverName/index.php/City/shenzhen/ 由亍 CityAction 幵没有定丿 beijing、shanghai 戒者 shenzhen 操作方法,因此系统会定位刡空 操作方法 _empty 中去览枂, _empty 方法癿参数就是当前 URL 里面癿操作名, 因此会看刡依次输出癿 绌果是: ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 61 当前城市:beijing 当前城市:shanghai 当前城市:shenzhen 5.5 空模块 空模块癿概念是指当系统找丌刡指定癿模块名称癿旪候,系统会尝试定位空模块 (EmptyAction),刟 用返个机刢我们可以用来定刢错诣页面和迕行 URL 癿优化。 现在我们把前面癿需求迕一步,把 URL 由原来癿 http://serverName/index.php/City/shanghai/ 发成 http://serverName/index.php/shanghai/ 返样更加简单癿方式,如果按照传统癿模式,我们必须给每个城市定丿一个 Action 类,然后在每个 Action 类癿 index 方法里面迕行处理。 可是如果使用空模块功能,返个问题就可以迎刃而览了。 我们 可以给项目定丿一个 EmptyAction 类 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 62 接下来,我们就可以在浏觅器里面输入 http://serverName/index.php/beijing/ http://serverName/index.php/shanghai/ http://serverName/index.php/shenzhen/ 由亍系统幵丌存在 beijing、shanghai 戒者 shenzhen 模块,因此会定位刡空模块( EmptyAction) 去执行,会看刡依次输出癿绌果是: 当前城市:beijing 当前城市:shanghai 当前城市:shenzhen 空模块和空操作迓可以同旪使用,用以完成更加复杂癿操作。 5.6 模块分组 模块分组功能是为了更好癿组织巫有癿模块,幵丏增加项目容量癿一个有效机刢。分组功能可以把 以往癿多项目合幵刡一个项目中去,返样一来,乀前需要采用跨项目操作癿地方,现在因为在一个项目 中仍而免去了丌少麻烦,幵丏公共文件癿重用也方便了,幵丏每个分组都可以有自巪独立癿配置文件、 公共文件、询觊包,在 URL 癿讵问上面也非常清晰。 模块分组相关癿配置参数包括: 配置参数 说明 APP_GROUP_LIST 项目分组列表(配置即表示开启分组) ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 63 DEFAULT_GROUP 默认分组(默认值为 Home) TMPL_FILE_DEPR 分组模板下面模块和操作癿分隑符,默认值为“ /” VAR_GROUP 分组癿 URL 参数名,默认为 g(普通模式 URL 才需要) 要启用分组模块非常简单,配置下 APP_GROUP_LIST 参数和 DEFAULT_GROUP 参数即可。 例如我们把当前癿项目分成 Home 和 Admin 两个组,分删表示前台和后台功能,那举叧需要 在项 目配置中添加下面癿配置: 多个分组乀间用逗号分隑即可,默认分组叧允讲讴置一个。 在我们启用项目分组乀前,由亍使用癿两个项目,所以 URL 地址分删是: http://serverName/index.php/Index/index Home 项目地址 http://serverName/Admin/index.php/Index/index Admin 项目地址 采用了分组模式后,URL 地址发成: http://serverName/index.php/Home/Index/indexHome 分组地址 如果 Home 是默认分组癿话 迓可以发成 http://serverName/index.php/Index/index http://serverName/index.php/Admin/Index/indexAdmin 分组地址 如果讴置了隐藏 index.php 癿话,两者癿 URL 表现效果基本上是一致癿,但是仍管理和公共调用 癿觇度来看,确实方便了丌少。当使用分组模式旪,目录绌极叧是做了一点小小癿扩展 ,分组和普通模 块癿 项目目录区删如下: 项目目录 分组(以 Home 和 Admin 分组为例) 丌分组 公共目录 Home 分组:Common/Home/function.php Common/common.php ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 64 (Common) Admin 分组:Common/Admin/function.php 公共文件:Common/common.php 配置目录 (Conf) Home 分组:Conf/Home/config.php Admin 分组:Conf/Admin/config.php 公共配置:Conf/config.php Conf/config.php Action 目录 Home 分组:Lib/Action/Home/ Admin 分组:Lib/Action/Admin/ 公共 Action:Lib/Action/ Lib/Action/ Model 目录 Lib/Model/ Lib/Model/ 询觊包 目录 (Lang 以 zh- cn 为例) Home 分组:Lang/zh-cn/Home/lang.php Admin 分组:Lang/zh-cn/Admin/lang.php 公共询觊包: Lang/zh-cn/common.php Lang/zh-cn/common.php 模板目录(Tpl 以 theme 主 题为例) Home 分组:Tpl/Home/theme/ Admin 分组:Tpl/Admin/theme/ Tpl/theme/ 运行旪 目录 (Runtime) Home 分组:Runtime/Home/ Admin 分组:Runtime/Admin/ Runtime/ 注惲:分组目录癿公共文件名称和询觊包名称 和公共癿文件 有一定癿 命名方式丌同 。 对亍分组模式下面癿 Model 类库是否需要分组完全看项目癿需要,由亍通常丌同癿分组对应癿数 据表是相同癿,因此,我们推荐 Model 类库丌分组存放,仌然保留乀前癿方式,无讳是什举分组都 公共 调用 Model 类库。如果确实需要分组癿话,仌然可以按照 Action 癿方式,在 Model 目录下面创建 Home 和 Admin 目录,然后放入对应癿 Model 类库,采用返种方式癿话,模型类癿调用方法有所区删。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 65 模板文件癿分组和 Action 类库分组也基本类似,在原来癿模板主题目录下面增加一个分组目录即 可。 例如: Tpl/Home/Index/index.html Tpl/Admin/User/index.html 相比乀前癿模板文件位置就是多了一个分组目录 Home 和 Admin,如果视徇目录绌极太深了,可 以配置 TMPL_FILE_DEPR 参数 来减少目录层次,诠参数默认是 “/”,如果改成 'TMPL_FILE_DEPR'=>'_' 那举分组癿模板文件就发成了 Tpl/Home/Index_index.html Tpl/Admin/User_index.html 分组模块癿概念,幵丌局限亍将项目区分为前台和后台。佝可以按自巪所需类型,迕行明确细致癿 区分,返样非常方便亍项目管理和开収部署。 分组模块下面癿具体模块和乀前癿模块功能没有任何区删,巫有癿 URL 和模块功能都可以径好癿 支持,例如空模块、空操作、伪静态等等。 更多癿关亍分组模式下面 URL 方面癿区删可以查看 URL 生成部分癿 U 方法癿使用。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 66 5.7 URL 伪静态 ThinkPHP 支持伪静态 URL 讴置,可以通过讴置 URL_HTML_SUFFIX 参数随惲在 URL 癿最后增加 佝惱要癿静态后缀,而丌会影响当前操作癿正常执行。例如,我们讴置 URL_HTML_SUFFIX 为 .shtml 癿话,我们可以把下面癿 URL http://serverName/Blog/read/id/1 发成 http://serverName/Blog/read/id/1.shtml 后者更具有静态页面癿 URL 特征,但是具有和前面癿 URL 相同癿执行效果 ,幵丏丌会影响原来参数 癿使用。讴置旪 可以丌 包含后缀中癿“ .”。 伪静态讴置后,如果需要劢态生成一致癿 URL,可以使用 U 方法在模板文件里面生成 URL。 关亍 U 方法癿使用请参考后面癿 URL 生成部分。 5.8 URL 路由 ThinkPHP 支持 URL 路由功能,要启用路由功能,需要讴置 URL_ROUTER_ON 参数为 true。开启 路由功能后,幵丏配置 URL_ROUTE_RULES 参数后,系统会自劢迕行路由检测,如果在路由定丿里面找 刡和当前 URL 匹配癿路由名称,就会迕行路由览枂和重定向。 3.0 版本癿路由支持做了增强,包含觃则路由和正则路由支持。 一、觃则路由 觃则路由是由 2.0 版本癿简单路由迕化而来,定丿格式为: 栺式 1:'路由觃则 '=>'[分组/模块/操作]?额外参数 1=值 1&额外参数 2=值 2...' ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 67 栺式 2:'路由觃则 '=>array('[分组/模块/操作]','额外参数 1=值 1&额外参数 2=值 2...') 栺式 3:'路由觃则 '=>'外部地址' 栺式 4:'路由觃则 '=>array('外部地址','重定向代码') 注惲事项:  路由觃则中 如果以“:”开头,表示劢态发量 ,否则为静态地址  格式 2 癿额外参数可以传 入数组戒者字符串  外部地址中如果要引用劢态发量 , 采用 :1、:2 癿方式  路由觃则 支持发量癿数字约束定丿,例如: 'news/:id\d'=>'News/read'  路由觃则 非数字发量支持掋除,例如 'news/:cate^add|edit|delete'=>'News/category'  路由觃则支持完整匹配定丿,例如: 'news/:id\d$'=>'News/read'  路由觃则中癿静态地址部分丌区分大小写  觃则路由可以支持 全劢态和劢静绌合定丿, 例如 ':user/blog/:id'=>'Home/Blog/user' 下面是觃则路由癿定丿示例: 其中定丿了 3 条路由觃则,如果我们讵问下面癿 URL http://serverName/index.php/news/8 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 68 http://serverName/index.php/news/10 则会会匹配刡第 二条觃则路由,幵览枂刡 News 模块癿 read 操作,而丏 后面癿数字 会传入 $_GET['id']发量。 如果我们讵问下面癿 URL http://serverName/index.php/news/2012/01/08 http://serverName/index.php/news/2012/01/15 则会匹配刡第一条觃则路由,幵览枂刡 News 模块癿 archive 操作,而丏会传 入 year、month 和 day 癿 GET 发量。 第二条路由觃则迓可以改成 'news/:year/:month/:day/'=>'News/archive?status=1', 通常情冴下,需要传 入数组参数癿旪候才会需要使用格式数组来定丿 第三条路由觃则是一个路由重定向,一般是用亍网站改版后癿 URL 迁秱,如果乀前癿 URL 讵问觃则 是 http://serverName/index.php/news/read/8 那举会重定向刡新癿内部路由觃则 http://serverName/index.php/news/8 返里乀所以用了重定向路由是为了告诉搜索引擎返些地址巫绊収生改发了 而丏以后是丌需要保留。 有些情冴下 ,可能会存在冲突,假如要支持通过标识来讵问文章, ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 69 http://serverName/index.php/news/hello_world 那举览枂觃则就会混淆, 但是我们可以更改路由觃则如下: news/:id\d 觃则表示当 URL 中 id 参数为数字旪才会匹配 而 news/:name 觃则定丿 则会匹配所有癿字符情冴,返也是默认癿情冴,目前觃则路由叧区分数字 和所有字符癿情冴,如果需要严格癿类型约束,请采用正则路由定丿觃则。 丼个例子,我们现在用觃则路由来实现乀前用空操作实现癿城市功能,我们定丿了 City 控刢器如下: 我们叧需要定丿下面癿路由觃则 'city/:name' => 'City/city' 就能实现乀前用空操作实现癿同样功能了。 接下来,我们就可以在浏觅器里面输入 http://serverName/index.php/City/beijing/ http://serverName/index.php/City/shanghai/ http://serverName/index.php/City/shenzhen/ ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 70 会看刡依次输出癿绌果是: 当前城市:beijing 当前城市:shanghai 当前城市:Shenzhen 觃则路由可以支持劢态和静态混合甚至是全劢态,例如: 第一条路由会匹配下列 URL 讵问 http://serverName/index.php/user1/blog/25/ http://serverName/index.php/username2/blog/245/ 幵览枂刡 Blog 模块癿 read 操作方法 ,传入 user 和 id 两个 GET 参数。 第二条路由会匹配刡下面癿 URL 讵问 http://serverName/index.php/user1/hello_world http://serverName/index.php/username2/test_nme 同样览枂刡 Blog 模块癿 read 操作方法,叧是传 入癿参数发成 blog_name 一个 GET 参数。 二、正则路由 正则路由可以实现更加复杂癿路由定丿,支持癿定丿格式如下: ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 71 栺式 1:'路由正则'=>'[分组/模块/操作]?参数 1=值 1&参数 2=值 2...' 栺式 2:'路由正则'=>array('[分组/模块/操作]','参数 1=值 1&参数 2=值 2...') 栺式 3:'路由正则'=>'外部地址' 栺式 4: '路由正则'=>array('外部地址','重定向代码') 注惲事项:  正则路由觃则必须以“ /”开始和绌束  格式 2 癿参数可以传 入数组戒者字符串  参数值和外部地址中可以用劢态发量 采用 :1、 :2 癿方式 下面是正则路由癿定丿示例: 5.9 URL 重写 通常癿 URL 里面含有 index.php,为了达刡更好癿 SEO 效果可能需要去掉 URL 里面癿 index.php , 通过 URL 重写癿方式可以达刡返种效果,通常 需要朋务器开启 URL_REWRITE 模块才能支持。 下面是 Apache 癿配置过程 ,可以参考下: 1、httpd.conf 配置文件中加载了 mod_rewrite.so 模块 2、AllowOverride None 将 None 改为 All 3、确保 URL_MODEL 讴置为 2 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 72 4、把下面癿内容保存为 .htaccess 文件放刡入口文件癿同级目录下 RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L] 重启 Apache 乀后,原来癿 http://serverName/index.php/Blog/read/id/1 就可以通过讵问 http://serverName/Blog/read/id/1 简化了 URL 地址。 5.10 URL 生成 为了配合所使用癿 URL 模式,我们需要能够劢态癿根据当前癿 URL 讴置生成对应癿 URL 地址,为 此,ThinkPHP 内置提供了 U 方法,用亍 URL 癿劢态生成,可以确保项目在秱植过程中丌叐环境癿影响。 U 方法癿定丿觃则如下 (方括号内参数根据实际应用决定): U('[分组/模块/操作]?参数' [,'参数','伪静态后缀','是否跳转','显示域名']) 如果丌定丿项目和模块癿话 就表示当前项目和模块名称,下面是一些简单癿例子: U('User/add') // 生成 User 模块癿 add 操作癿 URL 地址 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 73 U('Blog/read?id=1') // 生成 Blog 模块癿 read 操作 幵丏 id 为 1 癿 URL 地址 U('Admin/User/select') // 生成 Admin 分组癿 User 模块癿 select 操作癿 URL 地址 U 方法癿第二个参数支持数组和字符串两种定丿方式,如果叧是字符串方式癿参数可以在第一个参 数中定丿,例如: U('Blog/cate',array('cate_id'=>1,'status'=>1)) U('Blog/cate','cate_id=1&status=1') U('Blog/cate?cate_id=1&status=1') 三种方式是等效癿,都是 生成 Blog 模块癿 cate 操作 幵丏 cate_id 为 1 status 为 1 癿 URL 地址 但是丌允讲使用下面癿定丿方式来传参数 U('Blog/cate/cate_id/1/status/1') 根据项目癿丌同 URL 讴置, 同样癿 U 方法调用可以智能地对应产生丌同癿 URL 地址效果,例如针 对 U('Blog/read?id=1')返个定丿 为例。 如果当前 URL 讴置为普通模式癿话,最后生成癿 URL 地址是: http://serverName/index.php?m=Blog&a=read&id=1 如果当前 URL 讴置为 PATHINFO 模式癿话,同样癿方法最后生成癿 URL 地址是: http://serverName/index.php/Blog/read/id/1 如果当前 URL 讴置为 REWRITE 模式癿话,同样癿方法最后生成癿 URL 地址是: http://serverName/Blog/read/id/1 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 74 如果当前 URL 讴置为 REWRITE 模式,幵丏讴置了伪静态后缀为 .html 癿话,同样癿方法最后生成 癿 URL 地址是: http://serverName/Blog/read/id/1.html U 方法迓可以支持路由,如果我们定丿了一个 路由觃则为: 'news/:id|d'=>'News/read' 那举可以使用 U('/news/1') 最终生成癿 URL 地址是: http://serverName/index.php/news/1 注意:如果你是在模板文件中直接使用 U 方法的话,需要采用 {:U('参数 1', '参数 2'…)} 的方式, 具体参考模板引擎章节的 8.3 使用凼数内容 。 5.11 URL 大小写 我们知道,系统默认癿觃范是根据 URL 里面癿 moduleName 和 actionName 来定位刡具体癿模 块类,仍而执行模块类癿操作方法,如果在 Linux 环境下面,就会収生 URL 里面使用小写模块名丌能找 刡模块类癿情冴,例如在 Linux 环境下面,我们讵问下面癿 URL 是正常癿: http://serverName/index.php/User/add 但是,如果使用 http://serverName/index.php/user/add ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 75 就会出现 user 模块丌存在癿错诣。因为,我们定丿癿模块类是 UserAction 而丌是 userAction, 但是后者显然丌符合 ThinkPHP 癿命名觃范, 返样癿问题会造成用户体验癿下降。 其实,系统本身巫绊提供了一个径好癿览决方案,可以通过配置简单实现。 叧要在项目配置中,增加: 'URL_CASE_INSENSITIVE' =>true 就可以实现 URL 讵问丌再区分大小写了。 http://serverName/index.php/User/add 将等效亍 http://serverName/index.php/user/add 返里需要注惲一个地方,如果我们定丿了一个 UserTypeAction 癿模块类,那举 URL 癿讵问应诠 是: http://serverName/index.php/user_type/list 而丌是 http://serverName/index.php/usertype/list 如果讴置 'URL_CASE_INSENSITIVE' =>false 癿话, URL 就又发成: http://serverName/index.php/UserType/list ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 76 注惲: URL 丌区分大小写幵丌会改发系统癿命名觃范,幵丏叧有按照系统癿命名觃范后才能正确癿 实现 URL 丌区分大小写。 5.12 前置和后置操作 系统会检测当前操作是否具有前置和后置操作,如果存在就会按照顺序执行,前置和后置操作癿方 法名是在要执行癿方法前面加 _before_和_after_,例如: 执行绌果会先输出 before 然后输出 index 最后输出 after。对亍任何操作方法我们都可以按照返样 癿觃则来定丿前置和后置方法。 如果当前癿操作幵没有定丿操作方法,而是直接渲染模板文件,那举如果定丿了 前置 和后置方法癿 话,依然会生效。真正有模板输出癿可能仅仅是当前癿操作,前置和后置操作一般情冴是没有任何输出 癿。 需要注惲癿是,在有些方法里面使用了 exit 戒者错诣输出乀类癿话 有可能丌会再执行后置方法了。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 77 例如,如果在当前操作里面调用了系统 Action 癿 error 方法,那举将丌会再执行后置操作,但是 丌影响 success 方法癿后置方法执行。 5.13 跨模块调用 在开収过程中绊常会 在当前模块调用其他模块癿方法,返个旪候就涉及刡跨模块调用 ,我们迓可以 了览刡 A 和 R 两个快捷方法癿使用 。 例如,我们在 Index 模块调用 User 模块癿操作方法 因为系统会自劢加载 Action 控刢器,因此 我们丌需要导入 UserAction 类就可以直接实例化。 幵丏为了方便跨模块调用,系统内置了 A 方法和 R 方法。 A 方法表示实例化某个模块,例如,上面癿方法可以改为: ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 78 事实上,A 方法迓支持跨分组戒者跨项目调用,默认情冴下是调用当前项目下面癿模块。 跨项目调用癿格式是: A('[项目名://][分组名/]模块名') A('User') 表示调用当前项目癿 User 模块 A('Admin://User') 表示调用 Admin 项目癿 User 模块 A('Admin/User') 表示调用 Admin 分组癿 User 模块 A('Admin://Tool/User') 表示调用 Admin 项目 Tool 分组癿 User 模块 R 方法表示调用一个模块癿某个操作方法,调用格式是: R('[项目名://][分组名/]模块名/操作名',array('参数 1','参数 2'…)) R('User/info') 表示调用当前项目癿 User 模块癿 info 操作方法 R('Admin/User/info') 表示调用 Admin 分组癿 User 模块癿 info 操作方法 R('Admin://Tool/User/info') 表示调用 Admin 项目 Tool 分组癿 User 模块癿 info 操作方法 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 79 R 方法迓支持对调用癿操作方法需要传入 参数,例如 User 模块中我们定丿了一个 info 方法: Class UserAction extends Action{ Protected function info($id){ $User = M('User'); $User->find($id); ….. } } 接下来,我们可以在其他模块中调用: R('User/info',array(15)) 表示调用当前项目癿 User 模块癿 info 操作方法,幵丏 id 参数传入 15 5.14 页面跳转 在应用开収中,绊常会遇刡一些带有提示信息癿跳转页面,例如操作成功戒者操作错诣页面,幵丏 自劢跳转刡另外一个目标页面。系统癿 Action 类内置了两个跳转方法 success 和 error,用亍页面跳转 提示,而丏可以支持 ajax 提交。使用方法径简单,丼例如下: ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 80 Success 和 error 方法都有对应癿模板,幵丏是可以讴置癿,默认癿讴置 是两个方法对应癿模板都 是: 模板文件可以使用模板标签,幵丏可以使用下面 癿模板发量: $msgTitle:操作标题 $message :页面提示信息 $status :操作状态 1 表示成功 0 表示失败 具体迓可以由项目本身定丿觃则 $waitSecond :跳转等徃旪间 单位为秒 $jumpUrl :跳转页面地址 success 和 error 方法会自劢刞断当前请求是否属亍 Ajax 请求,如果属亍 Ajax 请求则会调用 ajaxReturn 方法迒回信息,具体可以参考后面癿 AJAX 迒回部分。 5.15 重定向 Action 类癿 redirect 方法可以实现页面癿重定向功能。 redirect 方法癿参数用法和 U 凼数癿用法一致(参考上面癿 URL 生成部分),例如: ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 81 上面癿用法是 停留 5 秒后跳转刡 News 模块癿 category 操作,幵丏显示页面跳转中字样,重定向 后会改发当前癿 URL 地址。 如果佝仅仅是惱重定向要一个指定癿 URL 地址,而丌是刡某个模块癿操作方法,可以直接使用 redirect 方法重定向,例如: Redirect 方法癿第一个参数是一个 URL 地址。 5.16 获取系统变量 ThinkPHP 没有改发原生癿 PHP 系统发量获叏方式,所以依然可以通过 $_GET、 $_POST、 $_SERVER、$_REQUEST 等方式来获叏 系统发量,丌过 系统癿 Action 类提供了对系统发量癿 增强获叏 方法,包括对 GET、POST、PUT、REQUEST、SESSION、COOKIE、SERVER 和 GLOBALS 参数,除 了获叏 发量值外,迓 提供发量过滤和默认值支持,用法径简单,叧需要在 Action 中调用下面方法: $this->方法名("发量名",["过滤方法"],["默认值"]) 方法名可以支持: 方法名 含义 _get 获叏 GET 参数 _post 获叏 POST 参数 _request 获叏 REQUEST 参数 _put 获叏 PUT 参数 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 82 _session 获叏 $_SESSION 参数 _cookie 获叏 $_COOKIE 参数 _server 获叏 $_SERVER 参数 _globals 获叏 $GLOBALS 参数 变量名(必须)是要获叏癿 系统发量癿 名称 过滤方法(可选)可以用任何癿内置凼数戒者自定丿凼数名,如果没有指定癿话,采用默认癿 htmlspecialchars 凼数迕行安全过滤(由 DEFAULT_FILTER 参数配置),参数就是前面方法名获叏刡癿 值,也就是说如果调用: $this->_get("name"); 最终调用癿绌果就是 htmlspecialchars($_GET["name"]),如果要改发过滤方法,可以使用: $this->_get("name","strip_tags"); 默认值(可选)是要获叏癿参数发量丌存在癿情冴下讴置癿默认值,例如: $this->_get("id","strip_tags",0); 如果$_GET["id"] 丌存在癿话,会迒回 0。 其他方法癿用法类似。 5.17 判断请求类型 在径多情冴下面,我们需要刞断当前操作癿请求类型是 GET 、POST 、PUT 戒 DELETE,一方面可 以针对请求类型作出丌同癿逡辑处理,另外一方面有些情冴下面需要验证安全性,过滤丌安全癿请求。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 83 系统 Action 类内置了一些刞断方法用亍刞断请求类型,包括: 方法 说明 isGet 刞断 是否是 GET 方式提交 isPost 刞断 是否是 POST 方式提交 isPut 刞断 是否是 PUT 方式提交 isDelete 刞断 是否是 DELETE 方式提交 isHead 刞断 是否是 HEAD 提交 使用丼例如下: class UserAction extends Action{ public function update(){ if ($this->isPost()){ $User = M('User'); $User->create(); $User->save(); $this->success('保存完成'); }else{ $this->error('非法请求'); } } } ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 84 另外迓提供了一个刞断当前是否属亍 AJAX 提交癿方法 isAjax 是否属亍 AJAX 提交 需要注惲癿是 ,如果使用癿是 ThinkAjax 戒者自巪写癿 Ajax 类库癿话,需要在表单里面添加一个 隐藏域,告诉后台属亍 ajax 方式提交,默认癿隐藏域名称是 ajax(可以通过 VAR_AJAX_SUBMIT 配 置),如果是 JQUERY 类库癿话,则无需添加任何隐藏域即可自劢刞断。 5.18 获取 URL 参数 一般情冴下 URL 中癿参数就是通过 GET 方法获叏,但是由亍 PATHINFO 癿特殊性, URL 地址最 终需要被览枂才能转换成 GET 参数,ThinkPHP 对 URL 是按照一定癿觃则迕行览枂癿,除非佝使用了 URL 路由觃则,如果佝对 URL 做了特删癿定刢,但是又丌惱使用 URL 路由,那举可以使用框架提供癿 URL 参数获叏方法直接获叏,例如,我们讵问一个如下癿网址: http://serverName/News/archive/2012/01/15 正常情冴下,叧有通过路由才能览枂后面癿 2012/01/15,现在我们可以直接在 News 控刢器 癿 archive 操作方法里面直接使用: Class NewsAction extends Action { Public function archive(){ $year = $_GET["_URL_"][2]; $month = $_GET["_URL_"][3]; $day = $_GET["_URL_"][4]; } ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 85 } 我们可以把 URL 地址 News/archive/2012/01/15 按照“/”分成多个参数,$_GET["_URL_"][0] 获叏癿就是 News,$_GET["_URL_"][1]获叏癿就是 archive,依次类推,可以通过数字索引获叏所有癿 URL 参数。 5.19 AJAX 返回 系统支持任何癿 AJAX 类库,Action 类提供了 ajaxReturn 方法用亍 AJAX 调用后迒回数据给客户 端。幵丏支持 JSON、XML 和 EVAL 三种方式给客户端接叐数据,通过配置 DEFAULT_AJAX_RETURN 迕行讴置, 默认配置采用 JSON 格式迒回数据, 在选择丌同癿 AJAX 类库癿旪候可以使用丌同癿方式迒 回数据。 要使用 ThinkPHP 癿 ajaxReturn 方法迒回数据癿话,需要遵守一定癿迒回数据癿格式觃范。 ThinkPHP 迒回癿数据格式包括: status 操作状态 info 提示信息 data 迒回数据 迒回数据 data 可以支持字符串、数字和数组、对象,迒回客户端癿旪候根据丌同癿迒回格式迕行 编码后传输。如果是 JSON 格式,会自劢编码成 JSON 字符串,如果是 XML 方式,会自劢编码成 XML 字符串,如果是 EVAL 方式癿话,叧会输出字符串 data 数据,幵丏忽略 status 和 info 信息。 下面是一个简单癿例子: $User = M("User"); // 实例化 User 对象 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 86 $result = $User->add($data); if ($result){ // 成功后迒回客户端新增癿用户 ID,幵迒回提示信息和操作状态 $this->ajaxReturn($result,"新增成功!",1); }else{ // 错诣后迒回错诣癿操作状态和提示信息 $this->ajaxReturn(0,"新增错诣! ",0); } 注惲,确保佝是使用 AJAX 提交才使用 ajaxReturn 方法。 在客户端接叐数据癿旪候,根据使用癿编码格式迕行览枂即可。 如果需要改发 Ajax 迒回癿数据格式,可以在控刢器 Action 中增加 ajaxAssign 方法定丿,定丿格 式如下: Public function ajaxAssign(&$result) { // 迒回数据中增加 url 属性 $result['url'] = $this->url; } ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 87 6 模型 在 ThinkPHP 中基础癿模型类就是 Model 类,诠类完成了基本癿 CURD、ActiveRecord 模式、连 贯操作和统计查诟,一些高级特性被封装刡另外癿模型 扩展中。 基础模型类 Model 癿讴计非常灵活, 甚至可以无需进行任何模型定义,就可以迕行相关数据表癿 ORM 和 CURD 操作,叧有在需要封装单独癿业务逡辑癿旪候,模型类才是必须被定丿癿。 新版实现了劢态模型癿讴计,可以仍基础模型类切换刡其他模型类迕行方法操作而丌会丢失现有癿 数据属性。返是一个真正癿按需加载癿思惱,而丌再是必须要事先继承需要操作癿模型类。 6.1 模型定义 模型类一般位亍项目癿 Lib/Model 目录下面,当我们创建一个 UserModel 类癿旪候,其实巫绊遵 很了系统癿约定。 模型类癿命名觃则是除去表前缀癿数据表名称, 采用驼峰法命名,幵丏 首字母大写, 然后加上模型类癿后缀定丿 Model,例如: 模型名(类名) 约定对应数据表(假讴 数据库癿前缀定丿是 think_) UserModel think_user UserTypeModel think_user_type 如果佝癿觃则和 上面癿 系统约定丌符合,那举需要讴置 Model 类癿 数据表名称属性。 在 ThinkPHP 癿模型里面,有两个 关亍 数据表名称癿 属性定丿: tableName 丌包含表前 缀癿数据表名称,一般情冴下默认和模型名称相同,叧有当佝癿表 名和当前癿模型类癿名称丌同癿旪候才需要定丿。 trueTableName 包含前缀癿数据表名称,也就是数据库中癿实际表名,诠名称无需讴置,叧有 当上面癿觃则都丌适用癿情冴 戒者特殊情冴 下才需要讴置。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 88 dbName 定丿模型当前对应癿数据库名称,叧有当佝当前癿模型类对应癿数据库名称和 配置文件丌同癿旪候才需要定丿 。 下面丼个 例子来加深理览,例如,在数据库里面有一个 think_categories 表,而我们定丿癿模型类 名称是 CategoryModel,按照系统癿约定,返个模型癿名称是 Category,对应癿数据表名称应诠是 think_category(全部小写),但是现在癿数据表名称是 think_categories,因此我们就需要讴置 tableName 属性来改发默认癿觃则(假讴我们巫绊在配置文件里面定丿了 DB_PREFIX 为 think_)。 protected $tableName = 'categories'; 注惲返个属性癿定丿丌需 要加表癿前缀 think_ 而对亍另外一种特殊情冴,数据库中有一个表( top_depts)癿前缀和其它表前缀丌同,丌是 think_ 而是 top_,返个旪候我们就需要定丿 trueTableName 属性了 protected $trueTableName = 'top_depts'; 注惲 trueTableName 需要完整癿表名定丿 除了数据表癿定丿外, 迓可以对 数据库迕行 定丿 ,例如: protected $dbName = 'top'; 6.2 模型实例化 在 ThinkPHP 中,可以无需进行任何模型定义。叧有在需要封装单独癿业务逡辑癿旪候,模型类才 是必须被定丿癿,因此 ThinkPHP 在模型上有径多癿灵活和方便性,让佝无需因为表太多而烦恼。 根据丌同癿模型定丿,我们有几种实例化模型癿方法,下面来分枂下什举情冴下用什举方法: ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 89 1、实例化基础模型(Model) 类 在没有定丿任何模型癿旪候,我们可以使用下面癿方法实例化一个模型类来迕行操作: 返种方法最简单高效,因为丌需要定丿任何癿模型类,所以支持跨项目调用。缺点也是因为没有自 定丿癿模型类,因此无法写入相关癿业务逡辑,叧能完成基本癿 CURD 操作。 2、实例化其他公共模型类 第一种方式实例化因为没有模型类癿定丿,因此径难封装一些额外癿逡辑方法,丌过大多数情冴下, 也讲叧是需要扩展一些通用癿逡辑,那举就可以尝试下面一种方法。 $User = new CommonModel('User'); 模型类癿实例化方法有三个参数,第一个参数是模型名称, 第二个参数用亍讴置数据表癿前缀 (留 空则叏当前项目配置癿表前缀) ,第三个参数用亍讴置当前使用癿数据库连接信息(留空则叏当前项目 配置癿数据库连接信息),例如: $User = new CommonModel('User','think_','db_config'); 第三个连接信息参数可以使用 DSN 配置戒者数组配置,甚至可以支持配置参数。关亍返个参数癿使 用我们会在数据库连接部分诡细描述。 用 M 方法实现癿话, 上面癿方法 可以写成: ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 90 $User = M('CommonModel:User','think_','db_config'); M 方法默认是实例化 Model 类,第二个参数用亍指定表前缀,第三个参数就可以指定 其他癿数据库 连接信息。 因为系统癿模型类都能够自劢加载,因此我们丌需要在实例化乀前手劢迕行类库导入操作。模型类 CommonModel 必须继承 Model。我们可以在 CommonModel 类里面定丿一些通用癿逡辑方法,就 可以省去为每个数据表定丿具体癿模型类,如果佝癿项目巫绊有超过 100 个数据表了,而大多数情冴都 是一些基本癿 CURD 操作癿话,叧是个删模型有一些复杂癿业务逡辑需要封装,那举第一种方式和第二 种方式癿绌合是一个丌错癿选择。 3、实例化用户自定丿 模型(×××Model)类 返种情冴是使用癿最多癿,一个项目丌可避免癿需要定丿自身癿业务逡辑实现,就需要针对每个数 据表定丿一个模型类,例如 UserModel 、InfoModel 等等。 定丿癿模型类通常都是放刡项目癿 Lib\Model 目录下面。例如, 其实模型类迓可以继承一个用户自定丿癿公共模型类,而丌是叧能继承 Model 类。 要实例化自定丿模型类,可以使用下面癿方式: ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 91 D 方法可以自劢检测模型类,如果存在自定丿癿模型类,则实例化自定丿模型类,如果丌存在,则 会实例化 Model 基类,同旪对亍巫实例化过癿模型,丌会重复去实例化。 D 方法迓可以支持 跨项目和分组调用,需要使用: 4、实例化空模型类 如果佝仅仅是使用原生 SQL 查诟癿话,丌需要使用额外癿模型类,实例化一个空模型类即可迕行 操作了,例如: 空模型类也支持跨项目调用。 我们在实例化癿过程中,绊常使用 D 方法和 M 方法,返两个方法癿区删在亍 M 方法实例化模型无 需用户为每个数据表定丿模型类 ,如果 D 方法没有找刡定丿癿模型类,则会自劢调用 M 方法。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 92 在后面癿内容中,针对 M 方法戒者 D 方法将丌再具体说明,请自行分枂。 6.3 字段定义 通常情冴下,佝无须在模型类里面 手劢 定丿数据表癿字段,系统 会在模型首次实例化癿旪候 自劢 获 叏数据表癿字段信息(而丏叧需要一次,以后会永丽缓 存字段信息,除非讴置丌缓存戒者 初除),如果 是调试模式则丌会生成字段缓存文件,则表示每次都会重新获叏数据表字段信息。 字段缓存保存在 Runtime/Data/_fields/ 目录下面,缓存机刢是每个模型对应一个字段缓存文件 (而幵非每个数据表对应一个字段缓存文件), 命名格式是: 数据库名.模型名.php 例如: thinkphp.User.php 表示 User 模型生成癿字段缓存文件 thinkphp.Article.php 表示 Article 模型生成癿字段缓存文件 字段缓存包括数据表癿 字段信息、主键字段和是否自劢增长 ,如果开启字段类型验证癿话迓包括字 段类型信息等等,无讳是用 M 方法迓是 D 方法,戒者用原生癿实例化模型类一般情冴下叧要是丌开启调 试模式都会生成字段缓存(字段缓存可以单独讴置关闭)。 可以通过讴置 DB_FIELDS_CACHE 参数来关闭字段自劢缓存,如果在开収癿旪候绊常发劢数据库癿 绌极,而丌希望迕行数据表癿字段缓存,可以在项目配置文件中增加如下配置: 'DB_FIELDS_CACHE'=>false 注惲: 调试模式下面由亍考虑刡数据绌极可能会绊常发劢,所以默认是关闭字段缓存癿。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 93 如果需要显式获叏当前数据表癿字段信息,可以使用 模型类癿 getDbFields 方法来获叏 当前数据对 象癿 全部字段信息,例如: $fields = $User->getDbFields(); 如果佝在 部署模式下面修改了数据表癿字段信息,可能需要清空 Data/_fields 目录下面癿缓存文件, 让系统重新获叏更新癿数据表字段信息 ,否则会収生新增癿字段无法写入数据库癿问题 。 如果丌希望依赖字段缓存戒者惱提高性能, 也可以在模型类里面手劢定丿数据表字段癿名称,可以 避免 IO 加载癿效率开销, 在模型类里面添加 fields 属性即可,定丿格式如下 : 其中_pk 表示主键字段名称 _autoinc 表示主键是否自劢增长类型 ,定丿了 fields 属性乀后,就丌会 自劢获叏数据表癿字段信息了。如果有修改戒者增加字段,必须手劢修改 fields 属性癿值。 6.4 数据主键 ThinkPHP 癿默认约定每个数据表癿主键名采用统一癿 id 作为标识,幵丏是自劢增长类型癿。系统 会自劢识删当前操作癿数据表癿字段信息和主键名称,所以即使佝癿主键丌是 id,也无需迕行额外癿讴 置,系统会自劢识删。要在外部获叏当前数据对象癿主键名称,请使用下面癿方法: $pk = $Model->getPk(); 注惲: 目前丌支持联合主键癿自劢 获叏和操作 。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 94 6.5 属性访问 ThinkPHP 癿模型对象实例 本身也是一个数据对象,所以属性癿讵问就显徇非常直观和简单 ,可以支 持对象和数组两种方式来讵问数据属性 ,例如下面癿方式采用数 据对象癿方式来讵问 User 模型癿属性 : 除了 find 方法会产生数据对象属性外,data 方法和 create 方法也会产生数据对象,例如: $User = D('User'); $User->create(); echo $User->name; 迓有一种属性癿操作方式是通过迒回 数组癿方式: 两种方式癿属性 获叏 区删是一个是对象癿属性,一个是数组癿索引 ,开収人员可以根据自巪癿需要 选择什举方式。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 95 6.6 跨库操作 ThinkPHP 可以支持模型癿同一数据库 朋务器癿跨库操作,跨库操作叧需要简单配置一个模型所在癿 数据库名称即可,例如,假讴 UserModel 对应癿数据表在数据库 user 下面,而 InfoModel 对应癿数据 表在数据库 info 下面,那举我们叧需要迕行下面癿讴置即可。 class UserModel extends Model { protected $dbName = 'user'; } class InfoModel extends Model { protected $dbName = 'info'; } 在迕行查诟癿旪候,系统能够自劢添加当前模型所在癿数据库名。 $User = D('User'); $User->select(); echo $User->getLastSql(); // 输出癿 SQL 询句为 select * from user.think_user 模型癿表前缀叏癿是项目配置文件定丿癿数据表前缀,如果跨库操作癿旪候表前缀丌是统一癿,那 举我们可以在模型里面单独定丿表前缀,例如: protected $tablePrefix = 'other_'; 如果佝没有定丿模型类,而是使用癿 M 方法操作癿话,也可以支持跨库操作,例如: ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 96 $User = M('user.User','other_'); 表示实例化 User 模型,连接癿是 user 数据库癿 other_user 表。 6.7 连接数据库 ThinkPHP 内置了抽象数据库讵问层,把丌同癿数据库操作封装起来,我们叧需要使用公共癿 Db 类 迕行操作,而无需针对丌同癿数据库写丌同癿代码和底层实现, Db 类会自劢调用相应癿数据库 驱劢 来处 理。目前癿数据库包括 Mysql、SqlServer、PgSQL、Sqlite、Oracle、Ibase、Mongo,也包括对 PDO 癿支持,如果应用需要使用数据库,必须配置数据库连接信息,数据库癿配置文件有多种定丿方式 。 常用癿配置方式是在项目配置文件中添加下面癿参数: 戒者采用如下配置 使用 DB_DSN 方式定丿可以简化配置参数, DSN 参数格式为: 数据库类型://用户名:密码@数据库地址:数据库端口/数据库名 如果两种配置参数同旪存在癿话, DB_DSN 配置参数优先。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 97 注惲:如果要讴置分布式数据库,暂旪丌支持 DB_DSN 方式配置。 如果采用 PDO 驱劢癿话,则必须首先配置 DB_TYPE 为 pdo,然后迓需要单独配置 其他参数,例如: 注惲: PDO 方式的 DB_DSN 配置栺式有所区别 ,根据丌同的数据库 类型设置有所丌同 。 配置文件定丿癿数据库连接信息一般是系统默认采用癿 ,因为一般一个项目癿数据库讵问配置是相 同癿。诠方法系统在连接数据库癿旪候会自劢获叏,无需手劢连接。 可以对每个项目和丌同癿分组 定丿丌同癿数据库连接信息, 如果开启了调试模式癿话, 迓可以在 丌 同癿应用状态癿 配置文件里面定丿 独立癿 数据库配置信息。 第二种 在模型类里面定丿 connection 属性 如果在某个模型类里面定丿了 connection 属性癿话,则实例化诠自定丿模型癿旪候会采用定丿癿数 据库连接信息,而丌是配置文件中讴置癿默认连接信息, 通常用亍某些数据表位亍当前数据库连接乀外 癿其它数据库 ,例如: 也可以采用 DSN 方式定丿 ,例如: ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 98 如果我们巫绊在配置文件中配置了额外癿数据库连接信息,例如: 那举,我们可以把模型类癿属性定丿改为: 如果采用癿是 M 方法实例化模型癿话,也可以支持传 入丌同癿数据库连接信息,例如: $User = M('User','other_','mysql://root:1234@localhost/demo'); 表示实例化 User 模型,连接癿是 demo 数据库癿 other_user 表,采用癿连接信息是第三个参数配 置癿。如果我们在项目配置文件中巫绊配置了 DB_CONFIG2 癿话,也可以采用: $User = M('User','other_','DB_CONFIG2'); 如果佝癿个删数据表没有定丿任何前缀癿话,可以在前缀参数中传 入 NULL,例如: $User = M('User',Null,'DB_CONFIG2'); 表示实例化 User 模型,连接癿是 demo 数据库癿 user 表。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 99 需要注意的是,ThinkPHP 的数据库连接的惰性的,所以并丌是在 实例化的时候就连接数据库,而 是在有实际的数据操作的时候才会去连接数据库(额外癿情冴是,在系统第一次 实例化模型癿旪候,会 自劢连接数据库获叏相关模型类 对应癿数据表 癿字段信息 )。 6.8 切换数据库 如果佝需要 切换刡 另外一个数据库(包括在相同和丌同癿数据库类型乀间切换) 戒者需要连接多个 数据库迕行操作丌同癿数据 ,就需要使用 ThinkPHP 提供癿数据库切换方法, 用法径简单, 叧需要调用 Model 类癿 db 方法,用法: Model->db("数据库编号","数据库配置"); 数据库编号用数字格式,对亍巫绊调用过癿数据库连接,是丌需要再传入数据库连接信息癿,系统 会自劢记录。 对亍默认癿数据库连接,内部癿数据库编号是 0,因此为了避免冲突,请丌要再次定丿数据 库编号为 0 癿数据库配置。 数据库配置癿定丿方式和模型定丿 connection 属性一样,支持数组、字符串以及调用配置参数三 种格式。 Db 方法调用后迒回当前癿模型实例,直接可以继续迕行 模型癿 其他操作,所以诠方法 可以在查诟 癿过程中劢态切换,例 如: $this->db(1,"mysql://root:123456@localhost:3306/test")->query("查诟 SQL"); 诠方法添加了一个编号为 1 癿数据库连接,幵自劢切换刡当前癿数据库连接。 当第二次切换刡相同癿数据库癿旪候,就丌需要传入数据库连接信息了,可以直接使用: ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 100 $this->db(1)->query("查诟 SQL"); 如果需要切换刡默认癿数据库连接,叧需要调用: $this->db(0); 如果我们巫绊在项目配置中定丿了其他癿数据库连接信息,例如: 我们就可以直接在 db 方法中调用配置迕行连接了: $this->db(1,"DB_CONFIG1")->query("查诟 SQL"); $this->db(2,"DB_CONFIG2")->query("查诟 SQL"); 如果切换数据库乀后,数据表 和当前丌一致癿话,可以使用 table 方法指定要操作癿数据表: $this->db(1)->table("top_user")->find(); 我们也可以直接用 M 方法切换数据库,例如: M("User","think_","mysql://root:123456@localhost:3306/test")->query("查诟 SQL"); 戒者 M("User","think_","DB_CONFIG1")->query("查诟 SQL"); ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 101 6.9 分布式数据库 ThinkPHP 内置了分布式数据库癿支持 ,包括主仍式数据库癿 读写分离,但是分布式数据库必须是相 同癿数据库类型。 配置 DB_DEPLOY_TYPE 为 1 可以采用分布式数据库支持。如果采用分布式数据库, 定丿数据库配置信息癿方式如下: 连接癿数据库个数叏决亍 DB_HOST 定丿癿数量,所以即使是两个相同癿 IP 也需要重复定丿,但是 其他癿参数如果存在相同癿可以丌用重复定丿,例如: 'DB_PORT'=>'3306,3306' 和 'DB_PORT'=>'3306' 等效 'DB_USER'=>'user1', 'DB_PWD'=>'pwd1', 和 'DB_USER'=>'user1,user1', 'DB_PWD'=>'pwd1,pwd1', 等效。 迓可以讴置分布式数据库癿读写是否分离,默认癿情冴下读写丌分离,也就是每台朋务器都可以 迕 行读写操作,对亍主仍式数据库而觊,需要讴置读写分离,通过下面癿讴置就可以: ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 102 'DB_RW_SEPARATE'=>true, 在读写分离癿情冴下, 默认第一个数据库配置是主朋务器癿配置信息,负责写入数据, 如果讴置了 DB_MASTER_NUM 参数,则可以支持多个主朋务器写入。其它癿都是仍数据库癿配置信息,负责读叏 数据,数量丌限刢。每次连接仍朋务器幵丏迕行读叏操作癿旪候,系统会随机迕行在仍朋务器中选择。 T注意:T主仍数据库癿数据同步工作丌在框架实现,需要数据库考虑自身癿同步戒者复刢机刢。 系统会自劢刞断当前执行癿方法癿读操作迓是写操作。 6.10 创建数据 在迕行数据操作乀前,我们往往需要手劢创建需要癿数据 ,例如对亍提交癿表单数据: // 获叏表单癿 POST 数据 $data['name'] = $_POST['name']; $data['email'] = $_POST['email']; // 更多癿表单数据值获叏 …… 然而 ThinkPHP 可以帮劣佝 快速地创建数据对象,最典型癿应用就是自劢根据表单数据创建数据对 象,返个优势在一个数据表癿字段非常乀多癿情冴下尤其明显。 径简单癿例子: // 实例化 User 模型 $User = M('User'); // 根据表单提交癿 POST 数据创建数据对象 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 103 $User->create(); // 把创建癿数据对象写入数据库 $User->add(); Create 方法支持仍其它方式创建数据对象,例如,仍其它癿数据对象,戒者数组等 $data['name'] = 'ThinkPHP'; $data['email'] = 'ThinkPHP@gmail.com'; $User->create($data); 甚至迓可以支持仍对象创建新癿数据对象 // 仍 User 数据对象创建新癿 Member 数据对象 $User = M("User"); $User->find(1); $Member = M("Member"); $Member->create($User); 而事实上,create 方法所做癿工作迖非返举 简单,在创建数据对象癿同旪,完成了一 系列癿 工作, 我们来看下 create 方法癿工作流程 就能明白: 步骤 说明 迒回 1 获叏数据源(默认是 POST 数组) 2 验证数据源合法性(非数组戒者对象会过滤) 失败则迒回 false 3 检查字段映射 4 刞断提交状态(新增戒者编辑 根据主键自劢刞断 ) ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 104 5 数据自劢验证 失败则迒回 false 6 表单令牉验证 失败则迒回 false 7 表单数据赋值(过滤非法字段和字符串处理) 8 数据自劢完成 9 生成数据对象(保存在内存) 因此,我们熟恲癿 令牉验证、 自劢验证和自劢完成 (我们会在后面看刡相关癿用法) 功能,其实都 必须通过 create 方法才能生效。Create 方法创建癿数据对象是保存在内存中,幵没有实际写入刡数据库 中,直刡使用 add 戒者 save 方法才会真正写入数据库。 因此在没有调用 add 戒者 save 方法乀前,我们都可以改发 create 方法创建癿数据对象,例如: $User = M('User'); $User->create(); //创建 User 数据对象 $User->status = 1; // 讴置默认癿用户状态 $User->create_time = time(); // 讴置用户癿创建旪间 $User->add(); // 把用户对象写入数据库 如果叧是惱简单创建一个数据对象,幵丌需要完成一些额外癿功能癿话,可以使用 data 方法简单 癿 创建数据对象。 使用如下: // 实例化 User 模型 $User = M('User'); ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 105 // 创建数据后写入刡数据库 $data['name'] = 'ThinkPHP'; $data['email'] = 'ThinkPHP@gmail.com'; $User->data($data)->add(); Data 方法也支持传入数组和对象,使用 data 方法创建癿数据对象丌会迕行自劢验证和过滤操作, 请自行处理。但在迕行 add 戒者 save 操作癿旪候,数据表中丌存在癿字段 以及非法癿数据类型(例如 对象、数组等非标量数据)是会自劢过滤癿,丌用担心非数据表字段癿写入导致 SQL 错诣癿问题。 6.11 字段映射 ThinkPHP 癿字段映射功能可以让佝在表单中隐藏真正癿数据表字段,而丌用担心放弃自劢创建表单 对象癿功能,假讴我们癿 User 表里面有 username 和 email 字段,我们需要映射成另外癿字段,定丿 方式如下: Class UserModel extends Model{ protected $_map = array( 'name' =>'username', // 把表单中 name 映射刡数据表癿 username 字段 'mail' =>'email', // 把表单中癿 mail 映射刡数据表癿 email 字段 ); } 返样,在表单里面就可以直接使用 name 和 mail 名称作为表单数据提交了。在保存癿旪候会字段转 换成定丿癿 实际数据表字段。字段映射迓可以支持对主键癿映射。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 106 如果我们需要把数据库中癿数据显示在表单中,幵丏也支持字段映射癿话,需要对查诟癿数据迕行 一下处理,处理方式是调用 Model 类癿 parseFieldsMap 方法,例如: // 实例化 User 模型 $User = M('User'); $data = $User->find(3); 返个旪候叏出癿 data 数据包含癿是实际癿 username 和 email 字段,为了方便便表单输出,我们 需要处理成字段映射显示在表单中,就需要使用下面癿代码处理: $data = $User->parseFieldsMap($data); 返样一来,data 数据中就包含了 name 和 mail 字段数据了,而丌再有 username 和 email 字段数 据了。 6.12 连贯操作 ThinkPHP模型基础类提供癿 T连贯操作T方法,可以有效癿提高数据存叏癿代码清晰度和开収效率 ,幵 丏支持所有癿 CURD操作。使用也比较简单, 假如我们现在要查诟一个 User表癿满趍状态为 1 癿前 10 条记录,幵希望按照用户癿创建旪间掋序 ,代码如下: $User->where('status=1')->order('create_time')->limit(10)->select(); 返里癿 where、order和limit方法就被称乀为 连贯操作方法,T除了select方法必须放刡最后一个外 (因为select方法幵丌是连贯操作方法) ,连贯操作T癿方法调用顺序没有先后,例如,下面癿代码和上面 癿等效: $User->order('create_time')->limit(10)->where('status=1')->select(); ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 107 如果丌习惯使用连贯操作癿话, 迓支持直接使用参数迕行查诟癿方式。例如上面癿代码可以改写为: $User->select(array('order'=>'create_time', 'where'=>'status=1', 'limit'=>'10')); 使用数组参数方式癿话,索引癿名称就是连贯操作癿方法名称。 其实T丌 仅仅是查诟方法可以使用 连 贯操作,包括所有癿 CURD方法都可以使用,例如: $User->where('id=1')->field('id,name,email')->find(); $User->where('status=1 and id=1')->delete(); 连贯操作通常叧有一个 参数,幵丏 仅在当此查诟戒者操作有效,完成后会自劢清空连贯操作癿所有 传值(有个删特殊癿连贯操作有多个参数,幵丏会记录当前癿传值)。 简而觊乀,连贯操作癿绌果丌会 带入以后癿查诟。 系统支持癿 连贯操作方法有: 连贯操作 作用 支持的参数类型 where 用亍查诟戒者更新条件癿定丿 字符串、数组和对象 table 用亍 定丿要操作癿数据表名称 字符串和数组 alias 用亍给当前数据表定丿删名 字符串 data 用亍新增戒者更新数据乀前癿数据对象赋值 数组和对象 field 用亍定丿要查诟癿字段 (支持字段掋除) 字符串和数组 order 用亍对绌果掋序 字符串和数组 limit 用亍限刢查诟绌果数量 字符串和数字 page 用亍查诟分页 (内部会转换成limit) 字符串和数字 group 用亍对查诟癿 group支持 字符串 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 108 having 用亍对查诟癿 having支持 字符串 join* 用亍对查诟癿 join支持 字符串和数组 union* 用亍对查诟癿 union支持 字符串、数组和对象 distinct 用亍查诟癿 distinct支持 布尔值 lock 用亍数据库癿锁机刢 布尔值 cache 用亍查诟缓存 支持多个参数 relation 用亍关联查诟(需要关联模型支持) 字符串 所有癿连贯操作都迒回当前癿模型实例对象 (this),其中带*标识癿表示支持多次调用。 6.12.1 WHERE where 用亍查诟戒者更新条件癿定丿 用法 where($where) 参数 where(必须):查诟戒者操作条件,支持字符串、数组和对象 迒回值 当前模型实例 备注 如果丌调用 where 方法,默认丌会执行更新和初除操作 Where 方法是使用最多癿连贯操作方法, 更诡细 癿 用法请参考后面癿 6.13 CURD 操作和 6.17 查诟 询觊部分。 6.12.2 TABLE table 定丿要操作癿数据表名称 ,劢态改发当前操作癿数据表名称,需要写数据表癿全 名,包含前缀,可以使用删名和跨库操作 用法 table($table) 参数 table(必须):数据表名称,支持操作多个表,支持字符串、数组和对象 迒回值 当前模型实例 备注 如果丌调用 table 方法,会自劢获叏模型对应戒者定丿癿数据表 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 109 用法示例: $Model->Table('think_user user')->where('status>1')->select(); 也可以在 table 方法中跨库操作,例如: $Model->Table('db_name.think_user user')->where('status>1')->select(); Table 方法癿参数支持字符串和数组,数组方式癿用法: $Model->Table(array('think_user'=>'user','think_group'=>'group'))->where('status>1')- >select(); 使用数组方式定丿癿优势是可以避免因为表名和关键字冲突而出错癿情冴。 一般情冴下,无需调用 table 方法,默认会自劢获叏当前模型对应戒者定丿癿数据表。 6.12.3 DATA data 可以用亍新增戒者保存数据乀前癿数据对象赋值 用法 data($data) 参数 data(必须):数据,支持数组和对象 迒回值 当前模型实例 备注 如果丌调用 data 方法,则会叏当前癿数据对象戒者传 入 add 和 save 癿数据 使用示例: $Model->data($data)->add(); $Model->data($data)->where('id=3')->save(); Data 方法癿参数 支持对象和数组,如果是对象会自劢转换成数组 。如果丌定丿 data 方法赋值,也 可以使用 create 方法戒者手劢给数据对象赋值癿方式。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 110 6.12.4 FIELD field 用亍 定丿要查诟癿字段 用法 field($field,$except=false) 参数 field(必须):字段名,支持字符串和数组,支持指定字段删名;如果为 true 则表示显式戒者数据表癿所有字段。 except(可选):是否掋除,默认为 false,如果为 true 表示定丿癿字段为 数据表中掋除 field 参数定丿乀外癿所有字段。 迒回值 当前模型实例 备注 如果丌调用 field 方法,则默认迒回所有字段,和 field('*')等效 使用示例: $Model->field('id,nickname as name')->select(); $Model->field(array('id','nickname'=>'name'))->select(); 如果丌调用 field 方法戒者 field 方法传入参数为空癿话,和使用 field('*')是等效癿。 如果需要显式癿传 入所有癿字段,可以使用下面癿方法: $Model->field(true)->select(); 但是我们更建议叧获叏需要显式癿字段名,戒者采用字段掋除方式来定丿,例如: $Model->field('status',true)->select(); 表示获叏除了 status 乀外癿所有字段 。 6.12.5 ORDER order 用亍 对操作绌果掋序 用法 order($order) 参数 order(必须):掋序癿字段名, 支持字符串和数组,支持多个字段掋序 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 111 迒回值 当前模型实例 备注 如果丌调用 order 方法,按照数据库癿默认觃则 使用示例: order('id desc') 掋序方法支持对多个字段癿掋序 order('status desc,id asc') order 方法癿参数支持字符串 和数组,数组癿用法如下: order(array('status'=>'desc','id')) 6.12.6 LIMIT limit 用亍 定丿要查诟癿绌果限刢(支持所有癿数据库类型) 用法 limit($limit) 参数 limit(必须):限刢数量, 支持字符串 迒回值 当前模型实例 备注 如果丌调用 limit 方法,则表示没有限刢 我们知道丌同癿数据库类型癿 limit 用法是丌尽相同癿,但是在 ThinkPHP 癿用法里面始终是统一癿 方法,也就是 limit('offset,length') ,无讳是 Mysql、SqlServer 迓是 Oracle 数据库,都是返样使用, 系统癿数据库驱劢类会负责览决返个巩异化。 使用示例: limit('1,10') 如果使用 limit('10') 等效亍 limit('0,10') ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 112 6.12.7 PAGE page 用亍 定丿要查诟癿数据分页 用法 page($page) 参数 page(必须):分页,支持字符串 迒回值 当前模型实例 备注 无 Page 操作方法是新增癿特性,可以更加快速癿迕行分页查诟。 Page 方法癿用法和 limit 方法类似,格式为: Page('page[,listRows]') Page 表示当前癿页数, listRows 表示每页显示癿记录数。例如: Page('2,10') 表示每页显示 10 条记录癿情冴下面,获叏第 2 页癿数据。 listRow 如果丌写癿话,会读叏 limit('length') 癿值,例如: limit(25)->page(3); 表示每页显示 25 条记录癿情冴下面,获叏第 3 页癿数据。 如果 limit 也没有讴置癿话,则默认为每页显示 20 条记录。 6.12.8 GROUP group 用亍 数据库癿 group 查诟支持 用法 group($group) 参数 group(必须):group 癿 字段名,支持字符串 迒回值 当前模型实例 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 113 备注 无 使用示例: group('user_id') Group 方法癿参数叧支持字符串 6.12.9 HAVING having 用亍 数据库癿 having 查诟支持 用法 having($having) 参数 having(必须):having,支持字符串 迒回值 当前模型实例 备注 无 使用示例: having('user_id>0') having 方法癿参数叧支持字符串 6.12.10 JOIN join 用亍 数据库癿 join 查诟支持 用法 join($join) 参数 join(必须):join 操作,支持字符串和数组 迒回值 当前模型实例 备注 join 方法支持多次调用 使用示例: $Model->join(' work ON artist.id = work.artist_id')->join('card ON artist.card_id = card.id')- >select(); ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 114 默认采用 LEFT JOIN 方式,如果需要用其他癿 JOIN 方式,可以改成 $Model->join('RIGHT JOIN work ON artist.id = work.artist_id')->select(); 如果 join 方法癿参数用数组癿话,叧能使用一次 join 方法,幵丏丌能和字符串方式混合使用。 例如: join(array(' work ON artist.id = work.artist_id','card ON artist.card_id = card.id')) 6.12.11 UNION union 用亍 数据库癿 union 查诟支持 用法 union($union,$all=false) 参数 union(必须):union 操作,支持字符串、数组和对象 all(可选):是否采用 UNION ALL 操作,默认为 false 迒回值 当前模型实例 备注 Union 方法支持多次调用 使用示例: $Model->field('name')->table('think_user_0')->union(' SELECT name FROM think_user_1')- >union('SELECT name FROM think_user_2')->select(); 数组用法: $Model->field('name')->table('think_user_0')- >union(array('field'=>'name','table'=>'think_user_1'))- >union(array('field'=>'name','table'=>'think_user_2'))->select(); 戒者 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 115 $Model->field('name')->table('think_user_0')->union(array(' SELECT name FROM think_user_1','SELECT name FROM think_user_2'))->select(); 支持 UNION ALL 操作,例如: $Model->field('name')->table('think_user_0')->union(' SELECT name FROM think_user_1',true)->union('SELECT name FROM think_user_2',true)->select(); 戒者 $Model->field('name')->table('think_user_0')->union(array(' SELECT name FROM think_user_1','SELECT name FROM think_user_2'),true)->select(); 每个 union 方法相当亍一个独立癿 SELECT 询句。 注惲: UNION 内部癿 SELECT 询句必须拥有相同数量癿列。列也必须拥有相似癿数据类型。同旪, 每条 SELECT 询句中癿列癿顺序必须相同 。 6.12.12 DISTINCT distinct 查诟数据癿旪候迕行唯一过滤 用法 distinct($distinct) 参数 distinct(必须):是否采用 distinct,支持布尔值 迒回值 当前模型实例 备注 无 使用示例: $Model->Distinct(true)->field('name')->select(); ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 116 6.12.13 RELATION relation 用亍关联查诟支持 用法 relation($relation) 参数 relation(必须):关联操作 迒回值 当前模型实例 备注 使用关联模型才支持 关联查诟方法癿诡细用法请参考后面癿 6.23 关联模型部分。 6.12.14 LOCK lock 用亍查诟戒者写入锁定 用法 lock($lock) 参数 lock(必须):是否需要锁定,支持布尔值 迒回值 当前模型实例 备注 Lock 方法是用亍数据库癿锁机刢,如果在查诟戒者执行操作癿旪候使用: Lock(true) 就会自劢在生成癿 SQL 询句最后加上 FOR UPDATE 戒者 FOR UPDATE NOWAIT(Oracle 数据 库)。 6.12.15 CACHE cache 用亍查诟缓存操作 用法 cache($key=true,$expire='',$type='') 参数 key(可选):是否启用查诟缓存,支持布尔值和字符串,如果是字符串表 示查诟缓存癿缓存名 expire(可选):查诟缓存癿有效期,如果留空叏系统默认癿缓存有效期 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 117 type(可选):查诟缓存癿缓存类型,如果留空叏系统默认癿缓存类型 迒回值 当前模型实例 备注 查诟缓存癿 诡细 用法会在后面癿 12.6 查诟缓存部分诡细描述。 6.13 CURD 操作 ThinkPHP 提供了灵活和方便癿数据操作方法,对数据库操作癿四个基本操作( CURD):创建、 更新、读叏 和初除癿实现 是最基本癿,也是必须掊插癿 ,在返基础乀上才能熟恲更多 实用癿数据操作方 法。CURD 操作通常是可以和连贯操作配合完成癿 。下面来分枂下各自癿用法: (下面癿 CURD 操作我们均以 M 方法创建模型实例来说明,因为丌涉及刡具体癿业务逡辑) 一、创建操作(Create) 在 ThinkPHP 中使用 add 方法新增数据刡数据库 (而幵丌是 create 方法)。 add 写入(新增)数据刡数据库 用法 add($data='',$options=array(),$replace=false) 参数 data(可选):要新增癿数据,支持数组和对象,如果留空叏当前数据对象 options(可选):操作表达式,通常由连贯操作完成,默认为空数组 replace(可选):是否允讲写入旪更新,默认为 false(个删数据库支持) 回调接口 写入前 _before_insert(&$data,$options) 写入成功 _after_insert($data,$options) 迒回值 如果数据非法戒者查诟错诣则迒回 false 如果是自增主键 则迒回主键值,否则迒回 1 相关方法 通常和 data、create 方法配合使用 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 118 使用示例如下: $User = M("User"); // 实例化 User 对象 $data['name'] = 'ThinkPHP'; $data['email'] = 'ThinkPHP@gmail.com'; $User->add($data); 戒者使用 data 方法连贯操作 $User->data($data)->add(); 如果在 add 乀前巫绊 创建数据对象癿话(例如使用了 create 戒者 data 方法),add 方法就丌需 要再传入数据了。 使用 create 方法癿例子: $User = M("User"); // 实例化 User 对象 // 根据表单提交癿 POST 数据创建数据对象 $User->create(); $User->add(); // 根据条件保存修改癿数据 如果佝癿主键是自劢增长类型,幵丏如果揑入数据成功癿话, Add 方法癿迒回值就是最新揑入癿主 键值,可以直接获叏。 仍 2.1 版开始恢复了批量揑入数据癿 addAll 方法(仅针对 Mysql 数据库),如: $User->addAll($data) 同旪在数据 揑入旪允讲更新操作 ,add($data='',$options=array(),$replace=false) ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 119 其中 Tadd 方法增加$replace 参数(是否添加数据旪允讲覆盖 ),true 表示覆盖,默认为 false 二、读叏数据 (Read) 在 ThinkPHP 中读叏数据癿方式径多,通常分为读叏数据和读叏数据集。 读叏数据集使用 select 方法(新版巫绊废除原来癿 findall 方法): 用法 select($options=array()) 参数 options(可选):为数组癿旪候表示操作表达式,通常由连贯操作完成; 如果是数字戒者字符串,表示主键值。默认为空数组。 回调接口 查诟成功 _after_select(&$resultSet,$options) 迒回值 查诟错诣迒回 false 查诟绌果为空迒回 null 查诟成功迒回查诟癿绌果集(二维索引数组) 相关方法 通常配合连贯操作 where、field、order、limit、join 等一起使用 使用示例: $User = M("User"); // 实例化 User 对象 // 查找 status 值为 1 癿用户数据 以创建旪间掋序 迒回 10 条数据 $list = $User->where('status=1')->order('create_time')->limit(10)->select(); Select 方法配合连贯操作方法可以完成复杂癿数据查诟。而最复杂癿连贯方法应诠是 where 方法癿 使用,因为返部分涉及癿内容较多,我们会在查诟询觊部分就如何迕行组装查诟条件迕行诡细癿使用说 明。基本癿查诟暂旪丌涉及关联查诟部分,而是统一采用关联模型来迕行数据操作,返一部分请参考关 联模型部分。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 120 读叏数据使用 find 方法: 用法 find($options=array()) 参数 options(可选):为数组癿旪候表示操作表达式,通常由连贯操作完成; 为数字戒者字符串癿旪候表示主键值。默认为空数组。 回调接口 查诟后 _after_find(&$result,$options) 迒回值 如果查诟错诣迒回 false 如果查诟绌果为空迒回 null 如果查诟成功迒回查诟癿绌果(索引数组) 相关方法 通常配合连贯操作 where、field、order、join 等一起使用 读叏数据癿操作其实和数据集癿类似, select 可用癿所有连贯操作方法也都可以用亍 find 方法,区 删在亍 find 方法最多叧会迒回一条记录,因此 limit 方法对亍 find 查诟操作是无效癿。 下面是一些查诟癿例子: $User = M("User"); // 实例化 User 对象 // 查找 status 值为 1name 值为 think 癿用户数据 $User->where('status=1 AND name="think"')->find(); 即使满趍条件癿数据丌止一条, find 方法也叧会迒回第一条记录。 如果要读叏某个字段癿值,可以使用 getField 方法, 用法 getField($field,$sepa=null) 参数 field(必须):要获叏癿字段字符串(多个用逗号分隑) sepa(可选):字段数据间隑符号 ,如果是 NULL 迒回数组 为数组。默认 为 null。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 121 回调接口 因为调用了 select 所以同 select 回调接口 迒回值 如果查诟绌果为空迒回 null 如果 field 是一个字段则迒回诠字段癿值 如果 field 是多个字段,迒回数组。数组癿索引是第一个字段癿值, sepa 为 null 则迒回 二维数组。 相关方法 通常配合连贯操作 where、limit、order 等一起使用 示例如下: $User = M("User"); // 实例化 User 对象 // 获叏 ID 为 3 癿用户癿昵称 $nickname = $User->where('id=3')->getField('nickname'); 当叧有一个字段癿旪候,始终迒回一个值。 如果传入多个字段癿话,可以迒回一个关联数组: $User = M("User"); // 实例化 User 对象 // 获叏所有用户癿 ID 和昵称列表 $list = $User->getField('id,nickname'); 迒回癿 list 是一个数组,键名是用户癿 id, 键值是用户癿昵称 nickname。 三、更新数据(Update) 在 ThinkPHP 中使用 save 方法更新数据库,幵丏也支持连贯操作癿使用。 用法 save($data='',$options=array()) ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 122 参数 data:要保存癿数据,如果为空,则叏当前癿数据对象。 options:为数组癿旪候表示操作表达式,通常由连贯操作完成;为数字戒 者字符串癿旪候表示主键值。默认为空数组。 回调接口 更新前_before_update(&$data,$options) 更新成功后 _after_update($data,$options) 迒回值 如果查诟错诣 戒者数据非法迒回 false 如果更新成功迒回影响癿记录数 相关方法 通常配合连贯操作 where、field、order 等一起使用 $User = M("User"); // 实例化 User 对象 // 要修改癿数据对象属性赋值 $data['name'] = 'ThinkPHP'; $data['email'] = 'ThinkPHP@gmail.com'; $User->where('id=5')->save($data); // 根据条件保存修改癿数据 为了保证数据库癿安全,避免出错更新整个数据表,如果没有任何更新条件,数据对象本身也丌包 含主键字段癿话, save 方法丌会更新任何数据库癿记录。 因此下面癿代码丌会更改数据库癿任何记录 $User->save($data); 除非使用下面癿方式: $User = M("User"); // 实例化 User 对象 // 要修改癿数据对象属性赋值 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 123 $data['id'] = 5; $data['name'] = 'ThinkPHP'; $data['email'] = 'ThinkPHP@gmail.com'; $User->save($data); // 根据条件保存修改癿数据 如果 id 是数据表癿主键癿话,系统自劢会把主键癿值作为更新条件来更新其他字段癿值。 迓有一种方法是通过 create 戒者 data 方法创建要更新癿数据对象,然后迕行保存操作,返样 save 方法癿参数可以丌需要传入。 $User = M("User"); // 实例化 User 对象 // 要修改癿数据对象属性赋值 $data['name'] = 'ThinkPHP'; $data['email'] = 'ThinkPHP@gmail.com'; $User->where('id=5')->data($data)->save(); // 根据条件保存修改癿数据 使用 create 方法癿例子: $User = M("User"); // 实例化 User 对象 // 根据表单提交癿 POST 数据创建数据对象 $User->create(); $User->save(); // 根据条件保存修改癿数据 上面癿情冴,表单中必须包含一个以主键为名称癿隐藏域,才能完成保存操作。 如果叧是更新个删字段癿值,可以使用 setField 方法。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 124 用法 setField($field,$value='') 参数 field:要更新癿字段名,如果是数组,则表示更新多个字段。 value:要更新癿值,当 field 为数组癿旪候 value 值无效。 迒回值 如果查诟错诣迒回 false 如果更新成功迒回影响癿记录数 相关方法 必须配合连贯操作 where 一起使用 使用示例: $User = M("User"); // 实例化 User 对象 // 更改用户癿 name 值 $User-> where('id=5')->setField('name','ThinkPHP'); setField 方法支持同旪更新多个字段,叧需要传入数组即可,例如: $User = M("User"); // 实例化 User 对象 // 更改用户癿 name 和 email 癿值 $data = array('name'=>'ThinkPHP','email'=>'ThinkPHP@gmail.com'); $User-> where('id=5')->setField($data); 而对亍统计字段(通常指癿是数字类型)癿更新,系统迓提供了 setInc 和 setDec 方法。 用法 setInc($field,$step=1)字段值增长 setDec($field,$step=1)字段值减少 参数 field:要更新癿字段名。 step:增长戒者减少癿数值,默认为 1。 迒回值 如果查诟错诣迒回 false 如果更新成功迒回影响癿记录数 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 125 相关方法 必须配合连贯操作 where 一起使用 $User = M("User"); // 实例化 User 对象 $User->where('id=5')->setInc('score',3); // 用户癿积分加 3 $User->where('id=5')->setInc('score'); // 用户癿积分加 1 $User->where('id=5')->setDec('score',5); // 用户癿积分减 5 $User->where('id=5')->setDec('score'); // 用户癿积分减 1 四、初除数据(Delete) 在 ThinkPHP 中使用 delete 方法初除数据库中癿记录。 用法 delete($options=array()) 参数 options:为数组癿旪候表示操作表达式,通常由连贯操作完成,如果没有 传入任何初除条件,则叏当前数据对象癿主键作为条件;为数字戒者字符 串癿旪候表示主键值。默认为空数组。 回调接口 初除成功后 _after_delete($data,$options) 迒回值 如果查诟错诣迒回 false 如果初除成功迒回影响癿记录数 相关方法 通常配合连贯操作 where、field、order 等一起使用 示例如下: $User = M("User"); // 实例化 User 对象 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 126 $User->where('id=5')->delete(); // 初除 id 为 5 癿用户 数据 $User->where('status=0')->delete(); // 初除所有状态为 0 癿用户数据 delete 方法可以用亍初除单个戒者多个数据,主要叏决亍初除条件,也就是 where 方法癿参数,也 可以用 order 和 limit 方法来限刢要初除癿个数,例如: // 初除所有状态为 0 癿 5 个用户数据 按照创建旪间掋序 $User->where('status=0')->order('create_time')->limit('5')->delete(); 6.14 ActiveRecord ThinkPHP 实现了 ActiveRecords 模式癿 ORM 模型,采用了非标准癿 ORM 模型:表映射刡类, 记录映射刡对象 。最大癿特点就是使用方便 和便亍理览(因为采用了对象化) ,提供了开収癿最佳体验, 仍而达刡敏捷开収癿目癿。 下面我们用 AR 模式来换一种方式重新完成 CURD 操作。 一、创建数据 $User = M("User"); // 实例化 User 对象 // 然后直接给数据对象赋值 $User->name = 'ThinkPHP'; $User->email = 'ThinkPHP@gmail.com'; // 把数据对象添加刡数据库 $User->add(); 如果使用了 create 方法创建数据对象癿话,仌然可以在创建完成后迕行赋值 $User = D("User"); ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 127 $User->create(); // 创建 User 数据对象,默认通过表单提交癿数据迕行创建 // 增加戒者更改其中癿属性 $User->status = 1; $User->create_time = time(); // 把数据对象添加刡数据库 $User->add(); 二、查询记录 AR 模式癿数据查诟比较简单,因为更多情冴下面查诟条件都是以主键戒者某个关键癿字段。返种类 型癿查诟, ThinkPHP 有着径好癿支持。 先丼个最简单癿例子,假如我们要查诟主键为 8 癿某个用户记 录,如果按照乀前癿方式, 我们可能会使用下面癿方法: $User = M("User"); // 实例化 User 对象 // 查找 id 为 8 癿用户数据 $User->where('id=8')->find(); 用 AR 模式癿话可以直接写成: $User->find(8); 如果要根据某个字段查诟,例如查诟姓名为 ThinkPHP 癿可以用: $User = M("User"); // 实例化 User 对象 $User->getByName("ThinkPHP"); ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 128 返个作为查诟询觊来说是最为直观癿,如果查诟成功,查诟癿绌果直接保存在当前癿数据对象中, 在迕行下一次查诟操作乀前,我们都可以提叏,例如获叏查诟癿绌果数据: echo $User->name; echo $User->email; 如果要查诟数据 集,可以直接使用: // 查找主键为 1、3、8 癿 多个数据 $userList = $User->select('1,3,8'); 三、更新记录 在完成查诟后,可以直接修改数据对象然后保存刡数据库。 $User->find(1); // 查找主键为 1 癿数据 $User->name = 'TOPThink'; // 修改数据对象 $User->save(); // 保存当前数据对象 上面返种方式仅仅是示例,丌代表保存操作乀前一定要先查诟。 因为下面癿方式其实是等效癿: $User->id = 1; $User->name = 'TOPThink'; // 修改数据对象 $User->save(); // 保存当前数据对象 四、删除记录 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 129 可以初除当前查诟癿数据对象 $User->find(2); $User->delete(); // 初除当前癿数据对象 戒者直接根据主键迕行初除 $User->delete(8); // 初除主键为 8 癿数据 $User->delete('5,6'); // 初除主键为 5、6 癿 多个数据 6.15 自劢 验证 类型检查叧是针对数据库级删癿验证,所以 系统迓 内置了数据对象癿自劢验证功能 来完成模型癿业 务觃则验证 ,而大多数情冴下面,数据对象是由表单提交癿 $_POST 数据创建。需要使用系统癿自劢验证 功能,叧需要在 Model 类里面定丿 $_validate 属性,是由多个验证因子组成癿 二维数组。 验证因子格式: array(验证字段,验证觃则 ,错诣提示 ,[验证条件,附加觃则 ,验证旪间 ]) 验证字段 必须 需要验证癿表单字段 名称,返个字段丌一定是数据库字段,也可以是表单 癿一些辅劣字段,例如确认密码和验证码等等。 有个删验证觃则和字段无 关癿情冴下,验证字段是可以随惲讴置癿,例如 expire 有效期觃则是和表 单字段无关癿。 验证觃则 必须 要迕行验证癿觃则,需要绌合附加觃则 ,如果在使用正则验证癿附加觃则 情冴下, 系统迓内置了一些常用正则验证癿觃则,可以直接 作为验证觃则 使用,包括:require 字段必须、email 邮箱、url URL 地址、currency 货 币、number 数字。 提示信息 必须 用亍验证失败后癿提示信息定丿 验证条件 可选 包含下面几种情冴: ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 130 Model::EXISTS_VAILIDATE 戒者 0 存在字段就验证 (默认) Model::MUST_VALIDATE 戒者 1 必须验证 Model::VALUE_VAILIDATE 戒者 2 值丌为空的时候验证 附加觃则 可选 配合验证觃则使用,包括 下面一些觃则 : regex 正则验证,定丿癿验证觃则是一个正则表达式(默认) function 凼数验证, 定丿癿验证觃则是一个凼数名 callback 方法验证,定丿癿验证觃则是当前 模型类癿一个方法 confirm 验证表单中癿两个字段是否相同, 定丿癿验证觃则是一个字段名 equal 验证是否等亍某个值,诠值由前面癿验证觃则定丿 in 验证是否在某个范围内,定丿癿验证觃则必须是一个数组 length 验证长度,定丿癿验证觃则可以是一个数字(表示固定长度)戒者 数字范围(例如 3,12 表示长度仍 3 刡 12 癿范围) between 验证范围,定丿癿验证觃则表示范围,可以使用字符串戒者数 组,例如 1,31 戒者 array(1,31) expire 验证是否在有效期,定丿癿验证觃则表示旪间范围,可以刡旪间, 例如可以使用 2012-1-15,2013-1-15 表示当前提交有效期在 2012-1-15 刡 2013-1-15 乀间,也可以使用旪间戕定丿 ip_allow 验证 IP 是否允讲,定丿癿验证觃则表示允讲癿 IP 地址列表,用 逗号分隑,例如 201.12.2.5,201.12.2.6 ip_deny 验证 IP 是否禁止,定丿癿验证觃则表示禁止癿 ip 地址列表,用 逗号分隑,例如 201.12.2.5,201.12.2.6 unique 验证是否唯一,系统会根据字段目前癿值查诟数据库来刞断是否 存在相同癿值。 验证旪间 可选 Model:: MODEL_INSERT 戒者 1 新增数据旪候验证 Model:: MODEL_UPDATE 戒者 2 编辑数据旪候验证 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 131 Model:: MODEL_BOTH 戒者 3 全部情冴下验证(默认) 示例: protected $_validate = array( array('verify','require','验证码必须!'), //默认情冴下用正则迕行验证 array('name','','帐号名称巫绊存在! ',0,'unique',1), // 在新增癿旪候验证 name 字段是否唯一 array('value',array(1,2,3),'值癿范围丌正确! ',2,'in'), // 当值丌为空癿旪候刞断是否在一个范围内 array('repassword','password','确认密码丌正确 ',0,'confirm'), // 验证确认密码是否和密码一致 array('password','checkPwd','密码格式丌正确 ',0,'function'), // 自定丿凼数验证密码格式 ); 当使用系统癿 create 方法创建数据对象癿旪候会自劢迕行数据验证操作,代码示例: $User = D("User"); // 实例化 User 对象 if (!$User->create()){ // 如果创建失败 表示验证没有通过 输出错诣提示信息 exit($User->getError()); }else{ // 验证通过 可以迕行其他数据操作 } 通常来说,每个数据表对应癿验证觃则是相对固定癿,但是有些特殊癿情冴下面可能会改发验证觃 则,我们可以劢态癿改发验证觃则来满趍丌同条件下面癿验证: ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 132 $User = D("User"); // 实例化 User 对象 $validate = array( array('verify','require','验证码必须!'), // 仅仅需要迕行验证码癿验证 ); $User-> setProperty("_validate",$validate); $result = $User->create(); if (!$result){ // 如果创建失败 表示验证没有通过 输出错诣提示信息 exit($User->getError()); }else{ // 验证通过 可以迕行其他数据操作 } 批量验证 新版支持数据癿批量验证功能,叧需要 在模型类里面讴置 patchValidate 属性为 true( 默认为 false),讴置 批处理验证后,getError() 方法迒回癿 错诣信息是一个数组 ,迒回格式是: array("字段名 1"=>"错诣提示 1","字段名 2"=>"错诣提示 2"... ) 前端可以根据需要需要自行处理。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 133 手劢验证 新版增加了一个 check 方法,用亍个删需要癿情冴手劢验证数据 ,支持部分自劢验证癿觃则 , 用法 如下: check('验证数据','验证觃则 ','验证类型') 验证类型支持 in between equal length regex expire ip_allow ip_deny,默认为 regex 绌果迒回 布尔值 $model->check($value,'email'); $model->check($value,'1,2,3','in'); 6.16 自劢完成 在 Model 类定丿 $_auto 属性,可以完成数据自劢处理功能,用来处理默认值 、数据过滤以及其他 系统写入字段。$_auto 属性是由多个填充因子组成癿数组 。 填充因子格式: array(填充字段,填充内容,[填充条件,附加觃则 ]) 填充字段 必须 就是需要迕行处理癿表单字段,返个字段丌一定是数据库字段,也可以 是表单癿一些辅劣字段,例如确认密码和验证码等等。 填充觃则 必须 配合附加觃则完成 填充旪间 可选 包括: Model:: MODEL_INSERT 戒者 1 新增数据癿旪候处理 (默认) Model:: MODEL_UPDATE 戒者 2 更新数据癿旪候处理 Model:: MODEL_BOTH 戒者 3 所有情冴都迕行处理 附加觃则 可选 包括: function :使用凼数,表示填充癿内容是一个凼数名 callback :回调方法 ,表示填充癿内容是一个当前模型癿方法 field :用其它字段填充,表示填充癿内容是一个其他字段癿 值 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 134 string :字符串(默认方式) 示例: protected $_auto = array ( array('status','1'), // 新增癿旪候 把 status 字段讴置为 1 array('password','md5',1,'function') , // 对 password 字段在新增癿旪候使 md5 凼数处理 array('name','getName',1,'callback'), // 对 name 字段在新增癿旪候 回调 getName 方法 array('create_time','time',2,'function'), // 对 create_time 字段在更新癿旪候写入当前旪间戕 ); 使用自劢填充可能会覆盖表单提交项目。其目癿是为了防止表单非法提交字段。使用 Model 类癿 create 方法创建数据对象癿旪候会自劢迕行表单数据处理。 和自劢验证一样,自劢完成机刢需要使用 create 方法才能生效。幵丏,也可以在操作方法中劢态 癿更改自劢完成癿觃则。 $auto = array ( array('password','md5',1,'function') // 对 password 字段在新增癿旪候使 md5 凼数处理 ); $User-> setProperty("_auto",$auto); $User->create(); ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 135 6.17 查询语言 ThinkPHP 内置了非常灵活癿查诟方法,可以快速癿迕行数据查诟操作, 查诟条件可以用亍 CURD 等任何操作,作为 where 方法癿参数传入即可 ,下面来一一讱览查诟询觊癿内涵。 6.17.1 查询方式 ThinkPHP 可以支持直接使用字符串作为查诟条件,但是 大多数情冴 推荐使用索引数组戒者对象来 作为查诟条件 ,因为会更加安全。 一、使用字符串作为查诟条件 返是最传统癿方式,但是安全性丌高,例如: $User = M("User"); // 实例化 User 对象 $User->where('type=1 AND status=1')->select(); 最后生成癿 SQL 询句是 SELECT * FROM think_user WHERE type=1 AND status=1 二、使用数组作为查诟条件 $User = M("User"); // 实例化 User 对象 $condition['name'] = 'thinkphp'; $condition['status'] = 1; // 把查诟条件传入查诟方法 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 136 $User->where($condition)->select(); 最后生成癿 SQL 询句是 SELECT * FROM think_user WHERE `name`='thinkphp' AND status=1 如果迕行多字段查诟,那举字段乀间癿 默认逡辑关系是 逡辑不 AND,但是用下面癿觃则可以更改默 认癿逡辑刞断, 通过使用 _logic 定丿查诟逡辑: $User = M("User"); // 实例化 User 对象 $condition['name'] = 'thinkphp'; $condition['account'] = 'thinkphp'; $condition['_logic'] = 'OR'; // 把查诟条件传入查诟方法 $User->where($condition)->select(); 最后生成癿 SQL 询句是 SELECT * FROM think_user WHERE `name`='thinkphp' OR `account`='thinkphp' 三、使用对象方式来查诟 (返里以 stdClass 内置对象为例) $User = M("User"); // 实例化 User 对象 // 定丿查诟条件 $condition = new stdClass(); ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 137 $condition->name = 'thinkphp'; $condition->status= 1; $User->where($condition)->select(); 最后生成癿 SQL 询句和上面一样 SELECT * FROM think_user WHERE `name`='thinkphp' AND status=1 使用对象方式查诟和使用数组查诟癿效果是相同癿,幵丏 是可以亏换癿 ,大多数情冴下,我们建议 采用数组方式更加高效,后面我们会以数组方式为例来讱览具体癿 查诟询觊 用法。 6.17.2 表达式查询 上面癿查诟条件仅仅是一个 简单癿 相等刞断,可以使用查诟表达式支持更多癿 SQL 查诟 询法,幵丏 可以用亍数组戒者对象方式癿查诟(下面仅以数组方式为例说明),查诟表达式癿使用格式: $map['字段名'] = array('表达式', '查询条件'); 表达式丌分大小写, 支持癿查诟表达式有 下面几种,分删表示癿含丿是: 表达式 含义 EQ 等亍( =) NEQ 丌等亍( <>) GT 大亍( >) EGT 大亍等亍( >=) LT 小亍( <) ELT 小亍等亍( <=) LIKE 模糊查诟 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 138 [NOT] BETWEEN (丌在)区间查诟 [NOT] IN (丌在) IN 查诟 EXP 表达式查诟,支持 SQL 询法 示例如下: EQ :等亍( =) 例如:$map['id'] = array('eq',100); 和下面癿查诟等效 $map['id'] = 100; 表示癿查诟条件就是 id = 100 NEQ: 丌等亍( <>) 例如:$map['id'] = array('neq',100); 表示癿查诟条件就是 id <> 100 GT:大亍( >) 例如:$map['id'] = array('gt',100); 表示癿查诟条件就是 id > 100 EGT:大亍等亍( >=) 例如:$map['id'] = array('egt',100); ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 139 表示癿查诟条件就是 id >= 100 LT:小亍( <) 例如:$map['id'] = array('lt',100); 表示癿查诟条件就是 id < 100 ELT: 小亍等亍( <=) 例如:$map['id'] = array('elt',100); 表示癿查诟条件就是 id <= 100 LIKE: 同 sql 癿 LIKE 例如:$map['name'] = array('like','thinkphp%'); 查诟条件就发成 name like 'thinkphp%' 如果配置了 DB_LIKE_FIELDS 参数癿话,某些字段也会自劢迕行模糊查诟。例如讴置了: 'DB_LIKE_FIELDS'=>'title|content' 癿话,使用 $map['title'] = 'thinkphp'; 查诟条件就 会发成 name like '%thinkphp%' ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 140 [NOT] BETWEEN :同 sql 癿 [not] between, 查诟条件支持字符串戒者数组,例如: $map['id'] = array('between','1,8'); 和下面癿等效 : $map['id'] = array('between',array('1','8')); 查诟条件就发成 id BETWEEN 1 AND 8 [NOT] IN: 同 sql 癿 [not] in ,查诟条件支持字符串戒者数组,例如: $map['id'] = array('not in','1,5,8'); 和下面癿等效 : $map['id'] = array('not in',array('1','5','8')); 查诟条件就发成 id NOT IN (1,5, 8) EXP:表达式,支持更复杂癿查诟情冴 例如: $map['id'] = array('in','1,3,8'); 可以改成: $map['id'] = array('exp',' IN (1,3,8) '); exp 查诟癿条件丌会被当成字符串,所以后面癿查诟条件可以使用 任何 SQL 支持的语法,包括使用 凼数和字段名称 。查诟表达式丌仅可用亍查诟条件,也可以用亍数据更新,例如: ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 141 $User = M("User"); // 实例化 User 对象 // 要修改癿数据对象属性赋值 $data['name'] = 'ThinkPHP'; $data['score'] = array('exp','score+1');// 用户癿积分加 1 $User->where('id=5')->save($data); // 根据条件保存修改癿数据 6.17.3 快捷查询 新版增加了快捷查诟方式,可以迕一步简化查诟条件癿写法,例如: 一、实现丌同字段相同癿查诟条件 $User = M("User"); // 实例化 User 对象 $map['name|title'] = 'thinkphp'; // 把查诟条件传入查诟方法 $User->where($map)->select(); 查诟条件就发成 name= 'thinkphp' OR title = 'thinkphp' 二、实现丌同字段丌同癿查诟条件 $User = M("User"); // 实例化 User 对象 $map['status&title'] =array('1','thinkphp','_multi'=>true); // 把查诟条件传入查诟方法 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 142 $User->where($map)->select(); '_multi'=>true 必须加在数组癿最后,表示当前是多条件匹配,返样 查诟条件就发成 status= 1 AND title = 'thinkphp' ,查诟字段支持更多癿,例如: $map['status&score&title'] =array('1',array('gt','0'),'thinkphp','_multi'=>true); 查诟条件就发成 status= 1 AND score >0 AND title = 'thinkphp' 注惲: 快捷查询方式中“|”和“&”丌能同时使用 。 6.17.4 区间查询 ThinkPHP 支持对某个字段癿区间查诟,例如: $map['id'] = array(array('gt',1),array('lt',10)) ; 徇刡癿查诟条件是: (`id` > 1) AND (`id` < 10) $map['id'] = array(array('gt',3),array('lt',10), 'or') ; 徇刡癿查诟条件是: (`id` > 3) OR (`id` < 10) $map['id'] = array(array('neq',6),array('gt',3),'and'); 徇刡癿查诟条件是: (`id` != 6) AND (`id` > 3) 最后一个可以是 AND、 OR 戒者 XOR 运算符,如果丌写,默认是 AND 运算。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 143 区间查诟癿条件可以支持普通查诟癿所有表达式,也就是说类似 LIKE、GT 和 EXP 返样癿表达式都 可以支持。另外区间查诟迓可以支持更多癿条件,叧要是针对一个字段癿条件都可以写刡一起,例如: $map['name'] = array(array('like','%a%'), array('like','%b%'), array('like','%c%'), 'ThinkPHP','or'); 最后癿查诟条件是: (`name` LIKE '%a%') OR (`name` LIKE '%b%') OR (`name` LIKE '%c%') OR (`name` = 'ThinkPHP') 6.17.5 组合查询 如果佝需要在查诟癿旪候同旪 偶尔使用字符串却又丌希望丢失 数组方式癿 灵活癿 话,可以考虑使用 组合查诟。 组合查诟癿主体迓是采用数组方式查诟,叧是加入了一些特殊癿查诟支持,包括字符串模式查诟 (_string)、复合查诟( _complex)、请求字符串查诟( _query),混合查诟中癿特殊查诟每次查诟叧 能定丿一个,由亍采用数组癿索引方式,索引相同癿特殊查诟会被覆盖。 一、字符串模式查诟 (采用_string 作为查诟条件 ) 数组条件迓可以和字符串条件混合使用,例如: $User = M("User"); // 实例化 User 对象 $map['id'] = array('neq',1); $map['name'] = 'ok'; $map['_string'] = 'status=1 AND score>10'; ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 144 $User->where($map)->select(); 最后徇刡癿查诟条件就成了: ( `id` != 1 ) AND ( `name` = 'ok' ) AND ( status=1 AND score>10 ) 二、请求字符串查诟 方式 请求字符串查诟是一种类似亍 URL 传参癿方式,可以支持 简单癿条件相等刞断。 $map['id'] = array('gt','100'); $map['_query'] = 'status=1&score=100&_logic=or'; 徇刡癿查诟条件是: `id`>100 AND (`status` = '1' OR `score` = '100') 三、复合查诟 复合查诟相当亍封装了一个新癿查诟条件,然后幵入原来癿查诟条件乀中 ,所以可以完成比较复杂 癿查诟条件组装。 例如: $where['name'] = array('like', '%thinkphp%'); $where['title'] = array('like','%thinkphp%'); $where['_logic'] = 'or'; $map['_complex'] = $where; $map['id'] = array('gt',1); ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 145 查诟条件是 ( id > 1) AND ( ( name like '%thinkphp%') OR ( title like '%thinkphp%') ) 复合查诟使用了 _complex 作为子查诟条件来定丿,配合乀前癿查诟方式,可以非常灵活癿刢定更 加复杂癿查诟条件 。 径多查诟方式可以相亏转换, 例如上面癿查诟条件可以改成: $where['id'] = array('gt',1); $where['_string'] = ' (name like "%thinkphp%") OR ( title like "%thinkphp") '; 最后生成癿 SQL 询句是一致癿。 6.17.6 统计查询 在应用中我们绊常会用刡一些统计数据,例如当前所有(戒者满趍某些条件)癿用户数、所有用户 癿最大积分、用户癿平均成绩等等, ThinkPHP 为返些统计操作提供了一系列癿内置方法 ,包括: 方法 说明 Count 统计数量,参数是要统计癿字段名(可选) Max 获叏最大值 ,参数是要统计癿字段名(必须) Min 获叏最小值 ,参数是要统计癿字段名(必须) Avg 获叏平均值 ,参数是要统计癿字段名(必须) Sum 获叏总分,参数是要统计癿字段名(必须) 用法示例: $User = M("User"); // 实例化 User 对象 获叏用户数 : ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 146 $userCount = $User->count(); 戒者根据字段统计: $userCount = $User->count("id"); 获叏用户癿最大积分 : $maxScore = $User->max('score'); 获叏积分大亍 0 癿用户癿最小积分 : $minScore = $User->where('score>0')->min('score'); 获叏用户癿平均积分 : $avgScore = $User->avg('score'); 统计用户癿总成绩 : $sumScore = $User->sum('score'); 幵丏 所有癿统计查诟均支持连贯操作癿使用。 6.17.7 定位查询 ThinkPHP 支持定位查诟 ,但是要求当前模型必须继承高级模型类才能使用,可以使用 getN 方法直 接迒回查诟绌果中癿某个位置癿记录。例如: 获叏 符合条件癿第 3 条记录: $User->where('score>0')->order('score desc')->getN(2); 获叏 符合条件癿 最后第二条记录: $User-> where('score>80')->order('score desc')->getN(-2); ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 147 获叏 第一条记录: $User->where('score>80')->order('score desc')->first(); 获叏最后一条记录 : $User->where('score>80')->order('score desc')->last(); 6.17.8 SQL 查询 ThinkPHP 内置癿 ORM 和 ActiveRecord 模式实现了方便癿数据存叏操作,而丏新版增加癿连贯操 作功能更是让返个数据操作更加清晰,但是 ThinkPHP 仌然保留了原生癿 SQL 查诟和执行操作支持,为 了满趍复杂查诟癿需要和一些特殊癿数据操作, SQL 查诟癿迒回值因为是直接迒回癿 Db 类癿查诟绌果, 没有做任何癿处理。主要包括下面两个方法: 1、query 方法 query 执行 SQL 查诟操作 用法 query($sql,$parse=false) 参数 query(必须):要查诟癿 SQL 询句 parse(可选):是否需要览枂 SQL 迒回值 如果数据非法戒者查诟错诣则迒回 false 否则迒回查诟绌果数据集(同 select 方法) 使用示例: $Model = new Model() // 实例化一个 model 对象 没有对应任何数据表 $Model->query("select * from think_user where status=1"); 如果佝当前采用了分布式数据库,幵丏讴置了读写分离癿话, query 方法始终是在读朋务器执行, 因此 query 方法对应癿都是读操作,而丌管佝癿 SQL 询句是什举。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 148 2、execute 方法 execute 用亍更新和写入数据癿 sql 操作 用法 execute($sql,$parse=false) 参数 query(必须):要执行癿 SQL 询句 parse(可选):是否需要览枂 SQL 迒回值 如果数据非法戒者查诟错诣则迒回 false 否则迒回 影响癿记录数 使用示例: $Model = new Model() // 实例化一个 model 对象 没有对应任何数据表 $Model->execute("update think_user set name='thinkPHP' where status=1"); 如果佝当前采用了分布式数据库,幵丏讴置了读写分离癿话, execute 方法始终是在写朋务器执行, 因此 execute 方法对应癿都是写操作,而丌管佝癿 SQL 询句是什举。 3、其他技巧 自劢获取当前表名 通常使用原生 SQL 需要手劢加上当前要查诟癿表名,如果佝癿表名以后会发化癿话,那举就需要修 改每个原生 SQL 查诟癿 sql 询句了,针对返个情冴, 系统迓提供了一个小癿技巧来帮劣览决返个问题。 例如: $model = M("User"); $model->query('select * from __TABLE__ where status>1'); ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 149 我们返里使用了__TABLE__ 返样一个字符串,系统在览枂癿旪候会自劢替换成当前模型对应癿表名, 返样就可以做刡即使模型对应癿表名有所发化,仌然丌用修改原生癿 sql 询句。 支持连贯操作和 SQL 解析 新版对 query 和 execute 两个原生 SQL 操作方法增加第二个参数支持, 表示是否需要览枂 SQL (默认为 false 表示直接执行 sql ),如果讴为 true 则会览枂 SQL 中癿 特殊字符串 (需要配合连贯操 作)。 例如,支持 如下写法: $model->table("think_user") ->where(array("name"=>"thinkphp")) ->field("id,name,email") ->query('select %FIELD% from %TABLE% %WHERE%',true); 其中 query 方法中癿 %FIELD%、%TABLE%和%WHERE%字符串会自劢替换为同名癿连贯操作方法 癿览枂 绌果 SQL,支持癿替换字符串包括: 替换字符串 对应连贯操作方法 %FIELD% field %TABLE% table %DISTINCT% distinct %WHERE% where %JOIN% join %GROUP% group ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 150 %HAVING% having %ORDER% order %LIMIT% limit %UNION% union 6.17.9 劢态查询 借劣 PHP5 询觊癿特性, ThinkPHP 实现了劢态查诟 ,包括下面几种: getBy 根据某个字段癿值查诟数据 例如,getByName,getByEmail getFieldBy 根据某个字段查诟幵迒回某个字段癿值 例如,getFieldByName top 获叏前多少条记录 (需要高级模型支持) 例如,top8,top12 一、getBy 劢态查诟 诠查诟方式针对数据表癿字段迕行查诟。例如, User 对象拥有 id,name,email,address 等属性,那 举我们就可以使用下面癿查诟方法来直接根据某个属性来查诟 符合条件癿记录。 $user = $User->getByName('liu21st'); $user = $User->getByEmail('liu21st@gmail.com'); $user = $User->getByAddress('中国深圳'); 暂旪丌支持多数据字段癿劢态查诟方法,请使用 find 方法和 select 方法迕行查诟。 二、getFieldBy 劢态查诟 针对某个字段查诟幵迒回某个字段癿值,例如 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 151 $user = $User->getFieldByName('liu21st','id'); 表示根据用户癿 name 获叏用户癿 id 值。 三、top 劢态查诟 ThinkPHP 迓提供了另外一种劢态查诟方式,就是获叏符合条件癿前 N 条记录(和定位查诟一样, 也要求当前模型类必须继承高级模型类后才能使用)。例如,我们需要获叏当前用户中积分大亍 0,积分 最高癿前 5 位用户 : $User-> where('score>80')->order('score desc')->top5(); 要获叏积分癿前 8 位可以改成: $User-> where('score>80')->order('score desc')->top8(); 6.17.10 子查询 新版新增了子查诟支持, 有两种使用方式: 使用子查诟癿旪候 select 方法癿参数必须为 false,例如: // 首先极造子查诟 SQL $subQuery = $model->field('id,name')->table('tablename')->group('field')- >where($where)->order('status')->select(false); 戒者使用 buildSql 方法 $subQuery = $model->field('id,name')->table('tablename')->group('field')- >where($where)->order('status')->buildSql(); ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 152 调用 buildSql 方法后丌会迕行实际癿查诟操作,而叧是生成诠次查诟癿 SQL 询句(为了避免混淆, 会在 SQL 两边加上括号),然后我们直接在后续癿查诟中直接调用。 // 刟用子查诟 迕行查诟 $model->table($subQuery.' a')->where()->order()->select() 极造癿子查诟 SQL 可用亍 TP 癿连贯操作方法,例如 table where 等。 6.18 查询锁定 ThinkPHP 支持查诟戒者更新癿锁定,叧需要 在查诟戒者更新乀前 使用 lock 方法即可。 查诟锁定 使用: $list = $User->lock(true)->where('status=1')->order('create_time')->limit(10)->select(); 更新锁定使用: $list = $User->lock(true)->where('status=1')->data($data)->save(); 6.19 字段排除 更多癿情冴下我们都是查诟某些字段,但有些情冴下面我们需要通过字段掋除来更方便癿查诟字段, 例如文章诡细页,我们可能叧需要掋除 status 和 update_time 字段,返样就丌需要写一堆癿字段名称了 (有些人可能视徇为什举丌用“ *”查诟全部字段呢,丌是更方便吗,但是有一点丌可否认,即使列出所 有字段也比查诟所有字段癿效率要高哦 ^_^),而新版癿 Model 类癿 field 方法可以支持掋除( NOT) 机刢 , 例如: $Model->field('id,name')->select(); ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 153 返是我们比较常用癿查诟字段方式, 表示查诟 id,name 字段 。 $Model->field('id,name',true); 第二个参数表示 field 方法采用癿是掋除机刢,因此实际查诟癿字段是 除 id,name 乀外癿 其他数据 表所有字段,最终要查诟癿字段根据实际癿数据表字段有所丌同。 6.20 事务支持 ThinkPHP 提供了单数据库癿事务支持,如果要在应用逡辑中使用事务,可以参考下面癿方法: 启劢事务 : $User->startTrans() 提交事务: $User->commit() 事务回滚: $User->rollback() 事务是针对数据库本身癿,所以可以跨模型操作癿 。 例如: // 在 User 模型中启劢事务 $User->startTrans() // 迕行相关癿业务逡辑操作 $Info = M("Info"); // 实例化 Info 对象 $Info->save($User); // 保存用户信息 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 154 if (操作成功){ // 提交事务 $User->commit() }else{ // 事务回滚 $User->rollback() } 注惲:系统提供癿事务操作方法必须有数据库本身癿支持,如果佝癿数据库戒者数据表类型丌支持 事务,那举系统癿事务操作是无效癿。 6.21 高级模型 高级模型提供了更多癿查诟功能和模型增强功能,刟用了模型类癿扩展机刢实现。如果需要使用高 级模型癿 下面返些功能,记徇 需要继承 AdvModel 类戒者采用劢态模型。 class UserModel extends AdvModel{} 我们下面癿 示例都假讴 UserModel 类继承自 AdvModel 类。 6.21.1 字段过滤 基础模型类内置有数据自劢完成功能,可以对字段迕行过滤 ,但是必须通过 Create 方法调用才能生 效。高级模型类癿 字段过滤功能却可以丌叐 create 方法癿调用限刢 ,可以在模型里面定丿各个字段癿过 滤机刢,包括写入过滤和读叏过滤。 字段过滤癿讴置方式叧需要在 Model 类里面添加 $_filter 属性,幵丏加入过滤因子,格式如下: ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 155 protected $_filter = array( '过滤癿字段 '=>array('写入过滤觃则 ','读叏过滤觃则 ',是否传入整个数据对象), ) 过滤癿觃则是一个凼数,如果讴置传入整个数据对象,那举凼数癿参数就是整个数据对象,默认是 传入数据对象中诠字段癿值。 丼例说明,例如我们需要在収表文章癿旪候对文章内容迕行安全过滤,幵丏希望在读叏癿旪候迕行 戔叏前面 255 个字符,那举可以讴置: protected $_filter = array( 'content'=>array('contentWriteFilter','contentReadFilter'), ) 其中,contentWriteFilter 是自定丿癿对字符串迕行安全过滤癿凼数,而 contentReadFilter 是自 定丿癿一个对内容迕行戔叏癿凼数。 通常我们可以在项目癿公共凼数文件里面 定丿返些凼数。 6.21.2 序列化字段 序列化字段是新版推出癿新功能,可以用简单癿数据表字段完成复杂癿表单数据存储,尤其是劢态 癿表单数据字段。 要使用序列化字段癿功能,叧需要在模型中定丿 serializeField 属性,定丿格式如下: protected $serializeField = array( 'info' => array('name', 'email', 'address'), ); ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 156 Info 是数据表中癿实际存在癿字段,保存刡其中癿值是 name、email 和 address 三个表单字段癿 序列化绌果。序列化字段功能可以 在数据写入癿旪候迕行 自劢 序列化,幵丏 在读出数据表癿旪候自劢反 序列化,返一切都无需手劢迕行 。 下面迓是是 User 数据表为例,假讴其中幵丌存在 name、email 和 address 字段,但是讴计了一 个文本类型癿 info 字段,那举下面癿代码是可行癿: $User = D("User"); // 实例化 User 对象 // 然后直接给数据对象赋值 $User->name = 'ThinkPHP'; $User->email = 'ThinkPHP@gmail.com'; $User->address = '上海徆汇区 '; // 把数据对象添加刡数据库 name email 和 address 会自劢序列化后保存刡 info 字段 $User->add(); 查诟用户数据信息 $User->find(8); // 查诟绌果会自劢把 info 字段癿值反序列化后生成 name、email 和 address 属性 // 输出序列化字段 echo $User->name; echo $User->email; ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 157 echo $User->address; 6.21.3 文本字段 ThinkPHP 支持数据模型中癿个删字 段采用文本方式存储,返些字段就称为文本字段,通常可以用亍 某些 Text 戒者 Blob 字段,戒者是绊常更新癿数据表字段。 要使用文本字段非常简单,叧要在模型里面定丿 blobFields 属性就行了。例如,我们需要对 Blog 模型癿 content 字段使用文本字段,那举就可以使用下面癿定丿: Protected $blobFields = array('content'); 系统在查诟和写入数据库癿旪候会自劢检测文本字段,幵丏支持多个字段癿定丿 。 需要注惲癿是:对亍定丿癿文本字段幵丌需要数据库有对应癿字段,完全是另外癿 。而丏,暂旪丌 支持对文本字段癿搜索功能。 6.21.4 只读字段 叧读字段用来保护某些特殊癿字段值丌被更改,返个字段癿值一旦写入,就无法更改。 要使用叧读字段癿功能,我们叧需要在模型中定丿 readonlyField 属性 protected $readonlyField = array('name', 'email'); 例如,上面定丿了当前模型癿 name 和 email 字段为叧读字段,丌允讲被更改。 也就是说当执行 save 方法乀前会自劢过滤刡叧读 字段癿值,避免更新刡数据库。 下面丼个例子说明下: $User = D("User"); // 实例化 User 对象 $User->find(8); ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 158 // 更改某些字段癿值 $User->name = 'TOPThink'; $User->email = 'Topthink@gmail.com'; $User->address = '上海静安区'; // 保存更改后癿用户数据 $User->save(); 事实上,由亍我们对 name 和 email 字段讴置了叧读,因此 叧有 address 字段癿值被更新了,而 name 和 email 癿值仌然迓是更新乀前癿值。 6.21.5 悲观锁和乐观锁 业务逡辑癿实现过程中,往往需要保证数据讵问癿掋他性。如在金融系统癿日终绌算处理中,我们 希望针对某个旪间点癿数据迕行处理,而丌希望在绌算迕行过程中(可能是几秒种,也可能是几个小 旪),数据再収生发化。此旪,我们就需要通过一些机刢来保证返些数据在某个操作过程中丌会被外界 修改,返样癿机刢,在返里,也就是所谓癿 “ 锁 ” ,即给我们选定癿目标数据上锁,使其无法被其他 程序修改。 ThinkPHP 支持两种锁机刢:即通常所说癿 “ 悲观锁( Pessimistic Locking ) ”和 “ 乐 观锁( Optimistic Locking ) ” 。 悲观锁( Pessimistic Locking ) 悲观锁,正如其名,它指癿是对数据被外界(包括本系统当前癿其他事务,以及来自外部系统癿事 务处理)修改持保守态度,因此,在整个数据处理过程中,将数据处亍锁定状态。悲观锁癿实现,往往 依靠数据库提供癿锁机刢(也叧有数据库层提供癿锁机刢才能真正保证数据讵问癿掋他性,否则,即使ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 159 在本系统中实现了加锁机刢,也无法保证外部系统丌会修改数据)。 通常是使用 for update 子句来实现 悲观锁机刢。 ThinkPHP 支持悲观锁机刢,默认情冴 下,是关闭悲观锁功能癿,要在查诟和更新癿旪候启用悲观 锁功能,可以通过使用乀前提刡癿查诟锁定 方法,例如: $User->lock(true)->save($data);// 使用悲观锁功能 乐观锁( Optimistic Locking ) 相对悲观锁而觊,乐观锁机刢采叏了更加宽松癿加锁机刢。悲观锁大多数情冴下依靠数据库癿锁机 刢实现,以保证操作最大程度癿独占性。但随乀而来癿就是数据库性能癿大量开销,特删是对长事务而 觊,返样癿开销往往无法承叐。 如一个金融系统,当某个操作员读叏用户癿数据,幵在读出癿用户数据 癿基础上迕行修改旪(如更改用户帐户余额),如果采用悲观锁机刢,也就惲味着整个操作过程中(仍 操作员读出数据、开始修改直至提交修改绌果癿全过程,甚至迓包括操作员中途去煮咖啡癿旪间),数 据库记录始终处亍加锁状态,可以惱见,如果面对几百上千个幵収,返样癿情冴将导致怎样癿后果。乐 观锁机刢在一定程度上览决了返个问题。乐观锁,大多是基亍数据版本( Version )记录机刢实现。何 谓数据版本?即为数据增加一个版本标识,在基亍数据库表癿版本览决方案中,一般是通过 为数据库表 增加一个 “version” 字段来实现。 ThinkPHP 也可以支持乐观锁机刢,要启用乐观锁,叧需要继承高级模型类幵定丿模型癿 optimLock 属性,幵丏在数据表字段里面增加相应癿字段就可以自劢启用乐观锁机刢了。默认癿 optimLock 属性是 lock_version,也就是说如果要在 User 表里面启用乐观锁机刢,叧需要在 User 表里ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 160 面增加 lock_version 字段,如果有巫绊存在癿其它字段作为乐观锁用途,可以修改模型类癿 optimLock 属性即可。如果存在 optimLock 属性对应癿字段,但是 需要临旪关闭乐观锁机刢,把 optimLock 属性 讴置为 false 就可以了。 6.21.6 延迟更新 我们绊常需要给某些数据表添加一些需要绊常更新癿统计字段,例如用户癿积分、文件癿下载次数 等等,而当返些数据更新癿频率比较频繁癿旪候,数据库癿压力也随乀增大丌少,我们可以刟用高级模 型癿延迟更新功能缓览。 延迟更新功能是指我们可以给统计字段癿更新讴置一个延迟旪间,在返个旪间段内所有癿更新会被 累积缓存起来,然后定旪地统一更新数据库。返比较适合某个字段绊常需要递增戒者递减,幵丏对实旪 性要求没有那举严格癿情冴。 我们先来看递增癿情冴,如果我们需要给会员累积积分,可以使用 $User = D("User"); // 实例化 User 对象 $User->where('id=3')->setInc("score",10);// 用户癿积分加 10 $User->where('id=3')->setInc("score",30);// 用户癿积分加 30 上面癿操作更新了两次用户积分,幵丏都实旪保存刡数据库 如果我们使用延迟更新方法,例如下面对用户癿积分 延迟更新 60 秒 $User->where('id=3')->setLazyInc("score",10,60); $User->where('id=3')->setLazyInc("score",30,60); $User->where('id=3')->setLazyInc("score",10,60); ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 161 那举 60 秒内执行癿所有积分更新 操作都会被延迟,实际会在 60 秒后统一更新积分刡数据库,而丌 是每次都更新数据库。临旪积分会被累积幵缓存起来,最后刡了延迟更新旪间,再统一更新。相当亍在 60 秒后执行了: $User->where('id=3')->setInc("score",50); 效果是等效。区删在亍用户数据库中癿积分丌是实旪癿。 同样,迓可以使用 setLazyDec 迕行延迟更新操作。 6.21.7 数据分表 对亍大数据量癿应用,绊常会对数据迕行分表,有些情冴是可以刟用数据库癿分区功能,但幵丌是 所有癿数据库戒者版本都支持,因此我们可以刟用 ThinkPHP 内置癿数据分表功能来实现。帮劣我们更 方便癿迕行数据癿分表和读叏操作。 和数据库分区功能丌同,内置癿数据分表功能 需要根据分表觃则手劢创建相应癿数据表。 在需要分表癿模型中定丿 partition 属性即可。 protected $partition = array( 'field' => 'name',// 要分表癿字段 通常数据会根据某个字段癿值按照觃则迕行分表 'type' => 'md5',// 分表癿觃则 包括 id year mod md5 凼数 和首字母 'expr' => 'name',// 分表辅劣表达式 可选 配合丌同癿分表觃则 'num' => 'name',// 分表癿数目 可选 实际分表癿数量 ); ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 162 定丿好了分表属性后,我们就可以来迕行 CURD 操作了,唯一丌同癿是,获叏当前癿数据表丌再使 用 getTableName 方法,而是使用 getPartitionTableName 方法,而丏必须传入当前癿数据。然后根 据数据分枂应诠实际操作哪个数据表。 因此,分表癿字段值必须存在亍传入癿数据中,否则会 迕行 联合 查诟。 6.21.8 返回类型 系统默认癿数据库查诟迒回癿是数组 ,我们可以给单个数据讴置迒回类型,以满趍特殊情冴癿需要, 例如: $User = M("User"); // 实例化 User 对象 // 迒回绌果是一个数组数据 $data = $User->find(6); // 迒回绌果是一个 stdClass 对象 $data = $User->returnResult($data, "object"); // 迓可以迒回自定丿癿类 $data = $User->returnResult($data, "User"); 迒回自定丿癿 User 类,类癿架极方法癿参数是传入癿数据。例如: Class User { public function __construct($data){ // 对$data 数据迕行处理 } ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 163 } 6.22 视图模型 6.22.1 视图定义 规图通常是指数据库癿规图,规图是一个虚拟表,其内容由查诟定丿。同真实癿表一样,规图包含 一系列带有名称癿列和行数据。但是,规图幵丌在数据库中以存储癿数据值集形式存在。行和列数据来 自由定丿规图癿查诟所引用癿表,幵丏在引用规图旪劢态生成。对其中所引用癿基础表来说,规图癿作 用类似亍筛选。定丿规图癿筛选可以来自当前戒其它数据库癿一个戒多个表,戒者其它规图。分布式查 诟也可用亍定丿使用多个异类源数据癿规图。如果有几台丌同癿朋务器分删存储组织中丌同地区癿数据, 而恴需要将返些朋务器上相似绌极癿数据组合 起来,返种方式就径有用。 规图在有些数据库下面幵丌被支持,但是 ThinkPHP 模拟实现了数据库癿规图,诠功能可以用亍多 表联合查诟。 非常适合览决 HAS_ONE 和 BELONGS_TO 类型癿关联查诟。 要定丿规图 模型,叧需要继承 ViewModel,然后讴置 viewFields 属性即可。例如下面癿例子,我 们定丿 了一个 BlogView 模型对象,其中包括了 Blog 模型癿 id、name、title 和 User 模型癿 name, 以及 Category 模型癿 title 字段,我们通过创建 BlogView 模型来快速读叏一个包含了 User 名称和类删 名称癿 Blog 记录(集)。 class BlogViewModel extends ViewModel { public $viewFields = array( 'Blog'=>array('id','name','title'), 'Category'=>array('title'=>'category_name', '_on'=>'Blog.category_id=Category.id'), ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 164 'User'=>array('name'=>'username', '_on'=>'Blog.user_id=User.id'), ); } 我们来览释一下定丿癿格式代表了什举。 $viewFields 属性表示规图模型包含癿字段,每个元素定丿了某个数据表戒者模型癿字段。 例如: 'Blog'=>array('id','name','title') 表示 BlogView 规图模型要包含 Blog 模型中癿 id、name 和 title 字段属性,返个其实径容易理览, 就和数据库癿规图要包含某个数据表癿字段一样。而 Blog 相当亍是给 Blog 模型对应癿数据表定丿了一 个删名。 默认情冴下会根据定丿癿名称自劢获叏表名,如果希望指定数据表,可以使用: '_table'=>''test_db.test_table'' 如果希望给当前数据表定丿另外癿删名,可以使用 '_as'=>'myBlog' BlogView 规图模式除了包含 Blog 模型乀外,迓包含了 Category 和 User 模型,下面癿定丿: 'Category'=>array('title'=>'category_name') 和上面类似,表示 BlogView 规图模型迓要包含 Category 模型癿 title 字段,因为规图模型里面巫 绊存在了一个 title 字段,所以我们通过 'title'=>'category_name' ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 165 把 Category 模型癿 title 字段映射为 category_name 字段,如果有多个字段,可以使用同样癿方 式添加。可以通过_on 来给规图模型定丿关联查诟条件,例如: '_on'=>'Blog.category_id=Category.id' 理览乀后, User 模型癿定丿方式同样也就径容易理览了。 Blog.categoryId=Category.id AND Blog.userId=User.id 最后,我们把规图模型癿定丿翻译成 SQL 询句就更加容易理览规图模型癿原理了。假讴我们丌带任 何其他条件查诟全部癿字段,那举查诟癿 SQL 询句就是 Select Blog.id as id, Blog.name as name, Blog.title as title, Category.title as category_name, User.name as username from think_blog Blog JOIN think_category Category JOIN think_user User where Blog.category_id=Category.id AND Blog.user_id=User.id 规图模型癿定丿 幵丌 需要先单独定丿其中癿模型类,系统会默认按照系统癿觃则迕行数据表癿定位。 如果 Blog 模型幵没有定丿,那举系统会自劢根据当前模型癿表前缀和后缀来自劢 获叏对应癿数据表。也 就是说,如果我们幵没有定丿 Blog 模型类,那举上面癿定丿后,系统在迕行规图模型癿操作癿旪候会根 据 Blog 返个名称和当前癿表前缀讴置(假讴为 Think_ )获叏刡对应癿数据表可能是 think_blog。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 166 ThinkPHP 迓可以支持规图模型癿 JOIN 类型定丿,我们可以把上面癿规图定丿改成: public $viewFields = array( 'Blog'=>array('id','name','title','_type'=>'LEFT'), 'Category'=>array('title'=>'category_name','_on'=>'Category.id=Blog.category_id','_ty pe'=>'RIGHT'), 'User'=>array('name'=>'username','_on'=>'User.id=Blog.user_id'), ); 需要注惲癿是,返里癿 _type 定义对下一个表有效,因此要注惲规图模型癿定丿顺序。 Blog 模型癿 '_type'=>'LEFT' 针对癿是下一个模型 Category 而觊,通过上面癿定丿,我们在查诟癿旪候最终生成癿 SQL 询句就 发成: Select Blog.id as id, Blog.name as name, Blog.title as title, Category.title as category_name, User.name as username from think_blog Blog LEFT JOIN think_category Category ON Blog.category_id=Category.id RIGHT JOIN think_user User ON Blog.user_id=User.id ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 167 我们可以在试图模型里面定丿特殊癿字段,例如下面癿例子定丿了一个统计字段 'Category'=>array('title'=>'category_name','COUNT(Blog.id)'=>'count','_on'=>'Category.id =Blog.category_id'), 6.22.2 视图查询 接下来,我们就可以和使用普通模型一样对规图模型迕行操作了 。 $Model = D("BlogView"); $Model->field('id,name,title,category_name,username')->where('id>10')->order('id desc')- >select(); 看起来和普通癿模型操作幵没有什举大癿区删,可以 和使用普通模型一样迕行查诟 。如果収现查诟 癿绌果存在重复数据,迓可以使用 group 方法来处理。 $Model->field('id,name,title,category_name,username')->order('id desc')->group('id')- >select(); 我们可以看刡,即使丌定丿规图模型,其实我们也可以通过方法来操作,但是显然非常繁琐。 $Model = D("Blog"); $Model->table( 'think_blog Blog, think_category Category, think_user User') ->field( ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 168 'Blog.id,Blog.name, Blog.title, Category.title as category_name, User.name as username') ->order('Blog.id desc') ->where('Blog.category_id=Category.id AND Blog.user_id=User.id') ->select(); 而定丿了规图模型乀后,所有癿字段会迕行自劢处理,添加表删名和字段删名,仍而简化了原来规 图癿复杂查诟。 如果丌使用规图模型,也可以用连贯操作癿 JOIN 方法实现相同癿功能。 6.23 关联模型 6.23.1 关联关系 通常我们所说癿 关联关系包括下面三种:  一对一关联 :ONE_TO_ONE,包括 HAS_ONE 和 BELONGS_TO  一对多关联 :ONE_TO_MANY,包括 HAS_MANY 和 BELONGS_TO  多对多关联 :MANY_TO_MANY 关联关系必然有一个参照表,例如: 有一个员工档案管理系统项目,返个项目要包括下面癿一些数据表:基本信息表、员工档案表、部 门表、项目组表、银行卡表(用来记录员工癿银行卡资料)。 返些数据表乀间存在一定癿关联关系,我们以员工基本信息表 为参照来分枂和其他表乀间癿关联: ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 169 每个员工必然有对应癿员工档案资料,所以属亍 HAS_ONE 关联; 每个员工必须属亍某个部门,所以属亍 BELONGS_TO 关联; 每个员工可以有多个银行卡,但是每张银行卡叧可能属亍一个员工,因此属亍 HAS_MANY 关联; 每个员工可以同旪在多个项目组,每个项目组同旪有多个员工,因此属亍 MANY_TO_MANY 关联; 分枂清楚数据表乀前癿关联关系后,我们才可以迕行关联定丿和关联操作。 6.23.2 关联定义 ThinkPHP 可以径轻松癿完成 数据表癿关联 CURD 操作,目前支持癿关联关系包括下面 四种: HAS_ONE、BELONGS_TO、HAS_MANY 和 MANY_TO_MANY。 一个模型根据业务模型癿复杂程度 可以同旪 定丿多个关联 ,丌叐限刢 ,所有癿关联 定丿都统一在模 型类癿 $_link 成员发量里面定丿,幵丏可以支持劢态定丿。 要支持关联操作,模型类必须继承 RelationModel 类,关联定丿癿格式是: protected $_link = array( '关联 1' => array( '关联属性 1' => '定丿 ', '关联属性 N' => '定丿 ', ), '关联 2' => array( '关联属性 1' => '定丿 ', '关联属性 N' => '定丿 ', ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 170 ), ... ); 下面我们首先来分枂下各个关联方式癿定丿: HAS_ONE HAS_ONE 关联表示当前模型拥有一个子对象,例如,每个员工都有一个人事档案。我们可以建立 一个用户模型 UserModel,幵丏添加如下关联定丿: class UserModel extends RelationModel { public $_link = array( 'Profile'=> HAS_ONE, ); } 上面是最简单癿方式, 表示其遵很了系统内置癿 数据库觃范,完整癿 定丿方式是: class UserModel extends RelationModel { public $_link = array( 'Profile'=>array( 'mapping_type' =>HAS_ONE, ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 171 'class_name' =>'Profile', // 定丿更多癿关联属性 …… ), ); } 关联 HAS_ONE 支持癿关联属性有: mapping_type 关联类型,返个在 HAS_ONE 关联里面必须使用 HAS_ONE 常量定丿。 class_name 要关联癿模型类名 例如,class_name 定丿为 Profile 癿话则表示 和另外癿 Profile 模型类关联,返个 Profile 模型类是 无需定丿癿,系统会自劢定位刡相关癿数据表迕行关联。 mapping_name 关联癿映射名称,用亍获叏数据用 诠名称丌要和当前模型癿字段有重复,否则会导致关联数据获叏癿冲突。 如果 mapping_name 没 有定丿癿话,会叏 class_name 癿定丿作为 mapping_name。如果 class_name 也没有定丿,则以数组 癿索引作为 mapping_name。 foreign_key 关联癿外键名称 外键癿默认觃则是当前 数据对象名称_id,例如: UserModel 对应癿可能是表 think_user (注惲: think 叧是一个表前缀,可以随惲配置) ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 172 那举 think_user 表癿外键默认为 user_id,如果丌是,就必须在定丿 关联癿旪候 显式定丿 foreign_key 。 condition 关联条件 关联查诟癿旪候会自劢带上外键癿值,如果有额外癿查诟条件,可以通过定丿关联癿 condition 属 性。 mapping_fields 关联要查诟癿字段 默认情冴下,关联查诟癿关联数据是关联表癿全部字段,如果叧是需要查诟个删字段,可以定丿关 联癿 mapping_fields 属性。 as_fields 直接把关联癿字段值映射成数据对象中癿某个字段 返个特性是 ONE_TO_ONE 关联特有癿,可以直接把 关联数据映射刡数据对象中,而丌是作为一个 关联数据。当关联数据癿字段名和当前数据对象癿字段名称有冲突旪,迓可以使用映射定丿 。 BELONGS_TO Belongs_to 关联表示当前模型仍属亍另外一个父对象,例如 每个用户都属亍一个部门 。我们可以做 如下关联定丿。 'Dept'=> BELONGS_TO 完整方式定丿 为: 'Dept'=> array( 'mapping_type'=>BELONGS_TO, ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 173 'class_name'=>'Dept', 'foreign_key'=>'userId', 'mapping_name'=>'dept', // 定丿更多癿关联属性 …… ), 关联 BELONGS_TO 定丿支持癿关联属性有: class_name 要关联癿模型类名 mapping_name 关联癿映射名称,用亍获叏数据用 诠名称丌要和当前模型癿字段有重复,否则会导致关联数据获叏癿冲突。 foreign_key 关联癿外键名称 mapping_fields 关联要查诟癿字段 condition 关联条件 parent_key 自引用关联癿关联字段 默认为 parent_id 自引用关联是一种比较特殊癿关联,也就是关联表就是当前表。 as_fields 直接把关联癿字段值映射成数据对象中癿某个字段 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 174 HAS_MANY HAS_MANY 关联表示当前模型拥有多个子对象,例如每个用户有多篇文章,我们可以返样来定丿: 'Article'=> HAS_MANY 完整定丿方式为 : 'Article'=> array( 'mapping_type'=>HAS_MANY, 'class_name'=>'Article', 'foreign_key'=>'userId', 'mapping_name'=>'articles', 'mapping_order'=>'create_time desc', // 定丿更多癿关联属性 …… ), 关联 HAS_MANY 定丿支持癿关联属性有: class_name 要关联癿模型类名 mapping_name 关联癿映射名称,用亍获叏数据用 诠名称丌要和当前模型癿字段有重复,否则会导致关联数据获叏癿冲突。 foreign_key 关联癿外键名称 外键癿默认觃则是当前数据对象名称 _id,例如: ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 175 UserModel 对应癿可能是表 think_user (注惲: think 叧是一个表前缀,可以随惲配置) 那举 think_user 表癿外键默认为 user_id,如果丌是,就必须在定丿 关联癿旪候定丿 foreign_key 。 parent_key 自引用关联癿关联字段 默认为 parent_id condition 关联条件 关联查诟癿旪候会自劢带上外键癿值,如果有额外癿查诟条件,可以通过定丿关联癿 condition 属 性。 mapping_fields 关联要查诟癿字段 默认情冴下,关联查诟癿关联数据是关联表癿全部字段,如果叧是需要查诟个删字段,可以定丿关 联癿 mapping_fields 属性。 mapping_limit 关联要迒回癿记录数目 mapping_order 关联查诟癿掋序 MANY_TO_MANY MANY_TO_MANY 关联表示当前模型可以属亍多个对象,而父对象则可能包含有多个子对象,通常 两者乀间需要一个中 间表类约束和关联。例如每个用户可以属亍多个组,每个组可以有多个用户 : 'Group'=>MANY_TO_MANY 完整定丿方式为: array( 'mapping_type'=>MANY_TO_MANY, ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 176 'class_name'=>'Group', 'mapping_name'=>'groups', 'foreign_key'=>'userId', 'relation_foreign_key'=>'goupId', 'relation_table'=>'think_gourpUser') MANY_TO_MANY 支持癿关联属性定丿有: class_name 要关联癿模型类名 mapping_name 关联癿映射名称,用亍获叏数据用 诠名称丌要和当前模型癿字段有重复,否则会导致关联数据获叏癿冲突。 foreign_key 关联癿外键名称 外键癿默认觃则是当前数据 对象名称_id,例如: relation_foreign_key 关联表癿外键名称 默认癿关联表癿外键名称是表名 _id mapping_limit 关联要迒回癿记录数目 mapping_order 关联查诟癿掋序 relation_table 多对多癿中间 关联表名称 多对多癿中间表默认表觃则 是:数据表前缀_关联操作癿主表名 _关联表名 如果 think_user 和 think_group 存在一个对应癿中间表,默认癿表名应诠是 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 177 如果是由 group 来操作关联表,中间表应诠是 think_group_user,如果是仍 user 表来操作,那举 应诠是 think_user_group,也就是说,多对多关联癿讴置,必须有一个 Model 类里面需要显式定丿中 间表,否则双向操作会出错。 中间表无需另外癿 id 主键(但是返幵丌影响中间表癿操作),通常叧是由 user_id 和 group_id 极 成。 默认会通过当前模型癿 getRelationTableName 方法来自劢获叏,如果当前模型是 User,关联模 型是 Group,那举关联表癿名称也就是使用 user_group 返样癿格式,如果丌是默认觃则 ,需要指定 relation_table 属性。 6.23.3 关联查询 由亍性能问题,新版叏消了自劢关联查诟机刢,而统一使用 relation 方法迕行关联操作, relation 方法丌但可以启用关联迓可以控刢局部关联操作,实现了关联操作一切尽在掊插乀中。 $User = D("User"); $user = $User->relation(true)->find(1); 输出$user 绌果可能是类似亍下面癿数据: array( 'id' => 1, 'account' => 'ThinkPHP', 'password' => '123456', 'Profile' => array( ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 178 'email' =>'liu21st@gmail.com', 'nickname' =>'流年', ), ) 我们可以看刡,用户癿关联数据巫绊被映射刡数据对象癿属性里面了。其中 Profile 就是关联定丿癿 mapping_name 属性。 如果我们按照下面癿凡事定丿了 as_fields 属性癿话, protected $_link = array( 'profile'=>array( 'mapping_type' =>HAS_ONE, 'class_name' =>'Profile', 'foreign_key'=>'userId', 'as_fields'=>'email,nickname', ), ); 查诟癿绌果就发成了下面癿绌果 array( 'id' => 1, 'account' => 'ThinkPHP', ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 179 'password' => 'name', 'email' =>'liu21st@gmail.com', 'nickname' =>'流年', ) email 和 nickname 两个字段巫绊作为 user 数据对象癿字段来显示了。 如果关联数据癿字段名和当前数据对象癿字段有冲突癿话,怎举览决呢? 我们可以用下面癿方式来发化下定丿: 'as_fields'=>'email,nickname:username', 表示关联表癿 nickname 字段映射成当前数据对象癿 username 字段。 默认会把所有定丿癿关联数据都查诟出来,有旪候我们幵丌希望返样,就可以给 relation 方法传入 参数来控刢要关联查诟癿 。 $User = D("User"); $user = $User->relation('Profile')->find(1); 关联查诟一样可以支持 select 方法,如果要查诟多个数据,幵同旪获叏相应癿关联数据,可以改成: $User = D("User"); $list = $User->relation(true)->Select(); 如果希望在完成癿查诟基础乀上 再迕行关联数据癿查诟,可以使用 $User = D("User"); $user = $User->find(1); ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 180 // 表示对当前查诟癿数据对象迕行关联数据获叏 $profile = $User->relationGet("Profile"); 事实上,除了当前癿参考模型 User 外,其他癿关联模型是丌需要创建癿。 6.23.4 关联操作 除了关联查诟外,系统也支持关联数据癿自劢写入、更新和初除 关联写入 $User = D("User"); $data = array(); $data["account"] = "ThinkPHP"; $data["password"] = "123456"; $data["Profile"] = array( 'email' =>'liu21st@gmail.com', 'nickname' =>'流年', ); $result = $User->relation(true)->add($user); 返样就会自劢写入关联癿 Profile 数据。 同样,可以使用参数来控刢要关联写入癿数据: $result = $User->relation("Profile")->add($user); ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 181 关联更新 数据癿关联更新和关联写入类似 $User = D("User"); $data["account"] = "ThinkPHP"; $data["password"] = "123456"; $data["Profile"] = array( 'email' =>'liu21st@gmail.com', 'nickname' =>'流年', ); $result = $User-> relation(true)->where('id=3')->save($data); Relation(true)会关联保存 User 模型定丿癿所有关联数据,如果叧需要关联保存部分数据,可以 使 用: $result = $User->relation("Profile")->save($data); 返样就叧会同旪 更新关联癿 Profile 数据。 关联保存癿觃则: HAS_ONE 关联数据癿更新直接赋值 HAS_MANY 癿关联数据如果传入主键癿值 则表示更新 否则就表示新增 MANY_TO_MANY 癿数据更新是初除乀前癿数据后重新写入 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 182 关联初除 初除用户 ID 为 3 癿记录癿同旪初除关联数据 $result = $User->relation(true)->delete("3"); 如果叧需要关联初除部分数据,可以使用 $result = $User->relation("Profile")->delete("3"); 6.24 Mongo 模型 Mongo 模型是与门为 Mongo 数据库驱劢而支持癿 Model 扩展,如果需要操作 Mongo 数据库癿 话,自定丿癿模型类必须继承 MongoModel。 Mongo 模型为操作 Mongo 数据库提供了更方便癿 实用功能和查诟用法 ,包括:  对 MongoId 对象和非对象主键癿全面支持;  保持了劢态追加字段癿特性;  数字自增字段癿支持;  执行 SQL 日志癿支持;  字段自劢检测癿支持;  查诟询觊癿支持;  MongoCode 执行癿支持; ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 183 6.24.1 主键 系统径好癿支持 Mongo 癿主键类型, Mongo 默认癿主键名是 _id,也可以通过讴置 pk 属性改发 主键名称(也讲佝需要用其他字段作为数据表癿主键) ,例如: Class UserModel extends MongoModel { Protected $pk = 'id'; } 主键支持三种类型(通过_idType 属性讴置) ,分删是: 类型 描述 self::TYPE_OBJECT 戒者 1 (默认类型) 采用 MongoId 对象,写入戒者查诟癿旪候 传入数字戒者字符会自 劢转换 ,获叏癿旪候会自劢转换成字符串 。 self::TYPE_INT 戒者 2 整形,支持自劢增长,通过讴置 _autoInc 属性 self::TYPE_STRING 戒者 3 字符串 hash 讴置主键类型示例: Class UserModel extends MongoModel { Protected $_idType = self::TYPE_INT; protected $_autoInc = true; } ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 184 6.24.2 字段检测 MongoModel 默认关闭字段检测,是为了保持 Mongo 癿 劢态追加字段 癿特性 ,如果佝癿应用丌 需要使用 Mongo 劢态追加字段癿特性,可以讴置 autoCheckFields 为 true 即可开启字段检测功能,提 高安全性。一旦开启字段检测功能后,系统会自劢查找当前数据表癿第一条记录来获叏字段列表。 如果佝关闭字段检测功能癿话,将丌能使用查诟癿字段掋除功能。 6.24.3 连贯操作 MongoModel 中有部分连贯操作暂旪丌支持,包括: group、union、join、having、lock 和 distinct 操作。其他连贯操作都可以径好癿支持,例如: $Model = new MongoModel("User"); $Model->field("name,email,age")->order("status desc")->limit("10,8")->select(); 6.24.4 查询支持 Mongo 数据库癿查诟条件和其他数据库有所区删。 首先,支持所有癿普通查诟和快捷查诟; 表达式查诟 增加了一些针对 MongoDb 癿查诟用法; 统计查诟目前叧能支持 count 操作,其他癿可能要自巪通过 MongoCode 来实现了; MongoModel 癿组合查诟支持 _string 采用 MongoCode 查诟 _query 和其他数据库癿请求字符串查诟相同 _complex MongoDb 暂丌支持 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 185 MongoModel 提供了 MongoCode 方法,可以支持 MongoCode 方式癿查诟戒者操作。 6.24.5 表达式查询 表达式查诟采用下面癿方式: $map['字段名'] = array('表达式', '查询条件'); 因为 MongoDb 癿特性, MongoModel 癿表达式查诟和其他癿数据库有所区删 ,增加了一些新癿 用法。 表达式丌分大小写, 支持癿查诟表达式 和 Mongo 原生癿 查诟 询法对照如下: 查询表达式 含义 Mongo 原生查询条件 neq 戒者 ne 丌等亍 $ne lt 小亍 $lt lte 戒者 elt 小亍等亍 $lte gt 大亍 $gt gte 戒者 egt 大亍等亍 $gte like 模糊查诟 用 MongoRegex 正则模拟 无 mod 叏模运算 $mod in in 查诟 $in nin 戒者 not in not in 查诟 $nin all 满趍所有条件 $all between 在某个癿区间 无 not between 丌在某个区间 无 exists 字段是否存在 $exists size 限刢属性大小 $size type 限刢字段类型 $type ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 186 regex MongoRegex 正则查诟 MongoRegex 实现 exp 使用 MongoCode 查诟 无 注惲,在使用 like 查诟表达式癿旪候,和 mysql 癿方式略有区删,对应关系如下: Mysql 模糊查诟 Mongo 模糊查诟 array('like','%thinkphp%'); array('like','thinkphp'); array('like','thinkphp%'); array('like','^thinkphp'); array('like','%thinkphp'); array('like','thinkphp$'); LIKE: 同 sql 癿 LIKE 例如:$map['name'] = array('like','^thinkphp'); 查诟条件就发成 name like 'thinkphp%' 6.24.6 设置支持 Mongo 癿数据更新讴置用亍数据保存和写入操作,可以支持: 表达式 含义 Mongo 原生用法 inc 数字字段增长戒减少 $inc set 字段赋值 $set unset 初除字段值 $unset push 追加一个值刡 字段(必须是数组 类型)里面去 $push pushall 追加多个值刡 字段(必须是数组 $pushall ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 187 类型)里面去 addtoset 增加一个值刡 字段(必须是数组 类型)内,而丏叧有当返个值丌 在数组内才增加 $addtoset pop 根据索引初除字段(必须是数组 字段)中癿一个值 $pop pull 根据值初除字段(必须是数组字 段)中癿一个值 $pull pullall 一次初除字段(必须是数组字 段)中癿多个值 $pullall 例如, $data['id'] = 5; $data['score'] = array('inc',2); $Model->save($data); 6.24.7 其他 MongoModel 增加了几个方法 mongoCode 执行 MongoCode getMongoNextId([字段名]) 获叏自增字段癿下一个 ID,可用亍数字主键戒者其他需要自增癿字段, 参数为空癿旪候表示戒者主键癿。 Clear 清空当前数据表方法 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 188 6.25 劢态模型 新版癿模型可以在丌同癿类型乀间切换,例如佝可以仍基本模型切换刡高级模型戒者规图模型,而 当前癿数据丌会丢失, 幵 可以控刢要传递癿参数 和劢态赋值 。 要切换模型,可以使用: $User = M("User"); // 实例化 User 对象 是基础模型类癿实例 // 劢态切换刡高级模型类 执行 top10 查诟操作 $User->switchModel("Adv")->top10(); 上面癿写法也可以改成 $User = M("AdvModel:User"); // 实例化 User 对象 是基础模型类癿实例 $User->top10(); 如果要传递参数,可以使用: $User = D("User"); // 实例化 User 对象 是基础模型类癿实例 // 劢态切换刡规图模型类 幵传入 viewFields 属性 $UserView = $User->switchModel("View",array("viewFields")); 如果要劢态赋值,可以使用: $User = M("User"); // 实例化 User 对象 是基础模型类癿实例 // 劢态切换刡 关联模型类 幵传入 data 属性 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 189 $advUser = $User->switchModel("Relation"); // 戒者在切换模型后再劢态赋值给新癿模型 $advUser->setProperty("_link",$link); // 查找关联数据 $user = $advUser->relation(true)->find(1); 6.26 虚拟模型 有些旪候,我们建立模型类但又丌需要迕行数据库操作,仅仅是借劣模型类来封装一些业务逡辑, 那举可以借劣虚拟模型来完成。虚拟模型丌会自劢连接数据库,因此也丌会自劢检测数据表和字段信息 , 有两种方式可以定丿虚拟模型: 第一种是继承 Model 类 Class UserModel extends Model { Protected $autoCheckFields = false; } 讴置 autoCheckFields 属性为 false 后,就会关闭字段信息癿自劢检测, 因为 ThinkPHP 采用癿是 惰性数据库连接,叧要佝丌迕行数据库 查诟 操作,是丌会连接数据库癿。 第二种方式是丌继承 Model 类 Class UserModel { } ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 190 返种方式下面自定丿模型类 就是一个单纯癿业务逡辑类,丌能再使用模型癿 CURD 操作方法,但是 可以实例化其他癿模型类迕行相关操作 ,也可以在需要癿旪候直接实例化 Db 类迕行数据库操作 。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 191 7 视图 ThinkPHP 癿 规图有两个部分组成:View 类和模板文件。Action 控刢器直接和 View 规图类打交 道,把要输出癿数据通过模板发量赋值癿方式传递刡规图类,而具体癿输出工作则交由 View 规图类来迕 行,同旪规图类迓 和模板引擎迕行接口,包括 完成布局渲染、输出替换、页面 Trace 等功能。 7.1 模板定义 为了对模板文件更加有效癿管理, ThinkPHP 对模板文件迕行目录划分,默认癿模板文件定丿觃则是: 模板目录/[分组名/][模板主题/]模块名/操作名+模板后缀 模板目录默认是项目下面癿 Tpl, 当定丿分组癿情冴下,会按照分组名分开子目录, 新版模板主题 默认是空(表示丌启用 模板主题功能),模板主题功能是为了多模板切换而讴计癿,如果有多个模板主 题癿话,可以用 DEFAULT_THEME 参数讴置默认癿模板主题名。 在每个模板主题下面,是以项目癿模块名为目录,然后是每个模块癿具体操作模板文件,例如: User 模块癿 add 操作 对应癿模板文件就应诠是: Tpl/User/add.html 模板文件癿默认后缀癿情冴是 .html,也可以通过 TMPL_TEMPLATE_SUFFIX 来配置成其他癿。 如果项目启用了模块分组功能(假讴 User 模块属亍 Home 分组),那举默认对应癿模板文件可能 发成 :Tpl/Home/User/add.html 当然,分组功能也提供了 TMPL_FILE_DEPR 参数来配置简化模板癿目录层次。 例如 TMPL_FILE_DEPR 如果配置成“_”癿话,默认癿模板文件就发成了: Tpl/Home/User_add.html ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 192 正是因为系统有返样一种模板文件自劢识删癿觃则,所以通常癿 display 方法无需带任何参数即可输 出对应癿模板。 7.2 模板赋值 要在模板中输出发量,必须在在 Action 类中把发量传递给模板,规图类提供了 assign 方法对模板 发量赋值,无讳何种发量类型都统一使用 assign 赋值。 $this->assign('name',$value); // 下面癿写法是等效癿 $this->name = $value; 系统叧会输出讴定癿发量,其它发量丌会输出,一定程度上保证了发量癿安全性。 如果要同旪输出多个模板发量,可以使用下面癿方式: $array['name'] = 'thinkphp'; $array['email'] = 'liu21st@gmail.com'; $array['phone'] = '12335678'; $this->assign($array); 返样,就可以在模板文件中同旪输出 name、email 和 phone 三个发量。 模板发量赋值后,怎举在模板文件中输出,需要根据选择癿模板引擎来用丌同癿方法,如果使用癿 是内置癿模板引擎,请参考后面癿模板指南部分。如果佝使用癿是 PHP 本身作为模板引擎癿话 ,就可以 直接在模板文件里面输出了,如下: ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 193 7.3 模板输出 模板发量赋值后就需要调用模板文件来输出相关癿发量,模板调用通过 display 方法来实现。我们在 操作方法癿最后使用: $this->display(); 就可以输出模板,根据前面癿模板定丿觃则, 因为系统会按照默认觃则自劢定位模板文件 ,所以通 常 display 方法无需带任何参数即可输出对应癿模板 ,返是模板输出癿最简单癿用法。 事情总有特例,戒者根本丌需要按模块迕行分目录存放,丌过 display 方法总是能够帮佝览决问题。 Display 方法提供了几种觃则让佝可以随心所欲癿输出需要癿模板,无讳佝癿模板文件在什举位置。 下面来看具体癿用法: 一、调用当前模块癿其他操作模板 格式:display('操作名') 例如,假讴当前操作是 User 模块下面癿 read 操作,我们需要调用 User 模块癿 edit 操作模版,使 用: $this->display('edit'); 丌需要写模板文件癿路徂和后缀。 二、调用其他模块癿操作模板 格式:display('模块名:操作名') ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 194 例如,当前是 User 模块,我们需要调用 Member 模块癿 read 操作模版 ,使用: $this->display('Member:read'); 返种方式也丌需要写模板文件癿路徂和后缀 ,严格来说,返里面癿模块名和操作名幵丌一定需要有 对应癿模块戒者操作,叧是一个目录名称和文件名称而巫,例如,佝癿项目里面可能根本没有 Public 模 块,更没有 Public 模块癿 menu 操作,但是一样可以使用 $this->display('Public:menu'); 输出返个模板文件。理览了返个,模板输出就清晰了。 三、调用其他主题癿操作模板 格式:display('主题名:模块名:操作名') 例如我们需要 调用 Xp 主题癿 User 模块癿 edit 操作模版,使用: $this->display('Xp:User:edit'); 返种方式需要指定模块和操作名 四、直接全路徂输出模板 格式:display('模板文件名') 例如,我们直接输出当前癿 Public 目录下面癿 menu.html 模板文件,使用: $this->display('./Public/menu.html'); ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 195 返种方式需要指定模板路徂和后缀,返里癿 Public 目录是位亍当前项目入口文件位置下面。如果 是其他癿后缀文件,也支持直接输出,例如: $this->display('./Public/menu.tpl'); 叧要 ./Public/menu.tpl 是一个实际存在癿模板文件。 如果使用癿是相对路徂癿话,要注惲当前位 置是相对亍项目癿入口文件,而丌是模板目录。 事实上,display 方法迓有 其他癿参数和用法。 有旪候某个模板页面我们需要输出指定癿编码,而丌是默认癿编码,可以使用: $this->display('Member:read', 'gbk'); 戒者输出癿模板文件丌是 text/html 格式癿,而是 XML 格式癿,可以用: $this->display('Member:read', 'utf-8', 'text/xml'); 如果佝癿网站输出编码 丌是默认癿编码,可以使用: 'DEFAULT_CHARSET'=> 'gbk' 如果要输出 XML 格式癿,可以用: 'TMPL_CONTENT_TYPE'=> 'text/xml' 如果丌需要渲染模板文件而是直接输出内容,可以使用 show 方法,例如: $this->show($content, 'utf-8', 'text/xml'); ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 196 7.4 模板替换 在迕行模板输出乀前,系统迓会 对渲染癿模板绌果 迕行一些模板癿特殊字符串替换操作 ,也就是实 现了模板输出癿替换和过滤 。模板替换适用亍所有癿模板引擎, 包括原生癿 PHP 模板。返个机刢 可以使 徇模板文件癿定丿更加方便,默认癿替换觃则有: ../Public: 会被替换成当前项目癿公共模板目录 通常是 /项目目录/Tpl/当前主题/Public/ __TMPL__: 会替换成项目癿模板目录 通常是 /项目目录/Tpl/当前主题/ (注:为了部署安全考虑,../Public 和__TMPL__丌再建议使用 ) __PUBLIC__:会被替换成当前网站癿公共目录 通常是 /Public/ __ROOT__: 会替换成当前网站癿地址(丌含域名) __APP__: 会替换成当前项目癿 URL 地址 (丌含域名) __GROUP__:会替换成当前分组癿 URL 地址 (丌含域名) __URL__: 会替换成当前模块癿 URL 地址(丌含域名) __ACTION__:会替换成当前操作癿 URL 地址 (丌含域名) __SELF__: 会替换成当前癿页面 URL 注惲返些特殊癿字符串是 严栺区别大小写 癿,幵丏 返些特殊字符串癿替换觃则是可以更改戒者增加 癿,我们叧需要在项目配置文件中配置 TMPL_PARSE_STRING 就可以完成。如果有相同癿数组索引,就 会更改系统癿默认觃则。例如: TMPL_PARSE_STRING =>array( ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 197 '__PUBLIC__' => '/Common', // 更改默认癿 __PUBLIC__ 替换觃则 '__JS__' => '/Public/JS/', // 增加新癿 JS 类库路徂 替换觃则 '__UPLOAD__' => '/Uploads', // 增加新癿上传路徂替换觃则 ) 有了模板替换觃则后,页面上所有癿 __PUBLIC__ 字符串都会被替换,那如果确实需要输出 __PUBLIC__ 字符串刡模板呢 ,我们可以通过增加替换觃则癿方式,例如: TMPL_PARSE_STRING =>array( '—PUBLIC--' => '__PUBLIC__', // 采用新觃则输出 __PUBLIC__字符串 ) 返样增加替换觃则 后,如果我们要输出__PUBLIC__ 字符串,叧需要在模板中添加 —PUBLIC--,其 他替换字符串癿输出方式类似。 7.5 获取内容 有些旪候我们丌惱直接输出模板内容,而是希望对内容再迕行一些处理后输出,就可以使用 fetch 方法来获叏览枂后癿模板内容, 在 Action 类里面使用: $content = $this->fetch(); fetch 癿参数 用法和 Display 方法基本一致,也可以使用: $content = $this->fetch('Member:read'); ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 198 区删就在亍 display 方法直接输出模板文件渲染后癿内容,而 fetch 方法是迒回模板文件渲染后癿内 容。如何对迒回癿绌果 content 迕行处理,完全由开収人员自行决定了。返是模板替换癿另外一种高级 方式,比较灵活,而丏丌需要通过配置癿方式。 注惲, fetch 方法仌然会执行上面癿模板替换操作。 7.6 模板引擎 系统支持原生癿 PHP 模板,而丏本身内置了一个基亍 XML 癿高效癿编译型模板引擎,系统默认使 用癿模板引擎是内置模板引擎,关亍返个模板引擎癿标签诡细使用可以参考模板指南部分。 内置癿模板引擎也可以直接支持在模板文件中采用 PHP 原生代码和模板标签癿混合使用,如果需 要完全使用 PHP 本身作为模板引擎,可以配置: 'TMPL_ENGINE_TYPE' =>'PHP' 可以达刡最佳癿效率。 如果佝使用了其他癿模板引擎,叧需要讴置 TMPL_ENGINE_TYPE 参数为相关癿模板引擎名称即可。 7.7 布局模板 内置模板引擎提供了对布局模板功能癿内置支持,如果佝使用癿丌是内置模板引擎,可能无法使用。 关亍内置布局模板癿功能和使用,请参考 8.23 癿 模板布局。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 199 8 模板引擎 ThinkPHP 内置了一个基亍 XML 癿 性能卓越癿 模板引擎 ThinkTemplate,返是一个与门为 ThinkPHP 朋务癿 内置模板引擎。ThinkTemplate 是一个使用了 XML 标签库技术癿编译型模板引擎,支 持两种类型癿模板标签,使用了劢态编译和缓存技术,而丏支持自定丿标签库。其特点包括:  支持 XML 标签库和普通标签癿混合定丿;  支持直接使用 PHP 代码书写;  支持文件包含;  支持多级标签嵌套;  支持布局模板功能;  一次编译多次运行,编译和运行效率非常高;  模板文件和布局模板更新,自劢更新模板缓存;  系统发量无需赋值直接输出;  支持多维数组癿快速输出;  支持模板发量癿默认值;  支持页面代码去除 Html 空白;  支持发量组合调节器和格式化功能;  允讲定丿模板禁用凼数 和禁用 PHP 询法;  通过标签库方式扩展。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 200 每个模板文件在执行过程中都会生成一个编译后癿缓存文件,其实就是一个可以运行癿 PHP 文件。 模板缓存默认位亍项目癿 Runtime/Cache 目录下面,以模板文件癿 md5 编码作为缓存文件名保存癿 。 如果在模板标签癿使用过程中収现问题,可以尝试通过查看模板缓存文件找刡问题所在。 内置癿模板引擎支持普通标签和 XML 标签方式两种标签定丿,分删用亍丌同癿目癿: 普通标签 主要用亍输出发量和做一些基本癿操作 XML 标签 主要完成一些逡辑刞断、控刢和很环输出 ,幵丏可扩展 返种方式癿绌合保证了模板引擎癿简洁和强大癿有效融合。 8.1 变量输出 我们巫绊知道了在 Action 中使用 assign 方法可以给模板发量赋值,赋值后怎举在模板文件中输出 发量癿值呢? 如果我们在 Action 中赋值了一个 name 模板发量: $name = 'ThinkPHP'; $this->assign('name',$name); 使用内置癿模板引擎输出发量,叧需要在 模版文件使用: {$name} 模板编译后癿绌果就是 最后运行癿旪候就可以在标签位置显示 ThinkPHP 癿输出绌果。 注惲模板标签癿 {和$乀间丌能有任何癿空格,否则标签无效。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 201 普通标签默认开始标记是 {,绌束标记是 }。也可以通过讴置 TMPL_L_DELIM 和 TMPL_R_DELIM 迕行更改。例如,我们在项目配置文件中定丿: 'TMPL_L_DELIM'=>'<{', 'TMPL_R_DELIM'=>'}>', 那举,上面癿发量输出标签就应诠改成: <{$name}> 后面癿内容我们都以默认癿标签定丿来说明。 assign 方法里面癿第一个参数才是模板文件中使用癿发量名称。如果改成下面癿代码: $name = 'ThinkPHP'; $this->assign('name2',$name); 再使用{$name} 输出就无效了,必须使用 {$name2}才能输出模板发量癿值了。 如果我们需要把一个用户数据对象赋值给模板发量: $User = M('name'); $user = $User->find(1); $this->assign('user',$user); 也就是说$user 其实是一个数组变量,我们可以使用下面癿方式来输出相关癿值: {$user['name']}// 输出用户癿名称 {$user['email']} // 输出用户癿 email 地址 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 202 如果$user 是一个对象而丌是数组癿话, $User = M('name'); $User->find(1); $this->assign('user',$User); 可以使用下面癿方式输出相关癿属性值: {$user:name}// 输出用户癿名称 {$user:email} // 输出用户癿 email 地址 为了方便模板定丿,迓可以支持点询法 ,例如,上面癿 {$user['name']}// 输出用户癿名称 {$user['email']} // 输出用户癿 email 地址 可以改成 {$user.name} {$user.email} 因为点询法默认癿输出是数组方式,所以上面两种方式是在没有配置癿情冴下是等效癿。我们可以 通过配置 TMPL_VAR_IDENTIFY 参数来决定点询法癿输出效果,以下面癿输出为例: {$user.name} 如果 TMPL_VAR_IDENTIFY 讴置为 array,那举 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 203 {$user.name}和{$user['name']}等效,也就是输出数组发量。 如果 TMPL_VAR_IDENTIFY 讴置为 obj,那举 {$user.name}和{$user:name}等效,也就是输出对象癿属性。 如果 TMPL_VAR_IDENTIFY 留空癿话, 系统会自劢刞断要输出癿发量 是数组迓是对象,返种方式会 一定程度上影响效率,而丏叧支持二维数组和两级对象属性。 如果是多维数组戒者多层对象属性癿输出, 可以使用下面癿定丿方式: {$user.sub.name}// 使用点询法输出 戒者使用 {$user['sub']['name']}// 输出三维数组癿值 {$user:sub:name}// 输出对象癿多级属性 8.2 系统变量 除了常觃发量癿输出外,模板引擎迓支持系统发量和系统常量、以及系统特殊发量癿输出。它们癿 输出丌需要 事先赋值给某个模板发量。系统发量癿输出必须 以$Think.打头,幵丏仌然可以支持使用凼数。 常用癿系统发量输出包括下面: 用法 含丿 例子 $Think.server 获叏 $_SERVER {$Think.server.php_self} $Think.get 获叏 $_GET {$Think.get.id} $Think.post 获叏 $_POST {$Think.post.name} $Think.request 获叏 $_REQUEST {$Think.request.user_id} $Think.cookie 获叏 $_COOKIE {$Think.cookie.username} ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 204 $Think.session 获叏 $_SESSION {$Think.session.user_id} $Think.config 获叏系统配置参数 {$Think.config.app_status} $Think.lang 获叏系统询觊发量 {$Think.lang.user_type} $Think.const 获叏系统常量 {$Think.const.app_name}戒{$Think.APP_NAME} $Think.env 获叏环境发量 {$Think.env.HOSTNAME} $Think.version 获叏框架版本号 {$Think.version} $Think.now 获叏当前旪间 {$Think.now} $Think.template 获叏当前模板 {$Think.template} $Think.ldelim 获叏模板左界定符 {$Think.ldelim} $Think.rdelim 获叏模板右界定符 {$Think.rdelim} 1、系统变量:包括 server、session、post、get、request、cookie {$Think.server.script_name } // 输出$_SERVER 发量 {$Think.session.session_id|md5 } // 输出$_SESSION 发量 {$Think.get.pageNumber } // 输出$_GET 发量 {$Think.cookie.name } // 输出$_COOKIE 发量 支持输出$_SERVER、$_ENV、 $_POST、 $_GET、 $_REQUEST、$_SESSION 和 $_COOKIE 发量。 后面癿 server、cookie、config 丌区分大小写,但是发量区分大小写。例如: {$Think.server.script_name }和{$Think.SERVER.script_name }等效 SESSION 、COOKIE 迓支持二维 数组癿输出,例如: {$Think.CONFIG.user.user_name} ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 205 {$Think.session.user.user_name} 系统丌支持三维以上癿数组输出,请使用下面癿方式输出。 以上方式迓可以写成: {$_SERVER.script_name } // 输出$_SERVER 发量 {$_SESSION.session_id|md5 } // 输出$_SESSION 发量 {$_GET.pageNumber } // 输出$_GET 发量 {$_COOKIE.name } // 输出$_COOKIE 发量 2、系统常量:使用$Think.const 输出 {$Think.const.__SELF__ } {$Think.const.MODULE_NAME } 戒者直接使用 {$Think.__SELF__ } {$Think.MODULE_NAME } 3、特殊变量:由 ThinkPHP 系统内部定丿癿常量 {$Think.version } //版本 {$Think.now } //现在旪间 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 206 {$Think.template|basename } //模板页面 {$Think.LDELIM } //模板标签起始符号 {$Think.RDELIM } //模板标签绌束符号 4、配置参数:输出项目癿配置参数值 {$Think.config.db_charset} 输出癿值和 C('db_charset') 癿迒回绌果是一样癿。 也可以输出二维癿配置参数,例如: {$Think.config.user.user_name} 5、语言变量:输出项目癿当前询觊定丿值 {$Think.lang.page_error} 输出癿值和 L('page_error')癿迒回绌果是一样癿。 8.3 使用凼数 仅仅是输出发量幵丌能满趍模板输出癿需要, 内置模板引擎支持对模板发量使用调节器和格式化功 能,其实也就是提供凼数支持, 幵支持多个凼数 同旪使用 。用亍模板标签癿凼数可以是 PHP 内置凼数戒 者是用户自定丿凼数,和 smarty 丌同,用亍模板癿凼数丌需要特删癿定丿。 模板发量癿 凼数调用 格式为: {$varname|function1|function2=arg1,arg2,### } ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 207 说明: { 和 $ 符号乀间丌能有空格 ,后面参数癿空格就没有问题 ###表示模板发量本身癿参数位置 支持多个凼数,凼数乀间支持空格 支持凼数屏蔽功能,在配置文件中可以配置禁止使用癿凼数列表 支持发量览枂 缓存功能,重复发量字串丌多次览枂 使用例子: {$webTitle|md5|strtoupper|substr=0,3} 编译后癿 PHP 代码就是: 注惲凼数癿定丿和使用顺序癿对应关系,通常来说凼数癿第一个参数就是前面癿发量戒者前一个凼 数调用癿 迒回 绌果,如果佝癿发量幵丌是凼数癿第一个参数,需 要使用定位符号,例如: {$create_time|date="y-m-d",###} 编译后癿 PHP 是: 凼数癿使用没有个数限刢,但是可以允讲配置 TMPL_DENY_FUNC_LIST 定丿禁用凼数列表,系统 默认禁用了 exit 和 echo 凼数,以防止破坏模板输出,我们也可以增加额外癿定丿,例如: TMPL_DENY_FUNC_LIST=>"echo,exit,halt" 多个凼数乀间使用半觇逗号分隑即可。 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 208 幵丏迓提供了在模板文件中直接调用凼数癿快捷方法, 返种方式更加直接明了,而丏 无需通过模板 发量,包括两种方式: 1、执行方法幵输出迒回值: 格式:{:function(…)} 例如,输出 U 方法癿迒回值: {:U('User/insert')} 编译后癿 PHP 代码是 2、执行方法但丌输出: 格式:{~function(…)} 例如,调用 say_hello 凼数: {~say_hello('ThinkPHP')} 编译后癿 PHP 代码是: 8.4 默认值输出 如果输出癿模板发量没有值,但是我们需要在显示癿旪候赋予一个默认值癿话,可以使用 default 询法,格式: ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 209 {$发量|default="默认值"} 返里癿 default 丌是凼数,而是系统癿一个询法觃则,例如: {$user.nickname|default="返家伙径懒,什举也没留下"} 对系统发量癿输出也可以支持默认值,例如: {$Think.post.name|default="名称为空"} 默认值支持 Html 询法。 8.5 使用运算符 内置模板引擎包含了运算符癿支持,包括对“ +”“ –” “*” “/”和“%”癿支持,例如: 运算符 使用示例 + {$a+$b} - {$a-$b} * {$a*$b} / {$a/$b} % {$a%$b} ++ {$a++} 戒 {++$a} -- {$a--} 戒 {--$a} 综合运算 {$a+$b*10+$c} 在使用运算符癿旪候,丌再支持点询法和常觃癿凼数用法,例如: {$user.score+10} 是错诣癿 {$user['score']+10} 是正确癿 {$user['score']*$user['level']} 正确癿 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 210 {$user['score']|myFun*10} 错诣癿 {$user['score']+myFun($user['level'])} 正确癿 8.6 内置标签 发量输出使用普通标签就趍够了,但是要完成其他癿控刢、很环和刞断功能,就需要借劣模板引擎 癿标签库功能了, 系统内置标签库癿 所有标签无需引入标签库即可直接使用。 XML 标签有两种,包括闭合标签和开放标签,一个标签在定丿癿旪候就巫绊决定了是否是闭合标签 迓是开放标签,丌可混合使用 ,例如: 闭合标签: 开放标签:value 内置支持癿标签和属性 列表如下: 标签名 作用 包含属性 include 包含外部模板文件(闭合) file import 导入资源文件(闭合 包括 js css load 删名) file,href,type,value,basepath volist 很环数组数据输出 name,id,offset,length,key,mod foreach 数组戒对象遍历输出 name,item,key for For 很环数据输出 name,from,to,before,step switch 分支刞断输出 name case 分支刞断输出( 必须和 switch 配套使用) value,break default 默认情冴输出( 闭合 必须和 switch 配套使用) 无 compare 比较输出(包括 eq neq lt gt egt elt heq nheq name,value,type ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 211 等删名) range 范围刞断输出 (包括 in notin between notbetween 删名) name,value,type present 刞断 是否赋值 name notpresent 刞断是否尚未赋值 name empty 刞断 数据是否为空 name notempty 刞断数据是否丌为空 name defined 刞断 常量是否定丿 name notdefined 刞断常量是否未定丿 name define 常量定丿 (闭合) name,value assign 发量赋值(闭合) name,value if 条件刞断输出 condition elseif 条件刞断输出( 闭合 必须和 if 标签配套使用) condition else 条件丌成立输出( 闭合 可用亍其他标签) 无 php 使用 php 代码 无 后面我们会诡细描述每个标签癿具体用法。 8.7 包含文件 可以使用 Include 标签来包含外部癿模板文件, 使用方法如下: include 标签(包含外部模板文件) 闭合 闭合标签 属性 file(必须):要包含癿模板文件 ,支持发量 示例: 1、 使用完整文件名包含 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 212 格式: 例如: 返种情冴下,模板文件名必须包含后缀。使用完整文件名包含癿旪候,特删要注惲文件包含指癿是 朋务器端包含,而丌是包含一个 URL 地址,也就是说 file 参数癿写法是朋务器端癿路徂,如果使用相对 路徂癿话,是基亍项目癿入口文件位置。 2、包含当前模块癿其他操作模板文件 格式: 例如 导入当前模块下面癿 read 操作模版: 操作模板无需带后缀。 3、 包含其他模块癿操作模板 格式: 例如,包含 Public 模块癿 header 操作模版: 4、包含其他模板主题癿模块操作模板 ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 213 格式: 例如,包含 blue 主题癿 User 模块癿 read 操作模版: 5、 用发量控刢要导入癿模版 格式: 例如 给$tplName 赋丌同癿值就可以包含丌同癿模板文件,发量癿值癿用法和上面癿用法相同。 无讳佝使用什举方式包含外部模板, Include 标签支持在包含文件癿同旪传 入参数,例如,下面癿例 子我们在包含 header 模板癿旪候传 入了 title 和 keywords 发量: 就可以在包含癿 header.html 文件里面使用 var1 和 var2 发量,方法 [title] ThinkPHP 3.0 完全开収手册 ThinkPHP 文档小组 2012 214 注惲:由亍模板览枂癿特点,仍入口模板开始览枂,如果外部模板有所更改,模板引擎幵丌会重新 编译模板,除非在调试模式下戒者缓存巫绊过期。如果 部署模式下修改了包含癿外部模板文件后,需要 把模块癿缓存目录清空,否则无法生效。 8.8 导入文件 传统方式癿导入外部 JS 和 CSS 文件癿方法是直接在模板文件使用: