运行
单一入口:index.php
1 |
|
运行流程:索引控制器
1 |
|
在浏览器地址栏输入: 网站地址/?m=index&a=index
来访问 index 的 index 方法
使用 ?m=index&a=test
来访问 index 的 test 方法
也可以多建几个 class 和 function,达到不同的 module 和 function
目录结构解析
- Common 存放当前项目的公共函数
- Conf 存放当前项目的配置文件
- Lang 存放当前项目的语言包
- Lib 存放当前项目的控制器和模型 (存放MVC中的M、C)
- Runtime 存放当前显示的运行时的文件:\Cache\、\Date\、\Logs\、\Temp\、~runtime.php
- Tpl 存放当前项目的模板文件 (存放MVC中的V)
ThinkPHP 配置文件
全局设置
总的文件路径:\ThinkPHP\Conf\convention.php
每个程序的设置
应用配置路径:\[应用名]\Common\Conf\config.php
1 |
|
如果有自定义配置文件,而且入口的
APP_DEBUG
不是为 true 的话,修改了默认的配置文件后,程序不会重新编译,需要重启才能生效。
控制配置路径:[应用名]\Home\Controller\IndexController.class.php
1 |
|
针对每个程序的配置,不会和其他程序公用
用户自定义配置文件
配置文件:\[应用名]\Common\Conf\config.php
1 |
|
新建:\[应用名]\Common\Conf\user.php
1 |
|
可以直接用 echo C('user');
来输出配置值
URL 模式
URL_MODEL
- 1 默认模式 pathinfo 模式
- 0 普通模式
- 2 重写模式
- 3 兼容模式
在配置文件:[应用名]\Home\Controller\IndexController.class.php
的 index 方法中加上:
1 | echo C('URL_MODEL'); |
来显示当前的URL模式。
U() 方法
U(‘模块/方法’, array(‘id’=>1), ‘xxx html htm sthml’, true/false, ‘localhost’);
- 参数2:URL后面传的值
- 参数3:后缀
- 参数4:是否需要跳转,true的话会加上 http://127.0.0.1前缀,(并直接跳转?)
- 参数5:域名
用来显示对应的完整的URL
示例
编辑配置文件:[应用名]\Home\Controller\IndexController.class.php
1 |
|
打开网站首页,运行结果:
1 | 1 |
访问网址localhost/ThinkPHP/index.php/Home/Index/user/id/1.html
,出现结果:
1 | id:1 |
修改URL模式
程序配置文件 \[应用名]\Common\Conf\config.php
加上配置项:
1 | 'URL_MODEL'=>0 |
或者可以在全局配置文件 \ThinkPHP\Conf\convention.php
中修改
模式说明
网站路径为:http://localhost/ThinkPHP/
- 1 默认模式:http://localhost/ThinkPHP/index.php/Home/Index/user/id/1.html
- 0 普通模式:http://localhost/ThinkPHP/index.php?m=Index&a=user&id=1
- 2 重写模式:http://localhost/ThinkPHP/Index/user/id/1.html 需要开启Apache的重写
- 3 兼容模式:http://localhost/ThinkPHP/index.php?s=/Home/Index/user/id/1.html
隐藏 index.php
即重写模式
打开 Apache 的配置文件 httpd.conf
,搜索 rewrite.so
,去除前面的 “#” 号
1 | #LoadModule rewrite_module modules/mod_rewrite.so // 去除前面的 # 号 |
重启 Apache
项目目录下建立一个文件:.htaccess
,写入以下内容:
1 | <Ifmodule mod_rewrite.c> |
分别是:开启重写引擎、重写判断条件、重写规则(正则)
404 Not Found : No input file specified
在Fastcgi模式下,php不支持rewrite的目标网址的PATH_INFO的解析,当我们的 ThinkPHP运行在URL_MODEL=2时,就会出现 No input file specified.的情况。
这时可以修改网站目录的.htaccess文件: 将RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]
改为RewriteRule ^(.*)$ index.php?s=$1 [QSA,PT,L]
URL 伪静态
把 shtml 改成和 html 一样作为后缀名来识别
全局配置文件,‘URL_HTML_SUFFIX' => ‘html’
在单个项目配置文件中(不建议改全局)改为:
1 | <?php |
伪静态有益于搜索引擎的抓取
自定义函数库
- 自动加载自定义函数文件
函数文件放在项目公共目录Common下。
项目目录下,需要在配置文件Conf/config.php
配置自动加载的函数文件的文件名。配置项为"LOAD_EXT_FILE"
,如"LOAD_EXT_FILE"=>"user,mysqldb"
表示在项目目录下Common/user.php
和Common/mysqldb.php
两个文件会自动加载。自动加载多项用逗号隔开。 - 手动加载函数文件
使用load函数,如load('@.myfunction');
表示系统会加载Common/myfunction.php
这个文件。 - 自动加载自定义类文件
类文件放在项目类库Lib下。
项目目录下,需要在配置文件Conf/conf.php
配置自动加载的函数文件的文件夹。配置项为'APP_AUTOLOAD_PATH' =>'‘,
,如'APP_AUTOLOAD_PATH' =>'@.Common'
,表示在项目目录下Lib/Common
文件夹下的类文件都会被自动加载,当然,类文件名要以***.class.php
文件命名。 自动加载多项用逗号隔开。 - 手动加载类文件
使用import()
函数。如import('@.Common.mysqldb');
则系统会加载Lib/Common/mysqldb.class.php
文件
模板技术
建立项目模板
模板路径: \[应用名]\Home\View\模块名\方法名.html
例如 Index 模块的 index 方法:\Application\Home\View\Index\index.html
使用模板
1 | $this->display(); // 默认 Index/index |
模板的赋值和输出
方法一:display()
\[应用名]\Home\Controller\IndexController.class.php
:
1 |
|
\[应用名]\Home\View\Index\index.html
:
1 | <html> |
结果:
Hello World~WXY
方法二:assign()
$this->assign('变量名', 变量值);
\Home\Controller\IndexController.class.php:
1 | $date = date("Y-m-d"); |
与直接赋值的区别在于,可以多次连续赋值
模板引擎
ThinkTemplate.class.php
:(文件位置未找到)
变量运算和输出
控制 \Home\Controller\IndexController.class.php
:
1 |
|
模板 \[应用名]\Home\View\Index\index.html
:
1 | Hello World~ <br /> |
注释是前面加两个斜杠。(也可以在中间加,但是可能会出错)
$me.sex|default='man'
如果 sex 没有定义,那么就能输出默认值。
算术运算可以使用+
、-
、*
、/
、++
、–-
,此时必须使用$me['age']
这种方式。
调用函数和系统参数
控制 \Home\Controller\IndexController.class.php
:
1 |
|
模板 \[应用名]\Home\View\Index\index.html
:
1 | MD5加密:{$me['name']|md5} |
函数等同于在控制文件中执行:
1 | echo substr(md5($me['name']), 0, 5); |
系统变量:
1 | 系统时间:{$Think.now} 输出格式化后的时间 |
volist和foreach循环
控制 \[应用名]\Home\Controller\IndexController.class.php
:
1 | // 套在外面的class等已略写 |
模板文件 \[应用名]\Home\View\Index\index.html
:
1 | name='原变量名' id='循环中的变量名' |
截取一部分:
1 | 从第二个到第三个 |
如果没有数据:
1 | 变量不存在时,输出empty中的内容 |
模板文件 \[应用名]\Home\View\Index\index.html
:
1 | name='原变量名' item='循环中的变量名' |
foreach 循环没有截取功能
for循环
- eq = neq !=
- gt > egt >=
- lt < elt <=
- heq === nheq !===
1 | <for start='1' end='10' comparison='elt' name='k'> |
等同于:
1 | for ($i = 0; $i < 10; $i++){ |
if 判断
1 | <if condition='$num gt 10'> num 大于 10 |
别忘了 <elseif />
和 <else />
后面结束的/
符号,如果没有则会继续运行到下一句(类似于break没写)。
switch 判断
1 | <switch name='peopleName'> |
同样别忘了 <default />
后面结束的/
符号
比较标签
1 | <比较标签 name='变量名' value='比较的值' > </比较标签> |
1 | <eq name='num' value='10'> num = 10 |
区间标签
- in 在区间里
- notin 不在区间里
- between 连续区间
- notbetween 不在连续区间
- range 只能替换 in 和 notin,不能替换 between
1 | <in name='num' value='1,2,3'> 在这个区间 |
三元运算符
1 | {$num > 10 ? '大于10' : '不大于10'} |
案例实战
判断人物有没有成年
1 | <foreach name='person' item='data'> |
原生态PHP标签
官方推荐使用<php>
而非<?php
,因为后者可能会被屏蔽掉。
1 | <html> |
ThinkPHP调试方法
开启调试模式 define('APP_DEBUG', true);
创建文件 \[应用名]\Conf\debug.php
:
1 |
|
控制 \Home\Controller\IndexController.class.php
:
1 |
|
访问路径:ThinkPHP路径/index.php/Index/user
输出:WXY_Debug
把define('APP_DEBUG', true);
取消后,就不会输出了
同名变量会覆盖普通配置的变量
数据库
连接数据库
配置文件:\[应用名]\Common\Conf\config.php
1 | <?php |
实例化模型
1、实例化基础模型
控制文件:[应用名]/Home/Controller/IndexController.class.php
1 |
|
2、实例化用户自定义模型
新建 Model 文件:[应用名]/Home/Model/[名字]Model.class.php
格式要规范,例如:UserModel.class.php
1 |
|
Think/Model 方法不存在 解决方法:
需要继承
RelationModel
,引入use Think\Model\RelationModel ;
1
2
3
4 > use Think\Model\RelationModel ;
> class UserModel extends RelationModel { /*...*/ }
>
>
Controller 文件:
1 | // $user = new UserModel(); // 要放到 Home\Controller 下才能用 |
如果 Model 文件不存在,D()
方法会自动执行M()
方法,即构建基础Model
3、实例化公共模型
能进行一些通用的方法
新建 Model 文件:[应用名]/Home/Model/CommonModel.class.php
1 |
|
Controller 文件:
如果提示找不到 CommonModel,顶部加上声明:
use Home\Model\CommonModel;
1 | public function index(){ |
用户自定义公共模型
自定义的XxxModel
不要继承Model
,继承CommonModel
,CommonModel
再继承自RelationModel
4、实例化空模型
Controller 文件:
1 | $model = M(); |
CURD操作
插入数据
controller 文件:
1 | $data = array( |
插入多条数据
addAll() 方法 (只适合MySQL)
1 | $data = array( |
查询数据
M(‘User’)->select() 会查询两次:
- Show columns from `user`
- SELECT * from `user`
如果 debug
开启,那么每次 SELECT
前都会查询字段,并缓存起来。
1、带条件查询:
1 | $data = M('User')->where('id=1')->select(); |
2、多个条件查询:
1 | $where['id'] = 1; |
3、表达式查询:
1 | $where['id'] = array('gt', 1); // id > 1 |
4、区间查询
1 | $where['id'] = array(array('gt',1), array('lt',10)); // 1<id<10,默认 AND 运算 |
5、混合用法
1 | $where['id'] = array('gt', 10); |
尽量不要用字符串方式,表达式查询会进行字符串格式化,安全
6、统计用法
1 | $data = M('User')->count(); |
更新数据
1 | $where['id'] = 1; |
删除数据
1 | $where['id'] = 1; |
1 | echo M('User')->delete(3); // 主要传入主键值(也只能传主键值) |
连贯操作
排序 order
1 | $data = M('User')->order('score desc, id asc')->select(); // score从大到小,ID、从小到大 |
筛选数据 field
field($string, false);
- 参数一 string 传入多个字段用英文逗号分开
- 参数二默认为false,即只显示string中的字段;为true时只有string中的字段不显示
1 | $data = M('User')->field('id, username')->select(); // 只显示 id 和 username |
限制数据量 limit 和 page
1 | $data = M('User')->limit(5)->select(); // 0 ~ 5,序号从0开始 |
1 | $data = M('User')->page(1)->select(); // 第一页,参数二默认每页20条 |
分组 group 和 having
1 | M('User')->field('score, count(*) as total')->group('score')->select(); // 每个成绩的数据数量 |
输出结果示例:
1 | arrar(10) { |
having
1 | M('User') |
多表查询
table 方法
table(array('完整表名'=>'别名'))
如果有前缀,表名一定要加前缀(M方法中的表名参数不用加config中设置的前缀)
1 | M()->table(array('tb_user'=>'user', 'tb_info'=>'info')) |
join 方法
1 | M('User') |
union 方法
union(string/array, false/true)
- 参数二默认false,使用union查询;true 为uni查询(去掉重复结果)
1 | M('User') |
查询字段的类型(包括field和union中的顺序)必须是一样的
过滤查询 distinct
1 | $data = M('User')->distinct(true)->field('score')->order('score asc')->select(); // 参数 true 为过滤 |
关于命名范围的使用
查询分数超过60的
[应用名]/Home/Model/UserModel.class.php
1 |
|
[应用名]/Home/Controller/IndexController.class.php
1 | public function fanwei() |
如果两个命名范围冲突(如一个 limit 10,另一个 limit 5,则后面的会覆盖前面的),没冲突(例如 where 条件)则会用 AND 连接