1、如何正确的认识封装函数
之前应该有些同学还不是很理解,什么情况下需要使用到function()
封装函数,
并且如何去正确封装一个函数,
还有封装函数有什么需要注意的地方和规范等等,这些知识点都会在下面的课程中一一讲解。
A、优化程序之一,功能拆分封装
有时候当我们需要编写一个复杂的功能,可能会需要编写多达上百行或上千行代码的时候,就可以将其中一些较为复杂的逻辑,用封装函数的方式拆分出来,
这样封装函数的方式,主要是方便项目后期的扩展、阅读、和维护。
假设,我们现在有一段功能需要实现,就是处理用户注册的信息,程序的步骤是这样的:
1、接收用户信息
2、检测用户注册信息是否合法
3、过滤用户注册信息中是否带有数据库注入内容,或者敏感词语
4、注册信息写入数据库,并检测是否注册信息已经被他人注册
5、注册成功后,自动登录该账号
按上面的逻辑,我们一但完整的编写下来,可能就会书写出上百行的代码,那如果在该基础上,继续增加新的功能、或者判断条件,就需要重新阅读代码,然后在中间修改代码,然后再运行调试。
这时候我们如果使用功能拆分的方法,将部分节点封装起来,就可以很好的优化程序,也方便后期增加功能,同时在哪个节点新增的功能,只需要单独调试该节点就能保证之后的代码不会出现BUG。
可能很多同学对上面的理论不是很理解,那么下面我们来从案例中,对比两次代码的扩展、阅读、和可维护性有什么不同的地方:
没有经过函数封装的流程:
php
# 1、接收用户信息
$name = $_POST['name'];
$pwd = $_POST['pwd'];
# 2、检测用户注册信息是否合法
if (empty($name)) { echo '用户名不允许为空';exit; }
if (empty($pwd)) { echo '密码不允许为空';exit; }
# 3、过滤用户注册信息中是否带有数据库注入内容,或者敏感词语
if ($name == '尼玛') { echo '用户名带有敏感词语';exit; }
# 4、注册信息写入数据库,并检测是否注册信息已经被他人注册
$DB = mysqli_connect('127.0.0.1', 'root', 'root', 'love_niu', 3306);
$select = "select if from user where name = '".$name."'";
$res = mysqli_query($DB, $select);
if ($res != false) { echo '用户名已经被注册';exit; }
$add = "INSERT INTO user (name, pwd) VALUES ('".$name."', '".$pwd."')";
$res = mysqli_query($DB, $add);
# 5、注册成功后,自动登录该账号
if ($res) {
session_start();
$_SESSION['user'] = $name;
echo '注册成功';
} else {
echo '注册失败';
}
# 操作完数据库,记得关闭链接,释放内存
mysqli_close($DB);
经过函数封装的流程:
php
/**
* ② 检测用户注册信息是否合法
* @param string $name 用户名
* @param string $pwd 密码
* @return bool 通过返回true,失败输出内容
*/
function vif_post($name, $pwd) {
# 2、检测用户注册信息是否合法
if (empty($name)) { echo '用户名不允许为空';exit; }
if (empty($pwd)) { echo '密码不允许为空';exit; }
return true;
}
/**
* ③ 过滤用户注册信息中是否带有数据库注入内容,或者敏感词语
* @param string $str 需要被过滤的内容
* @return bool 通过返回true,失败输出内容
*/
function filter_post($str) {
if ($str == '尼玛') { echo '注册信息带有敏感词语';exit; }
return true;
}
/**
* ④ 注册信息写入数据库,并检测是否注册信息已经被他人注册
* @param string $name 用户名
* @param string $pwd 密码
* @return bool 注册通过返回true,失败返回false,被注册输出内容
*/
function add_post($name, $pwd) {
$DB = mysqli_connect('127.0.0.1', 'root', 'root', 'love_niu', 3306);
$select = "select if from user where name = '".$name."'";
$res = mysqli_query($DB, $select);
if ($res != false) { echo '用户名已经被注册';exit; }
$add = "INSERT INTO user (name, pwd) VALUES ('".$name."', '".$pwd."')";
$res = mysqli_query($DB, $add);
# 操作完数据库,记得关闭链接,释放内存
mysqli_close($DB);
if ($res) {
return true;
}
return false;
}
/**
* ⑤ 注册成功后,自动登录该账号
* @param string $name 用户名
* @return 无返回值
*/
function session_login($name) {
session_start();
$_SESSION['user'] = $name;
}
# 使用案例如下:
# 接收用户信息
$name = $_POST['name'];
$pwd = $_POST['pwd'];
vif_post($name, $pwd);
filter_post($name);
$res = add_post($name, $pwd);
if ($res) {
session_login($name);
}
实际上,使用功能拆分封装来优化代码,会使代码函数变多,但相对而言它成功将一个功能分成了好几个部件,最后再重新组成使用,这种优化方式,在IT属于中一般称之为程序解耦。
如果在今后的工作中,有同事对你说,你写的代码耦合度很高,那就是你的代码并没有很好的解耦。
B、优化程序之二,重复功能封装
上一节我们已经学习过功能拆分封装的优化方式,这种优化方式主要是面向一个功能而言,将其解耦,(私有函数)。
而接下来我们学习的重复功能封装的优化方式,则是面向整个项目而言,将其中一些可能会在程序中多次重复出现的逻辑,单独拿出来封装成函数,(公共函数)。
例如:链接数据库、创建session、文件上传、目录创建、生成验证码、判断验证码等。
由于创建seesion比较特殊,就是它需要先使用session_start()
开启,但这个函数又不能重复使用,所以如果我们不单独封装函数,则每个用到的文件,都需要重复使用。
上面提到一个私有和公共函数,下面我们一起来看下2者的区别:
1、私有函数:功能拆分封装后所生成的函数,这些函数只单独服务该个功能,其他功能不能引用这些函数。
2、公共函数:重复功能封装后所生成的函数,这些函数可以被任何功能引用,因为他本身存在的意义就是为了减少其他功能中,重复出现的相同代码。
可能很多同学对上面的理论不是很理解,那么下面我们来从案例中,对比两次代码的扩展、阅读、和可维护性有什么不同的地方:
没有经过重复功能封装的流程:
php
/*---------------------- 假设这是登录页面 ----------------------*/
# 先开启session
session_start();
# 然后检测用户是否已经登录
if (!empty($_SESSION['user'])) {
echo '已经登录';
} else {
echo '还没登录';
}
/*---------------------- 假设这是下载页面 ----------------------*/
# 先开启session
session_start();
# 然后检测用户是否已经登录
if (!empty($_SESSION['user'])) {
echo '你可以下载了';
} else {
echo '请先登录后再下载';
}
从上面的代码,我们可以看出,两个页面都分别重复使用了session_start()
函数,这种重复出现的代码,实际上我们是可以使用函数将其封装起来的:
php
/*------------ 假设下面的每个页面都require了这个函数 ------------*/
/**
* 公共函数:创建和读取SESSION
* @param string $key 键名
* @param string $val 键值,当为空时则是读取session对应的值
* @return string OR bool 当返回false时,则表示读取失败
*/
function SESSION($key, $val=null) {
# 我们先判断session是否开启,如果没有则先开启
isset($_SESSION) || session_start();
# 再判断是读取session,还是创建session
if (!empty($val)) {
$_SESSION[$key] = $val;
} else {
return $_SESSION[$key];
}
}
/*---------------------- 假设这是登录页面 ----------------------*/
# 然后检测用户是否已经登录
if (!empty(SESSION('user'))) {
echo '已经登录';
} else {
echo '还没登录';
}
/*---------------------- 假设这是下载页面 ----------------------*/
# 然后检测用户是否已经登录
if (!empty(SESSION('user'))) {
echo '你可以下载了';
} else {
echo '请先登录后再下载';
}
使用功能拆分封装来优化代码,会使代码函数变多,相反,将重复出现的代码封装成函数,会使程序代码变少。
两者都是程序优化中非常重要的概念,结合使用可以让你的程序维护起来非常简单。
2、手把手教学之一,实现分页函数封装
数据分页显示,在项目开发中,必须会用到的功能之一。
分页样式,一般会出现下面3种场景:
A、分页的场景计算
根据上面图片里的样式,我们可以分析出3种场景:
1、如果当前页数小于9
2、如果当前页数大于9
3、如果当前分页大于5,那么显示前4和后4条
下面我们来想下大概的实现思路:
1、使用MySql的limit关键词,控制分页数
2、使用MySql的count()函数,获得分页的总数
3、使用$_GET超全局变量获得当前分页数
4、在MySql语句中使用count()函数,获得总记录数
5、使用ceil()函数对总记录数小数进1,计算出真正的总页数
6、根据3种不同分页场景,生成对应的html分页代码
7、使用MySql语句中的limit关键字,对数据查询进行分页控制
建议同学们可以先自己思考下怎么实现包含上面3种场景的分页函数封装,然后再对比学习下面的案例代码:
php
/**
* 分页函数
* @param int $num 每页显示多少条数据
* @return array 分页结果
*/
function Page($num = 1) {
# 1、先接受当前页数
if (empty($_GET['page']) || $_GET['page']==1) {
$page = 1;
$limit_left = 0;
$limit_right = $num;
} else {
$page = $_GET['page'];
$limit_left = ($page * $num) - $num;
$limit_right = $num;
}
# 2、链接数据库
$DB = mysqli_connect('127.0.0.1', 'root', 'root', 'love_niu', 3306);
# 3、查询总记录数
$sql = 'select count(*) from user';
$res = mysqli_fetch_array(mysqli_query($DB, $sql));
$count = $res[0];
# 4、总分页数,是应该用总记录数/$num,然后有余数则进1的
$total = ceil($count / $num);
# 分页实体
$html = '';
# 先来接个分页头
if ($page == 1) {
$html .= "首页";
$html .= "上一页";
} else {
$html .= "首页";
$html .= "上一页";
}
# 第一种场景
if ($total <= 9 || $page <= 4) {
if ($total >=9 ) {
$total = 9;
}
for ($i=1; $i <= $total; $i++) {
if ($i==$page){
$html .= "
$i
";
} else{
$html .= "$i";
}
}
} else {
# 第三种场景,当前分页数大于等于5,并且就算加5页也要小于等于总页数
if ($page >= 5 && (($page+5) <= $total) ) {
# 先计算出左边分页数
$left = $page - 4;
$key = $page - 1;
for ($i=$left; $i <= $key; $i++) {
$html .= "$i";
}
# 合并中间分页数
$html .= "
$i
";
# 再计算出右边分页数
$right = $page + 4;
$key = $page + 1;
for ($i=$key; $i <= $right; $i++) {
$html .= "$i";
}
# 第二种场景
} else {
$key = $total - 8;
for ($i=$key; $i <= $total; $i++) {
if ($i==$page){
$html .= "
$i
";
} else{
$html .= "$i";
}
}
}
}
# 最后接个分页尾
if ($page == $total) {
$html .= "下一页";
$html .= "尾页";
} else {
$html .= "下一页";
$html .= "尾页";
}
# 5、查询数据库记录
$sql = "select * from user limit $limit_left,$limit_right";
$res = mysqli_fetch_all(mysqli_query($DB, $sql), MYSQLI_ASSOC);
mysqli_close($DB);
# 6、返回结果
return [
'html' => $html,
'list' => $res,
];
}
$res = Page();
echo $res['html'].'
'
;
var_dump($res['list']);
?>
.pageination_align {text-align: center}
.pageination {color: #48576a;font-size: 12px;display: inline-block;user-select: none;}
.pagination_page {padding: 0 4px;border: 1px solid #d1dbe5;border-right: 0;background: #fff;font-size: 13px;min-width: 28px;height: 28px;line-height: 28px;cursor: pointer;box-sizing: border-box;text-align: center;float: left;text-decoration: none;color: #777;}
.pagination_page_right {border-right: 1px solid #d1dbe5;}
.pagination_page:hover {color: #20a0ff;}
.disabled {color: #e4e4e4 !important;background-color: #fff;cursor: not-allowed;}
.pagination_page_active {border-color: #20a0ff;background-color: #20a0ff;color: #fff !important;;cursor: default;}
.pagination_right{border-right: 1px solid #d1dbe5;}
老师提醒:热爱学习的同学可以自己思考如何通过封装函数的两种优化方式,来优化上面分页案例中的代码。记住:老师带入门,修行靠个人。