thinkPHP6.0入门笔记(四)——删除和修改用户信息

2023-11-02


在这里插入图片描述

1.删除用户信息

    删除用户信息,一般是采用Ajax发送delete请求来实现,但是这里主要是熟悉thinkPHP6.0的相关功能,因此不考虑API的封装。但是由于省去了Ajax封装,通常表单默认支持的是get请求和post请求两种方式。因此这里介绍一种新的方式,伪造delete(删除)和put(修改)请求。拿delete请求举例,其写入如下:

   <input type="hidden" name="_method"value="delete"/>

解释:其实仔细一想,原来还是很好理解的,浏览器你去要知道是哪一种请求,肯定需要知道发送的参数值。而这个参数便是method,这里是使用php能够识别的"_method"变量并传递delete值来实现的。其次,去要注意的是thinkPHP中对于数据的删除和修改资源路由都是通过url/:id实现的,传递的id便是数据在数据库中的额唯一标志id。
在这里插入图片描述
    回到之前的页面,重写button的删除代码如下:

 <td class="text-center">
     <form action="{:url('/user/'.$obj.id)}" method="post">
          <!--伪造请求表单-->
           <input type="hidden" name="_method"value="delete"/>
               <button class="btn btn-danger btn-sm btn-delete">删除</button>
               <a class="btn btn-warning btn-sm" href="{:url('/user/'.($obj.id).'/edit')}">修改</a>
     </form>
 </td>

解释:这样,根据表单提交原理,当表单中没有出现type=submit的表单组件时,button会代替并具有submit功能。至于修改部分,本篇文章后半部分再来详细说明。
    当我们进行一次数据设置之后,出现如下报错提示。这应该是thinkPHP框架内部做的检测,毕竟对于数据的删除还有连接据库等相关操作:
在这里插入图片描述
在controller/User.php文件中写入如下方法:

 public function delete($id){
        return UserModel::destroy($id) ? view('../view/public/toast.html',[
            'infos' => ['恭喜,删除成功!'],
            'url_text' => '去首页',
            'url_path' => url('/user')
        ]) : '删除失败';
    }

解释:重用toast提示模块,使用继承了think\model后的UserModel中的destroy方法,利用$id这个数据唯一标识实现数据的删除,这样数据删除就完成了。

2.优化bootstrap资源引入方式

    数据删除还是比较简单的,修改数据相对要复杂一点。首先描述一下模拟删除的需求:用户点击修改数据之后,会跳转到一个edit.html页面展示用户信息,并设置密码可修改,用户名和邮箱无法修改,修改信息同样要有验证。
    接下来便是具体的实现了,首先由于需要展示未修改前的用户数据。故而接上面的伪造表单做url路由重定向,跳转到用户数据展示与编辑页面edit.html.在controller/User.php中增加如下方法:

 public function edit($id){
        return view('edit',[
            'obj' => UserModel::find($id)
        ]);
    }

解释:edit方法用户将页面重定向到edit.html,方法中传递的$id实际上是用户数据字段唯一标识。可通过这个标识配上查询方法find找到用户具体数据,obj实际就是将用户原始数据传递到edit.html页面中。
在edit.html页面中添加如下表单,为了方便验证其实就是拿着create.html作略微修改得到的:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>新增用户页面</title>
    <!--引入css文件-->
    <link rel="stylesheet" href="__CSS__/bootstrap.css.map"/>
    <link rel="stylesheet" href="__CSS__/bootstrap.css"/>
    <link rel="stylesheet" href="__CSS__/style.css"/>
    <!--引入js文件-->
    <script src="__JS__/jquery-3.5.1.min.js"></script>
    <script src="__JS__/bootstrap.js"></script>
    <style>
        .create-form{
            margin-top: 100px;
        }
    </style>
</head>
<body>
<form class="form-horizontal create-form" role="form" action="{:url('/user/'.$obj.id)}" method="post">
    <div class="form-group">
        <label for="firstname" class="col-sm-2 control-label">用户昵称:</label>
        <div class="col-sm-10">
            <input type="text" class="form-control" id="firstname" disabled name="username" placeholder="请输入用户昵称" value={$obj.username}>
        </div>
    </div>
    <div class="form-group">
        <label for="email" class="col-sm-2 control-label" >用户邮箱:</label>
        <div class="col-sm-10">
            <input type="text" class="form-control" id="email" disabled name="email" value={$obj.email} placeholder="请输入用户邮箱">
        </div>
    </div>
    <div class="form-group">
        <label for="newpassword" class="col-sm-2 control-label">修改密码:</label>
        <div class="col-sm-10">
            <input type="password" class="form-control" id="newpassword" name="newpassword" placeholder="请输入用户密码">
        </div>
    </div>
    <div class="form-group">
        <label for="newpasswordnot" class="col-sm-2 control-label">重复密码:</label>
        <div class="col-sm-10">
            <input type="password" class="form-control" id="newpasswordnot" name="newpasswordnot" placeholder="请输入重复密码">
        </div>
    </div>
    <div class="form-group">
        <label for="email" class="col-sm-2 control-label">用户状态:</label>
        <div class="col-sm-10">
            <select name="status" class="form-control">
                <option class="disabled" value="">请选择用户状态</option>
                <option value="0" {$obj.status =='待审核' ? 'selected' : ''} >待审核</option>
                <option value="1" {$obj.status =='正常' ? 'selected' : ''}>正常</option>
            </select>
        </div>
    </div>
    <div class="form-group">
        <div class="col-sm-offset-2 col-sm-10">

            <input type="hidden"  name="__token__" value="{:token()}"  />
            <input type="hidden" name="_method" value="put"/>
            <button type="submit" class="btn btn-success">提交修改</button>
        </div>
    </div>
</form>
</body>
</html>

得到如下页面:
在这里插入图片描述
通过控制台查看发现是static文件中的bootstrap资源没有正确引入:
之前的资源引入为:

  'tpl_replace_string' => [
        '__JS__' => '../../static/js',
        '__CSS__' => '../../static/css',
    ]

这里使用的是相对路径,网站的入口文件目录为public,也就是说localhost/index.php/user写入之后要想将bootstrap资源引入,路径上需要用到两次‘…/’转到localhost(/public)目录下,之后在使用/static/js就能引入了。故而跳转edit.html,由于路径定向使用的相对路径,所以由于传递了依次id,被默认视为一级目录导致路径出错,由于是两种不同的路径,因此只能考虑使用绝对路径,修改为如下代码:

 'tpl_replace_string' => [
        '__JS__' => request()->domain().'/static/js',
        '__CSS__' => request()->domain().'/static/css',
    ]

解释:利用函数request()->domain()可以获取网站域名(也就是入口文件目录),这样就不必使用相对路径了。(补充说明一点:由于thinPHP6.0提供缓存,如果没有效果可以删除runtime/temp目录下的文件并刷新重试),设置完成后的页面展示如下:
在这里插入图片描述
展示部分就完成了,接下来就是数据修改部分的php实现了。

在这里插入图片描述

3.浏览器的cookie与session机制

在这里插入图片描述
    cookie,当用户使用浏览器访问一个支持Cookie的网站的时候,用户会提供包括用户名在内的个人信息并且提交至服务器;接着,服务器在向客户端回传相应的超文本的同时也会发回这些个人信息,当然这些信息并不是存放在HTTP响应体(Response Body)中的,而是存放于HTTP响应头(Response Header)。

    当客户端浏览器接收到来自服务器的响应之后,浏览器会将这些信息存放在一个统一的位置,对于Windows操作系统而言,我们可以从: [系统盘]:\Documents and Settings[用户名]\Cookies目录中找到存储的Cookie(该文件属于受保护的文件,如果想要查看需要在查看的选项中去掉 ‘隐藏受保护文件’ 提高访问权限,不过不安全修改了权限记得改回来,浏览器其实也是可以查看cookie的);自此,客户端再向服务器发送请求的时候,都会把相应的Cookie再次发回至服务器。而这次,Cookie信息则存放在HTTP请求头(Request Header)了。
在这里插入图片描述
    cookie特点:cookie不可跨域名,不同的网站服务器向客户端颁发的cookie不一样。cookie保存中文使用Unicode编码,内存中占用4个字符。其次,cookie名称被创建后不可更改。由于每次用户访问网站会携带网站的cookie信息,因此cookie信息需要做到小而精。

    有了Cookie这样的技术实现,服务器在接收到来自客户端浏览器的请求之后,就能够通过分析存放于请求头的Cookie得到客户端特有的信息,从而动态生成与该客户端相对应的内容。通常,我们可以从很多网站的登录界面中看到“请记住我”这样的选项,如果你勾选了它之后再登录,那么在下一次访问该网站的时候就不需要进行重复而繁琐的登录动作了,而这个功能就是通过Cookie实现的。


    session是一次浏览器和服务器的交互的会话。

    session会话的来历:浏览器打开网页使用的是http协议,而相邻的两个http协议之间没有联系。但是有的时候,在同一网站下面的两个不同页面需要登录用户才能访问,这个时候两次要求用户两次输入密码显得不太合理。其初解决上述问题是采用cookie来解决的,但是cookie存储数据少、不安全等导致了session的诞生,由于session的存储量更大,可以用于保存页面的退出前状态,提高用户友好性。

在这里插入图片描述

session的工作原理:如上图所示,当浏览器第一次访问服务器时,服务器创建一session对象(该对象有一个唯一的id,一般称之为sessionId),服务器会将sessionId以cookie的方式发送给浏览器。当浏览器再次访问服务器时,会将sessionId发送过来,服务器依据sessionId就可以找到对应的session对象。

 HttpSession s = request.getSession(boolean flag);

getSession函数的参数中,flag为true表示的是,先查看请求当中是否有sessionId,如果没有,则创建一个session对象。如果有,则依据sessionId 查找对应的session对象,如果找到了,则返回该对象,如果找不到,创建一个新的session对象。为false的话,只有当请求中存在sessionid才查找并返回session对象否则直接返回null。

session的特点:存储容量大,由于存在在服务器端,用于传递在客户端与服务器端的信息量被增大,加大了服务器的压力。

在这里插入图片描述

4.token令牌原理

    说到底,session终究还是cookie的一种优化,当浏览器禁用cookie时,二者都将失效,因此便诞生了当前比较流行、更为灵活的token令牌机制。但是token并不只是验证这一个作用,更胜一筹的是token优化了表单提交处理。

token的工作原理:和session有点相似,用户第一次登录网站提交用户名和密码,如果通过验证由服务器利用(用户唯一标识+网站设计者的秘钥),结合HMAC-SHA256 算法进行加密,这样能够更加安全,只要秘钥不丢失token伪造就几乎不可能,这样就能满足安全性和唯一性两大要求了。当然,至于token的加密和存储,很多博主也提到了对称加密,token存在解密过程,token直接使用mac地址(电脑唯一标识之一)或者sessionId(sessionId与token并不冲突)等,token存储在cookie或者Local Storage中等。不管是哪一种方法,在整体上表达的意思是:token诞生之后,服务器不在无脑存储session以及sessionId,存储的是一种验证算法,这种算法如果是堆成加密,那么token解密后得到的数据可以进行查询,如果是不可逆加密,两次token可用于鉴权(鉴权:是否登录或者说是使用网站api的权限)。

5.利用token防止表单重复提交

    接下来,我们回到thinkPHP修改用户数据上。一般我们会使用“返回修改”按钮回到edit.html页面,但是我们也可能会使用浏览器自带的返回,当我们使用浏览器自带按钮返回并提交表单时,实际数据是无效的,原因如下:
    在表单提交之后会生成一个token,该token存放在服务端的session或者cache中,并且后端会将该数据发一份给前端。在form表单中,页面使用一个隐藏表单域获取后端传过来的 token值,下一次便将该token再次传回到服务端,如果第二次生成的token与隐藏表单传值一致说明重复了,证明这是一次重复提交,将会像用户返回提示并终止后面的验证。
    实现起来也比较简单,在Validate/User.php中增加rule规则如下:

 '__token__' => 'require|token'

添加相应的规则并写入隐藏表单之后出现如下报错:
在这里插入图片描述
解决方法,在app/middleware.php文件中写入如下代码,开启session:

'think\middleware\SessionInit'

6.同步表单数据库修改

根据thinkPHP函数报错提示在controller/User.php中写入如下函数并打印表单提交参数:

  public function read(){

    }
    public function update(Request $request,$id){
//        return '修改:'.$id;
        dd($request->param());
    }

得到如下效果:
在这里插入图片描述
    接下来就是密码验证了,下面给出场景验证的概念,这里肯定是想要重用Validate模块,但是Validate中本来有username,并设置了require,我们需要设置部分验证(相对于batch全部验证而言),在app/Validate/User.php写入如下代码:

protected $scene=[
        'insert' =>['username','email','password','passwordnot','agree','__token__'],
        'edit'   =>['__token__','newpasswordnot']
    ];

解释:挺好理解的,就是将上面写好的规则组成一个小的数组集合,形成一套验证方案,之后在Validate中直接调用选择好的验证方案名字就行。
    修改后的update方法如下(注意场景之后还需要写batch(true),表示验证场景内部所有规则):

$data=$request->param();
        try{
            validate(UserValidate::class)->scene('edit')->batch(true)->check($data);
        }catch(ValidateException $exception){
            return view('../view/public/toast.html',[
                'infos' => $exception->getError(),
                'url_text' => '返回列表',
                'url_path' => url('/user')
            ]);
        }
        $id=UserModel::update($data)->getData('id');
        return $id ? view('../view/public/toast.html',[
            'infos' => ['恭喜你,修改成功!'],
            'url_text' => '返回首页',
            'url_path' => url('/user')
        ]): '注册失败';

效果展示如下:
在这里插入图片描述
    如此大功告成!

在这里插入图片描述

参考文献:

    1.理解cookie与session机制

    2.session的到底是做什么的?

    3.什么是Session?

    4.Cookie和token的区别

    5.token防止表单重复提交,token 原理

    6.thinkphp6.0没有开启session

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

thinkPHP6.0入门笔记(四)——删除和修改用户信息 的相关文章

  • kaminari ajax 分页不更新分页

    我正在使用 kaminari gem 在 Rails3 中实现分页 我一直在关注github上的这段代码https github com amatsuda kaminari example commits ajax https github
  • 创建动态多维对象/数组

    我正在尝试使用 JS 创建一个多维数组 以便我可以通过 Ajax 调用 PHP 来发布一些数据 这可能很简单 但我对 JS 的了解很少关于这个具体的事情 这是带有代码的 JSFiddle http jsfiddle net k5Q3p 我想
  • CORS 在 jquery 中工作正常,但在 angularjs 中不行

    我的服务器端是php mysql 我正在另一个域的 Web 服务中进行 Ajax 调用 其中启用了 的访问控制 var postUrl http logical brains com elance clone test login php
  • 为什么这会返回资源 id #2? [复制]

    这个问题在这里已经有答案了 可能的重复 我如何从 PHP 中的 MySql 响应中 回显 资源 id 6 https stackoverflow com questions 4290108 how do i echo a resource
  • 在字符串中间添加一个字符

    可能有一个简单的解决方案可以解决这个问题 但会引起面部表情 我将时间存储为 4 个字符长的字符串 即 1300 我试图将该字符串显示为 13 00 我觉得必须有一个比我现在正在做的更优雅的解决方案 我目前有 startTime get fi
  • 在 Laravel 5 中截断表

    描述 我有一个充满测试数据的表 有时 我想清除它以获取新数据 我可以在 DBMS 应用程序中执行截断 例如MySQL 工作台 但我试图在我的应用程序中实现它 Goal 创建一个按钮 单击时截断数据库中的表 这是我的步骤 1 声明一条路线 R
  • 第三个下拉菜单不从数据库填充

    我有以下 Index php
  • 通过 facebook graph API 检索 facebook 用户的邮政编码

    我正在尝试使用 facebook graph API 检索用户的邮政编码 我正在使用以下代码 代码在php ini中 facebook new Facebook array appId gt APP ID secret gt APP SEC
  • 使用 XSLT 将 XML 转换为 SQL

    由于我无法控制的原因 我将获得一个 XML 文件和一个 XSLT 文件 该文件可以将 XML 文件转换为 SQL 代码或错误 现在让我们假设我们可以信任提供 XML 文件的人不会在 XML 中包含危险的构造 我什至不知道是否应该使用 Sim
  • 强制 Composer 下载 git repo 而不是 zip

    我对作曲家有一些问题 require php gt 5 3 2 kriswallsmith buzz 0 7 Repo https github com kriswallsmith Buzz tree v0 7 https github c
  • apache_request_headers() 与 $_SERVER

    据我所知 apache request headers 提供与以下相同的信息 SERVER 但按键略有不同 为什么有人应该使用apache request headers 而不仅仅是从那里获取这些信息 SERVER 我在 Centos 上使
  • 从 HTTP 登录到 HTTPS

    我的网站默认使用 HTTP 我确实有一个启用 HTTPS 的证书 但只有其上的某些区域强制建立安全连接 登录是通过 Ajax 处理的 我想开始使用 SSL 即使请求来自 HTTP 我尝试强制请求的地址具有 HTTPS 并且它完美地回复 然而
  • phpunit测试调用其他需要mock的类方法的方法

    我正在尝试创建一个非常标准的单元测试 在其中调用一个方法并断言它的响应 但是我正在测试的方法调用同一类中的另一个方法 该方法做了一些繁重的工作 我想模拟该方法 但仍按原样执行我正在测试的方法 仅使用从调用另一种方法返回的模拟值 我简化了示例
  • 检查条件并通过 Zend 中的 Regex 识别 url 中的模式

    我正在实现 Zend Regex 路由 并且必须对 url 执行多次检查 例如 如果这是我的网址 http localhost application public index php module controller action 这是
  • 从数据库填充复选框

    我有两个表 第一个由与名称关联的 id 组成 1 汽车 2 火车 3 普通 ETC 第二个表由两个字段 user id 和第一个表中的 id 组成 例如 1 1 2 1 3 当用户转到该页面时 我试图重新填充选定的复选框 首先 您查询数据库
  • 如何在 Zend Framework 3 中注册自定义表单视图助手

    我正在将继承的 Zend Framework 2 应用程序迁移到 Zend Framework 3 并且在注册自定义表单视图助手时遇到了一些困难 这些助手在应用程序使用版本 2 时起作用 主要用于添加标签属性以实现可访问性 例如 这是一个自
  • 从 PHP 数组生成 HTML 表

    我不明白这一点 我需要解决看似简单的问题 但这超出了我的逻辑 我需要编写一个函数 table columns input cols 它将输出一个表 示例 input array apple orange monkey potato chee
  • 如何从父类中获取子类名

    我试图在不需要子类上的函数的情况下完成此任务 这可能吗 我有一种感觉 但我真的很想确定
  • Laravel $request->file() 返回 null

    尝试在后端使用 Laravel 上传文件时遇到问题 Issue Laravel request gt file 方法返回 null Setup 我使用以下方法构建了一个 AJAX 请求超级代理人 https github com visio
  • 将数组从 jquery ajax 传递到代码后面

    我必须将二维数组传递给在asp net网页代码后面编写的页面方法我有一个变量objList作为二维数组 我使用以下代码来实现此目的 但没有成功 并且未调用页面方法 脚本语言 function BindTable objList ajax u

随机推荐

  • WPF界面设计—撸大师

    WPF界面设计 模仿了金山卫士 360 鲁大师的界面
  • keepalived 笔记

    keepalived可以认为是VRRP协议在Linux上的实现 主要有三个模块 分别是core check和vrrp core模块为keepalived的核心 负责主进程的启动 维护以及全局配置文件的加载和解析 check负责健康检查 包括
  • STM32CubeMX系列教程

    微雪课堂 STM32CubeMX系列教程 https www waveshare net study portal php mod list catid 40 page 1
  • 如何保护自己知识产权,建立代码护城河——建立自己的静态库,x86和arm平台的实例讲解

    前言 1 想象一下 假如我们幸幸苦苦写了一个封装库代码 为了建立护城河 我们企业不愿意把真实的代码提供给用户 怕客户拿了代码 这个合同结束 稍微改一点点 就盗用我们的技术 然后说全自主创新 那真是有苦说不出啊 2 但是呢 你不把自己的代码给
  • 2023华为OD机试真题【分苹果/位运算】

    题目内容 A B两个人把苹果分为两堆 A希望按照他的计算规则等分苹果 他的计算规则是按照二进制加法计算 并且不计算进位 12 5 9 1100 0101 9 B的计算规则是十进制加法 包括正常进位 B希望在满足A的情况下获取苹果重量最多 输
  • 信号调理方式(放大、滤波、隔离、调制解调等)

    0 信号调理 百度百科 信号调理简单的说就是指将敏感元件检测到的各种信号转换为标准信号 数字量输入通道中的信号调理主要包括消抖 滤波 保护 电平转换 隔离等 1 一 目 的 将敏感元件检测到的各种信号转换为标准信号 二 方 式 放大电路 滤
  • gdb调试步骤

    gdb调试 Gdb调试过程 1 程序经过预处理后 即进入编译阶段 进入编译阶段 首先声明编译 2 格式 gdb o test test c g 3 进入编译 gdb test 4 显示需要编译调试的源程序 l list list filen
  • Python 基于openpyxl的表格数据处理 举例为统计身高数据

    基于openpyxl的表格数据处理 注意事项 将data html文件放到py文件同级目录下使用相对路径 或使用绝对路径 data xlsx群里有 没找到可以私聊我 注意事项 如果不确定自己的操作是否影响源数据 请在代码最后保存语句中换成其
  • 大数据基础——Linux常用命令

    一个优秀的操作系统 Linux Linux 内核最初只是由芬兰人林纳斯 托瓦兹 Linus Torvalds 在赫尔辛基大学上学时出于个人爱好而编写的 Linux 是一套免费使用和自由传播的类 Unix 操作系统 是一个基于 POSIX 和
  • 初级JS

    JS中实现一个简单日历
  • 贴片电容介质X5R与X7R之间的区别

    X5R X7R类介质贴片电容是在工业中广泛使用的一种温度稳定型电容器 属于II类介质材料 具有中等介电常数 在使用温度 55 125 85 范围内容值变化率在 15 以内 容值老化率为1 说了这么多都是几乎相同的材料 那么这两种材料的不同到
  • 解决nodejs中json序列化时Date类型默认为UTC格式的问题

    在nodejs中 json序列化时Date类型时 默认转为UTC格式 如下图 zhupengfei DESKTOP HJASOE3 MINGW64 d MyProject exp2 node gt new Date 2018 04 24T1
  • Vue3 :Pinia入门

    Vue3 Pinia入门 Date May 11 2023 Sum Pinia概念 实现counter getters 异步action storeToRefs保持响应式解构 什么是Pinia Pinia 是 Vue 的专属状态管理库 可以
  • 什么是第二人称,第二人称在游戏的表现

    油管up Nick Robinson 做过介绍 第一人是玩家角色自身 第二人是游戏内的其他角色 第三人是独立于游戏的观察者 所以说 第一人称视角来自玩家角色自身 玩家看到视角的和现实的视角一致 第三人称视角来自一个独立于游戏世界的第三方观察
  • Doris之rollup上卷及物化视图

    Rollup上卷 通过建表语句创建出来的表称为 Base 表 Base Table 基表 在 Base 表之上 我们可以创建任意多个 ROLLUP 表 这些 ROLLUP 的数据是基于 Base 表产生的 并且在物理上是独立存储的 Roll
  • Redhat Enterprise Linux 9安装配置图解教程

    2022 年 5 月 18 日 IBM 收购的红帽公司宣布推出红帽企业 Linux 9 RHEL 9 这是世界领先的企业 Linux 平台的最新版本 RHEL 9 为支持混合云创新提供了更灵活 更稳定的基础 并为跨物理 虚拟 私有和公共云和
  • workman 日志_workerman

    下载 手册参考 http doc3 workerman net 一 WorkerMan代码规范 1 类采用首字母大写的驼峰式命名 类文件名称必须与文件内部类名相同 以便自动加载 2 使用命名空间 命名空间名字与目录路径对应 并以开发者的项目
  • Java架构直通车——Redis的PF实现原理:HyperLogLog

    文章目录 引入 什么是基数统计 基数统计的常用方法 HyperLogLog原理 再近一步 分桶平均 更近一步 真实的HyperLogLog 引入 之前的文章Java架构直通车 点赞功能用Mysql还是Redis 一文中 我们介绍了分别从my
  • Java处理Excel

    1 引言 Excel是我们平时工作中比较常用的用于存储二维表数据的 Java中有两种常用的方法操作Excel jxl和poi 其中 在小数据量时jxl快于poi 在大数据量时poi要快于jxl 但差距都不明显 本文使用poi进行处理Exce
  • thinkPHP6.0入门笔记(四)——删除和修改用户信息

    thinkPHP6 0实现删除和修改用户信息 1 删除用户信息 2 优化bootstrap资源引入方式 3 浏览器的cookie与session机制 4 token令牌原理 5 利用token防止表单重复提交 6 同步表单数据库修改 参考文