thinkphp-响应输出和重定向、验证器定义、验证规则和错误信息

5541次阅读 422人点赞 作者: WuBin 发布时间: 2024-05-28 07:36:26
扫码到手机查看

响应操作

响应输出,有好几种:包括return、json()和view()等等;默认输出方式是以html 格式输出,如果你发起json 请求,则输出json

而背后是response 对象,可以用response()输出达到相同的效果

return response($data);

使用response()方法可以设置第二参数,状态码,或调用code()方法;

return response($data, 201);
return response($data)->code(202);
// 常用的304 缓存 404找不到页面

使用json()、view()方法和response()返回的数据类型不同,效果一样;

return json($data, 201);
return json($data)->code(202);

不但可以设置状态码,还可以设置header()头文件信息;

return json($data)->code(202)
                ->header(['Cache-control' => 'no-cache,must-revalidate']);
// 从浏览器的检查-网络-标头 中可以看到添加的响应头

重定向

使用redirect()方法可以实现页面重定向,需要return 执行;

return redirect('http://www.baidu.com');

站内重定向,直接输入路由地址或相对地址即可,第二参数状态码;

// 站内重定向 比如要跳转到这个链接http://localhost/xuexi/tp6/public/address/index
return redirect('/xuexi/tp6/public/address/index');
// 其中必须从/xuexi开始,否则重定向链接就是错误的
// 最简单方法 用url包含一下,无论是路由或者绝对路径 都可以
return redirect( url('address/index') );
注意!以后用地址都要用url方法。保证正确,自动识别
return redirect('ds/5'); // 跳转到路由
return redirect('/xuexi/tp6/address/details/id/5', 201); 

附加session 信息,并跳转重定向;

首先需要开启session,在app/middleware.php,中

// 全局中间件定义文件
return [
    // 全局请求缓存
    // \think\middleware\CheckRequestCache::class,
    // 多语言加载
    // \think\middleware\LoadLangPack::class,
    // Session初始化
    \think\middleware\SessionInit::class 解开这个注释即可
];

然后在controller/Address.php中的Index方法:

 echo session('name');

实现跳转到address/index,并携带session

 return redirect( url('address/index') )->with('name', 'mr 5');

重定向还提供了,记住上一次的url,和跳转到上一次url 的功能;

学习框架,建议多看看源码部分,这里的remember还是通过session实现的。

redirect( url('address/index') )->remember();
echo session('redirect_url');

可以发现,打印出的结果:/xuexi/tp6/public/rely/get/id/5

首先在控制器中,执行跳转到address/index

// ?flag判断session中是否有flag这个值
        if(session('?flag')) {
            return '死机警告';
        } else {
            return redirect( url('address/index') )->remember();
        }

其次在address控制器中,引导页面呈现address/index,并显示返回按钮,当点击返回时候,通过back方法回到初始的记录页面

 public function index()
    {
        // echo session('redirect_url');

        // return 'index';
        $url = url('address/back');
        return '<a href="'.$url.'">返回<a>';
    }

    public function back()
    {
        // restore() 跳转到上一次的url
        // redirect必须需要一个参数,实际上这里用不到默认给一个值
        // return redirect(1)->restore();
        // with('flag', 1)随便写的 目的是为了方式一直不断的来回重定向导致死机
        return redirect(1)->with('flag', 1)->restore();
    }
注意这里有个问题,6.1.4版本中,如果传入:redirect(’1‘),那么会报错address中没有1这个方法,如果为空,那么则没任何反应。经过验证,不要传入字符串'1',要传入数字1,正确方式:redirect(1)

验证器

验证器定义

验证器的使用,我们必须先定义它,系统提供了一条命令直接生成想要的类;

php think make:validate User
D:\phpstudy\phpstudy_pro\WWW\xuexi\tp6>php think make:validate User
Validate:app\validate\User created successfully.

创建成功后,会创建一个app/validate文件夹(文件夹与model和controller同级)

里面默认生成一个app/validate/User.php文件 以下为默认的内容:

