TP5学习(十三):其他

2023-11-14

一、缓存

设置


缓存支持采用驱动方式,所以缓存在使用之前,需要进行连接操作,也就是缓存初始化操作。

$options = [
    // 缓存类型为File
    'type'  =>  'File', 
    // 缓存有效期为永久有效
    'expire'=>  0, 
    //缓存前缀
    'prefix'=>  'think',
     // 指定缓存目录
    'path'  =>  APP_PATH.'runtime/cache/',
];
Cache::connect($options);

或者通过定义配置参数的方式,在应用配置文件中添加:

'cache'  => [
    'type'   => 'File',
    'path'   => CACHE_PATH,
    'prefix' => '',
    'expire' => 0,
],

支持的缓存类型包括file、memcache、wincache、sqlite、redis和xcache。

缓存参数根据不同的缓存方式会有所区别,通用的缓存参数如下:

在这里插入图片描述
使用


缓存初始化之后,就可以进行相关缓存操作了。

如果通过配置文件方式定义缓存参数的话,可以无需手动进行缓存初始化操作,可以直接进行缓存读取和设置等操作。

设置缓存

设置缓存(有效期一个小时)

Cache::set('name',$value,3600);

如果设置成功返回true,否则返回false。

V5.0.11版本开始,缓存有效期支持指定过期时间,用法:

Cache::set('name',$value,new DateTime('2017-10-1 12:00'));

表示缓存数据到2017年10月1日中午12点过期。

缓存自增

针对数值类型的缓存数据,可以使用自增操作,例如:

// name自增(步进值为1)
Cache::inc('name');
// name自增(步进值为3)
Cache::inc('name',3);

缓存自减

针对数值类型的缓存数据,可以使用自减操作,例如:

// name自减(步进值为1)
Cache::dec('name');
// name自减(步进值为3)
Cache::dec('name',3);

获取缓存

获取缓存数据可以使用:

dump(Cache::get('name')); 

如果name值不存在,则默认返回 false。

支持指定默认值,例如:

dump(Cache::get('name','')); 

表示如果name值不存在,则返回空字符串。

删除缓存

Cache::rm('name'); 

获取并删除缓存

Cache::pull('name'); 

如果name值不存在,则返回null。

清空缓存

Cache::clear(); 

不存在则写入缓存数据后返回(v5.0.2+)

Cache::remember('name',function(){
	return time();
});

获取缓存对象

可以获取缓存对象,并且调用驱动类的高级方法,例如:

$cache = Cache::init();
// 获取缓存对象句柄
$handler = $cache->handler();

助手函数

系统对缓存操作提供了助手函数cache,用法如下:

$options = [
     // 缓存类型为File
    'type'   => 'File', 
     // 缓存有效期为永久有效
    'expire' => 0,
     // 指定缓存目录
    'path'   => APP_PATH . 'runtime/cache/', 
];

// 缓存初始化
// 不进行缓存初始化的话,默认使用配置文件中的缓存配置
cache($options);

// 设置缓存数据
cache('name', $value, 3600);
// 获取缓存数据
var_dump(cache('name'));
// 删除缓存数据
cache('name', NULL);

// 设置缓存的同时并且进行参数设置
cache('test', $value, $options);

缓存标签


支持给缓存数据打标签,例如:

Cache::tag('tag')->set('name1','value1');
Cache::tag('tag')->set('name2','value2');
// 或者批量设置缓存标签
Cache::set('name1','value1');
Cache::set('name2','value2');
Cache::tag('tag',['name1','name2']);
// 清除tag标签的缓存数据
Cache::clear('tag');

同时使用多个缓存类型


如果要同时使用多个缓存类型进行操作的话,可以做如下配置:

'cache' =>  [
    // 使用复合缓存类型
    'type'  =>  'complex',
    // 默认使用的缓存
    'default'   =>  [
        // 驱动方式
        'type'   => 'File',
        // 缓存保存目录
        'path'   => CACHE_PATH,
    ],
    // 文件缓存
    'file'   =>  [
        // 驱动方式
        'type'   => 'file',
        // 设置不同的缓存保存目录
        'path'   => RUNTIME_PATH . 'file/',
    ],  
    // redis缓存
    'redis'   =>  [
        // 驱动方式
        'type'   => 'redis',
        // 服务器地址
        'host'       => '127.0.0.1',
    ],     
],

cache.type配置为complex之后,就可以缓存多个缓存类型和缓存配置,每个缓存配置的方法和之前一样,并且你可以给相同类型的缓存类型(使用不同的缓存标识)配置不同的缓存配置参数。

当使用

Cache::set('name', 'value');
Cache::get('name');

的时候,其实使用的是default缓存标识的缓存配置,如果需要切换到其它的缓存标识操作,可以使用:

// 切换到file操作
Cache::store('file')->set('name','value');
Cache::get('name');
// 切换到redis操作
Cache::store('redis')->set('name','value');
Cache::get('name');

二、Session

session初始化


在TP5中使用\think\Session类进行Session相关操作,Session会在第一次调用Session类的时候按照配置的参数自动初始化,例如,我们在应用配置中添加如下配置:

'session'                => [
    'prefix'         => 'think',
    'type'           => '',
    'auto_start'     => true,
],

如果我们使用上述的session配置参数的话,无需任何操作就可以直接调用Session类的相关方法,例如:

Session::set('name','thinkphp');
Session::get('name');

如果你应用下面的不同模块需要不同的session参数,那么可以在模块配置文件中重新设置:

'session'                => [
    'prefix'         => 'module',
    'type'           => '',
    'auto_start'     => true,
],

或者调用init方法进行初始化:

Session::init([
    'prefix'         => 'module',
    'type'           => '',
    'auto_start'     => true,
]);

如果你没有使用Session类进行Session操作的话,例如直接操作$_SESSION,必须使用上面的方式手动初始化或者直接调用session_start()方法进行session初始化。

设置参数


默认支持的session设置参数包括:
在这里插入图片描述

如果做了session驱动扩展,可能有些参数不一定有效。

基础用法


赋值

// 赋值(当前作用域)
Session::set('name','thinkphp');
// 赋值think作用域
Session::set('name','thinkphp','think');

判断是否存在

// 判断(当前作用域)是否赋值
Session::has('name');
// 判断think作用域下面是否赋值
Session::has('name','think');

取值

// 取值(当前作用域)
Session::get('name');
// 取值think作用域
Session::get('name','think');

如果name的值不存在,返回null。

删除

// 删除(当前作用域)
Session::delete('name');
// 删除think作用域下面的值
Session::delete('name','think');

指定作用域

// 指定当前作用域
Session::prefix('think');

取值并删除

// 取值并删除
Session::pull('name');

如果name的值不存在,返回Null。

清空

// 清除session(当前作用域)
Session::clear();
// 清除think作用域
Session::clear('think');

闪存数据,下次请求之前有效(v5.0.2+)

// 设置session 并且在下一次请求之前有效
Session::flash('name','value');

提前清除当前请求有效的数据(v5.0.2+)

// 清除当前请求有效的session
Session::flush();

二级数组


支持session的二维数组操作,例如:

// 赋值(当前作用域)
Session::set('name.item','thinkphp');
// 判断(当前作用域)是否赋值
Session::has('name.item');
// 取值(当前作用域)
Session::get('name.item');
// 删除(当前作用域)
Session::delete('name.item');

助手函数


系统也提供了助手函数session完成相同的功能,例如:

// 初始化session
session([
    'prefix'     => 'module',
    'type'       => '',
    'auto_start' => true,
]);

// 赋值(当前作用域)
session('name', 'thinkphp');

// 赋值think作用域
session('name', 'thinkphp', 'think');

// 判断(当前作用域)是否赋值
session('?name');

// 取值(当前作用域)
session('name');

// 取值think作用域
session('name', '', 'think');

// 删除(当前作用域)
session('name', null);

// 清除session(当前作用域)
session(null);

// 清除think作用域
session(null, 'think');

Session驱动


支持指定 Session 驱动,配置文件如下:

'session' => [
    'prefix'     => 'module',
    'type'       => 'redis',
    'auto_start' => true,
     // redis主机
    'host'       => '127.0.0.1',
     // redis端口
    'port'       => 6379,
     // 密码
    'password'   => '',
]

表示使用redis作为session类型。

三、Cookie

基本操作


初始化

// cookie初始化
Cookie::init(['prefix'=>'think_','expire'=>3600,'path'=>'/']);
// 指定当前前缀
Cookie::prefix('think_');

支持的参数及默认值如下:

// cookie 名称前缀
'prefix'    => '',
// cookie 保存时间
'expire'    => 0,
// cookie 保存路径
'path'      => '/',
// cookie 有效域名
'domain'    => '',
//  cookie 启用安全传输
'secure'    => false,
// httponly设置
'httponly'  => '',
// 是否使用 setcookie
'setcookie' => true,

设置

// 设置Cookie 有效期为 3600秒
Cookie::set('name','value',3600);
// 设置cookie 前缀为think_
Cookie::set('name','value',['prefix'=>'think_','expire'=>3600]);
// 支持数组
Cookie::set('name',[1,2,3]);

判断

Cookie::has('name');
// 判断指定前缀的cookie值是否存在
Cookie::has('name','think_');

获取

Cookie::get('name');
// 获取指定前缀的cookie值
Cookie::get('name','think_');

删除

删除cookie

Cookie::delete('name');
// 删除指定前缀的cookie
Cookie::delete('name','think_');

清空

// 清空指定前缀的cookie
Cookie::clear('think_');

助手函数


系统提供了cookie助手函数用于基本的cookie操作,例如:

// 初始化
cookie(['prefix' => 'think_', 'expire' => 3600]);

// 设置
cookie('name', 'value', 3600);

// 获取
echo cookie('name');

// 删除
cookie('name', null);

// 清除
cookie(null, 'think_');

四、多语言

开启和加载语言包


默认情况下,系统载入的是配置的默认语言包,并且不会自动侦测当前系统的语言。

默认语言由default_lang配置参数设置,系统默认设置为:

// 默认语言
'default_lang'           => 'zh-cn',

要启用语言自动侦测和多语言自动切换,需要开启多语言切换,在应用的公共配置文件添加:

// 开启语言切换
'lang_switch_on' => true,   

开启后,系统会自动检测当前语言(主要是指浏览器访问的情况下)会对两种情况进行检测:

  • 是否有$_GET[‘lang’]
  • 识别$_SERVER[‘HTTP_ACCEPT_LANGUAGE’]中的第一个语言
  • 检测到任何一种情况下采用Cookie缓存
  • 如果检测到的语言在允许的语言列表内认为有效,否则使用默认设置的语言

如果不希望浏览器自动侦测语言,请关闭lang_switch_on后设置默认语言。

如果在自动侦测语言的时候,希望设置允许的语言列表,不在列表范围的语言则仍然使用默认语言,可以使用:

// 设置允许的语言
Lang::setAllowLangList(['zh-cn','en-us']);

语言变量定义


语言变量的定义,只需要在需要使用多语言的地方,写成:

Lang::get('add user error');
// 使用系统封装的助手函数
lang('add user error');

也就是说,字符串信息要改成Lang::get方法来表示。

