ThinkPHP

框架下载地址:版本5.0.24

http://www.thinkphp.cn/down/framework.html

TP5

1
2
3
4
5
6
7
8
9
10
11
12
13
14
tp5
├─application 应用目录
├─extend 扩展类库目录(可定义)
├─public 网站对外访问目录
├─runtime 运行时目录(可定义)
├─vendor 第三方类库目录(Composer)
├─thinkphp 框架核心目录
├─build.php 自动生成定义文件(参考)
├─composer.json Composer定义文件
├─LICENSE.txt 授权说明文件
├─README.md README 文件
├─think 命令行工具入口

如果在linux环境下面的话,需要给runtime目录755权限。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
├─thinkphp 框架系统目录
│ ├─lang 语言包目录
│ ├─library 框架核心类库目录
│ │ ├─think think 类库包目录
│ │ └─traits 系统 traits 目录
│ ├─tpl 系统模板目录
│ │
│ ├─.htaccess 用于 apache 的重写
│ ├─.travis.yml CI 定义文件
│ ├─base.php 框架基础文件
│ ├─composer.json composer 定义文件
│ ├─console.php 控制台入口文件
│ ├─convention.php 惯例配置文件
│ ├─helper.php 助手函数文件(可选)
│ ├─LICENSE.txt 授权说明文件
│ ├─phpunit.xml 单元测试配置文件
│ ├─README.md README 文件
│ └─start.php 框架引导文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
├─application           应用目录(可设置)
│ ├─index 模块目录(可更改)
│ │ ├─config.php 模块配置文件
│ │ ├─common.php 模块公共文件
│ │ ├─controller 控制器目录
│ │ ├─model 模型目录
│ │ └─view 视图目录
│ │
│ ├─command.php 命令行工具配置文件
│ ├─common.php 应用公共文件
│ ├─config.php 应用配置文件
│ ├─tags.php 应用行为扩展定义文件
│ ├─database.php 数据库配置文件
│ └─route.php 路由配置文件

引导文件

start.php文件就是系统默认的一个引导文件

在引导文件中,会依次执行下面操作:

  • 加载系统常量定义;
  • 加载环境变量定义文件;
  • 注册自动加载机制;
  • 注册错误和异常处理机制;
  • 加载惯例配置文件;
  • 执行应用;

start.php引导文件首先会调用base.php基础引导文件,某些特殊需求下面可能直接在入口文件中引入基础引导文件

控制器与模板跳转

控制器->模板

内置了一个基于XML的编译型模板引擎

控制器类继承think\Controller类之后,可以直接使用封装好的assign和fetch方法进行模板变量赋值和渲染输出

控制器

1
2
3
4
5
6
7
8
9
10
11
12
public function index()
{
$data = Db::name('data')--->find();
$this->assign('result', $data);
$this->assign([
'temp_id'=>$temp_id,
'templateinfo'=>$temptinfo,
'members'=>$mems
]);
return $this->fetch();
return $this->fetch('add');//
}

视图

1
2
3
{$result.id}--{$result.data}//1--thinkphp

模板标签的用法和Smarty类似,就是用于输出数据的字段,这里表示输出think_data表的id和data字段的值。

若fetch方法中没有指定任何模板,则按照系统默认的规则(视图目录/控制器/操作方法)输出了view/index/hello.html模板文件

模板->控制器

5.0的URL访问受路由决定,如果关闭路由或者没有匹配路由的情况下,则是基于

1
http://serverName/index.php(或者其它应用入口文件)/模块/控制器/操作/参数/值...

重定向:return $this->redirect(‘index/login/index’);(模块名/控制器/方法)

系统渲染模板 return view(‘index/login/index’);//不经过方法,直达视图

或者return this>fetch(),默认模板。this->fetch(),默认模板。this->fetch(‘XXX’),指定跳到xxx模板,与view()相同