declare (strict_types = 1);

namespace app\validate;

use think\Validate;

class User extends Validate
{
    /**
     * 定义验证规则
     * 格式:'字段名' =>  ['规则1','规则2'...]
     *
     * @var array
     */
    protected $rule = [];

    /**
     * 定义错误信息
     * 格式:'字段名.规则名' =>  '错误信息'
     *
     * @var array
     */
    protected $message = [];
}

比如,我们定义一个如下的验证规则,针对user表

class User extends Validate
{
    /**
     * 定义验证规则
     * 格式:'字段名' =>  ['规则1','规则2'...]
     *
     * @var array
     */
    protected $rule = [
        // 这里的名称不一定要与数据库一模一样 可以自己写自己的
        'name' => 'require|max:20', //对应表中username字段,不得为空,不得大于20 位
        'price' => 'number|between:1,100', //必须是数值,1-100 之间
        'email' => 'email' //邮箱格式要正确
    ];

    /**
     * 定义错误信息
     * 格式:'字段名.规则名' =>  '错误信息'
     *
     * @var array
     */
    protected $message = [
        'name.require' => '姓名不得为空',
        'name.max' => '姓名不得大于20 位',
        'price.number' => '价格必须是数字',
        'price.between' => '价格必须1-100 之间',
        'email' => '邮箱的格式错误'
    ];
}
如果不设置$message 定义的话,将提示默认的错误信息;

验证器定义好了之后,我们需要进行调用测试,创建一个app/controller/Verify.php 控制器;

namespace app\controller;

use think\exception\ValidateException;

class Verify
{
    public function index()
    {
        try {

        } catch(ValidateException $e) {

        }
    }
}
ValidateException $e 这个就是固定格式。

比如,下面就实现了一个基本的验证:

namespace app\controller;

use app\validate\User;
use think\exception\ValidateException;

class Verify
{
    public function index()
    {
        try {

            // 使用助手函数,直接放一个验证类进去
            validate(User::class)->check([
                'name' => '蜡笔小新',
                'price' => 90,
                'email' => 'xiaoxin@163.com'
            ]);

        } catch(ValidateException $e) {
            dump($e->getError());
        }
    }
}

如果这里规则中设置了姓名不能为空

validate(User::class)->check([
                'name' => '',
                'price' => 90,
                'email' => 'xiaoxin@163.com'
]);

这样页面会直接输出你定义的错误报错信息:姓名不能为空。

默认情况下,出现一个错误就会停止后面字段的验证,我们也可以设置批量验证(将错误信息一起验证出来);

validate(User::class)->batch(true)...
validate(User::class)->batch(true)->check([
                'name' => '',
                'price' => 120,
                'email' => 'xiaoxin163.com'
 ]);
注意,batch不能写在check后面,必须写在check前面!

设置好后,再执行,会返回一个错误提示的结果数组:

array:3 [
  "name" => "姓名不得为空"
  "price" => "价格必须1-100 之间"
  "email" => "邮箱的格式错误"
]

系统提供了常用的规则让开发者直接使用,也可以自行定义独有的特殊规则;

<?php
declare (strict_types = 1);
namespace app\validate;
use think\Validate;

class User extends Validate
{
    /**
     * 定义验证规则
     * 格式:'字段名' =>  ['规则1','规则2'...]
     *
     * @var array
     */
    protected $rule = [
        // 这里的名称不一定要与数据库一模一样 可以自己写自己的
        'name' => 'require|max:20|checkName:wubin.work', //对应表中username字段,不得为空,不得大于20 位
        'price' => 'number|between:1,100', //必须是数值,1-100 之间
        'email' => 'email' //邮箱格式要正确
    ];

    /**
     * 定义错误信息
     * 格式:'字段名.规则名' =>  '错误信息'
     *
     * @var array
     */
    protected $message = [
        'name.require' => '姓名不得为空',
        'name.max' => '姓名不得大于20 位',
        'price.number' => '价格必须是数字',
        'price.between' => '价格必须1-100 之间',
        'email' => '邮箱的格式错误'
    ];