语言定义一般采用英语来描述。

语言文件定义


系统会默认加载下面三个语言包:

框架语言包: thinkphp\lang\当前语言.php
应用语言包: application\lang\当前语言.php
模块语言包: application\模块\lang\当前语言.php

如果你还需要加载其他的语言包,可以在设置或者自动检测语言之后,用load方法进行加载:

Lang::load(APP_PATH . 'common\lang\zh-cn.php');

ThinkPHP语言文件定义采用返回数组方式:

return [
     'hello thinkphp'  => '欢迎使用ThinkPHP',
     'data type error' => '数据类型错误',
];

也可以在程序里面动态设置语言定义的值,使用下面的方式:

Lang::set('define2','语言定义');
$value = Lang::get('define2');

通常多语言的使用是在控制器里面,但是模型类的自动验证功能里面会用到提示信息,这个部分也可以使用多语言的特性。例如原来的方式是把提示信息直接写在模型里面定义:

['title','require','标题必须!',1],

如果使用了多语言功能的话(假设,我们在当前语言包里面定义了’ lang_var’=>‘标题必须!’),就可以这样定义模型的自动验证

['title','require','{%lang_var}',1],

如果要在模板中输出语言变量不需要在控制器中赋值,可以直接使用模板引擎特殊标签来直接输出语言定义的值:

{$Think.lang.lang_var}

可以输出当前语言包里面定义的 lang_var语言定义。

变量传入支持


语言包定义的时候支持传入变量,有两种方式

使用命名绑定方式,例如:

'file_format'    =>    '文件格式: {:format},文件大小:{:size}',

在模板中输出语言字符串的时候传入变量值即可:

{:lang('file_format',['format' => 'jpeg,png,gif,jpg','size' => '2MB'])}

第二种方式是使用格式字串,如果你需要使用第三方的翻译工具,建议使用该方式定义变量。

'file_format'    =>    '文件格式: %s,文件大小:%d',

在模板中输出多语言的方式更改为:

{:lang('file_format',['jpeg,png,gif,jpg','2MB'])}

五、分页

THP5内置了分页实现,要给数据添加分页输出功能在5.0变得非常简单,可以直接在Db类查询的时候调用paginate方法:

// 查询状态为1的用户数据 并且每页显示10条数据
$list = Db::name('user')->where('status',1)->paginate(10);
// 把分页数据赋值给模板变量list
$this->assign('list', $list);
// 渲染模板输出
return $this->fetch();

也可以改成模型的分页查询代码:

// 查询状态为1的用户数据 并且每页显示10条数据
$list = User::where('status',1)->paginate(10);
// 把分页数据赋值给模板变量list
$this->assign('list', $list);
// 渲染模板输出
return $this->fetch();

模板文件中分页输出代码如下:

<div>
<ul>
{volist name='list' id='user'}
    <li> {$user.nickname}</li>
{/volist}
</ul>
</div>
{$list->render()}

也可以单独赋值分页输出的模板变量

// 查询状态为1的用户数据 并且每页显示10条数据
$list = User::where('status',1)->paginate(10);
// 获取分页显示
$page = $list->render();
// 模板变量赋值
$this->assign('list', $list);
$this->assign('page', $page);
// 渲染模板输出
return $this->fetch();

模板文件中分页输出代码如下:

<div>
<ul>
{volist name='list' id='user'}
    <li> {$user.nickname}</li>
{/volist}
</ul>
</div>
{$page}

默认情况下,生成的分页输出是完整分页功能,带总分页数据和上下页码,分页样式只需要通过样式修改即可,完整分页默认生成的分页输出代码为:

<ul class="pagination">
<li><a href="?page=1">&laquo;</a></li>
<li><a href="?page=1">1</a></li>
<li class="active"><span>2</span></li>
<li class="disabled"><span>&raquo;</span></li>
</ul>

传入总记录数( V5.0.1)

V5.0.1版本开始,支持传入总记录数而不会自动进行总数计算,例如:

// 查询状态为1的用户数据 并且每页显示10条数据 总记录数为1000
$list = User::where('status',1)->paginate(10,1000);
// 获取分页显示
$page = $list->render();
// 模板变量赋值
$this->assign('list', $list);
$this->assign('page', $page);
// 渲染模板输出
return $this->fetch();

分页后数据处理 (V5.0.9)

V5.0.9版本开始 支持分页类后数据直接each遍历处理,方便修改分页后的数据,而不是只能通过模型的获取器来补充字段。

$list = User::where('status',1)->paginate()->each(function($item, $key){
    $item->nickname = 'think';
});

如果是Db类操作分页数据的话,each方法的闭包函数中需要使用返回值,例如:

$list = Db::name('user')->where('status',1)->paginate()->each(function($item, $key){
    $item['nickname'] = 'think';
    return $item;
});

简洁分页


如果你仅仅需要输出一个 仅仅只有上下页的分页输出,可以使用下面的简洁分页代码:

// 查询状态为1的用户数据 并且每页显示10条数据
$list = User::where('status',1)->paginate(10,true);
// 把分页数据赋值给模板变量list
$this->assign('list', $list);
// 渲染模板输出
return $this->fetch();

简洁分页模式的输出代码为:

<ul class="pager">
<li><a href="?page=1">&laquo;</a></li>
<li class="disabled"><span>&raquo;</span></li>
</ul>

由于简洁分页模式不需要查询总数据数,因此可以提高查询性能。

分页参数


主要的分页参数如下:
在这里插入图片描述
分页参数的设置方式有两种,第一种是在配置文件中定义,例如:

//分页配置
'paginate'               => [
    'type'     => 'bootstrap',
    'var_page' => 'page',
],

type属性支持命名空间,例如:

