【CTF部分基础知识二之PHP(二十八)】

ThinkPHP简介

ThinkPHP框架可以方便、快捷地进行项目开发和部署应用,而且不仅是企业级应用,任何PHP应用开发都可以从ThinkPHP的简单和快速的特性中受益。ThinkPHP本身具有很多的原创特性,并且倡导“大道至简,开发由我”的开发理念,用最少的代码完成更多的功能,其宗旨就是让Web应用开发更简单、更快速。

ThinkPHP是一个性能卓越并且功能丰富的轻量级PHP开发框架,有多个版本。

主要新特性主要新特性如下:
☑ 采用PHP7强类型(严格模式)。
☑ 支持更多的PSR规范。
☑ 多应用支持。
☑ ORM组件独立。
☑ 改进的中间件机制。
☑ 更强大和易用的查询。
☑ 全新的事件系统。
☑ 支持容器invoke回调。
☑ 模板引擎组件独立。
☑ 内部功能中间件化。
☑ SESSION机制改进。
☑ 缓存及日志支持多通道。
☑ 引入Filesystem组件。
☑ 对Swoole以及协程支持改进。
☑ 对IDE更加友好。
☑ 统一和精简大量用法。

ThinkPHP基础

资源包ThinkPHP遵循简洁实用的设计原则,兼顾开发速度和执行速度的同时,也注重易用性。

  1. MVC设计模式
    MVC是一种经典的程序设计理念,此模式将应用程序分为3个部分:模型层(Model)、视图层(View)和控制层(Controller)。MVC是这3个部分英文字母的缩写。

说明
MVC设计模式产生的原因:应用程序中用来完成任务的代码——模型层(也叫业务逻辑层),通常是程序中相对稳定的部分,重用率高;而与用户交互的界面——视图层,却经常改变。如果因需求变动而不得不对业务逻辑代码修改,或者要在不同的模块中应用相同的功能而重复地编写业务逻辑代码,不仅会降低整体开发的进度,也会使未来的维护变得非常困难。因此,将业务逻辑代码与外观界面分离,可更方便地根据需求改进程序,这就是MVC设计模式。

  1. 入口文件
    用户请求的PHP文件,负责处理一个请求(注意,不一定是URL请求)的生命周期。入口文件位于public目录下面,最常见的入口文件就是index.php。
  2. 应用
    ThinkPHP 每个应用都是一个app目录的子目录(或者指定的composer库),每个应用都具有独立的路由、配置,以及MVC相关文件。这些应用可以公用框架核心以及扩展,而且可以支持composer应用加载。
  3. 路由
    路由用于规划(同时也会进行简化)请求的访问地址,在访问地址和实际操作方法之间建立一个路由规则,映射路由地址间的关系。
    ThinkPHP并不强制使用路由。如果没有定义路由,可以直接使用“控制器/操作”的方式进行访问。如果定义了路由,则该路由对应的路由地址就不能直接访问了。一旦开启强制路由参数,就必须为每个请求定义路由(包括首页)。
    使用路由有一定的性能损失,但随之也会更加安全。因为每个路由都有自己的生效条件,如果请求不满足条件,将会被过滤掉。这远比用户在控制器操作中进行各种判断要实用得多。路由的作用不只是规范URL,还可以实现验证、权限、参数绑定及响应设置等功能。
  4. 容器
    ThinkPHP使用(对象)容器统一管理对象实例及依赖注入。容器类的工作由think\Container类完成,但大多数情况下都是通过应用类(think\App类)或是app助手函数来完成容器操作。可以为容器中的对象实例绑定一个对象标识,如果没有绑定则使用类名作为容器标识。
  5. 系统服务
    系统服务的概念是指在执行框架的某些组件或者功能的时候需要依赖的一些基础服务,服务类通常可以继承系统的think\Service类,但并不强制。可以在系统服务中向容器中注册一个对象,或者对某些对象进行相关的依赖注入。由于系统服务的执行优先级问题,可以确保相关组件在执行的时候已经完成相关依赖注入。
  6. 控制器
    每个应用都拥有独立的类库及配置文件,一个应用下面有多个控制器负责响应请求。控制器其实就是一个独立的控制器类,主要负责请求的接收,并调用相关的模型处理,最终通过视图输出。严格来说,控制器不应该过多地介入业务逻辑处理。

说明
事实上,控制器是可以被跳过的。通过路由可以把请求直接调度到某个模型或者其他的类进行处理。

  1. 操作
    一个控制器包含多个操作(方法),操作方法是一个URL访问的最小单元。
  2. 模型
    模型类通常完成实际的业务逻辑和数据封装,并返回和格式无关的数据。模型类并不一定要访问数据库,而且在ThinkPHP的架构设计中,只有在进行实际的数据库查询操作时,才会进行数据库连接,是真正的惰性连接。
    ThinkPHP的模型层支持多层设计,可以对模型层进行更细化的设计和分工。例如,把模型层分为逻辑层、服务层、事件层等。
  3. 视图
    控制器调用模型类后,返回的数据通过视图组装成不同格式被输出。视图会根据不同的需求,确定是调用模板引擎进行内容解析后输出还是直接输出。
    视图通常会有一系列的模板文件,对应不同的控制器和操作方法,并且支持动态设置模板目录。
  4. 模板引擎
    模板文件中可以使用一些特殊的模板标签,这些标签的解析通常由模板引擎负责实现。新版不再内置think-template模板引擎,如果需要使用ThinkPHP官方模板引擎,则需要单独安装think-view模板引擎驱动扩展。

