首先,看一看 错误场景:

比如说我们有这样一个编辑界面:

而我们有这样一些验证方法(注:采用的是thinkphp5.0的验证规则)

namespace app\admin\validate;
use think\Validate;
class Link extends Validate
{
    protected $rule = [
        "title" => "require|max:30",
        "priority" => "require|between:1,100",
        "url" => "url|require",
        "des" => "length:1,255",
    ];
    protected $message = [
        "title.require" => "标题是必须的",
        "title.max" => "标题的最大长度为30",
        "priority.require" => "优先级是必须的",
        "priority.between" => "优先级必须在1~100之间",
        "url.url" => "链接地址不合法",
        "url.require" => "链接地址是必须的",
        "des.between" => "描述必须在1~255个字符之间"
    ];

}

比如说我们验证优先级,会要求我们输入的优先级在1~100之间,但如果我们输入的数大于100呢?会发生什么?

 

如下:

验证不通过!很好,到现在都没有什么问题,但是当等待的时间过去之后,会发生什么?

为什么会发生这样的事情呢?我们来看看edit控制器里面的代码。

 

public function edit(){
        if(request()->isPost()){//如果是表单提交
            $data = input("post.");//获取到编辑界面的数据
            $validate = Loader::validate("Link");//加载验证器类
            if(!$validate->check($data)){//验证数据是否和我们定义的验证规则一致
                $this -> error($validate->getError(),"edit","","2");
                die;
            }
            
            $linkModel = new LinkModel();
$updateRes
= $linkModel -> updateLink(input("post."));//调用LinkModel里面的方法更新数据 if($updateRes){ $this->success("修改成功","index","","1"); }else{ $this->error("修改失败","edit","","1"); } return; } $res=db("link")->where("id",input("id"))->find();//通过最开始点击编辑按钮,然后去数据库查找数据 if($res){ $this->assign("link",$res);//将数据分配给edit界面 }else{ $this->assign("link","");//如果找不到数据则分配给edit界面一个空(不然有可能会报错) } return view();//加载界面 }

看以上代码,到底是哪里出现问题了呢?

我猜想是分配$res数据给界面出了问题。如果$res的数据为空的话,那么我们分配给edit界面的数据就是一个空字符串。

来看看我们的edit界面是怎样获取数据的:

 

注意,此刻我们的link是空字符串,那么$link.id肯定是取不到值的,所以会报上面所说的那个错?

可是为什么$res会为空呢?如下:

 

不知道大家有没有注意到这样一句代码:

$res=db("link")->where("id",input("id"))->find();//通过最开始点击编辑按钮,然后去数据库查找数据

当我们验证失败时,重定向到edit界面,此刻我们通过点击编辑按钮传过来的id已经被刷新了,此刻的id是没有值得,所以自然就找不到。那怎么解决呢?

我们验证失败,跳转的代码如下:

if(!$validate->check($data)){//验证数据是否和我们定义的验证规则一致
                $this -> error($validate->getError(),"edit","","2");
                die;
            }

在我们验证失败的时候:

 if(!$validate->check($data)){
                session("redirectId",$data['id']);
                $this -> error($validate->getError(),"edit","2");
                die;
            }

 我们用session将id保存起来,然后在给edit分配数据的时候这样写:

  $redirectId = session("redirectId");//从session里面将id取出来
        if($redirectId){//判断session是不是为空
            $res=db("link")->where("id",$redirectId)->find();//用session里面的id进行查找
        }
        else{
            $res=db("link")->where("id",input("id"))->find();//如果session为空,也就是我们的验证没有失败,或者一开始点击编辑按钮进入编辑界面时的情景,用我们点击编辑按钮传入进来的id进行查找
        }
        if($res){
           $this->assign("link",$res);//分配数据给模板
        }else{
            $this->assign("link","");
        }

这样,无论怎样从定向我们都能保证查询得到值。但是还有一个问题,当你验证失败时,重定向到编辑界面之后,你不再对编辑界面操作,而是返回到列表页。

此时因为你已经验证失败一次了,所以session里面是有值的,当你点击另外一条数据编辑的时候,还记得上面的代码么?我们首先是判断你的session里面是否有值,而此刻session里面是存在一个id,那么即使我们点击不同的数据,编辑界面显示的还是你的上一条数据。

蛋疼,怎么解决?

其实很简单,在你的列表页的方法将session清空就可以了。如下:

 public function index(){
        session("redirectId",null);//删除编辑的时候残留的ID
        $res = db("link") ->order("priority","desc")-> paginate(2);
        if($res){
            $this->assign("linkList",$res);
        }else{
            $this->assign("linkList",array());
        }
        return view();
    }

好了,到现在一切都解决了。