//分页配置
'paginate'               => [
    'type'     => '\org\page\bootstrap',
    'var_page' => 'page',
],

也可以在调用分页方法的时候传入,例如:

$list = Db::name('user')->where('status',1)->paginate(10,true,[
    'type'     => 'bootstrap',
    'var_page' => 'page',
]);

六、上传

上传文件


TP5对文件上传的支持更加简单。

内置的上传只是上传到本地服务器,上传到远程或者第三方平台的话需要自己扩展。

假设表单代码如下:

<form action="/index/index/upload" enctype="multipart/form-data" method="post">
<input type="file" name="image" /> <br> 
<input type="submit" value="上传" /> 
</form> 

然后在控制器中添加如下的代码:

public function upload(){
    // 获取表单上传文件 例如上传了001.jpg
    $file = request()->file('image');
    
    // 移动到框架应用根目录/public/uploads/ 目录下
    if($file){
        $info = $file->move(ROOT_PATH . 'public' . DS . 'uploads');
        if($info){
            // 成功上传后 获取上传信息
            // 输出 jpg
            echo $info->getExtension();
            // 输出 20160820/42a79759f284b767dfcb2a0197904287.jpg
            echo $info->getSaveName();
            // 输出 42a79759f284b767dfcb2a0197904287.jpg
            echo $info->getFilename(); 
        }else{
            // 上传失败获取错误信息
            echo $file->getError();
        }
    }
}

move方法成功的话返回的是一个\think\File对象,你可以对上传后的文件进行后续操作。

多文件上传


如果你使用的是多文件上传表单,例如:

<form action="/index/index/upload" enctype="multipart/form-data" method="post">
<input type="file" name="image[]" /> <br> 
<input type="file" name="image[]" /> <br> 
<input type="file" name="image[]" /> <br> 
<input type="submit" value="上传" /> 
</form> 

控制器代码可以改成:

public function upload(){
    // 获取表单上传文件
    $files = request()->file('image');
    foreach($files as $file){
        // 移动到框架应用根目录/public/uploads/ 目录下
        $info = $file->move(ROOT_PATH . 'public' . DS . 'uploads');
        if($info){
            // 成功上传后 获取上传信息
            // 输出 jpg
            echo $info->getExtension(); 
            // 输出 42a79759f284b767dfcb2a0197904287.jpg
            echo $info->getFilename(); 
        }else{
            // 上传失败获取错误信息
            echo $file->getError();
        }    
    }
}

上传验证


支持对上传文件的验证,包括文件大小、文件类型和后缀:

public function upload(){
    // 获取表单上传文件 例如上传了001.jpg
    $file = request()->file('image');
    // 移动到框架应用根目录/public/uploads/ 目录下
    $info = $file->validate(['size'=>15678,'ext'=>'jpg,png,gif'])->move(ROOT_PATH . 'public' . DS . 'uploads');
    if($info){
        // 成功上传后 获取上传信息
        // 输出 jpg
        echo $info->getExtension();
        // 输出 20160820/42a79759f284b767dfcb2a0197904287.jpg
        echo $info->getSaveName();
        // 输出 42a79759f284b767dfcb2a0197904287.jpg
        echo $info->getFilename(); 
    }else{
        // 上传失败获取错误信息
        echo $file->getError();
    }
}

getSaveName方法返回的是图片的服务器文件地址,并不能直接用于图片的URL地址,尤其在windows平台上必须做转换才能正常显示图片。

如果上传文件验证不通过,则move方法返回false。
在这里插入图片描述

还有一个额外的自动验证规则是,如果上传的文件后缀是图像文件后缀,则会检查该文件是否是一个合法的图像文件。

上传规则


默认情况下,会在上传目录下面生成以当前日期为子目录,以微秒时间的md5编码为文件名的文件,例如上面生成的文件名可能是:

/home/www/upload/20160510/42a79759f284b767dfcb2a0197904287.jpg

我们可以指定上传文件的命名规则,使用rule方法即可,例如:

// 获取表单上传文件 例如上传了001.jpg
$file = request()->file('image');
// 移动到服务器的上传目录 并且使用md5规则
$file->rule('md5')->move('/home/www/upload/');

最终生成的文件名类似于:

/home/www/upload/72/ef580909368d824e899f77c7c98388.jpg

系统默认提供了几种上传命名规则,包括:

加粗样式

其中md5和sha1规则会自动以散列值的前两个字符作为子目录,后面的散列值作为文件名。

如果需要使用自定义命名规则,可以在rule方法中传入函数或者方法,例如:

// 获取表单上传文件 例如上传了001.jpg
$file = request()->file('image');
// 移动到服务器的上传目录 并且使用uniqid规则
$file->rule('uniqid')->move('/home/www/upload/');

生成的文件名类似于:

/home/www/upload/573d3b6d7abe2.jpg

如果你希望保留原文件名称,可以使用:

// 获取表单上传文件 例如上传了001.jpg
$file = request()->file('image');
// 移动到服务器的上传目录 并且使用原文件名
$file->move('/home/www/upload/','');

默认情况下,会覆盖服务器上传目录下的同名文件,如果不希望覆盖,可以使用:

// 获取表单上传文件 例如上传了001.jpg
$file = request()->file('image');
// 移动到服务器的上传目录 并且设置不覆盖
$file->move('/home/www/upload/',true,false);

获取文件hash散列值


可以获取上传文件的哈希散列值,例如:

// 获取表单上传文件
$file = request()->file('image');
// 移动到服务器的上传目录 并且使用原文件名
$upload = $file->move('/home/www/upload/');
// 获取上传文件的hash散列值
echo $upload->md5();
echo $upload->sha1();