路由

路由是应用开发中比较关键的一个环节,其主要作用包括但不限于以下几个方面。
☑ 让URL更加规范和优雅。
☑ 隐式传入额外请求参数。
☑ 统一拦截并进行权限检查等操作。
☑ 绑定请求数据。
☑ 使用请求缓存。
☑ 路由中间件支持。
路由在框架中的作用好比是Web应用的总调度室,对于访问的URL地址,路由可以拒绝或者接受某个URL请求,并进行分发调度。
定义路由必须在应用的路由定义文件中完成。路由的定义和检测是针对应用的,因此如果采用多应用模式,而每个应用的路由都是完全独立的,那么路由定义文件应放在应用目录下,并且路由地址不能跨应用(除非采用重定向路由)。

路由模式
ThinkPHP中路由比较灵活,不要求强制定义。主要包括默认模式和强制模式两种,通过config/route.php文件的url_route_must参数进行配置。
☑ 默认模式的参数配置如下:

'url_route_must' => false,

在默认模式下,采用ThinkPHP框架默认的PATH_INFO模式访问URL,代码如下:

http://serverName/index.php/app/controller/action/param/value/...

☑ 强制模式的参数配置如下:

'url_route_must' => true,

在强制模式下,必须严格给每一个访问地址定义路由规则(包括首页),否则将抛出异常。

定义路由

路由文件的默认路径为route/app.php。其中,app.php文件中包含如下代码:

use think\facade\Route;
Route::get('think', fun
ction() {    return 'hello,Think
PHP6!';});Route::get('hello/:name
', 'index/hello');

定义路由有两种模式:常规模式和快捷方法名模式。

  1. 常规模式
    常规模式定义方法如下:
Route::rule('路由表达式', '路由地址', '请求类型');
  1. 快捷方法名模式
    使用快捷方法名模式定义路由的方法如下:
Route::快捷方法名('路由表达式', '路由地址');

路由表达式

无论是使用“Route::rule()”还是使用“Route::快捷方法名()”定义路由,其第1个参数都是路由表达式。路由表达式统一使用字符串定义,采用规则表达式定义的方式。

路由地址

路由地址表示定义的路由表达式最终需要路由的地址以及一些需要的额外参数。

路由分组

路由分组功能允许把相同前缀的路由定义合并分组,这样可以提高路由匹配的效率,不必每次都去遍历完整的路由规则。实现路由分组可以使用Route类的group方法。

MISS路由

  1. 全局MISS路由
    当所有的路由规则都无法匹配时,如果希望执行一条设定的路由,可以使用MISS路由功能。使用miss方法可以注册一个MISS路由。
  2. 分组MISS路由
    分组支持独立的MISS路由。

控制器

控制器的定义

控制器就是MVC设计模式中的C(Controller),通常用于读取视图V(View)、完成用户输入以及处理模型数据M(Model)。控制器类文件的实际位置是app\index\controller\Index.php。

重定向

使用redirect助手函数可以实现页面的重定向功能。

数据库

新版的数据库和模型操作已经独立为ThinkORM库,在安装应用的时候会自动安装。如果不需要使用该ORM库,则可以单独卸载topthink/think-orm后安装其他的ORM库。

数据库的连接

如果应用需要使用数据库,必须配置数据库连接信息。

数据库基础操作
对数据库进行操作需要使用Db类。要使用Db类,首先需要在类文件中引入该类,代码如下:

use think\facade\Db;
  1. 查询数据
    1)基本查询
    查询一条数据使用find方法,示例代码如下:
Db::table('think_book')->where('id', 1)->find();

table方法中,必须指定完整的数据表名;find方法中,如果查询结果不存在,则返回null。
查询数据集使用select方法,示例代码如下:

Db::table('think_book')->where('status', 1)->select();

select方法中,如果查询结果不存在,则返回空数组。
如果设置了数据表前缀参数,可以使用如下代码:

Db::name('book')->where('id', 1)->find();
Db::name('book')->where('status', 1)->select();

如果数据表没有使用表前缀功能,那么使用name和table方法的效果是一样的。
在find和select方法之前可以使用所有的链式操作方法。默认情况下,find和select方法返回的都是数组。

2)值和列查询
查询某个字段的值使用value方法,示例代码如下:

Db::table('book')->where('id', 1)->value('name');  //返回某个字段的值

使用value方法,当查询结果不存在时,返回null。
查询某一列的值使用column方法,示例代码如下:

Db::table('book')->where('status', 1)->column('name');           //返回数组
Db::table('book')->where('status', 1)->column('name','id');      //指定索引

使用column方法,当查询结果不存在时,返回空数组。

  1. 添加数据
    1)添加一条数据
    使用Db类的save方法可以向数据库中统一写入数据,在写入时自动判断是新增数据还是更新数据,代码如下:
$data = ['name' => ' C++从入门到精通', 'price' => 49.8];
Db::table('book')->save($data);

或者使用Db类的insert方法向数据库提交数据,代码如下:

$data = ['name' => ' C++从入门到精通', 'price' => 49.8];
Db::table('book')->insert($data);

如果在database.php配置文件中配置了数据库前缀(prefix),则可以直接使用Db类的name方法提交数据,代码如下:

Db::name('book')->insert($data);

insert方法添加数据成功后会返回添加成功的条数,正常情况下返回1。添加数据后,如果需要返回新增数据的自增主键,可以使用insertGetId方法新增数据并返回主键值:

$bookId = Db::name('book')->insertGetId($data);

insertGetId方法添加数据成功,将返回添加数据的自增主键。
2)添加多条数据
添加多条数据时,直接向Db类的insertAll方法传入需要添加的数据即可。代码如下:

$data = [
     ['name' => 'C#从入门到精通', 'price' => 59.8],    
     ['name' => ' VB从入门到精通', 'price' => 49.8],     
     ['name' => '.NET从入门到精通', 'price' => 69.8]     ];
Db::name('book')->insertAll($data);

insertAll方法添加数据成功,将返回添加成功的条数。
3. 更新数据
1)更新数据表中的数据
更新数据表中的数据可以使用save方法,代码如下:

Db::table('book')->save(['id' => 1, 'name' => 'thinkphp']);

或者使用update方法,代码如下:

Db::table('book')->where('id', 1)->update(['name' => 'thinkphp']);

如果数据中包含主键,可以直接使用:

Db::table('book')->update(['name' => 'thinkphp', 'id'=>1]);

update方法返回影响数据的条数,如果未修改任何数据,则返回0。
如果要更新的数据需要使用SQL函数或者其他字段,可以使用下面的方式:

Db::table('book') ->where('id', 1) ->exp('publish_date','now()')  ->update();

2)自增、自减某个字段的值
可以使用inc或dec方法自增或自减一个字段的值。如不添加第二个参数,则默认值为1。

Db::table('book')->where('id', 1)->inc('count')->update();       //count字段加1
Db::table('book')->where('id', 1)->inc('count', 5)->update();    //count字段加5
Db::table('book')->where('id', 1)->dec('count')->update();       //count字段减1
Db::table('book')->where('id', 1)->dec('count', 5)->update();    //count字段减5
  1. 删除数据
    删除数据表中的数据使用delete方法,代码如下:
//根据主键删除
Db::table('book')->delete(1);Db::tabl
e('book')->delete([1, 2, 3]);			//条件删除Db::tabl
e('book')->where('id', 1)->delete();
Db::table('book')->where('id', '<', 10)->delete();

delete方法返回影响数据的条数,如果没有删除,则返回0。
5. 查询方法
查询表达式支持大部分的SQL查询语法,也是ThinkPHP查询语言的精髓,使用格式如下:

where('字段名', '查询表达式', '查询条件');
whereOr('字段名', '查询表达式', '查询条件');

1)where方法
使用where方法进行AND条件查询,代码如下:

Db::table('book')  ->where('name', 'like', '%thinkphp')  ->where('status', 1) ->find();

多字段相同条件的AND查询可以简化为如下方式:

Db::table('book')->where('name&title', 'like', '%thinkphp') ->find();

使用字符串条件进行AND查询,代码如下:

Db::table('book')->whereRaw('name like "%thinkphp" AND status=1')->find();

2)whereOr方法
使用whereOr方法进行OR查询,代码如下:

Db::table('book') ->whereOr('name', 'like', '%thinkphp') ->whereOr('title', 'like', '%thinkphp') -find();

多字段相同条件的OR查询可以简化为如下方式:

Db::table('book') ->where('name|title', 'like', '%thinkphp')->find();

使用字符串条件进行OR查询,代码如下:

Db::table('book')->whereRaw('name like "%thinkphp" OR status=1')->find();

模型

模型的主要作用是封装数据库的相关逻辑。也就是说,每执行一次数据库操作,都要遵循定义的数据模型规则来完成。

模型的定义

模型类通常需要继承系统的\Think\Model类或其子类,下面是一个User模型类的定义:

namespace app\model;
use think\Model;class User extends Model {}

说明
请确保已经在数据库配置文件中配置了数据库连接信息。

视图

视图功能由\think\View类配合视图驱动(模板引擎)类一起完成,新版仅内置了PHP原生模板引擎(主要用于内置的异常页面输出),如果需要使用其他的模板引擎需要单独安装相应的模板引擎扩展。
如果需要使用think-template模板引擎,只需要安装think-view模板引擎驱动。执行命令如下:

composer require topthink/think-view

模板

ThinkPHP内置了一个基于XML的性能卓越的模板引擎,其使用了XML标签库技术的编译型模板引擎、动态编译和缓存技术,而且支持自定义标签库。

  • 19
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Liana-Fany

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值