一个数据过滤以及验证逻辑问题

问题背景

大家好,我目前在学习开发一个博客,使用的是自己写的一个 MVC 框架(不完善的框架),目前正在学习如何修改后台管理员账号,当我把数据提交到控制器中的 update() 方法之后,对于数据的验证逻辑我产生了一些疑惑,希望能得到帮助.

具体过程

这是我的账号修改视图,即 edit.html ,id 值放在了隐藏域中
file
当我点击确认之后,数据会发送到控制器的 update() 方法,然后就要接收数据,问题就来了: 如果新密码和确认密码字段不全为空,我就验证这俩字段是否相同,相同则接收新密码字段并执行插入操作,不相同则返回试图页面;如果新密码和确认密码全为空,我就不接收密码字段,直接执行插入操作.
file
基于我所考虑的这个逻辑,我写出了下面这样的代码

public function update() {
    $id                  = $_POST['id'];
    $data['name']        = $_POST['name'];
    $data['tel']         = $_POST['tel'];
    $data['status']      = $_POST['status'];
    $data['role']        = $_POST['role'];
    $data['update_time'] = time();

    //下面这段代码,我觉得又臭又长,又判断是不是全为空,又判断是不是相等,又判断是不是都不为空,令人窒息
    if (!empty($_POST['password']) || !empty($_POST['password_confirmation'])) {
        if (md5($_POST['password']) != md5($_POST['password_confirmation'])) {
            $this->sessionFlash('danger', '两次密码不一致');
            $this->back();
        } else {
            $data['password'] = md5($_POST['password']);
            $model            = UserModel::getInstance();

            if ($model->update($id, $data)) {
                $this->sessionFlash('success', '修改信息成功');
                $this->redirect("?c=User");
            } else {
                $this->sessionFlash('danger', '修改信息失败');
                $this->back();
            }
        }
    } elseif (empty($_POST['password']) && empty($_POST['password_confirmation'])) {
        $model = UserModel::getInstance();

        if ($model->update($id, $data)) {
            $this->sessionFlash('success', '修改信息成功');
            $this->redirect("?c=User");
        } else {
            $this->sessionFlash('danger', '修改信息失败');
            $this->back();
        }
    }
}

我觉得上面的代码写的很啰嗦,并不是一个好办法,以前也没有写用户模块的经验,特来请教大家,是不是有更好的办法处理这类问题.或者说我本来就不该把修改密码与修改其他信息混为一谈.

php
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
jltxwesley
最佳答案

我简单地帮你 refactor 了下,就是把一个冗长的方法抽离成了几个简短的方法,原则:每个方法干自己该干的事情,看下是不是要好点:

    public function update()
    {
        $data = $this->collectData();

        if ($this->needToUpdatePassword($data['password'], $data['password_confirmation'])) {
            if ($this->validatePassword($data['password'], $data['password_confirmation'])) {
                $data['password'] = md5($data['password']);
                $this->updateModel($data);
            } else {
                $this->sessionFlash('danger', '两次密码不一致');
                $this->back();
            }
        } else {
            $this->updateModel($data);
        }
    }

    private function collectData()
    {
        return [
            'id'                    => $_POST['id'],
            'name'                  => $_POST['name'],
            'tel'                   => $_POST['tel'],
            'status'                => $_POST['status'],
            'role'                  => $_POST['role'],
            'password'              => $_POST['password'],
            'password_confirmation' => $_POST['password_confirmation'],
            'update_time'           => time()
        ];
    }

    private function needToUpdatePassword($password, $password_confirmation)
    {
        return !empty($password) || !empty($password_confirmation);
    }

    private function validatePassword($password, $password_confirmation)
    {
        return $data['password'] === $data['password_confirmation'];
    }

    private function updateModel($data)
    {
        if (UserModel::getInstance()->update($data['id'], $data)) {
            $this->sessionFlash('success', '修改信息成功');
            $this->redirect('?c=User');
        } else {
            $this->sessionFlash('danger', '修改信息失败');
            $this->back();
        }
    }
5年前 评论
讨论数量: 4
DianWang

1,修改密码跟修改其他信息放一起并不冲突,取决于具体需要;
2,

if (md5($_POST['password']) != md5($_POST['password_confirmation'])) 

这里没有必要md5,

 $model = UserModel::getInstance();

            if ($model->update($id, $data)) {
                $this->sessionFlash('success', '修改信息成功');
                $this->redirect("?c=User");
            } else {
                $this->sessionFlash('danger', '修改信息失败');
                $this->back();
            }

这里大量代码冗余,可抽离一个方法出来。
逻辑其实没问题,是面向对象设计不成熟,代码重复的太多了。

5年前 评论

@DianWang 谢谢指点,我需要在研究研究.感谢

5年前 评论
jltxwesley

我简单地帮你 refactor 了下,就是把一个冗长的方法抽离成了几个简短的方法,原则:每个方法干自己该干的事情,看下是不是要好点:

    public function update()
    {
        $data = $this->collectData();

        if ($this->needToUpdatePassword($data['password'], $data['password_confirmation'])) {
            if ($this->validatePassword($data['password'], $data['password_confirmation'])) {
                $data['password'] = md5($data['password']);
                $this->updateModel($data);
            } else {
                $this->sessionFlash('danger', '两次密码不一致');
                $this->back();
            }
        } else {
            $this->updateModel($data);
        }
    }

    private function collectData()
    {
        return [
            'id'                    => $_POST['id'],
            'name'                  => $_POST['name'],
            'tel'                   => $_POST['tel'],
            'status'                => $_POST['status'],
            'role'                  => $_POST['role'],
            'password'              => $_POST['password'],
            'password_confirmation' => $_POST['password_confirmation'],
            'update_time'           => time()
        ];
    }

    private function needToUpdatePassword($password, $password_confirmation)
    {
        return !empty($password) || !empty($password_confirmation);
    }

    private function validatePassword($password, $password_confirmation)
    {
        return $data['password'] === $data['password_confirmation'];
    }

    private function updateModel($data)
    {
        if (UserModel::getInstance()->update($data['id'], $data)) {
            $this->sessionFlash('success', '修改信息成功');
            $this->redirect('?c=User');
        } else {
            $this->sessionFlash('danger', '修改信息失败');
            $this->back();
        }
    }
5年前 评论

@jltxwesley 我看懂了,非常感谢,抱紧大腿.

5年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!