v5.0.1以上版本可以统一使用hash方法获取文件散列值

// 获取表单上传文件
$file = request()->file('image');
// 移动到服务器的上传目录 并且使用原文件名
$upload = $file->move('/home/www/upload/');
// 获取上传文件的hash散列值
echo $upload->hash('sha1');
echo $upload->hash('md5');

返回对象


上传成功后返回的仍然是一个File对象,除了File对象自身的方法外,并且可以使用SplFileObject的属性和方法,便于进行后续的文件处理。

七、验证码

首先使用Composer安装think-captcha扩展包:

composer require topthink/think-captcha

验证码的简单用法


扩展包内定义了一些常见用法方便使用,以下示例说明

注意:需要开启URL路由。

模版内验证码的显示

<div>{:captcha_img()}</div>

或者

<div><img src="{:captcha_src()}" alt="captcha" /></div>

上面两种的最终效果是一样的,根据需要调用即可

使用TP5的内置验证功能,添加captcha验证规则即可

$this->validate($data,[
    'captcha|验证码'=>'require|captcha'
]);

或者手动验证

if(!captcha_check($captcha)){
 //验证失败
};

验证码的自定义用法


如果项目未开启路由,或者有实际需求可自行调用Captcha类操作

验证码的生成:

$captcha = new Captcha();
return $captcha->entry();

如果你需要在一个页面中生成多个验证码的话,entry方法需要传入可标识的信息,例如:

$captcha = new Captcha();
return $captcha->entry(1);

验证码的验证:
可以用Captcha类的check方法检测验证码的输入是否正确,例如,下面是封装的一个验证码检测的函数:

// 检测输入的验证码是否正确,$code为用户输入的验证码字符串,$id多个验证码标识
function check_verify($code, $id = ''){
    $captcha = new Captcha();
    return $captcha->check($code, $id);
}

验证码的配置参数


Captcha类带有默认的配置参数,支持自定义配置。这些参数包括:

如果使用了扩展内置的方法,务必在应用配置文件中配置,5.0.1及以上支持者在应用配置目录下面extra子目录内配置captcha.php文件

在这里插入图片描述
参数设置使用两种方式。

实例化传入参数:

$config =    [
    // 验证码字体大小
    'fontSize'    =>    30,    
    // 验证码位数
    'length'      =>    3,   
    // 关闭验证码杂点
    'useNoise'    =>    false, 
];
$captcha = new Captcha($config);
return $captcha->entry();

或者采用动态设置的方式,如:

$captcha = new Captcha();
$captcha->fontSize = 30;
$captcha->length   = 3;
$captcha->useNoise = false;
return $captcha->entry();

验证码字体

默认情况下,验证码的字体是随机使用扩展包内 think-captcha/assets/ttfs目录下面的字体文件,我们可以指定验证码的字体,例如:

$captcha = new Captcha();
$captcha->fontttf = '5.ttf'; 
return $captcha->entry();

背景图片

支持验证码背景图片功能,可以如下设置:

$captcha = new Captcha();
// 开启验证码背景图片功能 随机使用扩展包内`think-captcha/assets/bgs`目录下面的图片
$captcha->useImgBg = true; 
return $captcha->entry();

中文验证码

如果要使用中文验证码,可以设置:

$captcha = new Captcha();
//中午 验证码字体使用扩展包内`think-captcha/assets/zhttfs`字体文件
$captcha->useZh = true; 
return $captcha->entry();

指定验证码字符

指定验证码的字符,可以设置:

$captcha = new Captcha();
// 设置验证码字符为纯数字
$captcha->codeSet = '0123456789'; 
return $captcha->entry();

如果是中文验证码,可以使用zhSet参数设置,例如:

$captcha = new Captcha();
$captcha->useZh = true;
// 设置验证码字符
$captcha->zhSet = '们以我到他会作时要动国产的一是工就年阶义发成部民可出能方进在了不和有大这'; 
return $captcha->entry();

默认的验证码字符已经剔除了易混淆的1l0o等字符

八、图像处理

安装扩展


使用Composer安装ThinkPHP5的图像处理类库:

composer require topthink/think-image

图像操作


下面来看下图像操作类的基础方法。

打开图像文件

假设当前入口文件目录下面有一个image.png文件,如图所示:在这里插入图片描述
使用open方法打开图像文件进行相关操作:

$image = \think\Image::open('./image.png');

也可以从直接获取当前请求中的文件上传对象,例如:

$image = \think\Image::open(request()->file('image'));

获取图像信息

可以获取打开图片的信息,包括图像大小、类型等,例如:

$image = \think\Image::open('./image.png');
// 返回图片的宽度
$width = $image->width(); 
// 返回图片的高度
$height = $image->height(); 
// 返回图片的类型
$type = $image->type(); 
// 返回图片的mime类型
$mime = $image->mime(); 
// 返回图片的尺寸数组 0 图片宽度 1 图片高度
$size = $image->size(); 

裁剪图片

使用crop和save方法完成裁剪图片功能。

$image = \think\Image::open('./image.png');
//将图片裁剪为300x300并保存为crop.png
$image->crop(300, 300)->save('./crop.png');

生成的图片如图:
在这里插入图片描述
支持从某个坐标开始裁剪,例如下面从(100,30)开始裁剪,例如:

$image = \think\Image::open('./image.png');
//将图片裁剪为300x300并保存为crop.png
$image->crop(300, 300,100,30)->save('./crop.png');

生成的图片如图:
在这里插入图片描述
生成缩略图

使用thumb方法生成缩略图,例如:

$image = \think\Image::open('./image.png');
// 按照原图的比例生成一个最大为150*150的缩略图并保存为thumb.png
$image->thumb(150, 150)->save('./thumb.png');