thinkphp视图中{:url()}或者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//配合ajax的提示后的加载
$("#addForm").submit(function(){
// $('#save').attr('disabled',true);
$.ajax({
url: "{:\\think\\Url::build('contract/addfirst')}",
data: $(this).serialize(),
dataType: "json",
type: "post",
success: function(data){
if (data.code==1) {
if (data.code === 1) {
parent.layer.msg(data.msg, {icon: 1, time: 1500});
window.location.href = "{:\\think\\Url::build(\'contract/contractfirst\')}";
} else {
parent.layer.msg(data.msg, {icon: 2});
}
} else {
parent.layer.msg('服务器错误,请重试', {icon: 2});
}
},

});
return false;
});

模块和模块之间的关系

其他

数据库配置文件application/database.php中添加数据库的连接信息

添加模块

1
php think build --module demo(模块名)

调试模式: 应用配置文件(application/config.php)

1
2
3
// 关闭调试模式
'app_debug' => false,
避免泄露你的服务器WEB目录信息等资料,一定记得正式部署的时候关闭调试模式。

命名空间

app命名空间通常表示文件的起始目录为application,而think命名空间则表示文件的目录为thinkphp/library/think

有几个关键的路径

1
2
3
4
5
tp5	            项目根目录	       ROOT_PATH
tp5/application 应用目录 APP_PATH
tp5/thinkphp 框架核心目录 THINK_PATH
tp5/exend 应用扩展目录 EXTEND_PATH
tp5/vendor Composer扩展目录 VENDOR_PATH

路由共有4种形式

  1. 基本get形式
    http://域名/index.php?m=分组&c=控制器&a=操作方法
    该方式是最底层的get形式、传统的参数传递方式,不时尚、不安全。
  2. pathinfo路径形式[默认方式]
    http://域名/index.php/分组/控制器/操作方法
    http://域名/index.php/Home/Index/advert
  3. rewrite重写形式(伪静态技术)省略index.php入口文件
    http://域名/分组模块/控制器/操作方法(用过了)
    http://域名/Home/Index/index
  4. 兼容形式
    http://域名/index.php?s=/分组/控制器/操作方法
    http:/域名/index.php?s=/Home/Index/advert

参考链接:

https://www.w3cschool.cn/thinkphp/xi581rtn.html

https://blog.csdn.net/voke_/article/details/78766663
https://blog.csdn.net/weixin_39768635/article/details/78195443

数据库配置文件:

1
2
yunyi\application\extra\database_news.php(数据库配置文件)
yunyi\application\database.php(这个才是)

sql调用:

原生的:

TP的模型可以支持原生SQL操作,提供了query和execute两个方法

query用于查询,返回的是数据集,和select或者findall一样,所以可以直接在模板里面使用volist标签输出query的查询结果,注意query是查功能、插入

execute用于写操作,返回的是状态或者影响的记录数,注意execute是增删改功能

只是需要new一个空的模型继承Model中的方法

1
2
3
4
5
6
$Model = new Model();//或者 $Model = D(); 或者 $Model = M();
$sql = "select * from `order`";
$voList = $Model->query($sql);

Db::query("select * from think_user where status=1");
如果你当前采用了分布式数据库,并且设置了读写分离的话,query方法始终是在读服务器执行,因此query方法对应的都是读操作,而不管你的SQL语句是什么。

增删改

1
2
3
4
$voList = $Model->execute('update think_user set status=1 where id=1');

Db::execute("update think_user set name='thinkphp' where status=1");
如果你当前采用了分布式数据库,并且设置了读写分离的话,execute方法始终是在写服务器执行,因此execute方法对应的都是写操作,而不管你的SQL语句是什么。
封装的:

增(add)

1
2
3
4
5
6
7
8
9
$model = M('WxuserCollection');
$data = array('user_id' = >$user_id, 'store_id' = >$store_id, 'good_id' = >$good_id, 'addtime' = >$addtime);
$model - >data($data) - >add();

$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

改(edit)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$model = M('WxuserCollection');
$data = array('user_id' = >$user_id, 'store_id' = >$store_id, 'good_id' = >$good_id, 'addtime' = >$addtime);
$model - >data($data) - >where('id=3') - >save();