    // 自定义规则 支持5个参数,$value, $rule最重要
    protected function checkName($value, $rule)
    {
        dump($value);
        dump($rule);
    }
}

控制器中

validate(User::class)->batch(true)->check([
                'name' => '蜡笔小新',
                'price' => 100,
                'email' => 'xiaoxin@163.com'
]);

最终,打印出来:

"蜡笔小新"  // $value
 "wubin.work"  // $rule

比如,自定义wubin.work这个名字不允许注册

<?php
declare (strict_types = 1);
namespace app\validate;
use think\Validate;

class User extends Validate
{
    /**
     * 定义验证规则
     * 格式:'字段名' =>  ['规则1','规则2'...]
     *
     * @var array
     */
    protected $rule = [
        // 这里的名称不一定要与数据库一模一样 可以自己写自己的
        'name' => 'require|max:20|checkName:wubin.work', //对应表中username字段,不得为空,不得大于20 位
        'price' => 'number|between:1,100', //必须是数值,1-100 之间
        'email' => 'email' //邮箱格式要正确
    ];

    /**
     * 定义错误信息
     * 格式:'字段名.规则名' =>  '错误信息'
     *
     * @var array
     */
    protected $message = [
        'name.require' => '姓名不得为空',
        'name.max' => '姓名不得大于20 位',
        'price.number' => '价格必须是数字',
        'price.between' => '价格必须1-100 之间',
        'email' => '邮箱的格式错误'
    ];

    // 自定义规则 支持5个参数,$value, $rule最重要
    protected function checkName($value, $rule)
    {
        // 通过了就返回true 
        return $value != $rule ? true : '非法名称,不得注册';
    }

}

这时如果我提交的是非法称谓:

 validate(User::class)->batch(true)->check([
                'name' => 'wubin.work',
                'price' => 100,
                'email' => 'xiaoxin@163.com'
]);

那么就会输出:

array:1 [
  "name" => "非法名称,不得注册"
]

对于自定义规则中,一共可以有五个参数,我们分别了解一下;

protected function checkName($value, $rule, $data, $field, $title)
{
 dump($data); //所有数据信息 做一些深度比较
 dump($field); //当前字段名 到底是哪个字段再用验证器
 dump($title); //字段描述,没有就是字段名
}

按照本例,最终结果

^ array:3 [
  "name" => "wubin.work"
  "price" => 100
  "email" => "xiaoxin@163.com"
] // $data
^ "name" // $field
^ "name" // $title

默认情况下,field与title都是一样的,但是,如果我们对验证的规则做如下修改 name|用户名

protected $rule = [
        'name|用户名' => 'require|max:20|checkName:wubin.work', //对应表中username字段,不得为空,不得大于20 位
];

此时打印出结果,此时title即为用户名,而field还是name

那么这个主要的用处是什么呢?比如,我修改一下验证的内容

 validate(User::class)->batch(true)->check([
                'name' => ''
]);

此时,会输出提示

^ array:1 [▼
  "name" => "用户名不能为空"
]

如果不设置name|用户名,那么这里的提示就是name不能为空。所以title参数主要服务于默认的提示的

验证规则

在上面验证器定义的时候,我们采用的字符串模式,也支持数组模式

protected $rule = [
'name' => [
'require',
'max' => 10,
'checkName' => '李炎恢'
],
'price' => [
'number',
'between' => '1,100'
],
'email' => 'email'
];

数组模式在验证规则很多很乱的情况下,更容易管理,可读性更高;

如果你想使用独立验证,就是手动调用验证类,而不是调用User.php 验证类;这种调用方式,一般来说,就是独立、唯一,并不共享的调用方式;就是不用单独创建验证类文件,而是直接在控制器中进行数据的验证。

<?php
namespace app\controller;
// 使用门面模式引入验证类
use think\facade\Validate;

class Verify
{
    public function rule()
    {
        // 这里不使用try-catch
        // 实现独立验证规则
        $validate = Validate::rule([
            'name' => 'require|max:20', 
            'price' => 'number|between:1,100', 
            'email' => 'email'
        ]);
        // 对数据进行验证
        $result = $validate->check([
            'name' => '',
            'price' => 100,
            'email' => 'xiaoxin@163.com'
        ]);
        // 如果没有结果 那么输出错误信息
        if(!$result) {
            dump($validate->getError());
        }
    }
}

同样的这里如果有错误,默认只输出遇到的第一个错误,如果要显示全部的错误。

独立验证默认也是返回一条错误信息,如果要批量返回所有错误使用batch();

$result = $validate->batch(true)->check([
            'name' => '',
            'price' => 100,
            'email' => 'xiaoxin163.com'
]);

独立验支持对象化的定义方式,但不支持在属性方式的定义;

$validate = Validate::rule([
            'name' => ValidateRule::isRequire()->max(20), 
            'price' => ValidateRule::isNumber()->between([1, 100]), 
            'email' => ValidateRule::isEmail()
        ]);
        // 对数据进行验证
        $result = $validate->batch(true)->check([
            'name' => '',
            'price' => 145,
            'email' => 'xiaoxin163.com'
        ]);
        // 如果没有结果 那么输出错误信息
        if(!$result) {
            dump($validate->getError());
        }
注意:这里的'price'=>ValidateRule::isNumber()->between('1, 100','价格在1-100之间') 也可以不用数组方式,使用字符串方式'1, 100'

 独立验证的自定义错误提示,可以在方法的第二参数,参数一是规则,参数二是错误提示

 $validate = Validate::rule([
            'name' => ValidateRule::isRequire()->max(20), 
            'price' => ValidateRule::isNumber()->between([1, 100], '价格在1-100之间'), 
            'email' => ValidateRule::isEmail(null, '邮箱格式不正确')
]);

根据参考的源代码,isEmail等第一个参数默认都是Null,所以当无参可传的时候,可以传一个Null进行占位。

也可以独立使用message()方法,来设置相关错误信息;

$validate = Validate::rule([
            'name' => ValidateRule::isRequire()->max(20), 
            'price' => ValidateRule::isNumber()->between([1, 100], '价格在1-100之间'), 
            'email' => ValidateRule::isEmail(null, '邮箱格式不正确')
]);
        // 使用message方法 对错误信息单独定义
$validate->message([
             'name.require' => '姓名不得为空',
             'name.max' => '姓名不得大于20 位',
]);

错误信息也可以传入一个数组,给出错误代码以及错误信息

$validate->message([
            'name.require' => ['code'=>1001, 'msg'=>'姓名不得为空'],
             'name.max' => '姓名不得大于20 位',
]);
array:3 [
  "name" => array:2 [
    "code" => 1001
    "msg" => "姓名不得为空"
  ]
  "price" => "价格在1-100之间"
  "email" => "邮箱格式不正确"
]

独立验支持闭包的自定义方式,但这种方式会不支持字段的多规则;(就是设置闭包后,上面的规则会被覆盖掉)

$validate = Validate::rule([
            'name' => ValidateRule::isRequire()->max(20), 
            'price' => ValidateRule::isNumber()->between([1, 100], '价格在1-100之间'), 
            'email' => ValidateRule::isEmail(null, '邮箱格式不正确')
]);

$validate = Validate::rule([
            'name' => function() {}
]);

结果只是如下,可见其他price email字段的验证规则也都被覆盖了

array:1 [
  "name" => null
]
如果这样写,下面的闭包函数定义的规则,会把上面的规则全部(所有字段的验证规则)都覆盖掉!如果不想覆盖之前定义的方法,那么就要使用->rule
$validate = Validate::rule([
    'name' => ValidateRule::isRequire()->max(20), 
    'price' => ValidateRule::isNumber()->between([1, 100], '价格在1-100之间'), 
    'email' => ValidateRule::isEmail(null, '邮箱格式不正确')
]);

$validate = $validate->rule([
    'name' => function() {}
]);

最终结果

array:3 [
  "name" => null
  "price" => "价格在1-100之间"
  "email" => "邮箱格式不正确"
]

这里可以发现,其name字段规则被覆盖掉了!,所以它是不支持多字段的。

$validate = Validate::rule([
    'name' => ValidateRule::isRequire()->max(20), 
    'price' => ValidateRule::isNumber()->between([1, 100], '价格在1-100之间'), 
    'email' => ValidateRule::isEmail(null, '邮箱格式不正确')
]);

$validate = $validate->rule([
    'name' => function ($value) {
        return $value != '' ? true : '姓名不得为空';
    },
    'price'=> function ($value) {
        return $value > 0 ? true : '价格不得小于零';
    }
]);
点赞 支持一下 觉得不错?客官您就稍微鼓励一下吧!
关键词:thinkphp
推荐阅读
  • uniapp实现被浏览器唤起的功能

    当用户打开h5链接时候,点击打开app若用户在已经安装过app的情况下直接打开app,若未安装过跳到应用市场下载安装这个功能在实现上主要分为两种场景,从普通浏览器唤醒以及从微信唤醒。

    9603次阅读 623人点赞 发布时间: 2022-12-14 16:34:53 立即查看
  • Vue

    盘点Vue2和Vue3的10种组件通信方式

    Vue中组件通信方式有很多,其中Vue2和Vue3实现起来也会有很多差异;本文将通过选项式API组合式API以及setup三种不同实现方式全面介绍Vue2和Vue3的组件通信方式。

    4297次阅读 317人点赞 发布时间: 2022-08-19 09:40:16 立即查看
  • JS

    几个高级前端常用的API

    推荐4个前端开发中常用的高端API,分别是MutationObserver、IntersectionObserver、getComputedstyle、getBoundingClientRect、requ...

    14452次阅读 948人点赞 发布时间: 2021-11-11 09:39:54 立即查看
  • PHP

    【正则】一些常用的正则表达式总结

    在日常开发中,正则表达式是非常有用的,正则表达式在每个语言中都是可以使用的,他就跟JSON一样,是通用的。了解一些常用的正则表达式,能大大提高你的工作效率。

    13497次阅读 491人点赞 发布时间: 2021-10-09 15:58:58 立即查看
  • 【中文】免费可商用字体下载与考证

    65款免费、可商用、无任何限制中文字体打包下载,这些字体都是经过长期验证,经得住市场考验的,让您规避被无良厂商起诉的风险。

    12015次阅读 963人点赞 发布时间: 2021-07-05 15:28:45 立即查看
  • Vue

    Vue3开发一个v-loading的自定义指令

    在vue3中实现一个自定义的指令,有助于我们简化开发,简化复用,通过一个指令的调用即可实现一些可高度复用的交互。

    16376次阅读 1307人点赞 发布时间: 2021-07-02 15:58:35 立即查看
  • JS

    关于手机上滚动穿透问题的解决

    当页面出现浮层的时候,滑动浮层的内容,正常情况下预期应该是浮层下边的内容不会滚动;然而事实并非如此。在PC上使用css即可解决,但是在手机端,情况就变的比较复杂,就需要禁止触摸事件才可以。

    15187次阅读 1234人点赞 发布时间: 2021-05-31 09:25:50 立即查看
  • Vue

    Vue+html2canvas截图空白的问题

    在使用vue做信网单页专题时,有海报生成的功能,这里推荐2个插件:一个是html2canvas,构造好DOM然后转canvas进行截图;另外使用vue-canvas-poster(这个截止到2021年3月...

    29849次阅读 2347人点赞 发布时间: 2021-03-02 09:04:51 立即查看
  • Vue

    vue-router4过度动画无效解决方案

    在初次使用vue3+vue-router4时候,先后遇到了过度动画transition进入和退出分别无效的情况,搜遍百度没没找到合适解决方法,包括vue-route4有一些API都进行了变化,以前的一些操...

    25911次阅读 1994人点赞 发布时间: 2021-02-23 13:37:20 立即查看
交流 收藏 目录