生成的缩略图如图所示:

我们看到实际生成的缩略图并不是150*150,因为默认采用原图等比例缩放的方式生成缩略图,最大宽度是150。
可以支持其他类型的缩略图生成,设置包括\think\Image的下列常量或者对应的数字:

//常量,标识缩略图等比例缩放类型
const THUMB_SCALING   = 1; 
//常量,标识缩略图缩放后填充类型
const THUMB_FILLED    = 2; 
//常量,标识缩略图居中裁剪类型
const THUMB_CENTER    = 3; 
//常量,标识缩略图左上角裁剪类型
const THUMB_NORTHWEST = 4;
//常量,标识缩略图右下角裁剪类型
const THUMB_SOUTHEAST = 5; 
//常量,标识缩略图固定尺寸缩放类型
const THUMB_FIXED     = 6; 

比如我们居中裁剪:

$image = \think\Image::open('./image.png');
// 按照原图的比例生成一个最大为150*150的缩略图并保存为thumb.png
$image->thumb(150,150,\think\Image::THUMB_CENTER)->save('./thumb.png');

后生成的缩略图效果如图:
在这里插入图片描述
再比如我们右下角剪裁

$image = \think\Image::open('./image.png');
// 按照原图的比例生成一个最大为150*150的缩略图并保存为thumb.png
$image->thumb(150,150,\think\Image::THUMB_SOUTHEAST)->save('./thumb.png');

生成的缩略图效果如图:
在这里插入图片描述
这里就不再对其他用法一一举例了。

图像翻转

使用flip可以对图像进行翻转操作,默认是以x轴进行翻转,例如:

$image = \think\Image::open('./image.png');
// 对图像进行以x轴进行翻转操作
$image->flip()->save('./filp_image.png');

生成的效果如图:
在这里插入图片描述

我们也可以改变参数,以y轴进行翻转,例如:

$image = \think\Image::open('./image.png');
// 对图像进行以y轴进行翻转操作
$image->flip(\think\image::FLIP_Y)->save('./filp_image.png');

生成的效果如图:
在这里插入图片描述

图像的翻转可以理解为图像的镜面效果与图像旋转有所不同。

图像旋转

使用rotate可以对图像进行旋转操作(默认是顺时针旋转90度),我们用默认90度进行旋转举例:

$image = \think\Image::open('./image.png');
// 对图像使用默认的顺时针旋转90度操作
$image->rotate()->save('./rotate_image.png');

生成的效果如图:
在这里插入图片描述
图像保存参数

save方法可以配置的参数
在这里插入图片描述

设置隔行扫描的情况下在网页进行浏览时。是从上到下一行一行的显示,否则图片整个显示出来 然后由模糊到清晰显示。

添加水印

系统支持添加图片及文字水印,下面依次举例说明
添加图片水印,我们下载官网logo文件到根目录进行举例:

$image = \think\Image::open('./image.png');
// 给原图左上角添加水印并保存water_image.png
$image->water('./logo.png')->save('water_image.png'); 

water方法的第二个参数表示水印的位置,默认值是WATER_SOUTH,可以传入下列\think\Image类的常量或者对应的数字:

//常量,标识左上角水印
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; 

我们用左上角来进行测试:

$image = \think\Image::open('./image.png');
// 给原图左上角添加水印并保存water_image.png
$image->water('./logo.png',\think\Image::WATER_NORTHWEST)->save('water_image.png');

生成的图片效果如下:
在这里插入图片描述
还可以支持水印图片的透明度(0~100,默认值是100),例如:

$image = \think\Image::open('./image.png');
// 给原图左上角添加透明度为50的水印并保存alpha_image.png
$image->water('./logo.png',\think\Image::WATER_NORTHWEST,50)->save('alpha_image.png');

生成的图片效果如下:
在这里插入图片描述
也可以支持给图片添加文字水印(我们复制一个字体文件HYQingKongTiJ.ttf到入口目录),我们现在生成一个像素20px,颜色为#ffffff的水印效果:

$image = \think\Image::open('./image.png');
// 给原图左上角添加水印并保存water_image.png
$image->text('十年磨一剑 - 为API开发设计的高性能框架','HYQingKongTiJ.ttf',20,'#ffffff')->save('text_image.png');

生成的图片效果:
在这里插入图片描述
文字水印参数

文字水印比较多,在此只做说明不做演示了
在这里插入图片描述

九、文件处理

TP5内置了一个文件处理类 \think\File,内置的文件上传操作也是调用了该类进行处理的。

File类继承了PHP的SplFileObject类,因此可以调用SplFileObject类所有的属性和方法。

十、单元测试

单元测试


首先安装ThinkPHP5的单元测试扩展,进入命令行,切换到tp5的应用根目录下面,执行:

composer require topthink/think-testing

安装完成后,会在应用根目录下面增加tests目录和phpunit.xml文件。

默认带了一个tests/ExampleTest.php单元测试文件,我们可以直接在命令行下面运行单元测试:

php think unit

添加单元测试文件


我们来添加一个新的单元测试文件,单元测试文件为tests/IndexTest.php,内容如下:

<?php
use tests\TestCase;

class IndexTest extends TestCase
{

    public function testSomethingIsTrue()
    {
        $this->assertTrue(true);
    }

}

注意,单元测试文件中定义的测试类如果不存在冲突,可以不需要使用命名空间。

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

TP5学习(十三):其他 的相关文章

  • 未捕获的异常“Google_IO_Exception”,消息为“HTTP 错误:无法连接”

    我有一个任务 查询 运行一些从 gmail 邮箱检索数据的 php 代码 直到上周五 2015 年 4 月 10 日 它一直工作正常 现在我收到以下错误日志 E 11 58 26 094 2015 04 15 200 3 38 KB 14
  • 将 MySQL 结果作为 PHP 数组

    mysql 表 config name config value allow autologin 1 allow md5 0 当前的 php 代码 sth mysql query SELECT rows array while r mysq
  • 如何从字符串中删除所有数字?

    我想删除字符串 0 9 中的所有数字 我写了这段有效的代码 words preg replace 0 words remove numbers words preg replace 1 words remove numbers words
  • PHP文件上传

    如果我想在文件名转到服务器的永久位置 而不是临时位置 之前更改文件名 我该如何执行此操作 代码如下
  • php下拉菜单人口

    我正在尝试编写一个 php 脚本 该脚本将根据主下拉菜单的选择填充第二个下拉菜单 我想使用 jquery 来完成所有非页面刷新的事情 但我发现现有的所有东西都很难理解和修改 你知道有什么写得很好且易于理解的东西吗 或者可能是现有的教程 下面
  • 文件修改时间检查的成本

    对于Linux下包含少量字节的文件 我只需要处理自上次处理以来发生更改的时间 我通过调用 PHP 检查文件是否被更改clearstatcache filemtime 定期 由于整个文件总是很小 因此删除对 filemtime 的调用并通过将
  • PHPUnit\Framework\TestCase 和 Tests\TestCase 有什么区别?

    我注意到在示例测试中 这两个类是内置的 功能测试 gt use Tests TestCase 单元测试 gt PHPUnit Framework TestCase 两者有什么区别 在什么情况下您会使用其中一种 PHPUnit Framewo
  • 包含包含文件的 php 文件

    这是目录结构 global php includes class bootstrap php includes init php plugins myplugin php 这是这些文件中的代码 start php require inclu
  • PHP 基本身份验证 file_get_contents() [重复]

    这个问题在这里已经有答案了 我需要从网站解析一些 XML 数据 XML 数据是原始格式 但在我需要进行身份验证之前 基于基本网络服务器的身份验证 使用用户名和密码 I tried homepage file get contents htt
  • 尝试获取 Google accessToken

    看起来 无论我做什么 谷歌都在竭尽全力阻止我完成这个研究项目 我的项目让我使用 Google 电子表格作为数据库 并使用所述电子表格中的数据执行程序化的 Google 图片搜索 并向最终用户显示一些结果 设置说明 我开始按照此处的说明进行操
  • PHP使用auto_increment生成短唯一ID?

    我想生成一个简短的 唯一的 ID 而不必检查冲突 我目前正在做类似的事情 但是我当前生成的 ID 是随机的 并且在循环中检查冲突很烦人 并且如果记录数量显着增加 将会变得昂贵 通常担心冲突不是问题 但我想要生成的唯一 ID 是一个由 5 8
  • 重新排列数组键 php [重复]

    这个问题在这里已经有答案了 我有这个数组 Array 15 gt 13 1 16 gt Mark one answer 19 gt You see a car on the hard shoulder of a motorway with
  • 如何解决 Laravel 8 UI 分页问题?

    我在尝试最近发布的 laravel 8 时遇到了问题 我试图找出变化是什么以及它是如何工作的 当我这样做时 我遇到了分页 laravel 8 UI 变得混乱的问题 不知何故它发生了 有人可以帮助我吗 或者经历过同样的事情 像这样我在 lar
  • CSS 无法从带有 php“includes”的相对路径工作

    文件夹结构 index php includes header html css style css 我的主项目文件夹中有 2 个子文件夹 一个是名为 includes 的文件夹 另一个名为 css 我有我的 index php主文件夹中的
  • MySQL 数据库无法在 XAMPP for Mac 上启动

    突然我在 mac 上遇到了这个问题 我无法启动我的 MySQL 数据库 我只能启动 ProFTPD 和 Apache Web Server 这是应用程序日志 Starting all servers Starting MySQL Datab
  • 我怎样才能让这个脚本在 WordPress 上运行?

    我有这个脚本 document ready function text1 click function this hide 代码html div class div1 p class text1 text to appear when th
  • phpinfo 说 php.ini 路径是 C:\Windows 但那里没有 php.ini

    我们正在尝试从 PHP5 切换到 PHP7 现在我们已经安装了 Apache 并且 PHP 可以运行了 然而 我们在php ini文件没有任何作用 Via phpinfo 我们意识到原因是Configuration File php ini
  • 简单的dom php解析获取自定义数据属性值

    HTML div class something ddsf PHP foreach dom gt find something data rel as this var dump this gt attr 我尝试了这个但错误 在其文档中找不
  • 更改API数据输出的布局

    我是 API 集成和 PHP 的新手 我最近将 VIN 解码器集成到我的应用程序中 在输入框中输入车辆的 VIN 选择提交 然后就会显示 API 数据库中有关该车辆的所有信息 数据存储为关联数组 其中包含类别及其相应元素 例如 对于 VIN
  • 使用“INSERT ... ON DUPLICATE KEY UPDATE”插入多条记录

    我的表结构 table marks 我的目标 我想用条件插入或更新多条记录 我目前正在通过此查询进行检查 第一步 SELECT FROM marks WHERE student 115 AND param 1 第二步 if records

随机推荐

  • 【建议收藏】数据库 SQL 入门——数据查询操作(内附演示)

    引言 在上一节中 我们讨论了DML的使用方法 本节我们继续开始DQL的学习 首先回归一下DQL的基于定义 DQL Data Query Language 数据查询语言 用来查询数据库中表的记录 在本节中我们主要讨论DQL的用法以及基本语法
  • 计算机视觉之人脸识别(Yale数据集)--HOG和ResNet两种方法实现

    1 问题描述 在给定Yale数据集上完成以下工作 在给定的人脸库中 通过算法完成人脸识别 算法需要做到能判断出测试的人脸是否属于给定的数据集 如果属于 需要判断出测试的人脸属于数据集中的哪一位 否则 需要声明测试的人脸不属于数据集 这是一个
  • 思维导图 函数

  • PCL点云处理之最小二乘空间直线拟合(3D) (二百零二)

    PCL点云处理之最小二乘空间直线拟合 3D 二百零二 一 算法简介 二 实现代码 三 效果展示 一 算法简介 对于空间中的这样一组点 大致呈直线分布 散乱分布在直线左右 我们可采用最小二乘方法拟合直线 更进一步地 可以通过点到直线的投影 最
  • 5款程序员必备的免费在线画图工具,超级好用!

    点击上方 芋道源码 选择 设为星标 管她前浪 还是后浪 能浪的浪 才是好浪 每天 10 33 更新文章 每天掉亿点点头发 源码精品专栏 原创 Java 2021 超神之路 很肝 中文详细注释的开源项目 RPC 框架 Dubbo 源码解析 网
  • java中的集合基础

    集合介绍 集合类的特点 提供一种存储空间可变的存储模型 存储的数据容量可以发生改变 集合和数组的区别 共同点 都是存储数据的容器 不同点 数组的容量是固定的 集合的容量是可变的 数组可以存基本数据类型和引用数据类型 集合只能存引用数据类型
  • 【Android进阶篇】WebView显示网页详解

    概述 WebView是Android用于显示网页的控件 通过WebView 我们可以查看本地的网页 也可以查看网络资源 本文内容如下 一 加载本地网页 二 加载网络资源 三 在WebView中使用JavaScript和CSS 四 WebCh
  • 多线程案例(1) - 单例模式

    目录 单例模式 饿汉模式 懒汉模式 前言 多线程中有许多非常经典的设计模式 这就类似于围棋的棋谱 这是用来解决我们在开发中遇到很多 经典场景 简单来说 设计模式就是一份模板 可以套用 单例模式 顾名思义 就是一个程序只能含有一个实例 有的场
  • Permission denied

    Permission denied 出现的原因的是 没有权限进行读 写 创建文件 删除文件等操作 解决方法 输入命令 sudo chmod R 777 工作目录 例如 sudo chmode R 777 home HDD 此时就可以在该路径
  • poium测试库介绍

    poium测试库前身为selenium page objects测试库 我在以前的文章中也有介绍过 这可能是最简单的Page Object库 项目的核心是基于Page Objects实现元素定位的封装 该项目由我个人在维护 目前在公司项目中
  • 使用ChatGPT的方式与在其他地方使用它的方式基本相同。以下是一些步骤:

    在中国使用ChatGPT的方式与在其他地方使用它的方式基本相同 以下是一些步骤 访问OpenAI的官方网站 OpenAI 在网站上找到GPT 3或ChatGPT的相关信息 OpenAI提供了详细的API文档 可以帮助你理解如何使用它们 你需
  • mysql数据库之跨表复制

    背景说明 目标库 target db 目标数据表 target tb 将目标库的制定表复制到当前数据库中 包括一下几个方面 一 表结构复制 仅仅复制了表的结构 没有数据 create table current db new tb like
  • Logitech G系鼠标脚本编程,实现鼠标自动定位控制

    利用罗技官方提供的API来写一个鼠标自动定位移动脚本 点击脚本编辑器中的帮助选项 查看罗技官方提供的API说明 有很多实现好的鼠标功能 G series Lua API V8 45 Overview and Reference 下面是我写的
  • 深入解析SpringBoot启动原理

    1 启动类中的SpringApplication run方法会创建一个SpringApplication的实例 并做一些初始化工作 SpringBootApplication Slf4j public class HuotuUserServ
  • Linux C编程基础:获取时间

    1 前言 对于linux下的编程 无论是用户态还是内核态 时间获取都是经常需要使用到的 以下分别从用户态和内核态整理了几个常用的时间获取接口 供编写代码时快速查阅 linux时间子系统的发展历史及详细介绍 可以参考 深入理解Linux时间子
  • stm32 机械周期_STM32定时器周期计算

    STM32定时器周期计算 公式是 1 TIM Prescaler 时钟 1 TIM Period F103配置生成1ms的时钟 1 35 36M 1 999 1MS TIM TimeBaseInitTypeDef TIM TimeBaseS
  • LeNet-5识别数字

    LeNet识别数字 前言 环境 实现 结果 前言 实现经典卷积神经网络LeNet LeNet 5 识别数字 这里将激活函数从sigmoid换成ReLU 参考资料 动手学深度学习 环境 python pytorch 实现 import tor
  • 设计模式八大原则知多少

    设计模式是一种通用的解决问题的经验 可以帮助我们设计出可重用 可维护和可扩展的软件 在设计模式中 有八个常见的原则 它们是 单一职责原则 SRP Single Responsibility Principle 一个类应该只有一个引起变化的原
  • AlexNet(深度学习模型)详解

    AlexNet是一种深度卷积神经网络 由Alex Krizhevsky Ilya Sutskever和Geoffrey Hinton于2012年在ImageNet图像分类竞赛中首次引入 这项竞赛是一个庞大的数据集 其中包含超过100万张图像
  • TP5学习(十三):其他

    一 缓存 设置 缓存支持采用驱动方式 所以缓存在使用之前 需要进行连接操作 也就是缓存初始化操作 options 缓存类型为File type gt File 缓存有效期为永久有效 expire gt 0 缓存前缀 prefix gt th