edit 和delete之外的所有字符串,我们建议更好的方式还是改进你的路由规则,避免路由规则和模块同名的情况存在,例如
?? 'new/:cate'=>'News/category'
就可以更简单的定义路由规则了。 完全匹配
规则匹配检测的时候只是对URL从头开始匹配,只要URL地址包含了定义的路由规则就会匹配成功,如果希望完全匹配,可以使用$符号,例如:
?? 'new/:cate$'=> 'News/category', ?? http://serverName/index.php/new/info
会匹配成功 而
?? http://serverName/index.php/new/info/2
则不会匹配成功 如果是采用
?? 'new/:cate'=> 'News/category',
方式定义的话,则两种方式的URL访问都可以匹配成功。
路由地址和额外参数
路由地址和额外参数表示前面的路由表达式最终需要路由到的地址并且允许隐式传入URL里面没有的一些参数,这里允许使用字符串或者数组方式定义,支持下面5种方式定义: 定义方式 方式1:路由到内部地址(字符串) 方式2:路由到内部地址(数组)参数采用字符串方式
方式3:路由到内部地址(数组)参数采用数组方式
46
定义格式 '[分组/模块/操作]?额外参数1=值1&额外参数2=值2...'
array('[分组/模块/操作]','额外参数1=值1&额外参数2=值2...')
array('[分组/模块/操作]',array('额外参数1'=>'值1','额外参数2'=>'值2'...))
方式4:路由到外部地址(字符串)301重定向
方式5:路由到外部地址(数组)可以指定重定向代码
'外部地址'
array('外部地址','重定向代码')
如果路由地址以“/”或者“http”开头则会认为是一个重定向地址或者外部地址,例如:
?? 'blog/:id'=>'/blog/read/id/:1'
和
?? 'blog/:id'=>'blog/read/'
虽然都是路由到同一个地址,但是前者采用的是301重定向的方式路由跳转,这种方式的好处是URL可以比较随意(包括可以在URL里面传入更多的非标准格式的参数),而后者只是支持模块和操作地址。举个例子,如果我们希望avatar/123重定向到
/member/avatar/id/123_small的话,只能使用:
?? 'avatar/:id'=>'/member/avatar/id/:1_small'
路由地址采用重定向地址的话,如果要引用动态变量,也是采用:1、:2 的方式。 采用重定向到外部地址通常对网站改版后的URL迁移过程非常有用,例如:
?? 'blog/:id'=>'http://blog.thinkphp.cn/read/:1'
表示当前网站(可能是http://thinkphp.cn)的 blog/123地址会直接重定向到 http://blog.thinkphp.cn/read/123。
在路由跳转的时候支持额外传入参数对(额外参数指的是不在URL里面的参数,隐式传入需要的操作中,有时候能够起到一定的安全防护作用,后面我们会提到),支持“额外参数1=值1&额外参数2=值2”或者array('额外参数1'=>'值1','额外参数2'=>'值2'...)这样的写法,可以参考不同的定义方式选择。例如:
?? 'blog/:id'=>'blog/read/?status=1&app_id=5', ?? 'blog/:id'=>array('blog/read/?status=1&app_id=5'), ?? 'blog/:id'=>array('blog/read/','status=1&app_id=5'),
?? 'blog/:id'=>array('blog/read/',array('status'=>1,'app_id'=>5)),
47
上面的路由规则定义中额外参数的传值方式都是等效的。status和app_id参数都是URL里面不存在的,属于隐式传值,当然并不一定需要用到,只是在需要的时候可以使用。 实例说明
通过上面的讲解,我们了解了如何定义路由规则,下面我们来举个例子加深印 假设我们定义了News控制器如下(代码实现仅供参考):
?? class NewsAction extends Action{ ?? public function read(){ ?? $New = M('New');
?? if(isset($_GET['id'])) { ?? // 根据id查询结果
?? $data = $New->find($_GET['id']); ?? }elseif(isset($_GET['name'])){ ?? // 根据name查询结果
?? $data = $New->getByName($_GET['name']); ?? }
?? $this->data = $data; ?? $this->display(); ?? } ??
?? public function archive(){ ?? $New = M('New');
?? $year = $_GET['year']; ?? $month = $_GET['month'];
?? $begin_time = strtotime($year . $month . \); ?? $end_time = strtotime(\, $begin_time);
?? $map['create_time'] = array(array('gt',$begin_time),array('lt',$end_time)); ?? $map['status'] = 1;
?? $list = $New->where($map)->select(); ?? $this->list = $list; ?? $this->display(); ?? } ?? }
定义路由规则如下:
?? 'URL_ROUTE_RULES' => array( //定义路由规则 48
?? 'new/:id\\d' => 'News/read', ?? 'new/:name' => 'News/read',
?? 'new/:year\\d/:month\\d' => 'News/archive', ?? ),
然后,我们访问:
?? http://serverName/index.php/new/8
会匹配到第一个路由规则,实际执行的效果等效于访问:
?? http://serverName/index.php/News/read/id/8
当访问:
?? http://serverName/index.php/new/hello
会匹配到第二个路由规则,实际执行的效果等效于访问:
?? http://serverName/index.php/News/read/name/hello
那么如果访问:
?? http://serverName/index.php/new/2012/03
是否会匹配第三个路由规则呢?我们期望的实际执行的效果能够等效于访问:
?? http://serverName/index.php/News/archive/year/2012/month/03
事实上却没有,因为http://serverName/index.php/new/2012/这个URL在进行路由匹配过程中已经优先匹配到了第一个路由规则了,把2012当成id的值传入了,这种情况属于路由规则的冲突,解决办法有两个: 1、调整定义顺序 路由定义改成:
?? 'URL_ROUTE_RULES' => array( //定义路由规则 ?? 'new/:year\\d/:month\\d' => 'News/archive', ?? 'new/:id\\d' => 'News/read', ?? 'new/:name' => 'News/read', ?? ),
49
接下来,当我们再次访问:
?? http://serverName/index.php/new/2012/03
的时候,达到了预期的访问效果。所以如果存在可能规则冲突的情况,尽量把规则复杂的规则定义放到前面,确保最复杂的规则可以优先匹配到。但是如果路由规则定义多了之后,仍然很容易混淆,所以需要寻找更好的解决办法。 2、利用完全匹配功能
现在我们来利用路由的完全匹配定义功能,把路由定义改成:
?? 'URL_ROUTE_RULES' => array( //定义路由规则
?? 'new/:id\\d$' => 'News/read', ?? 'new/:name$' => 'News/read',
?? 'new/:year\\d/:month\\d$' => 'News/archive', ?? ),
在规则最后加上$符号之后,表示完整匹配当前的路由规则,就可以避免规则定义的冲突了。对于规则路由来说,简单的理解就是URL里面的参数数量或者类型约束要完全一致。 所以,如果我们访问
?? http://serverName/index.php/new/2012/03/01
的话,是不会匹配成功任何一条路由的。 3、利用正则路由
当然,解决问题的办法总是不止一种,对于复杂的情况,我们不要忘了使用正则路由规则定义,在你找不到解决方案的时候,正则路由总能帮到你。 要实现上面的同样路由功能的话,还可以用下面的规则定义:
?? 'URL_ROUTE_RULES' => array( //定义路由规则 ?? '/^new\\/(\\d+)$/' => 'News/read?id=:1', ?? '/^new\\/(\\w+)$/' => 'News/read?name=:1',
?? '/^new\\/(\\d{4})\\/(\\d{2})$/' => 'News/achive?year=:1&month=:2', ?? ),
50
ThinkPHP3.1快速入门教程系列
ThinkPHP3.1快速入门(1)基础 ................................................................ 错误!未定义书签。 ThinkPHP3.1快速入门(2)数据CURD .................................................... 错误!未定义书签。 ThinkPHP3.1快速入门(3)查询语言 ........................................................ 错误!未定义书签。 ThinkPHP3.1快速入门(4)连贯操作 ........................................................ 错误!未定义书签。 ThinkPHP3.1快速入门(5)变量 ................................................................ 错误!未定义书签。 ThinkPHP3.1快速入门(6)路由 ................................................................ 错误!未定义书签。 ThinkPHP3.1快速入门(8)视图 ................................................................ 错误!未定义书签。 ThinkPHP3.1快速入门(9)变量输出 ........................................................ 错误!未定义书签。 ThinkPHP3.1快速入门(10)缓存 .............................................................. 错误!未定义书签。 ThinkPHP3.1快速入门(11)控制器高级特性 .......................................... 错误!未定义书签。 ThinkPHP3.1快速入门(12)自动验证 ...................................................... 错误!未定义书签。 ThinkPHP3.1快速入门(13)自动完成 ...................................................... 错误!未定义书签。 ThinkPHP3.1快速入门(14)命名范围 ...................................................... 错误!未定义书签。 ThinkPHP3.1快速入门(15)模板布局 ...................................................... 错误!未定义书签。 ThinkPHP3.1快速入门(16)安全 .............................................................. 错误!未定义书签。 ThinkPHP3.1快速入门(17)多语言 .......................................................... 错误!未定义书签。 ThinkPHP3.1快速入门(18)数据分页 ...................................................... 错误!未定义书签。 ThinkPHP3.1快速入门(19)文件上传 ...................................................... 错误!未定义书签。 ThinkPHP3.1快速入门(20)验证码 .......................................................... 错误!未定义书签。 ThinkPHP3.1快速入门(21)IP地址定位 ................................................. 错误!未定义书签。 ThinkPHP3.1快速入门(22)行为 .............................................................. 错误!未定义书签。
ThinkPHP3.1快速入门(1)基础
简介
ThinkPHP是一个快速、简单的基于MVC和面向对象的轻量级PHP开发框架,遵循Apache2开源协议发布,从诞生以来一直秉承简洁实用的设计原则,在保持出色的性能和至简的代码的同时,尤其注重开发体验和易用性,并且拥有众多的原创功能和特性,为WEB应用开发提供了强有力的支持。
目录结构
ThinkPHP(
最
新
版
本
可
以
在)
官或
方者
网
站
http://thinkphp.cn/down/framework.html
Github
(https://github.com/liu21st/thinkphp/downloads)下载。
把下载后的压缩文件解压到你的WEB目录(或者任何目录都可以),框架的目录结构为:
1
? ? ? ? ? ? ? ? ?
├─ThinkPHP.php 框架入口文件 ├─Common 框架公共文件 ├─Conf 框架配置文件 ├─Extend 框架扩展目录 ├─Lang 核心语言包目录 ├─Lib 核心类库目录
│ ├─Behavior 核心行为类库 │ ├─Core 核心基类库 │ ├─Driver 内置驱动
?? │ │ ├─Cache 内置缓存驱动 ?? │ │ ├─Db 内置数据库驱动 ?? │ │ ├─TagLib 内置标签驱动 ?? │ │ └─Template 内置模板引擎驱动 ?? │ └─Template 内置模板引擎 ?? └─Tpl 系统模板目录
注意,框架的公共入口文件ThinkPHP.php是不能直接执行的,该文件只能在项目入口文件中调用才能正常运行(后面会讲到),这是很多新手很容易犯的一个错误。
入口文件
在开始之前,你需要一个Web服务器和PHP运行环境,如果你暂时还没有,我们推荐使用集成开发环境WAMPServer(是一个集成了Apache、PHP和MySQL的开发套件,而且支持多个PHP版本、MySQL版本和Apache版本的切换)来使用ThinkPHP进行本地开发和测试。
接下来我们先在WEB根目录下面创建一个app子目录(这个app就是我们的项目名),然后在该目录下面创建一个index.php文件,添加一行简单的代码:
??
?? require '/ThinkPHP框架所在目录/ThinkPHP.php';
这行代码的作用就是加载ThinkPHP框架的入口文件ThinkPHP.php,这是所有基于ThinkPHP开发应用的第一步。 然后,在浏览器中访问这个入口文件。
?? http://localhost/app/
一般Web服务器的默认文件是index.php,所以我们可以不需要在URL地址中加
2
上index.php。运行后我们会看到欢迎页面,
而且已经自动生成了项目目录,目录结构如下:
?? ├─index.php 项目入口文件 ?? ├─Common 项目公共文件目录 ?? ├─Conf 项目配置目录 ?? ├─Lang 项目语言目录 ?? ├─Lib 项目类库目录
?? │ ├─Action Action类库目录 ?? │ ├─Behavior 行为类库目录 ?? │ ├─Model 模型类库目录 ?? │ └─Widget Widget类库目录 ?? ├─Runtime 项目运行时目录 ?? │ ├─Cache 模板缓存目录 ?? │ ├─Data 数据缓存目录 ?? │ ├─Logs 日志文件目录 ?? │ └─Temp 临时缓存目录 ?? └─Tpl 项目模板目录
如果你希望项目的入口文件移动到app目录的外面,那么只需要修改入口文件index.php的内容为:
??
?? define('APP_NAME','app'); ?? define('APP_PATH','./app/');
?? require '/ThinkPHP框架所在目录/ThinkPHP.php';
APP_NAME和APP_PATH分部用于定义项目名和项目目录,项目名通常就是指项目的目录名称。
3
移动并修改完项目的入口文件后,我们就可以通过
?? http://localhost/
访问app项目了。当然你也可以在Web根目录下面创建多个子目录来部署多个项目。
配置
每个项目都有一个独立的配置文件(位于项目目录的Conf/config.php),配置文件的定义格式均采用PHP返回数组的方式,例如:
?? // 项目配置文件 ?? return array(
?? '配置参数' => '配置值', ?? // 更多配置参数 ?? //... ?? );
一旦有需要,我们就可以在项目配置文件中添加相关配置项目。通常我们提到的添加配置项目,就是指在项目配置文件中添加:
?? '配置参数' => '配置值',
配置值可以支持包括字符串、数字、布尔值和数组在内的数据,通常我们建议配置参数均使用大写定义。如果有需要,我们还可以为项目定义其他的配置文件。
控制器
需要为每个模块定义一个控制器类,控制器类的命名规范是: 模块名+Action.class.php (模块名采用驼峰法并且首字母大写)
系统的默认模块是Index,对应的控制器就是项目目录下面的Lib/Action/IndexAction.class.php,类名和文件名一致。默认操作是index,也就是控制器的一个public方法。初次生成项目目录结构的时候,系统已经默认生成了一个默认控制器(就是之前看到的欢迎页面),我们把index方法改成下面的代码:
?? class IndexAction extends Action { ?? public function index(){ ?? echo 'hello,world!';
4
?? } ?? }
控制器必须继承Action类,一个模块可以包括多个操作方法。如果你的操作方法是protected或者private类型的话,是无法直接通过URL访问到该操作的。
URL请求
入口文件是项目的单一入口,对项目的所有请求都定向到项目的入口文件,系统会从URL参数中解析当前请求的模块和操作,我们之前访问的URL地址中没有任何参数,因此系统会访问默认模块(Index)的默认操作(index),因此下面的访问和之前是等效的:
?? http://localhost/app/index.php/Index/index
这种URL模式就是系统默认的PATHINFO模式,不同的URL模式获取模块和操作的方法不同,ThinkPHP支持的URL模式有四种:普通模式、PATHINFO、REWRITE和兼容模式。
普通模式:也就是传统的GET传参方式来指定当前访问的模块和操作,例如:
?? http://localhost/app/?m=module&a=action&var=value
m参数表示模块,a操作表示操作(模块和操作的URL参数名称是可以配置的),后面的表示其他GET参数。
PATHINFO模式:是系统的默认URL模式,提供了最好的SEO支持,系统内部已经做了环境的兼容处理,所以能够支持大多数的主机环境。对应上面的URL模式,PATHINFO模式下面的URL访问地址是:
?? http://localhost/app/index.php/module/action/var/value/
PATHINFO地址的第一个参数表示模块,第二个参数表示操作。 PATHINFO模式下面,URL是可定制的,例如,通过下面的配置:
?? 'URL_PATHINFO_DEPR'=>'-', // 更改PATHINFO参数分隔符
我们还可以支持下面的URL访问:
?? http://localhost/app/index.php/module-action-var-value/
5
_server _globals
获取$_SERVER参数 获取$GLOBALS参数
变量名:(必须)是要获取的系统变量的名称
过滤方法:(可选)可以用任何的内置函数或者自定义函数名,如果没有指定的话,采用默认的htmlspecialchars函数进行安全过滤(由DEFAULT_FILTER 参数配置),参数就是前面方法名获取到的值,也就是说如果调用:
?? $this->_get(\);
最终调用的结果就是 htmlspecialchars($_GET[\,如果要改变过滤方法,可以使用:
?? $this->_get(\,\);
默认值:(可选)是要获取的参数变量不存在的情况下设置的默认值,例如:
?? $this->_get(\,\,0);
如果$_GET[\不存在的话,会返回0。
如果没有设置任何默认值的话,系统默认返回NULL。 其他方法的用法类似。
看起来好像差别不大,但是有一个明显的优势,就是如果我需要增加或者改变对这些变量做统一的过滤,一般不需要修改变量获取的代码,只是在项目配置文件中增加一个配置参数即可,例如:
?? 'DEFAULT_FILTER'=>'strip_tags'
对所有的采用动态方式获取的变量使用strip_tags方法进行统一过滤,也可以支持多个过滤方法,例如:
?? 'DEFAULT_FILTER'=>'strip_tags,htmlspecialchars'
表示先进行strip_tags过滤,然后再进行htmlspecialchars过滤。 如果你在获取某个变量的时候 需要自定义过滤方法,则可以改成:
41
?? $name = $this->_post('content','trim,strip_tags'); // 获取post变量并过滤
如果你在项目配置中设置了统一的变量过滤方法,但是希望对某些变量不进行过滤,则可以用:
?? $name = $this->_post('id','',0);
如果你的参数可能会来自于多个提交方式,那么可以使用_param方法来更方便的获取,例如:
?? $this->_param('id');
当前为get方式提交的时候,就等效于
?? $this->_get('id');
当前为post方式提交的时候,就等效于
?? $this->_post('id');
如果为put方式提交的话,就等效于
?? $this->_put('id');
其优点自然很明显,同一个方法可以接受不同提交类型的变量,不用手动做太多的判断再来获取不同的参数了。
获取URL参数
在某些情况下面,我们还有一种获取URL参数的特殊需求,一般来说,获取URL参数是采用get变量的方式就够用了,但是对于我们定制过的URL,或者采用了路由的情况下面,URL的参数可能会没有规律,这个时候,我们可以采用另外一种方式来获取。 例如,当前的URL地址是:
?? http://localhost/index.php/news/hello_world/thinkphp
我们要获取其中的参数,可以用:
?? $this->_param(0); // 获取news ?? $this->_param(1); // 获取hello_world 42
?? $this->_param(2); // 获取thinkphp
不过_param(数字) 方式的变量获取,仅对PATHINFO模式URL地址有效
变量过滤
前面我们已经了解了如何使用Action类提供的方法来进行变量获取和过滤了,但是在没有调用这些动态方法的前提下,我们怎么来进行数据过滤呢? ThinkPHP还提供了两种方式来进行数据过滤操作: 第一:配置全局的变量过滤
这种情况是针对一些会在多使用的情况,可以通过配置全局过滤 简化操作,例如在项目配置文件中添加参数:
?? 'VAR_FILTERS'=>'strip_tags'
则会对全局的get和post变量进行过滤,其他类型的系统变量需要自行过滤。 第二:在写入数据库之前进行变量过滤
如果你的变量数据是要写入到数据库的话,可以在数据写入数据库之前调用filter方法对数据进行安全过滤,例如:
?? $this->data($data)->filter('strip_tags')->add();
在执行add方法之前,会对$data数据进行strip_tags过滤处理。但是,这种方式下面,filter方法不支持多个过滤方法。 总结
使用ThinkPHP,我们可以轻松地对系统变量的获取和过滤,你的开发功力明显提升了不少。加油,后面还会讲解如何使用路由。
ThinkPHP3.1快速入门(6)路由
ThinkPHP框架对URL有一定的规范,所以如果你希望定制你的URL格式的话,就需要好好了解下内置的路由功能了,它能让你的URL变得更简洁和有文化。 启用路由
43
要使用路由功能,前提是你的URL支持PATH_INFO,并且在项目配置文件中开启路由:
?
'URL_ROUTER_ON' => true, //开启路由
然后就是配置路由规则了,使用URL_ROUTE_RULES参数进行配置,配置格式是一个数组,每个元素都代表一个路由规则,例如:
? ? ? ? ?
'URL_ROUTE_RULES'=>array(
'news/:year/:month/:day' => array('News/archive', 'status=1'), 'news/:id' => 'News/read', 'news/read/:id' => '/news/:1', ),
系统会按定义的顺序依次匹配路由规则,一旦匹配到的话,就会定位到路由定义中的模块(支持分组)和操作方法去执行,并且后面的规则不会继续匹配。 路由定义
路由规则的定义方式如下:
?
'路由表达式'=>'路由地址和额外参数'
路由表达式
路由表达式包括规则路由和正则路由的定义表达式,只能使用字符串。 表达式 正则表达式 规则表达式 正则表达式
路由表达式支持的正则定义必须以“/”开头,否则就视为规则表达式。也就是说如果采用
?
'#^blog\\/(\\d+)$#'
示例 /^blog\\/(\\d+)$/ blog/:id
方式定义的正则表达式不会被支持,而会被认为是规则表达式进行解析,从而无法正确匹配。
? 44
'/^new\\/(\\d{4})\\/(\\d{2})$/' => 'News/achive?year=:1&month=:2',
对于正则表达式中的每个变量(即正则规则中的子模式)部分,如果需要在后面的路由地址中引用,可以采用:1、:2这样的方式,序号就是子模式的序号。 更多的关于如何定义正则表达式就不在本文的描述范畴了。 规则表达式
3.0的规则路由是从2.1的简单路由进化而来,虽然无法完美实现正则路由的功能,但是相比简单路由确实增强了不少,而且比正则路由更方便定义和容易理解。 规则表达式通常包含静态地址和动态地址,或者两种地址的结合,例如下面都属于有效的规则表达式:
?? 'my'=>'Member/myinfo', // 静态地址路由 类似于之前版本的简单路由 ?? 'blog/:id'=>'Blog/read', // 静态地址和动态地址结合
?? 'new/:year/:month/:day'=>'News/read', // 静态地址和动态地址结合 ?? ':user/:blog_id'=>'Blog/read',// 全动态地址
规则表达式的定义以“/”为参数分割符(无论你的URL_PATHINFO_DEPR设置是什么,请确保在定义规则表达式的时候统一使用“/”进行URL参数分割)。 每个参数中以“:”开头的参数都表示动态参数,并且会自动对应一个GET参数,例如:id表示该处匹配到的参数可以使用$_GET['id']方式获取,:year :month :day 则分别对应$_GET['year'] $_GET['month'] $_GET['day']。 数字约束
支持对变量的类型检测,但仅仅支持数字类型的约束定义,例如
?? 'blog/:id\\d'=>'Blog/read',
表示只会匹配数字参数,如果你需要更加多的变量类型检测,请使用正则表达式定义来解决。 规则排除
非数字变量支持简单的排除功能,主要是起到避免解析混淆的作用,例如:
?? 'news/:cate^add|edit|delete'=>'News/category'
因为规则定义的局限性,恰巧我们的路由规则里面的news和实际的news模块是相同的命名,而:cate并不能自动区分当前URL里面的动态参数是实际的操作名还是路由变量,所以为了避免混淆,我们需要对路由变量cate进行一些排除以帮助我们进行更精确的路由匹配,格式^add|edit|delete表示,匹配除了add
45
* distinct lock
用于查询的distinct支持 用于数据库的锁机制
布尔值 布尔值
支持多个参数(以后在缓存部分再详细描述) 字符串
cache 用于查询缓存 relation validate auto filter scope*
用于关联查询(需要关联模型扩展支持) 用于数据自动验证 用于数据自动完成 用于数据过滤 用于命名范围
数组 数组 字符串 字符串、数组
所有的连贯操作都返回当前的模型实例对象(this),其中带*标识的表示支持多次调用。
用法
由于连贯操作的使用往往涉及到多个方法的联合使用,下面大概介绍下各个连贯操作的基本用法: WHERE
where 用于查询或者更新条件的定义 用法 参数 返回值 备注
where($where)
where(必须):查询或者操作条件,支持字符串、数组和对象 当前模型实例
如果不调用where方法,默认不会执行更新和删除操作
Where方法是使用最多的连贯操作方法,更详细的用法请参考:快速入门(3)查询语言。
31
TABLE
table 定义要操作的数据表名称,动态改变当前操作的数据表名称,需要写数据表的全名,包含前缀,可以使用别名和跨库操作 用法 参数 返回值 备注
table($table)
table(必须):数据表名称,支持操作多个表,支持字符串、数组和对象
当前模型实例
如果不调用table方法,会自动获取模型对应或者定义的数据表
用法示例:
?
$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方法,默认会自动获取当前模型对应或者定义的数据表。 DATA
data 可以用于新增或者保存数据之前的数据对象赋值 用法 参数 返回值 备注
data($data)
data(必须):数据,支持数组和对象 当前模型实例
如果不调用data方法,则会取当前的数据对象或者传入add和save的数据
使用示例:
32
? ?
$Model->data($data)->add();
$Model->data($data)->where('id=3')->save();
Data方法的参数支持对象和数组,如果是对象会自动转换成数组。如果不定义data方法赋值,也可以使用create方法或者手动给数据对象赋值的方式。 模型的data方法除了创建数据对象之外,还可以读取当前的数据对象, 例如:
?? $this->find(3); ?? $data = $this->data();
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之外的所有字段。 ORDER
order 用于对操作结果排序
33
用法 参数 返回值 备注
order($order)
order(必须):排序的字段名,支持字符串和数组,支持多个字段排序 当前模型实例
如果不调用order方法,按照数据库的默认规则
使用示例:
?? order('id desc')
排序方法支持对多个字段的排序
?? order('status desc,id asc')
order方法的参数支持字符串和数组,数组的用法如下:
?? order(array('status'=>'desc','id'))
LIMIT
limit 用于定义要查询的结果限制(支持所有的数据库类型) 用法 参数 返回值 备注
limit($limit)
limit(必须):限制数量,支持字符串 当前模型实例
如果不调用limit方法,则表示没有限制
备注 如果不调用limit方法,则表示没有限制
我们知道不同的数据库类型的limit用法是不尽相同的,但是在ThinkPHP的用法里面始终是统一的方法,也就是limit('offset,length') ,无论是Mysql、SqlServer还是Oracle数据库,都是这样使用,系统的数据库驱动类会负责解决这个差异化。 使用示例:
?? limit('1,10')
也可以用下面的写法,是等效的:
?? limit(1,10)
如果使用
?? limit('10')
等效于
34
?? limit('0,10')
PAGE
page 用于定义要查询的数据分页 用法 参数 返回值 备注
page($page)
page(必须):分页,支持字符串 当前模型实例 无
Page操作方法是新增的特性,可以更加快速的进行分页查询。 Page方法的用法和limit方法类似,格式为:
?? Page('page[,listRows]')
Page表示当前的页数,listRows表示每页显示的记录数。例如:
?? Page('2,10')
表示每页显示10条记录的情况下面,获取第2页的数据。 下面的写法等效:
?? Page(2,10);
listRow如果不写的话,会读取limit('length') 的值,例如:
?? limit(25)->page(3);
表示每页显示25条记录的情况下面,获取第3页的数据。 如果limit也没有设置的话,则默认为每页显示20条记录。 page方法增加第二个参数支持,例如:
?? $this->page(5,25)->select();
和之前的用法
?? $this->limit('5,25')->select();
等效。 GROUP
group 用于数据库的group查询支持 用法 参数 返回值
group($group)
group(必须):group的字段名,支持字符串 当前模型实例
35
备注 无
使用示例:
?? group('user_id')
Group方法的参数只支持字符串 HAVING
having 用于数据库的having查询支持 用法 参数 返回值 备注
having($having)
having(必须):having,支持字符串 当前模型实例 无
使用示例:
?? having('user_id>0')
having方法的参数只支持字符串 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();
默认采用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'))
UNION
36
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();
或者
?? $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')
37
?? ->union(array('SELECT think_user_2'),true) ?? ->select();
name FROM think_user_1','SELECT name FROM
每个union方法相当于一个独立的SELECT语句。
注意:UNION 内部的 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条 SELECT 语句中的列的顺序必须相同。 DISTINCT 用法 参数 返回值 备注
distinct($distinct)
distinct(必须):是否采用distinct,支持布尔值 当前模型实例 无
使用示例:
?? $Model->Distinct(true)->field('name')->select();
LOCK 用法 参数 返回值 备注
lock($lock)
lock(必须):是否需要锁定,支持布尔值 当前模型实例
join方法支持多次调用
Lock方法是用于数据库的锁机制,如果在查询或者执行操作的时候使用:
?? lock(true)
就会自动在生成的SQL语句最后加上 FOR UPDATE或者FOR UPDATE NOWAIT(Oracle数据库)。 VALIDATE 用法 参数 返回值 备注
validate($validate)
validate(必须):自动验证定义 当前模型实例
只能和create方法配合使用
validate方法用于数据的自动验证,我们会在数据验证部分详细描述。 AUTO 用法
38
auto($auto)
参数 返回值 备注
auto(必须):定义自动完成 当前模型实例
auto方法只能配合create方法使用
auto方法用于数据的自动完成操作,具体使用我们会在数据自动完成部分描述。 SCOPE 用法 参数 返回值 备注
scope($scope)
scope(必须):命名范围定义 当前模型实例
scope方法其实是连贯操作的预定义
scope方法的具体用法可以参考:3.1的新特性 命名范围 FILTER
filter 用于数据的安全过滤 用法 参数 返回值 备注
filter($filter)
filter(必须):过滤方法名 当前模型实例
filter方法一般用于写入和更新操作
filter方法用于对数据对象的安全过滤,例如:
?? $Model->data($data)->filter('strip_tags')->add();
目前filter方法不支持多个方法的过滤。
总结
连贯操作为我们的数据操作带来了很大的便捷之处,并且只要SQL可以实现的操作,基本上都可以用ThinkPHP的连贯操作来实现,并且不用考虑数据库之间的表达差异,具有可移植性。后面会和大家讲解如何操作和获取变量。
ThinkPHP3.1快速入门(5)变量
本篇我们来学习如何在ThinkPHP中使用变量和对变量进行过滤。
在Web开发过程中,我们经常需要获取系统变量或者用户提交的数据,这些变量数据错综复杂,而且一不小心就容易引起安全隐患,但是如果利用好ThinkPHP
39
提供的变量获取功能,就可以轻松的获取和驾驭变量了。
获取变量
首先,我们来谈下如何获取变量。 第一种方式:传统获取方式
你仍然可以在开发过程中使用传统方式获取各种系统变量,例如:
? ? ? ? ?
$id = $_GET['id']; // 获取get变量 $name = $_POST['name']; // 获取post变量 $value = $_SESSION['var']; // 获取session变量 $name = $_COOKIE['name']; // 获取cookie变量 $file = $_SERVER['PHP_SELF']; // 获取server变量
不建议直接使用传统方式获取,因为没有统一的安全处理机制,后期如果调整的话,改起来会比较麻烦。
第二种方式:使用Action类提供的动态方法
系统的Action类提供了对系统变量的增强获取方法,包括对GET、POST、PUT、REQUEST、SESSION、COOKIE、SERVER和GLOBALS参数,除了获取变量值外,还提供变量过滤和默认值支持,用法很简单,只需要在Action中调用下面方法:
? ? ? ?
$id = $this->_get('id'); // 获取get变量 $name = $this->_post('name'); // 获取post变量 $value = $this->_session('var'); // 获取session变量 $name = $this->_cookie('name'); // 获取cookie变量
?? $file = $this->_server('PHP_SELF'); // 获取server变量
调用格式为:
$this->方法名(\变量名\过滤方法\默认值\ 方法名可以支持: _get _post _param _request _put _session _cookie
40
获取GET参数 获取POST参数
自动判断请求类型获取GET、POST或者PUT参数 获取REQUEST参数 获取PUT参数 获取$_SESSION参数 获取$_COOKIE参数
百度搜索“70edu”或“70教育网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,70教育网,提供经典综合文库ThinkPHP3.1快速入门系列教程在线全文阅读。
相关推荐: