目录
ThinkPHP-MVC简介
ThinkPHP是一个免费开源的,快速、简单的面向对象的轻量级PHP开发框架,简洁快速是它的一大特点,同时他也是使用了MVC的框架模式。本篇文章将会从安全的角度重新理解ThinkPHP。
MVC模式
什么是MVC模式
MVC即Model View Controller,模型,视图,控制器。为什么会有这个东西呢,答案是为了更科学的编写代码,降低代码的耦合性,等价聚合性。
模型
模型表示数据库模型,是为了更方便的操作数据库而出现的,使用模型层之前需要实现绑定数据库。
模型会自动对应数据表,模型类的命名规则是除去表前缀的数据表名称,采用驼峰法命名,并且首字母大写:
模型名称 | 约定数据表(前缀think) |
---|---|
User | think_user |
Type | think_type |
当模型和数据表对应之后,数据库的查询会非常简单,例如:
//没有模型
Db::name('user')->where('id','>',10)->select();
//有模板后
User::where('id','>',10)->select();
当然模板的好处可不止这些,可以对绑定的数据表书写不同的功能,例如:获取器,修改器,搜索器
通过各个功能的叠加也可以自己制作更多的方法,从而实现 增强数据库的作用
从而极大的简化控制器的代码,也方便后期的修改于重构。
视图
视图就是我们所见到的页面的 雏形,通常由前端工程师完成,视图需要由来自于模板的数据渲染后才可以呈现出真正是页面——动态页面。
视图的主要完成的操作除了对网站的基本图像构建以外,还要告诉 渲染器如何渲染页面。
-
变量
对于一个简单的变量而言,只需要用
{$name}
就可以定义,此处就是定义了一个name的变量在前端页面中,当渲染的时候,控制器传入name变量的时候,就可以直接进行替换,例如:例如:
hello,{$name}! //模板编译之后 hello !
当然此处的模板渲染开始标志
{}
是可以在设置中修改的当然对于数组可以使用使用
.
或者[]
获取,例如:Name:{$data.name} Name:{$data['name']}
都是可以的
字典也可以使用
—>
来访问,也可以使用:
来访问,例如:Name:{$data:name} Name:{$data->name}
-
函数
如果只是这样赤裸裸的使用数据,那么对于前端工程师来说是不公平的,为了实现更多功能,渲染变量还有一些操作符,官方文档叫做函数,也可以叫做装饰器。
对于这样一个例子:
{$data.name|md5}
它被渲染(编译)后得到的结果是:
这也是人家为什么叫函数的原因
对于需要传参的函数,我们也可以直接传入,例如:
{$name|md5|strtoupper|substr=0,3}
结果就是:
此处可以使用的函数很多,php自带的,自己写的,甚至是静态方法都可以传入。
-
内置标签
设想下面的一种情况,当我们需要渲染某个商品,但是商品的数量和信息需要后端传入,这时候要怎么办呢?
这个问题难点在于后端输入的数据数量不知道,也就是对应前端的某些标签数量不清楚。
那么有没有一种可以循环写标签的功能呢?
-
Volist标签
volist标签用于处理数据库输出的数据,可以直接对数据进行输出,看一个例子:
{$vo.id}:{$vo.name}
它的数据来源于:
$User = M('User'); $list = $User->limit(10)->select(); $this->assign('list',$list);
对于上面的volist数据,name属性是这 模板赋值的变量名称, 后面的id是在此次循环中的变量名称,然后会更加多个数据进行 循环输出输出个数完全取决于后端输出。
-
foreach标签
foreach是一个更为简单的循环,是volist的简化版,例如:
{$k}|{$vo} 这个例子中,name就是赋值变量,item是循环变量,key是索引名
相比于volist,foreach则是指定了一些特定的变量名来循环,不向volist那样可以直接调用所有的变量。
-
for标签
说起循环就不能没有for标签:
开始值、结束值、步进值和循环变量都可以支持变量,开始值和结束值是必须,其他是可选。comparison 的默认值是lt;;name的默认值是i,步进值的默认值是1,举例如下:
{$i} 进过解析之后就会得到一个php标准的for循环:
for ($i=1;$i<100;$i+=1){ echo $i; }
-
switch标签
switch是一个非常经典的操作符号,表示选择,而在前端标签中,switch也是十分重要的,看一个例子:
输出内容1 输出内容2 默认情况 其实当这个例子放上去之后就已经非常清楚明了了,但我们需要理一下这个逻辑
switch有一个属性name,是变量的来源通常是传入的数据赋值的数据
case标签又两个属性,标签中间是输出的内容,两个属性的意思分别是对比的值value和是否要break
default就是缺省。
-
IF标签
value1 value2 value3 if标签需要注意的就是判断操作符号是在conditioin中完成的,但是由于标签占用了<>符号,所以对比的时候不能使用大于小于符号,需要使用
eq,rt,lt
等指令操作
-
通过这些操作就可以快速上手模板的开发。
控制器
控制器是一个联通 模型和 视图的重要部分,下面就来详细讨论下控制器如何在MVC中发挥重要的作用呢
按照ThinkPHP的架构设计,所有的URL请求(无论是否采用了路由),最终都会定位到控制器(也许实际的类不一定是控制器类,但也属于广义范畴的控制器)。
对于控制器而言,由于它通常位于app目录下(Thinkphp6.0+)的controller文件夹下,对于任意一个控制器而言他的类名应当和文件名相同,并且规定一个控制器下 只能有一个类
下面让我们看一下MVC的访问流程:
当我们访问index.php的时候,发送的请求通过多个中转后会到达控制器中,然后控制器选择一个操作,然后执行操作中的代码,这个过程可以使用事先写好的模型模板来从数据库中获取数据,然后把数据发送到视图去渲染。
简单使用
控制器
我们简单做个MVC模式的网站,来用一下前面的内容,主要是感受下MVC模式在项目的应用。
MVC的三个文件都需要放在app目录下,分别创建三个文件夹model
view
controller
,
先写控制器文件:
<?php
namespace app\controller;
use app\BaseController;
use think\facade\View;
use app\model;
class Index extends BaseController
{
public function index(): string
{
dump(view::fetch());
return view::fetch();
}
public function hello(): string
{
dump(view::fetch());
return view::fetch();
}
public function login(): \think\response\View
{
dump(view('index/login',['name'=>'libestor6666','qq'=>'libestor.top']));
return view('index/login',['name'=>'libestor6666','qq'=>'libestor.top']);
}
public function alluser()
{
$user = new model\User();
$data1 = $user->select();
dump($data1);
View::assign('list',$data1);
return view::fetch();
}
}
这个文件中,index操作是简单渲染,单纯就是让控制器渲染一下文件
之后的login是一个渲染文件,他会向login.html模板中输入name
和qq
的值
第三个则是先调用模型User,获得所有数据,接着把查询到的数据发送给alluser模板来渲染。
模板
模板文件名称就是User.php,然后写入内容
<?php
namespace app\model;
use think\Model;
class User extends Model{
}
此处只是简单的时候,没有太多的数据处理,所以只使用原生的方法即可
之后我们像配置连接数据库,并且给数据库中写入一些数据:
其中表头是think_ 库名是tplast6,
之后我们创建一个tplast6
的库,并创建一个think_user
的表,在里面写入三组数据
视图
视图文件需要和控制器相互对应起来(也可以指指定,但是对应起来好操作,明了)
像上面的例子,在控制器Index中,有四个操作,我们使用四个文件:
到此文件就创建好了,主要看一下有参数传入的login.php和alluser.php
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
username:{$name}
<br>
qq:{$qq}
</body>
</html>
alluser.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{$list}
</body>
</html>
没有使用内置标签渲染,就直接打印了结果
结果
(只展示alluser):
可以看到成功得到渲染数据。
参考文章: