thinkphp笔记-验证码、分页功能、图像处理
验证码功能
https://www.bilibili.com/video/BV12E411y7u8?p=74&vd_source=1f21d9ebff6d1276c8c078b52f10b41d
验证码功能不是系统内置的功能了,需要通过composer 引入进来;
composer require topthink/think-captcha //开启session 方可使用
2024-6-26,版本是3.0.9
安装完成后,会发现config/captcha.php文件。而安装好的部分在vendor/topthink/think-captcha中。
新建一个controller/Code.php控制器
namespace app\controller;
use think\facade\View;
class Code
{
public function form()
{
return View::fetch('form');
}
}
<!-- 作为一个图片直接引入,且每次点击,图片都会改变,且验证码会自动写入session 用于对比验证 -->
{:captcha_img()}
<!-- 作为一个链接,Img标签要自己写,但是这次点击刷新需要自己手动写 -->
<img src="{:captcha_src()}" alt="">
在html模板中
<!-- 作为一个图片直接引入,且每次点击,图片都会改变,且验证码会自动写入session 用于对比验证 -->
{:captcha_img()}
<form action="../code/check" method="post">
<input type="text" name="code">
<input type="submit" value="验证">
</form>
书写一个check方法
use think\facade\Validate;
use think\facade\View;
public function check()
{
$validate = Validate::rule([
// 验证需要使用一个隐藏字段(在安装插件后就会有了)
// captcha验证规则是内置的
'captcha' => 'require|captcha'
]);
// 和表单数据对比
$result = $validate->check([
'captcha' => input('post.code') // 是input框的name属性指向
]);
dump($result);
}
验证码结果不区分大小写
如果要输出验证错误信息
if(!$result) {
$validate->getError();
}
也可以使用助手函数直接进行判断验证;(其实就是将上面的一大段,都整合进一个函数中了)
if(!captcha_check(input('post.code'))) {
echo '验证失败';
}
验证码的所有配置参数如下,根据需要进行调用(在config/captcha.php中修改配置):
配置文件在config/captcha.php 中,直接进行参数配置即可;
参数 | 描述 | 默认 |
---|---|---|
codeSet | 验证码字符集合 | 略 |
expire | 验证码过期时间(s) | 1800 |
math | 使用算术验证码 | false |
useZh | 使用中文验证码 | false |
zhSet | 中文验证码字符串 | 略 |
useImgBg | 使用背景图片 | false |
fontSize | 验证码字体大小(px) | 25 |
useCurve | 是否画混淆曲线 | true |
useNoise | 是否添加杂点 | true |
imageH | 验证码图片高度,设置为0为自动计算 | 0 |
imageW | 验证码图片宽度,设置为0为自动计算 | 0 |
length | 验证码位数 | 5 |
fontttf | 验证码字体,不设置是随机获取 | 空 |
bg | 背景颜色 | [243, 251, 254] |
reset | 验证成功后是否重置 | true |
上面的配置是全局配置,配置后全局生效,如果要单独生成一个验证器。
use think\captcha\facade\Captcha;
public function verify()
{
return Captcha::create();
}
如此,访问tp6/public/code/verify,就会直接看到一张验证码的图片。然后在个别地方直接引入这个图片的链接即可!
上面的Captcha::create()依然使用的是全局配置,如果要针对某个验证码进行单独配置,需要在config/captcha.php中
return [
//验证码位数
'length' => 3,
// 验证码字符集合
'codeSet' => '2345678abcdefhijkmnpqrstuvwxyzABCDEFGHJKLMNPQRTUVWXY',
// 验证码过期时间
'expire' => 1800,
// 是否使用中文验证码
'useZh' => false,
// 是否使用算术验证码
'math' => false,
// 是否使用背景图
'useImgBg' => false,
//验证码字符大小
'fontSize' => 50,
// 是否使用混淆曲线
'useCurve' => true,
//是否添加杂点
'useNoise' => true,
// 验证码字体 不设置则随机
'fontttf' => '',
//背景颜色
'bg' => [243, 251, 254],
// 验证码图片高度
'imageH' => 0,
// 验证码图片宽度
'imageW' => 0,
// 默认下面是被注释的部分,需要额外的解开
// 添加额外的验证码设置
'verify' => [
'length' => 6,
'useZh' => true
],
];
额外的配置项与全局配置项属性一致,且与全局配置不冲突。当注册了额外的配置项,在控制器中:
use think\captcha\facade\Captcha;
public function verify()
{
return Captcha::create('verify');
}
直接在create函数中传入即可。
分页功能
先构建基本的控制器和模板
controller/Page.php控制器
namespace app\controller;
use think\facade\View;
use app\model\User;
class Page
{
public function index()
{
return View::fetch('index', [
'list' => User::select()
]);
}
}
app/view/page/index.html 模板
<table border="1">
<tr>
<th>编号</th>
<th>姓名</th>
<th>性别</th>
<th>邮箱</th>
<th>价格</th>
</tr>
{volist name='list' id='user'}
<tr>
<td>{$user.id}</td>
<td>{$user.username}</td>
<td>{$user.gender}</td>
<td>{$user.email}</td>
<td>{$user.price}</td>
</tr>
{/volist}
</table>
不管是数据库操作还是模型操作,都使用paginate()方法来实现;
namespace app\controller;
use think\facade\View;
use app\model\User;
class Page
{
public function index()
{
// 每页显示5条 paginate直接使用 与select方法类似
$list = User::paginate(5);
return View::fetch('index', [
'list' => $list
]);
}
}
分页功能还提供了一个固定方式,实现分页按钮,只需要设置相应的CSS 即可;
<table border="1">
{volist name='list' id='user'}
....
{/volist}
</table>
{$list|raw}
{$list|raw} 就是默认直接添加分页的按钮,但是没有样式,需要手动添加样式。
我们可以通过数组来传递多个参数,具体分页参数如下:
参数 | 描述 |
---|---|
list_rows | 每页数量 |
page | 当前页 |
path | url路径 |
query | url额外参数 |
fragment | url瞄点 |
var_page | 分页变量 |
// 每页显示5条
// $list = User::paginate(5);
// 通过数组传参 可以传递更多参数
$list = User::paginate([
// 每页显示的行数 每页显示4条
'list_rows' => 4,
// 修改后tp6/public/page?abc=1
'var_page' => 'abc' // 默认是page
]);
return View::fetch('index', [
'list' => $list
]);
可以单独赋值分页的模版的HTML
$pageHtml = $list->render();
模板中使用 {$page|raw}
单独获取到总记录数量等
$list = User::paginate([
// 每页显示的行数 每页显示4条
'list_rows' => 4
]);
// 总共多少条
echo $list->total();
// 每页显示的条数
echo $list->count();
// 最后一页的页码
echo $list->lastpage();
// 分页的HTML
$pageHTML = $list->render();
return View::fetch('index', [
'list' => $list,
'pageHTML' => $pageHTML
]);
在模板中 使用获取的分页HTML
{$pageHTML|raw}
也可以设置分页的页码为简洁分页,就是没有1,2,3,4 这种,只有上下页;
$list = User::paginate(5, true);
如果你使用模型方式分页,则可以通过获取器修改每个字段的值,而分页本身也可以;
$list = User::paginate(5)->each(function($item) {
$item['gender'] = "【{$item['gender']}】";
return $item;
});
图像处理
图像处理功能不是系统内置的功能了,需要通过composer 引入进来;
composer require topthink/think-image
安装好后,插件会存在vendor/topthink/think-image中
引入进来之后,首先创建图像处理对象;获得了图像处理对象后,可以得到这张图片的各种属性;
namespace app\controller;
use think\Image;
class Picture
{
public function index()
{
// 引入public目录下的image.jpg图片
$image = Image::open('image.jpg');
//图片宽度
echo $image->width();
//图片高度
echo $image->height();
//图片类型
echo $image->type();
//图片mime
echo $image->mime();
//图片大小
dump($image->size());
}
}
使用crop()方法可以裁剪图片,并使用save()方法保存到指定路径;
// 裁剪 (save没写路径默认在public目录里)
$image->crop(550, 400)->save('crop1.jpg');
将图片剪裁为500 * 400的图片,保存在public目录中。还有更多的参数。可以点击追踪方法内部,参看源码参数,了解更多的传值方法;
使用thumb()方法,可以生成缩略图,配合save()把缩略图保存下来;
// 缩略图
$image->thumb(500, 500)->save('1.png');
这里要注意一个问题,虽然设置了宽和高,但高度变成了282,说明是等比例的;可以点击追踪方法内部,第三个参数默认为:$type = self::THUMB_SCALING;
更多的常量参数
const THUMB_SCALING = 1; //常量,标识缩略图等比例缩放类型
const THUMB_FILLED = 2; //常量,标识缩略图缩放后填充类型
const THUMB_CENTER = 3; //常量,标识缩略图居中裁剪类型
const THUMB_NORTHWEST = 4; //常量,标识缩略图左上角裁剪类型
const THUMB_SOUTHEAST = 5; //常量,标识缩略图右下角裁剪类型
const THUMB_FIXED = 6; //常量,标识缩略图固定尺寸缩放类型
// 补全填充 (原图为横幅 则宽100同时 上下两侧留白边)
$image->thumb(500, 500, 2)->save('1.png');
// 按照高度500放大图片 填充满画布
$image->thumb(500, 500, 3)->save('1.png');
使用rotate()方法,可以旋转图片,默认是90 度,参数可以设置;
// 旋转图片 (180度旋转)
$image->rotate(180)->save('1.jpg');
save()方法可以配置的参数除了保存文件名的路径,还有以下几个:
save('路径',['类型','质量','是否隔行扫描']),追踪到方法查看;
save($pathname, $type = null, $quality = 80, $interlace = true)
$interlace隔行扫描是与图片渲染时候效果有关,1是由模糊逐渐变清晰;2是直接出来的时候就是清晰,设置为true那么就是控制保存后的图片渲染时候是由模糊逐渐变清晰的。
water()方法,可以给图片增加一个图片水印,默认位置为右下角,可看源码常量;
// 图片水印 (默认在右下角)
$image->water('watermark.png')->save('water1.jpg');
// 水印在左上角
$image->water('watermark.png', 1)->save('water1.jpg');
/* 水印相关常量定义 */
const WATER_NORTHWEST = 1; //常量,标识左上角水印
const WATER_NORTH = 2; //常量,标识上居中水印
const WATER_NORTHEAST = 3; //常量,标识右上角水印
const WATER_WEST = 4; //常量,标识左居中水印
const WATER_CENTER = 5; //常量,标识居中水印
const WATER_EAST = 6; //常量,标识右居中水印
const WATER_SOUTHWEST = 7; //常量,标识左下角水印
const WATER_SOUTH = 8; //常量,标识下居中水印
const WATER_SOUTHEAST = 9; //常量,标识右下角水印
text()方法,可以给图片增加一个文字水印
先来看一个PHP原生函数 十分有用
// PHP原生函数 得到当前文件的位置 会输出D:\phpstudy\phpstudy_pro\WWW\xuexi\tp6\public
echo getcwd();
因为PHP在使用字体时候,必须要指定磁盘的绝对路径,不能仅仅使用字符串!
// 文字水印 错的!!
// $image->text('wubin',
// 'water-mark-font.ttf', 错!!
// 30,
// '#fff'
// )->save('text1.png');
以下是正确的方式
$image->text('wubin', getcwd().'\water-mark-font.ttf', 20, '#ffffff')->save('text1.png');
注意,\water-mark-font.ttf 因win系统与其他系统不同会有差异,win下\代表路径分隔,其他系统应该是/
以下是完整测试代码
<?php
namespace app\controller;
use think\Image;
class Picture
{
public function index()
{
// 引入public目录下的image.jpg图片
$image = Image::open('image.jpg');
//图片宽度
echo $image->width();
//图片高度
echo $image->height();
//图片类型
echo $image->type();
//图片mime
echo $image->mime();
//图片大小
dump($image->size());
// 裁剪 (save没写路径默认在public目录里)
$image->crop(550, 400)->save('crop1.jpg');
// 缩略图
// 补全填充 (原图为横幅 则宽100同时 上下两侧留白边)
$image->thumb(500, 500, 2)->save('1.png');
// 按照高度500放大图片 填充满画布
$image->thumb(500, 500, 3)->save('1.png');
// 旋转图片 (180度旋转)
$image->rotate(180)->save('1.jpg');
// 图片水印 (默认在右下角)
$image->water('watermark.png')->save('water1.jpg');
// 水印在左上角
$image->water('watermark.png', 1)->save('water1.jpg');
// PHP原生函数 得到当前文件的位置 会输出D:\phpstudy\phpstudy_pro\WWW\xuexi\tp6\public
echo getcwd();
// 文字水印
$image->text('wubin', getcwd().'\water-mark-font.ttf', 20, '#ffffff')->save('text1.png');
}
}