$goods=D("emptest");
$goods->name="Cool";
$goods->garde="2";
$goods->email="Cool@qq.com";
$goods->salary="7777";
$goods->where('id=2')->save();

$goods=M("emptest");
$arr=array('id'=>'7','name'=>'xu2xuning','salary'=>5555);
$res=$goods->save($arr);

查(find与select,field,order,join,getField)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$model = M('WxuserCollection');
$res1 = $model - >find(1);
$res2 = $model - >find(2);
$res3 = $model - >where('good_id=1105 AND store_id = 1 AND user_id = 20') - >find();

find(1)获取id为1的数据,find(2)获取id为2的数据。最后一个是获取条件为where的中的第一条数据
$model = M('WxuserCollection');
$res = $model - >where('good_id=1105 AND store_id = 1 AND user_id = 20') - >field('id,good_id as good') - >select();
获取所有数据。这里的好处就是,不用考虑sql语句的顺序了,随心所欲调用函数就可以了

$res = $model - >field('id,good_id as good') - >select();
$res = $model - >field(array('id', 'good_id' = >'good')) - >select();
$res = $model - >field('id', true) - >select();
字符串,数组两种方式,第三个是表示获取处理id之外的所有字段

$res = $model - >order('id desc') - >select();
$res = $model - >order(array('id' = >'desc')) - >select();
字符串,数组两种方式,默认asc。

$Model->join(' work ON artist.id = work.artist_id')->join('card ON artist.card_id = card.id')->select();
$Model->join('RIGHT JOIN work ON artist.id = work.artist_id')->select();
$Model->join(array(' work ON artist.id = work.artist_id','card ON artist.card_id = card.id'))->select();
默认采用LEFT JOIN 方式,如果需要用其他的JOIN方式,可以改成第二种,
如果join方法的参数用数组的话,只能使用一次join方法,并且不能和字符串方式混合使用。

getfield

1
2
3
4
5
6
7
8
9
10
11
// 获取ID为3的用户的昵称 ,即使有满足条件的多个字段,也只会返回一个结果
$nickname = $User->where('id=3')->getField('nickname');
返回的nickname则是一个数组,包含了所有满足条件的昵称列表。
$nickname = $User->where('status=1')->getField('nickname',true);
限制返回结果数量
$nickname = $User->where('status=1')->getField('nickname',8);

2字段名称的话,默认返回一个关联数组,以第一个字段的值为索引(所以第一个字段要尽量选择不会重复的)
$nickname = $User->where('status=1')->getField('id,nickname');
2个以上的字段名,则返回一个二维关联数组(类似select方法的返回值,区别在于索引是二维数组的键名是第一个字段的值)
$result = $User->where('status=1')->getField('id,account,nickname');

删(delete)

1
2
3
4
5
$model = M('WxuserCollection');
$res = $model - >where('id=1') - >delete(); // 成功返回1 失败返回0
$model->delete(9);//删除指定主键的数据行
$model->delete(”1,2,3“);//也可以删除多个主键的值得行,一定要带引号
$model->where("id>=13 and id<=18")->delete();//条件性的删除操作

实践

1
2
3
4
$where = array('a.store_id' => $this->store_id, 'a.user_id' => $this->user_id);
$collects = $this->collectModel->table("sh_wxuser_collection a")->field(array('b.name','b.price','b.oprice','b.logoimg','a.goods_id'))->limit($start, $offset)->order('a.addtime DESC')->where($where)->join(' sh_goods b ON a.goods_id = b.id')->select();// 获取当前页的记录
echo M()->getLastSql(); // 调试sql语句用
$count = $this->collectModel->table("sh_wxuser_collection a")->where($where)->count(); // 获取总的记录数

参考链接: https://www.cnblogs.com/jiqing9006/p/4975293.html

OOP与AOP

Aspect Oriented Programming(AOP) 面向切面编程

例如:对 “权限检查”这一动作片断进行封装

Object Oriented Programming (OOP)面向对象编程

例如:将“雇员”相关的属性和行为封装入 “Employee”类中