Thinkphp5.1应用初探

直接审计tp的话应该会很有难度,不妨先了解一些tp内置规则和用法,便于在后续的审计中更好的理解代码含义。

[ 源码下载链接](https://www.sec-
in.com/outLinkPage/?target=https://github.com/heyguojing/thinkphp5.1)

[ThinkPHP5.1 开发手册 ](https://www.sec-
in.com/outLinkPage/?target=https://www.kancloud.cn/manual/thinkphp5_1/353951)

安装

没有composer可以去下载,傻瓜式安装即可[ Composer (getcomposer.org)](https://www.sec-
in.com/outLinkPage/?target=https://getcomposer.org/download/)

使用composer安装

composer create-project topthink/think tp

启动服务

cd tp
php think run

然后就可以在浏览器中访问

http://localhost:8000

搭建成功

wKg0C2JeviAUGrMAABfbxtCDSc342.png

目录结构

www  WEB部署目录(或者子目录)
application           应用目录
  common             公共模块目录(可以更改)
  module_name        模块目录
    common.php      模块函数文件
    controller      控制器目录
    model           模型目录
    view            视图目录
     ...            更多类库目录
  
  command.php        命令行定义文件
  common.php         公共函数文件
  tags.php           应用行为扩展定义文件

config                应用配置目录
  module_name        模块配置目录
    database.php    数据库配置
    cache           缓存配置
     ...            
  
  app.php            应用配置
  cache.php          缓存配置
  cookie.php         Cookie配置
  database.php       数据库配置
  log.php            日志配置
  session.php        Session配置
  trace.php          Trace配置

route                 路由定义目录
  route.php          路由定义
  ...                更多

public                WEB目录(对外访问目录)
  index.php          入口文件
  router.php         快速测试文件
  .htaccess          用于apache的重写

thinkphp              框架系统目录
  lang               语言文件目录
  library            框架类库目录
    think           Think类库包目录
    traits          系统Trait目录
  
  tpl                系统模板目录
  base.php           基础定义文件
  console.php        控制台入口文件
  convention.php     框架惯例配置文件
  helper.php         助手函数文件
  phpunit.xml        phpunit配置文件
  start.php          框架入口文件

extend                扩展类库目录
runtime               应用的运行时目录(可写,可定制)
vendor                第三方类库目录(Composer依赖库)
build.php             自动生成定义文件(参考)
composer.json         composer 定义文件
LICENSE.txt           授权说明文件
README.md             README 文件
think                 命令行入口文件

命名规范

ThinkPHP5 遵循PSR-2命名规范和PSR-4自动加载规范,并且注意如下规范:

目录和文件

目录不强制规范,驼峰和小写+下划线模式均支持;

类库、函数文件统一以.php为后缀;

类的文件名均以命名空间定义,并且命名空间的路径和类库文件所在路径一致;

类名和类文件名保持一致,统一采用驼峰法命名(首字母大写);

函数和类、属性命名

  • 类的命名采用驼峰法,并且首字母大写,例如UserUserType ,默认不需要添加后缀,例如UserController 应该直接命名为User
  • 函数的命名使用小写字母和下划线(小写字母开头)的方式,例如get_client_ip
  • 方法的命名使用驼峰法,并且首字母小写,例如getUserName
  • 属性的命名使用驼峰法,并且首字母小写,例如tableNameinstance
  • 以双下划线“__”打头的函数或方法作为魔法方法,例如__call__autoload

常量和配置

  • 常量以大写字母和下划线命名,例如APP_PATH THINK_PATH
  • 配置参数以小写字母和下划线命名,例如url_route_onurl_convert

数据表和字段

  • 数据表和字段采用小写加下划线方式命名,并注意字段名不要以下划线开头,例如 think_user 表和user_name 字段,不建议使用驼峰和中文作为数据表字段命名。

URL解析模式

http://localhost/index.php/模块/控制器/操作/参数/值

如果使用的是伪静态,就不必加上/thinkphp/tp5/public/index.php/

http://127.0.0.1:8000/index/index/hello/name/Sentiment

wKg0C2JewqALi9iAACDi9FfNU102.png

wKg0C2JexGAAnY3AAAvtBHmZ54837.png

在url地址栏里面如果不写模块、控制器和操作名,默认访问的就是index模块下面的index控制器下面的index操作,可以在config/app.php文件中进行修改。

wKg0C2JexiAVZQtAACP9fAkPrg521.png

控制器定义

控制器,即 controller,控制器文件存放在 controller 目录下

类名和文件名大小写保持一致,采用驼峰法()

如果类名是 双字母组合,比如 class HelloWorld,url 访问时必须用:hello_world;

想要原样方式访问 URL,则需要关闭配置文件中的自动转换

‘url_convert’ => false;

在Test模块下,定义一个HelloWorld控制器,test操作

<?php
namespace app\test\controller;

class HelloWorld{
    public function test(){
        return 'hello_world!!!!!';
    }
}

访问HelloWorld控制器时,就必须以hello_world形式才行

wKg0C2JeyOAZagrAAAe3OgNmR4383.png

渲染输出

使用 view 输出模板

方法同名文件

tp中内置了一个view()方法,它可以找到同模块下的view/控制器同名文件夹(这里就是test)/与方法同名的文件.html(定义的是show方法,所以会自动追踪到show.html)

wKg0C2Jey2ADFtwAABzgrHNlTA929.png

wKg0C2JezSAAwsfAABrJGinL04751.png

根据url解析模式,直接访问test模块,test控制器,show操作

wKg0C2Jez2AJ2rKAAAnU3sK1dw363.png

不同名文件

若不是方法同名.html,在view()中加上对应的html文件名即可(`view/同名控制器/参数同名.html)

wKg0C2Je0iAc3VuAAB6WBLnJhU282.png

wKg0C2Je06AQe3NAAAyQxzG6g619.png

数据库操作

数据库配置在config/database.php下,数据库操作分为两种类型:DB类,模型类

这里先设置下数据库名,用户名,密码,表前缀可选我这里填的think_

wKg0C2Je1iAZvZ4AACOPnhorE450.png

下一步就是创建数据库了,在think数据库的think_data表下创建三个字段

wKg0C2Je2SAC2WSAACMB3i1xyg450.png

DB类

原生查询

支持query (查询操作)和execute (写入操作)方法

添加数据
<?php

namespace app\test\controller;
use think\Db;

class Data{
    public function index(){
        $resault = Db::execute('insert into think_data (id,name,status) values(1,"Sentiment",1)');
        return dump($resault);
    }
}

访问方法

wKg0C2Je3WAVQRAABEyL5iTMY585.png

执行成功

wKg0C2Je36AOe98AACTyevia9w926.png

再插入一条

$resault = Db::execute('insert into think_data (id,name,status) values(1,"Tana",1)');

wKg0C2Je5GABnUvAAAT6iTV2l8336.png

更新数据
<?php

namespace app\test\controller;
use think\Db;

class Data{
    public function index(){
        $resault = Db::execute('update think_data set id=2 where name="Sentiment"');
        return dump($resault);
    }
}

wKg0C2Je7OARwvRAAAUA3fmvtQ771.png

删除数据
<?php

namespace app\test\controller;
use think\Db;

class Data{
    public function index(){
        $resault = Db::execute('delete from think_data where name ="Tana"');
        return dump($resault);
    }
}

wKg0C2Je6uAcMfnAAAPkbyUnvI188.png

查询数据

query用于查询,默认情况下返回数组集,execute方法的返回值是影响的行数

<?php

namespace app\test\controller;
use think\Db;

class Data{
    public function index(){
        $resault = Db::query('select * from think_data');
        return dump($resault);
    }
}

wKg0C2Je7ActcAABoZ91v3I794.png

查询构造器

添加数据

通过insert语句添加数据,如果设置了表前缀(prefix)则可以使用name(表后缀),若没设置则需全名即:table(think_data),也可应inserAll插入多条数据

<?php

namespace app\test\controller;
use think\Db;

class Data{
    public function index(){
        $data=['id' => 1, 'name' => 'Sentiment','status'=>1];
        $resault = Db::name('data')->insert($data);
        return dump($resault);
    }
}
更新数据

可以用update语句,也可以是tp封装的setField,同时若需要字段自增/自减也可以用setInc/setDec

<?php

namespace app\test\controller;
use think\Db;

class Data{
    public function index(){
        $resault = Db::name('data')->where('name', "Sentiment")->update(['id' => '2']);
        //tp5封装函数
        $resault = Db::name('data')->where('name', "Sentiment")->setField('id',2);
        //不给第二个参数,默认为1
        $resault = Db::name('data')->where('name', "Sentiment")->setInc('id');
        //自减2
        $resault = Db::name('data')->where('name', "Sentiment")->setDec('id',2);
        return dump($resault);
    }
}
删除数据
<?php

namespace app\test\controller;
use think\Db;

class Data{
    public function index(){
        $resault = Db::name('data')->where('name', "Tana")->delete();
        return dump($resault);
    }
}
查询数据
<?php

namespace app\test\controller;
use think\Db;

class Data{
    public function index(){
        $resault = Db::name('data')->select();
        return dump($resault);
    }
}

助手函数

$db=\db('data');代替Db::name('data'),db 助手函数默认会每次重新连接数据库,因此应当尽量避免多次调用。

<?php

namespace app\test\controller;
use think\Db;

class Data{
    public function index(){
        $db=\db('data');
        $resault=$db->select();
        return dump($resault);
    }
}

链式操作

数据库提供的链式操作方法,可以有效的提高数据存取的代码清晰度和开发效率,并且支持所有的CURD操作(原生查询不支持链式操作)。

链式操作不分先后,只要在查询方法(select()、find())前调用就行

Db::name('data') -> where('status',1) -> order('create_time') -> limit(10) -> select();
链式操作查询方法
连贯操作作用支持的参数类型
where *用于AND查询字符串、数组和对象
whereOr *用于OR查询字符串、数组和对象
wheretime *用于时间日期的快捷查询字符串
table用于定义要操作的数据表名称字符串和数组
alias用于给当前数据表定义别名字符串
field *用于定义要查询的字段(支持字段排除)字符串和数组
order *用于对结果排序字符串和数组
limit用于限制查询结果数量字符串和数字
page用于查询分页(内部会转换成limit)字符串和数字
group用于对查询的group支持字符串
having用于对查询的having支持字符串
join *用于对查询的join支持字符串和数组
union *用于对查询的union支持字符串、数组和对象
view *用于视图查询字符串、数组
distinct用于查询的distinct支持布尔值
lock用于数据库的锁机制布尔值
cache用于查询缓存支持多个参数
relation *用于关联查询字符串
with *用于关联预载入字符串、数组
bind *用于数据绑定操作数组或多个参数
comment用于SQL注释字符串
force用于数据集的强制索引字符串
master用于设置主服务器读取数据布尔值
strict用于设置是否严格检测字段名是否存在布尔值
sequence用于设置Pgsql的自增序列名字符串
failException用于设置没有查询到数据是否抛出异常布尔值
partition用于设置分表信息数组 字符串

查询表达式

select()用于查询数据集,查询成功则返回一个二维数组,如果没有满足条件则返回空数组

find()用于查找满足条件的第一个记录,如果查询成功,返回一个以为数组,如果失败则返回null

表达式含义快捷查询方法
=等于

< >| 不等于|

>| 大于|

> =| 大于等于|

<| 小于|

< =| 小于等于|

[NOT] LIKE| 模糊查询| whereLike/whereNotLike
[NOT] BETWEEN| (不在)区间查询| whereBetween/whereNotBetween
[NOT] IN| (不在)IN 查询| whereIn/whereNotIn
[NOT] NULL| 查询字段是否(不)是NULL| whereNull/whereNotNull
[NOT] EXISTS| EXISTS查询| whereExists/whereNotExists
[NOT] REGEXP| 正则(不)匹配查询(仅支持Mysql)|

[NOT] BETWEEM TIME| 时间区间比较| whereBetweenTime
> TIME| 大于某个时间| whereTime
< TIME| 小于某个时间| whereTime
> = TIME| 大于等于某个时间| whereTime
< = TIME| 小于等于某个时间| whereTime
EXP| 表达式查询,支持SQL语法| whereExp

比较查询

查询id不等于1的数据

<?php

namespace app\test\controller;
use think\Db;

class Data{
    public function index(){
        $result = Db::name('data')->where("id",'<>','1')->select();
        return dump($result);
    }
}
区间查询
<?php

namespace app\test\controller;
use think\Db;

class Data{
    public function index(){
        //模糊查询name中带n的数据
        //$result = Db::name('data')->where("name",'like','%n%')->select();
        //区间查询id为1-3的数据
        $result = Db::name('data')->where("id",'BETWEEN','[1,3]')->select();
        return dump($result);
    }
}
时间查询

查询2022-5-11以后的数据

$result = Db::name('data')->where("create_time",'> TIME','2022-5-11')->select();
其它查询

查询id=1或3的数据

$result = Db::name('data')->where("id",'EXP','IN (1,3)')->select();
或
$result = Db::name('data')->whereExp("id",'IN (1,3)')->select();

模型类

在模型中除了可以调用数据库类的方法之外(换句话说,数据库的所有查询方法模型中都可以支持),可以定义自己的方法,所以也可以把模型看成是数据库的增强版。

模型定义

先建个think_user表

wKg0C2Je9CAECEAAC2gjHGPw176.png

在test/model下建个think_user模型User,这里的模型名=表名,所以必须叫User

wKg0C2Je9qAL4UHAAB3lBYdWPo227.png

新增数据

建好模型就开始数据库操作了,use部分用到的就是刚刚定义的User,但为了不与控制器重名加了个as,这里用了两种方式添加数据

<?php
namespace app\test\controller;
use app\test\model\User as UserModel;

class User
{
    public function insert()
    {
//        $user = new UserModel();
//        $user->id=1;
//        $user->name = 'Sentiment';
//        $user->email = 'Sentiment@qq.com';
//        $user->birthday=strtotime('2001-12-7');
//        $user->save();
    //数组形式自定义
          $user['id']=2;
          $user['name']='Tana';
          $user['email']='Tana@qq.com';
          $user['birthday']=strtotime('2000-1-1');
          UserModel::create($user);

    }

}

访问test/user/insert,执行成功(注:这里定义了四个字段,所以在insert时候必须都加上,一开始以为会自动创建id就没加,结果一直没成功)

wKg0C2JeOATu81AAA9XSeDsiI178.png

批量添加

也可以通过saveAll,批量新增

public function insertList(){
    $user = new UserModel();
    $list=[
        ['id'=>'3','name'=>'Mumu','email'=>'Mumu@qq.com','birthday'=>strtotime('2002-1-1')],
        ['id'=>'4','name'=>'Shelter','email'=>'Shelter@qq.com','birthday'=>strtotime('2003-1-1')]
    ];
    if($user->saveAll($list)){
        return 'Success';
    }else{
        return 'faild';
    }
}

更新数据

查找并更新

get获取id=1的数据

public function update(){
    $user = UserModel::get(1);
    $user->name='Mumu';
    $user->email='Mumu@qq.com';
    $user->birthday=strtotime('2002-1-1');
    $user->save();
    #dump($user);
}
直接更新数据
$user = new UserModel();
$user->save(['name'=>'Shelter','email'=>'Shelter@qq.com'],['id'=>1]);
批量更新
$user = new UserModel();
$list=[
    ['id'=>'3','name'=>'Mumu','email'=>'Mumu@qq.com','birthday'=>strtotime('2002-1-1')],
    ['id'=>'4','name'=>'Shelter','email'=>'Shelter@qq.com','birthday'=>strtotime('2003-1-1')]
];
通过数据库类更新
$user = new UserModel();
$user->where('id',1)->update(['name'=>'Sentiment']);
//包括主键的话也可以用下边这种方法
//$user->update(['id'=>1,'name'=>'Tana']);
静态方法
UserModel::where('id',1)->update(['name'=>'Sentiment']);
//包括主键的话也可以用下边这种方法
//UserModel::update(['id'=>1,'name'=>'Tana']);

查询数据

查询单个数据
//获取单个数据
$user=UserModel::get(1);
echo $user->name;

//使用数组查询
$user=UserModel::get(1);
echo $user->email;

//实例化模型后查询
$user = new UserModel();
$result = $user -> where('name','Sentiment')->find();
echo $result->name;
查询多个数据
//  获取多个数据
//$list=UserModel::all('1,2');
//  数组形式
//$list=UserModel::all([1,2]);
//foreach ($list as $key=>$value){
//    echo $value->name;
//  }

//   实例化模型后查询
$user = new UserModel();
echo $user->where('id',1)->limit(2)->order('birthday','desc')->select();

删除数据

//删除当前模型
$user = UserModel::get(1);
$user->delete();

//根据主键删除
UserModel::destroy(1);
//也可以删除多个
UserModel::destroy('1,2');
UserModel::destroy([1,2]);

//条件删除
UserModel::destroy(['id'=>1]);
UserModel::where('id','>',0)->delete();

视图

视图功能由\think\View
类配合视图驱动(也即模板引擎驱动)类一起完成,目前的内置模板引擎包含PHP原生模板和Think模板引擎。

渲染模板最常用的是控制器类在继承系统控制器基类(\think\Controller )后调用fetch 方法,调用格式:

fetch('[模板文件]'[,'模板变量(数组)'])

常用方法:

方法说明
fetch渲染模板输出
assign模板变量赋值
engine初始化模板引擎

视图渲染

不给任何参数情况下默认返回,当前文件/view/控制器名/方法名.html

<?php
namespace app\test\controller;
use think\Controller;

class See extends Controller{
    public function index(){
        // 自动定位
        //return $this->fetch();
        //test/view/see/index.html

        // 指定模板
        //return  $this->fetch('test');
        //test/view/see/test.html

        //指定目录
        //return $this->fetch('test/show');
        //test/view/test/show.html

        // 指定模块下的模板,适用于多模块
        //return $this->fetch('admin@public/test');
        //admin/view/public/test.html

        //view_path 下的模块
        //return $this->fetch('/Sentiment');
        //test/view/Sentiment.html

        // 如果没有继承 Controller 模块的话,可以使用助手函数 view() 方法,具体使用方法同上
        return view();
        //test/view/see/index.html
    }
}

视图赋值

视图赋值主要通过assign函数

assign赋值
//test/controller/Assign.php

<?php
namespace app\test\controller;
use think\Controller;

class Assign extends Controller{
    public function index(){
        //模板变量赋值
        $name='Sentiment';
        $age=18;
//        $this->assign('name',$name);
//        $this->assign('age',$age);
        //也可以通过数组赋值
        $this->assign([
            'name'=>$name,
            'age'=>$age,
        ]);
        return $this->fetch();
    }

}

想输出变量直接{$name}即可

/test/view/assign/index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Assign Test</title>
</head>
<body>
this is assign/index.html</br>
{$name}</br>
{$age}
</body>
</html>

访问/test/assign/index方法 成功返回body内容及变量值

wKg0C2JeeAWc34AAA2mCZNak667.png

fetch赋值
return $this->fetch('index',['name'=>$name,'age'=>$age]);
助手函数
return view('index',['name'=>$name,'age'=>$age]);

wKg0C2JfAaAEA0GAAAka7wArDE410.png

视图过滤

将6替换成了 < br/ >

wKg0C2JfBOATIG1AAA20w3xP0A355.png

初始化中全局过滤
<?php
namespace app\test\controller;
use think\Controller;

class Assign extends Controller{
    public function index(){
            $this->assign(['name' => 'Sentiment6', 'age'=>186]);
        return $this->fetch();
    }
    public function initialize()
    {
        return $this->filter(function ($content) {
            return str_replace('6', '<br>', $content);
        });
    }

}

模板

变量输出

普通输出方式

//test/controller/Assign.php
<?php
namespace app\test\controller;
use think\Controller;

class Assign extends Controller{
    public function index(){
        $this->assign('name', 'Sentiment');
        return $this->fetch();
    }
}

模板

//test/view/assign/index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Assign Test</title>
</head>
<body>
this is assign/index.html</br>
Hello {$name}
</body>
</html>

wKg0C2JfDaAX4GfAAAu2j4L9zo458.png

系统变量输出

{$Think.server.script_name} // 输出$_SERVER['SCRIPT_NAME']变量
{$Think.session.user_id} // 输出$_SESSION['user_id']变量
{$Think.get.page} // 输出$_GET['page']变量
{$Think.cookie.name}  // 输出$_COOKIE['name']变量

在index.html中加上{$Think.server.script_name},即可输出对应的script_name值

常量输出

{$Think.const.PHP_VERSION}
或
{$Think.PHP_VERSION}

Assign.php 中定义个常量

define('AAA','this is define');

在index.html加上

{$Think.AAA}

wKg0C2JfGAS7jJAAAmIBygbc126.png

配置输出

{$Think.config.default_module}
{$Think.config.default_controller}

语言配置

{$Think.lang.page_error}
{$Think.lang.var_error}

使用函数

过滤方法描述
date日期格式化(支持各种时间类型)
format字符串格式化
upper转换为大写
lower转换为小写
first输出数组的第一个元素
last输出数组的最后一个元素
default默认值
raw不使用(默认)转义

Assign.php

<?php
namespace app\test\controller;
use think\Controller;
define('AAA','this is define');
class Assign extends Controller{
    public function index(){
        $name='Sentiment';
        $time=time();
        $this->assign('name',$name);
        $this->assign('time',$time);
        return $this->fetch();
    }
}

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Assign Test</title>
</head>
<body>
this is assign/index.html<br> 
{$name|md5}<br>                 //md5('Sentiment')
{$name|upper|substr=0,3}<br>    //substr(upper('Sentiment'))
{$time|date='Y-m-d H:i'}<br>    //时间
</body>
</html>

wKg0C2JfICABzZWAABElNObf1I051.png

原样输出

加上{literal}后,{$name}就不会被解析,而是原样输出

{literal}
    Hello,{$name}!
{/literal}

模板输出

单行注释

格式:

{/* 注释内容 */ } 或 {// 注释内容 } 

例如

{// 这是模板注释内容 }

注:{ 和注释标记之间不能有空格。

多行注释

支持多行注释,例如:

{/* 这是模板
注释内容*/ }

模板注释支持多行,模板注释在生成编译缓存文件后会自动删除,这一点和Html的注释不同。

模板布局

全局配置方式

开启layout_on** 参数(默认不开启),并且设置布局入口文件名**layout_name
(默认为layout)。(assign为我的view目录下的文件,根据自己情况修改或不加)

'layout_on'     =>  true,
'layout_name'   =>  'assign/layout',

在不开启layout_on
布局模板之前,会直接渲染application/test/view/assign/index.html模板文件,开启之后,首先会渲染application/test/view/layout.html**
模板,布局模板的写法和其他模板的写法类似,本身也可以支持所有的模板标签以及包含文件,区别在于有一个特定的输出替换变量**{__CONTENT__}
,例如,下面是一个典型的layout.html模板的写法:

{include file="public/header" /}
 {__CONTENT__}
{include file="public/footer" /}

在view/assign/下,新建layout.html,包含的是see/index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>a Test</title>
</head>
<body>
    {include file="see/index" /}<br>
    {__CONTENT__}
    {include file="see/index" /}<br>
</body>
</html>

原本的assign/index.html把html标签去掉即可

{$name|md5}<br>
{$name|upper|substr=0,3}<br>
{$time|date='Y-m-d H:i'}<br>

访问后{ CONTENT }部分自动替换成了index.html内容

wKg0C2JfKWAYqKOAABkk6OMIm4991.png

这里的{ CONTENT }是默认的也可以通过修改配置来定义

这里通过配置文件定义的是全局配置,若某个文件不想使用该配置,则可以在html文件中加入{__NOLAYOUT__}
来取消本文件的全局配置

{__NOLAYOUT__}                  //加上后就不会被解析了
{$name|md5}<br>
{$name|upper|substr=0,3}<br>
{$time|date='Y-m-d H:i'}<br>

模板标签方式

直接在模板文件中指定布局模板即可(前边的layout_on设置需要关闭)

{//__NOLAYOUT__}
{layout name="assign/layout" /}
{$name|md5}<br>
{$name|upper|substr=0,3}<br>
{$time|date='Y-m-d H:i'}<br>

若需要使用其他模板布局(假设要用lay.html),直接修改标签即可

{//__NOLAYOUT__}
{layout name="assign/lay" /}
{$name|md5}<br>
{$name|upper|substr=0,3}<br>
{$time|date='Y-m-d H:i'}<br>

动态布局

也不需要设置layout_on ,加上$this->view->engine->layout(true); 即可

<?php
namespace app\test\controller;
use think\Controller;
define('AAA','this is define');
class Assign extends Controller{
    public function index(){
        $name='Sentiment';
        $time=time();
        $this->assign('name',$name);
        $this->assign('time',$time);
        $this->view->engine->layout(true);          //在这里在这里
        return $this->fetch();
    }
}

模板继承

通过{block} {/block}标签,实现继承

在view/assign/下,新建base.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>base</title>
</head>
<body>
    {block name="header"}
        <div style= "width:10%; height:30px; background-color:yellow;">this is header</div>
    {/block}<br>
    {block name="footer"}
        <div style= "width:10%; height:30px; background-color:green;">this is footer</div>
    {/block}<br>
</body>
</html>

view/assign/index.html

通过extend继承{extend name="assign/base" /}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index</title>
</head>
<body>
    {extend name="assign/base" /}

</body>
</html>

wKg0C2JfLaAMq8IAAAwMwM72wA040.png

如果在子类中实现了与父类中同样的模板,则以子类中的内容显示,若此时想同时显示父类中的内容则可以通过{ block }实现

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index</title>
</head>
<body>
    {extend name="assign/base" /}
    {block name="header"}{__block__}        //在这里 在这里
    <div style= "width:10%; height:30px; background-color:red;">this is header</div>
    {/block}<br>
    {block name="footer"}
    <div style= "width:10%; height:30px; background-color:blue;">this is footer</div>
    {/block}<br>
</body>
</html>

wKg0C2JfMWAZxSUAABQKTV88nY289.png

包含文件

在模板布局中已经用到过了就不多解释了

{include file="see/index" /}

内置标签

标签名作用包含属性
include包含外部模板文件(闭合)file
load导入资源文件(闭合 包括js css import别名)
file,href,type,value,basepath
volist循环数组数据输出name,id,offset,length,key,mod
foreach数组或对象遍历输出name,item,key
forFor循环数据输出name,from,to,before,step
switch分支判断输出name
case分支判断输出(必须和switch配套使用)value,break
default默认情况输出(闭合 必须和switch配套使用)
compare比较输出(包括eq neq lt gt egt elt heq nheq等别名)
name,value,type
range范围判断输出(包括in notin between notbetween别名)name,value,type
present判断是否赋值name
notpresent判断是否尚未赋值name
empty判断数据是否为空name
notempty判断数据是否不为空name
defined判断常量是否定义name
notdefined判断常量是否未定义name
define常量定义(闭合)name,value
assign变量赋值(闭合)name,value
if条件判断输出condition
elseif条件判断输出(闭合 必须和if标签配套使用)condition
else条件不成立输出(闭合 可用于其他标签)
php使用php代码

volist

这里以数据库内容举例,模板类获取数据库所有内容(数据库— >模板类有说过)

<?php
namespace app\test\controller;
use think\Controller;
use app\test\model\User as UserModel;

class Assign extends Controller{
    public function index(){
        $name=UserModel::all();
        $this->assign('name',$name);
        return $this->fetch();
    }
}

assign/index.html

"name"为assign的值,根据变量进行修改

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index</title>
</head>
<body>
    {volist name="name" id="vo"}
        {$vo.id}====>{$vo.name}<br/>
    {/volist}
</body>
</html>

wKg0C2JfNiAAdfHAAAjMfEEhuI397.png

可以加上offset="0" length="1" ,定义获取数据的个数

{volist name="name" id="vo" offset="0" length="1"}
    {$vo.id}====>{$vo.name}<br/>
{/volist}

foreach

实现结果同上

{foreach $name as $vo}
    {$vo.id}====>{$vo.name}<br/>
{/foreach}

for

{for start="开始值" end="结束值" comparison="用于比较,默认值是<" step="步长" name="循环变量名"}
{/for}

循环输出1-10

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index</title>
</head>
<body>
    {for start="1" end="10"}
    {$i}
    {/for}
</body>
</html>

wKg0C2JfOGAPP63AAAh6YAvdqg993.png

php

执行php语句

{php}
    echo 'hi Sentiment';
{/php}

路由

静态

Route::get('unserialize', 'unserialize/unserialize');

访问unserialize后,便会自动跳转到unserialize/unserialize界面

动态

Route::get('route/:id','test/Index/index');

index.php

<?php
namespace app\test\controller;
use think\facade\Request;

class Index
{
    public function index(){
        dump(Request::route());
    }
}

id为我们动态输入的值,修改id后返回信息也会动态变化

请求

请求对象

1.当控制器继承了控制器基类时,会自动被注入 Request 请求对象的功能

<?php
namespace app\test\controller;
use think\Controller;
class Index extends Controller{
    public function index(){
        return $this->request->param('name');
    }
}

wKg0C2JfQOAYPtoAAAmzU09FU698.png

2.不继承控制器基类(操作方法注入)

无论是否继承系统的控制器基类,都可以使用操作方法注入。

<?php
namespace app\test\controller;
use think\Request;

class Index {
    public function index(Request $request){
        return $request->param('name');
    }
}

1 传参方式一样

3、构造方法注入

<?php
namespace app\test\controller;
use think\Request;

class Index {
    public function __construct(Request $request)
    {
        $this->request = $request;
    }
    public function index(){
        return $this->request->param('name');
    }
}

4、Facade调用(无依赖注入)

在没有使用依赖注入的场合,可以通过Facade 机制来静态调用请求对象的方法(注意use 引入的类库区别)。

<?php
namespace app\test\controller;
use think\facade\Request;

class Index {

    public function index(){
        return Request::param('name');
    }
}

5、助手函数(有无继承都可)

为了简化调用,系统还提供了request 助手函数,可以在任何需要的时候直接调用当前请求对象。

<?php
namespace app\test\controller;

class Index
{
    public function index()
    {
        return request()->param('name');
    }
}

请求信息

Request 对象支持获取当前的请求信息,包括:

方法含义
host当前访问域名或者IP
scheme当前访问协议
port当前访问的端口
remotePort当前请求的REMOTE_PORT
protocol当前请求的SERVER_PROTOCOL
contentType当前请求的CONTENT_TYPE
domain当前包含协议的域名
subDomain当前访问的子域名
panDomain当前访问的泛域名
rootDomain当前访问的根域名(V5.1.6+
url当前完整URL
baseUrl当前URL(不含QUERY_STRING)
query当前请求的QUERY_STRING参数
baseFile当前执行的文件
rootURL访问根地址
rootUrlURL访问根目录
pathinfo当前请求URL的pathinfo信息(含URL后缀)
path请求URL的pathinfo信息(不含URL后缀)
ext当前URL的访问后缀
time获取当前请求的时间
type当前请求的资源类型
method当前请求类型

对于上面的这些请求方法,一般调用无需任何参数,但某些方法可以传入true 参数,表示获取带域名的完整地址,例如:

use think\facade\Request;

// 获取完整URL地址 不带域名
Request::url();
// 获取完整URL地址 包含域名
Request::url(true);
// 获取当前URL(不含QUERY_STRING) 不带域名
Request::baseFile();
// 获取当前URL(不含QUERY_STRING) 包含域名
Request::baseFile(true);
// 获取URL访问根地址 不带域名
Request::root();
// 获取URL访问根地址 包含域名
Request::root(true);

获取完整URL,不带域名

<?php
namespace app\test\controller;
use think\facade\Request;
class Index
{
    public function index()
    {
        return Request::url();
    }
}

wKg0C2JfVyADHdcAAAlTAzQylE262.png

请求变量

可以通过Request 对象完成全局输入变量的检测、获取和安全过滤,支持包括$_GET $_POST
$_REQUEST $_SERVER $_SESSION $_COOKIE $_ENV
等系统变量,以及文件上传信息。(所有示例代码均使用Facade 方式)

use think\facade\Request;

1、使用 has() 方法,可以检测全局变量是否已经设置

<?php
namespace app\test\controller;
use think\facade\Request;
class Index
{
    public function index()
    {
        dump(Request::has('name','get'));
        dump(Request::has('id','post'));
    }
}

wKg0C2JfWOAYph0AABmtetlU676.png

2、变量获取

变量获取使用\think\Request 类的如下方法及参数:

变量类型方法(‘变量名/变量修饰符’,‘默认值’,‘过滤方法’)

变量类型方法包括:

方法描述
param获取当前请求的变量
get获取 $_GET 变量
post获取 $_POST 变量
put获取 PUT 变量
delete获取 DELETE 变量
session获取 $_SESSION 变量
cookie获取 $_COOKIE 变量
request获取 $_REQUEST 变量
server获取 $_SERVER 变量
env获取 $_ENV 变量
route获取 路由(包括PATHINFO) 变量
file获取 $_FILES 变量

获取当前强求变量

// 获取当前请求的name变量(过滤)
Request::param('name');
// 获取当前请求的所有变量(过滤)
Request::param();
// 获取当前请求的所有变量(原始数据、不过滤)
Request::param(false);
// 获取当前请求的所有变量(包含上传文件、过滤)
Request::param(true);



<?php
namespace app\test\controller;
use think\facade\Request;
class Index
{
    public function index()
    {
        dump(Request::param());
    }
}

wKg0C2JfW6AKF9sAABQnNJgB60054.png

3、变量过滤

框架默认没有设置任何全局过滤规则,可以在应用配置文件中设置全局的过滤规则:

# config/app.php

// 默认全局过滤方法 用逗号分隔多个
'default_filter'         => 'htmlspecialchars',
如果设置过滤方法,上传变量信息会获取不到

# 单个设置
dump(Request::param('name','','htmlspecialchars'));



<?php
namespace app\test\controller;
use think\facade\Request;
class Index
{
    public function index()
    {
          dump(Request::param('name','','htmlspecialchars'));
    }
}

php7.3没成功,换成了7.4

wKg0C2JfXiAGYmeAAA1p4f1Pk4552.png

4、获取部分变量(only)

只获取当前请求的name变量

<?php
namespace app\test\controller;
use think\facade\Request;
class Index
{
    public function index()
    {   // 只获取当前请求的name变量
        dump(Request::only('name'));
        //数组形式
        //dump(Request::only(['name']));
    }
}

wKg0C2JfYeAcWvoAABPnvVuSU832.png

except排除某些变量后获取

dump(Request::except('id'));
//数组形式
dump(Request::except(['id']));

5、默认值

Request::get('name'); // 返回值为null
Request::get('name',''); // 返回值为空字符串
Request::get('name','default'); // 返回值为default



<?php
namespace app\test\controller;
use think\facade\Request;
class Index
{
    public function index()
    {
        dump(Request::param('name','Sentiment'));
        dump(Request::param('name'));
        dump(Request::param('name','default'));

    }
}

wKg0C2JfZKADqAFAABjUFhJxwQ544.png

6、变量修饰符

Request::变量类型(‘变量名/修饰符’);

/s(字符串) 
/d(整型) 
/b(布尔) 
/a(数组) 
/f(浮点)



<?php
namespace app\test\controller;
use think\facade\Request;
class Index
{
    public function index()
    {
        dump(Request::param('name/s'));
        dump(Request::param('name/d'));
        dump(Request::param('name/a'));

    }
}

wKg0C2JfZuACSDsAABoeDnKUr4546.png

7、路由获取

//test/controller/index
<?php
namespace app\test\controller;
use think\facade\Request;
class Index
{
    public function index($id)
    {
        dump(Request::route());
    }
}

//route/route.php
Route::get('route/:id','test/Index/index');

wKg0C2JfbmAAoAABGdFKi94704.png

8、助手函数

为了简化使用,还可以使用系统提供的input 助手函数完成上述大部分功能。

  • 判断变量是否定义
<?php
namespace app\test\controller;
use think\facade\Request;
class Index
{
    public function index()
    {   //get
        dump(input('?get.name'));
        //post
        dump(input('?post.name'));
    }
}

wKg0C2JfciAenR4AABa7CiTI7o545.png

  • 获取PARAM参数

    dump(input(‘param.name’)); // 获取单个参数
    dump(input(‘param.’)); // 获取全部参数
    // 下面是等效的
    dump(input(‘name’));
    dump(input(‘’));

wKg0C2Jfd2ABGqwAACNJJ7Bvk125.png

  • 获取GET参数

    // 获取单个变量
    dump(input(‘get.id’));
    // 使用过滤方法获取 默认为空字符串
    dump(input(‘get.name’));
    // 获取全部变量
    dump(input(‘get.’));

  • 使用过滤方法

    dump(input(‘get.name’,‘’,‘htmlspecialchars’)); // 获取get变量 并用htmlspecialchars函数过滤
    dump(input(‘username’,‘’,‘strip_tags’)); // 获取param变量 并用strip_tags函数过滤
    dump(input(‘post.name’,‘’,‘org\Filter::safeHtml’)); // 获取post变量 并用org\Filter类的safeHtml方法过滤

  • 使用变量修饰符

    input(‘get.id/d’);
    input(‘post.name/s’);
    input(‘post.ids/a’);

HTTP信息

<?php
namespace app\test\controller;
use think\facade\Request;
class Index
{
    public function index()
    {
        $info = Request::header();
        dump($info);
        dump($info['host']);
        dump($info['user-agent']);
    }
}

wKg0C2JfeqAOf4OAACbof2QHM242.png

伪静态

URL伪静态通常是为了满足更好的SEO效果,ThinkPHP支持伪静态URL设置,可以通过设置url_html_suffix
参数随意在URL的最后增加你想要的静态后缀,而不会影响当前操作的正常执行。

可以通过ext()方法获取后缀

<?php
namespace app\test\controller;
use think\facade\Request;
class Index
{
    public function index()
    {
        return Request::ext();
    }

}

当访问index.pdf后会报错,但访问index.html则不会

wKg0C2JffOAFwMMAAAYZWWqhis573.png

这是因为在配置文件中设置的伪静态为html,若想用pdf,通过| 分割加上即可

'url_html_suffix'        => 'html|pdf',

在不该设置的情况下,使用 url::build() 获取当前完整 url,得到默认后缀为 .html

<?php
namespace app\test\controller;
use think\facade\Request;
class Index
{
    public function index()
    {
        return \think\facade\Url::build();
    }

}

wKg0C2Jff2AXBsZAAAeMEDgjM174.png

若不想使用伪静态关闭即可

'url_html_suffix' => false,

参数绑定

1、默认参数

<?php
namespace app\test\controller;
class Index
{
    public function index($name='Sentiment',$id=1)
    {
        return 'name:'.$name.'<br>'.'id:'.$id;
    }
}

wKg0C2JfgWAKYnZAAAfo4CRI567.png

wKg0C2Jfg2AZPKAAAAiOeDrzw264.png

2、成对解析,可以换顺序

wKg0C2JfhSAXma0AAAkA5ngE2A537.png

// URL参数方式 0 按名称成对解析 1 按顺序解析
'url_param_type'         => 0,

请求缓存

全局缓存

// 是否开启请求缓存 true自动缓存 支持设置请求缓存规则
'request_cache'          => false,
// 请求缓存有效期,建议3600,时间太短没有意义
'request_cache_expire'   => null,  

// 全局请求缓存排除规则
'request_cache_except'   => [],

开启缓存后,第二次访问时,会自动获取请求缓存的数据响应输出,并发送304状态码

单独缓存

//route/route.php
Route::get('route/:id','test/Index/index')->cache(3600);
//test/controller/index.php
<?php
namespace app\test\controller;
use think\facade\Request;
class Index
{
    public function index()
    {
        dump(Request::param());
        dump(Request::route());
    }
}

刷新一次后状态码变成304,这时就已经缓存了,当我改变index.php的内容后,访问/route/777仍然是这个界面

wKg0C2JfhyAUi53AACZmeOizXs757.png

响应

响应(Response
)对象用于动态响应客户端请求,控制发送给用户的信息。通常用于输出数据给客户端或者浏览器。由think\Response 类或者子类完成。

响应参数

响应输出,包括 return(),json(),view()

<?php
namespace app\test\controller;
class Index
{
    public function response(){
        return response('index','201');
        //return response('index')->code('201');
        //设置头信息
        //return response('index')->code('201')->header(['Cache-control' => 'no-cache,must-revalidate']); sh
    }

}

wKg0C2JfiaAd7pxAABX2lpsMc585.png

重定向

redirect() 方法页面重定向

<?php
namespace app\test\controller;
class Index
{
    public function response(){
        return redirect('http://sentiment1.top');
    }
}

站内重定向,直接输入路由地址或相对地址即可

return redirect('/index/index/hello/name/Sentiment');

return redirect('hello')->params(['name'=>'Sentiment']);

return redirect('hello',['name'=>'Sentiment']);

文件下载

文本文件和图片文件都可以使用 download() 方法下载

<?php
namespace app\test\controller;
class Index
{
    public function down(){
        $data='this is test';
        return download($data,'test.txt',true);
    }
}

访问/test/index/down后便可下载test.txt,内容为this is test

     => false,
// 请求缓存有效期,建议3600,时间太短没有意义
'request_cache_expire'   => null,  

// 全局请求缓存排除规则
'request_cache_except'   => [],

开启缓存后,第二次访问时,会自动获取请求缓存的数据响应输出,并发送304状态码

单独缓存

//route/route.php
Route::get('route/:id','test/Index/index')->cache(3600);
//test/controller/index.php
<?php
namespace app\test\controller;
use think\facade\Request;
class Index
{
    public function index()
    {
        dump(Request::param());
        dump(Request::route());
    }
}

刷新一次后状态码变成304,这时就已经缓存了,当我改变index.php的内容后,访问/route/777仍然是这个界面

[外链图片转存中…(img-27f8QRPg-1690965533192)]

响应

响应(Response
)对象用于动态响应客户端请求,控制发送给用户的信息。通常用于输出数据给客户端或者浏览器。由think\Response 类或者子类完成。

响应参数

响应输出,包括 return(),json(),view()

<?php
namespace app\test\controller;
class Index
{
    public function response(){
        return response('index','201');
        //return response('index')->code('201');
        //设置头信息
        //return response('index')->code('201')->header(['Cache-control' => 'no-cache,must-revalidate']); sh
    }

}

[外链图片转存中…(img-VwmuaKJP-1690965533193)]

重定向

redirect() 方法页面重定向

<?php
namespace app\test\controller;
class Index
{
    public function response(){
        return redirect('http://sentiment1.top');
    }
}

站内重定向,直接输入路由地址或相对地址即可

return redirect('/index/index/hello/name/Sentiment');

return redirect('hello')->params(['name'=>'Sentiment']);

return redirect('hello',['name'=>'Sentiment']);

文件下载

文本文件和图片文件都可以使用 download() 方法下载

<?php
namespace app\test\controller;
class Index
{
    public function down(){
        $data='this is test';
        return download($data,'test.txt',true);
    }
}

访问/test/index/down后便可下载test.txt,内容为this is test

学习网络安全技术的方法无非三种:

第一种是报网络安全专业,现在叫网络空间安全专业,主要专业课程:程序设计、计算机组成原理原理、数据结构、操作系统原理、数据库系统、 计算机网络、人工智能、自然语言处理、社会计算、网络安全法律法规、网络安全、内容安全、数字取证、机器学习,多媒体技术,信息检索、舆情分析等。

第二种是自学,就是在网上找资源、找教程,或者是想办法认识一-些大佬,抱紧大腿,不过这种方法很耗时间,而且学习没有规划,可能很长一段时间感觉自己没有进步,容易劝退。

如果你对网络安全入门感兴趣,那么你需要的话可以点击这里👉网络安全重磅福利:入门&进阶全套282G学习资源包免费分享!

第三种就是去找培训。

image.png

接下来,我会教你零基础入门快速入门上手网络安全。

网络安全入门到底是先学编程还是先学计算机基础?这是一个争议比较大的问题,有的人会建议先学编程,而有的人会建议先学计算机基础,其实这都是要学的。而且这些对学习网络安全来说非常重要。但是对于完全零基础的人来说又或者急于转行的人来说,学习编程或者计算机基础对他们来说都有一定的难度,并且花费时间太长。

第一阶段:基础准备 4周~6周

这个阶段是所有准备进入安全行业必学的部分,俗话说:基础不劳,地动山摇
image.png

第二阶段:web渗透

学习基础 时间:1周 ~ 2周:

① 了解基本概念:(SQL注入、XSS、上传、CSRF、一句话木马、等)为之后的WEB渗透测试打下基础。
② 查看一些论坛的一些Web渗透,学一学案例的思路,每一个站点都不一样,所以思路是主要的。
③ 学会提问的艺术,如果遇到不懂得要善于提问。
image.png

配置渗透环境 时间:3周 ~ 4周:

① 了解渗透测试常用的工具,例如(AWVS、SQLMAP、NMAP、BURP、中国菜刀等)。
② 下载这些工具无后门版本并且安装到计算机上。
③ 了解这些工具的使用场景,懂得基本的使用,推荐在Google上查找。

渗透实战操作 时间:约6周:

① 在网上搜索渗透实战案例,深入了解SQL注入、文件上传、解析漏洞等在实战中的使用。
② 自己搭建漏洞环境测试,推荐DWVA,SQLi-labs,Upload-labs,bWAPP。
③ 懂得渗透测试的阶段,每一个阶段需要做那些动作:例如PTES渗透测试执行标准。
④ 深入研究手工SQL注入,寻找绕过waf的方法,制作自己的脚本。
⑤ 研究文件上传的原理,如何进行截断、双重后缀欺骗(IIS、PHP)、解析漏洞利用(IIS、Nignix、Apache)等,参照:上传攻击框架。
⑥ 了解XSS形成原理和种类,在DWVA中进行实践,使用一个含有XSS漏洞的cms,安装安全狗等进行测试。
⑦ 了解一句话木马,并尝试编写过狗一句话。
⑧ 研究在Windows和Linux下的提升权限,Google关键词:提权
image.png
以上就是入门阶段

第三阶段:进阶

已经入门并且找到工作之后又该怎么进阶?详情看下图
image.png

给新手小白的入门建议:
新手入门学习最好还是从视频入手进行学习,视频的浅显易懂相比起晦涩的文字而言更容易吸收,这里我给大家准备了一套网络安全从入门到精通的视频学习资料包免费领取哦!

![](https://img-blog.csdnimg.cn/3e9a39bf040d46da93e80689b407bb25.png)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: thinkphp5.1是一款基于PHP语言的MVC框架,它采用了Laravel框架中的一些优秀设计思想,并在此基础上进行了改进和优化,是一款颇受欢迎的PHP框架。 该框架具有非常完善的文档和教程,学习起来非常容易。它的核心思想是“约定优于配置”,通过一些默认的规则来简化代码,提高开发效率。同时,它也提供了很多实用的工具和函数,如请求对象、响应对象、验证器、缓存处理、日志记录等,使得开发者能够更加便捷地实现业务逻辑。 在源码方面,thinkphp5.1采用了比较优秀的代码结构和注释规范,代码风格清晰易读,符合现代编程的标准。同时,它也支持非常灵活的扩展机制,可以通过composer方式引入其他第三方组件来扩展功能。 总的来说,thinkphp5.1源码是一款非常优秀的PHP框架,具有清晰的代码结构、丰富的功能和非常好的可扩展性,适合开发各种规模的Web应用程序。 ### 回答2: ThinkPHP 5.1是一个基于MVC设计模式的PHP开源框架,它的源码是开放的,可以供开发者进行学习和使用。通过阅读ThinkPHP 5.1源码,开发者可以深入了解框架的核心设计思想和运行原理,从而更好地进行二次开发和定制。ThinkPHP 5.1源码的主要特点包括:使用面向对象的编程思想,提供了丰富的内置库函数和类库,支持依赖注入和控制反转,提供了强大的缓存机制,支持多种数据库操作,具有良好的安全性和可扩展性。此外,ThinkPHP 5.1还提供了详细的文档和示例代码,方便开发者学习和使用。总之,ThinkPHP 5.1源码为PHP开发者提供了强有力的支持,帮助开发者快速高效地开发出安全、稳定、高性能的web应用程序。 ### 回答3: thinkphp5.1源码是一个基于PHP的开发框架,它的思想是快速、可靠、简单、灵活,它提供了许多丰富的功能,包括模板引擎、数据库访问、缓存机制等等。 thinkphp5.1源码是一个开放源代码的框架,目前为止已经发展成为非常成熟的架构体系,拥有非常多的使用者和开发者,也得到了非常多的好评和支持。 thinkphp5.1源码的特点是快速开发、规范化开发、灵活、可扩展,它采用MVC的设计模式,在架构上很好地实现了分层开发原则,从而提高了开发效率和代码的可维护性。 此外,thinkphp5.1源码在数据库访问、缓存机制、模板引擎等方面也都有很好的支持,通过它们能够更好地管理数据、提高应用的性能和减少开发周期。 总之,thinkphp5.1源码具有很好的可用性和可扩展性,它已经成为PHP开发者中的主流框架之一,许多项目都已经采用了它的开发方式,包括PHP电商、PHP CMS等等,而且它也在不断不断地完善,使得它在未来的开发过程中仍然能保持其领先地位。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值