一、昨日回顾
1. 知识回顾
mvc的三大组件是什么?
M:model 模型
V:view 视图
C:Controller 控制器
mvc的三大组件分别代表什么意思?
M:专门用来操作数据表的
V:专门用来展示视图模板的
C:专门用来处理业务逻辑,比如说什么时候该调用模型操作数据,什么时候该调用视图展示模板,都是由控制器里来处理。
2. 昨日反馈
二、知识路径
web项目开发流程介绍
需求分析
功能分析
ER图设计
表设计
项目部署
项目实现
实现后台用户管理系统
封装验证码工具类
==目标:能够设计项目所需的表、能够部署自主框架、能够实现后台用户管理系统==
三、今日课程内容:博客项目
1. web项目开发流程介绍
1)制定计划:博客项目(blog31) 开发周期:4天
2)需求分析:功能分析 ER图设计
3)软件设计:项目环境 表设计
4)程序编写
5)软件测试
6)运行维护
2. 需求分析
功能分析
- 后台用户管理系统;
- 后台分类管理系统;
- 后台博文管理系统;
- 评论管理系统;
- 后台登陆和七天免登录;
- 前台首页;
- 前台注册和登陆功能;
- 前台博客文章详情页;
ER图设计
E-R图也称实体-联系图(Entity Relationship Diagram),提供了表示实体类型、属性和联系的方法,用来描述现实世界的概念模型。它是描述现实世界概念结构模型的有效方法。是表示概念模型的一种方式,用矩形表示实体型,矩形框内写明实体名;用椭圆表示实体的属性,并用无向边将其与相应的实体型连接起来;用菱形表示实体型之间的联系,在菱形框内写明联系名,并用无向边分别与有关实体型连接起来,同时在无向边旁标上联系的类型(1:1,1:n或m:n)。
专业的ER图工具:Viso和Power Designer
==实体== ==》表:矩形表示
==属性== ==》表字段:椭圆
==关系== ==》表与表的关系:菱形(1:1表示1对1关系;1:n表示1对多关系;m:n表示多对多关系)
博客项目的ER关系图如下:
3. 表设计
1 | drop database blog31; |
4. 项目部署
将code/mvc目录改名为blog31,
下图这个mvc目录:
改名为blog31:
配置一个基于域名虚拟主机,域名为www.blog31.com
在httpd-vhosts.conf文件中增加如下图所示的虚拟主机配置项:
修改hosts文件,
重启apache,测试访问效果:
访问效果为:
能够看到上图,则说明部署成功。
5. 项目实现
实现后台用户管理系统
实现列表页
将code/templates/admin目录中如下图所示的目录复制一份,
转移拷贝到code/blog31/app/admin/view目录中,
在blog31/app/admin/controller目录中创建一个名为UserController.class.php的文件,
在blog31/app/admin/controller/UserController.class.php中构建如下代码,展示三个页面,
测试访问后台用户管理系统列表页
进一步做调整,将后台模板使用到的资源文件全部转移进项目中,
在blog31/public目录中创建一个名为admin的目录,专门保存后台的资源文件,
复制code/templates/admin/libs目录下的所有文件,如下图所示,
转移拷贝到blog31/public/admin目录中,
调整blog31/app/admin/view/User/userIndex.html中引入资源文件的路径,
在blog31/conf/conf.php中增加本网站域名配置项,
然后在blog31/app/admin/view/User/userIndex.html使用配置项URL的值来引入配置文件,
上图中替换的是所有图片文件引入路径,截取不全,实际替换的内容以blog31/app/admin/view/User/userIndex.html中的为准。
再次测试访问后台新闻管理系统列表页,
在blog31/app/model目录中创建UserModel.class.php文件,
内容如下:
调整blog31/conf/conf.php中PDO配置项的默认选择的数据库名,
在blog31/app/admin/controller/UserController.class.php中showIndex方法里渲染模板之前调用模型查询数据,
然后在blog31/app/admin/view/User/userIndex.html中回显查询得到的用户数据,
测试访问后台用户管理系统列表页:
实现添加页
访问后台用户管理系统添加页,
调整blog31/app/admin/view/User/userAdd.html中引入资源文件的路径,将”../libs”全部替换为”{C(‘URL’)}/public/admin”,如下图所示,代码截取不全,以实际文件中的代码为准,
调整blog31/app/admin/view/User/userAdd.html中的form表单域各项的值,
在blog31/app/admin/controller/UserController.class.php中创建一个处理添加用户的方法,adh方法,
测试添加用户使用效果:
在添加表单页面构建数据,点击提交,
提交后的效果:效果为添加成功,说明功能实现OK。
实现编辑页
访问后台新闻管理系统编辑页:
修改blog31/app/admin/view/User/userIndex.html中编辑按钮的链接:
调整blog31/app/admin/view/User/userEdit.html中引入资源文件的路径,将”../libs”全部替换为”{C(‘URL’)}/public/admin”,如下图所示,代码截取不全,以实际文件中的代码为准,
调整blog31/app/admin/view/User/userEdit.html中form表单里的代码,
在blog31/app/admin/controller/UserController.class.php中创建updh方法,代码如下:
测试使用效果:
点击进入编辑也,如下图所示:
修改数据,
点击更新,
跳回到更新页面:
密码也是被改变了的,如下图所示:
说明编辑功能实现OK。
6. 全天总结
项目中的建表部分:
如果某字段是需要保存时间,一般在PHP的项目中给int数据类型;
如果某字段需要保存状态类型的值,使用tinyint会更加好;
如果某字段保存的数据,我们可以预期的很准确,比如说手机号码,通常就是11位,但是我们在项目中一般会采取宁大不小的原则,给11位以上的值,比如给varchar(15);
在构建字段的时候,我们一般都会给字段设置default默认值,如果不设置默认值,则今后这个字段无论是否需要添加数据,都必须指定上值。
项目开发部分:
我们使用框架进行开发,一般程序开发人员从模板入手,先尝试展示出模板页面的效果,然后再考虑是否需要调用模型操作数据库的问题,所以我们通常在MVC框架中,1)首先会将模板页面转移进项目目录;2)然后会创建控制器类,构建方法调用视图展示模板页面;3)调试模板页面展示的效果;4)以上都成功之后,如果没有模型则需要创建模型,如果有模型则直接去考虑调用模型操作数据;
四、昨日回顾
1. 知识回顾
建表注意事项:
如果在项目中要保存一个时间的数据,则我们一般选择使用int类型来保存;
如果在项目中要保存一个状态或类型这样的数据时,我们一般选择使用tinyint类型来保存;
如果在项目中能够明确要保存的数据需要占多少个字节时,我们一般采用的做法是宁大不小,比如,保存手机号码一般是11位,但是我们通常会选择给varchar(15)
如果在项目中构建字段时,通常我们会给字段指定一个默认值,一方面方便程序的默认操作,比如注册时,如果给用户类型指定了默认值为0表示普通会员,则构建注册功能的代码就无需给这个字段设置值,MYSQL会直接给这个字段用上默认值;另外一方面可以避免在添加数据操作时,如果没给这个字段指定值,将会报错的情况。
在项目代码开发中的基本流程是:
1)从模板文件入手,创建相关的控制器类和该类中的相应方法,渲染模板展示到浏览器;
2)在方法中渲染模板之前调用模型操作数据,比如我们之前开发的后台用户管理系统列表页,在渲染列表页模板之前,我们需要调用模型把列表页需要展示的数据查询出来;如果没有模型,则需要创建模型,如果有,则直接使用;
3)在方法中构建逻辑处理代码,生成相关功能;
2. 昨日反馈
五、知识路径
六、今日课程内容:博客项目
1. 封装验证码工具类
在blog31/plugins目录下创建CaptchaTool.class.php的文件,
构建的代码如下,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
namespace plugins;//创建一个 全局空间 下的 plugins空间
class CaptchaTool{
private $_w;//画布的宽度
private $_h;//画布的高度
private $_img;//画布资源
public function __construct($w=200, $h=80){
#初始化参数
$this->_w = $w;
$this->_h = $h;
$this->_img = imagecreatetruecolor($this->_w, $this->_h);//创建画布
#填充背景色
$color = $this->color();//获得随机色
imagefill($this->_img, 0, 0, $color);//填充背景色
#写字
$randStr = $this->randStr();//构建4个随机字
$color = $this->color();//获得随机色
$fontPath = PUBLIC_PATH . '/fonts/font1.ttf';//字体文件所在路径
$bx = $this->_w/4;//左下角起点x坐标
$by = $this->_h*3/4;//左下角起点y坐标
$fontSize = $this->_h *37/80;//字体大小,高度尺寸的37/80
imagettftext($this->_img, $fontSize, 0, $bx, $by, $color, $fontPath, $randStr);//写字
#设置干扰元素
//设置干扰点
$this->setPoint(180);
//设置干扰线
$this->setLine(8);
}
#画干扰线
private function setLine($num){
for($i=0; $i<$num; $i++ ){ //画$num个点
$color = $this->color();//获得随机色
$bx = mt_rand(0, $this->_w/2);//起点x坐标
$by = mt_rand(0, $this->_h);//起点y坐标
$ex = mt_rand($this->_w/2, $this->_w);//终点x坐标
$ey = mt_rand(0, $this->_h);//终点y坐标
imageline($this->_img, $bx, $by, $ex, $ey, $color);//画点
}
}
#画干扰点
private function setPoint($num){
for($i=0; $i<$num; $i++ ){ //画$num个点
$color = $this->color();//获得随机色
$bx = mt_rand(0, $this->_w);//起点x坐标
$by = mt_rand(0, $this->_h);//起点y坐标
$ex = mt_rand($bx-2, $bx+2);//终点x坐标
$ey = mt_rand($by-2, $by+2);//终点y坐标
imageline($this->_img, $bx, $by, $ex, $ey, $color);//画点
}
}
#构建随机字
private function randStr($num=4){
$mixedArr = array_merge(range('a', 'z'), range('A', 'Z'), range(0, 9));//构建随机字采集库
$str = '';
for($i=0; $i<$num; $i++ ){ //采集$num次
$key = mt_rand(0, count($mixedArr)-1);//取得当前随机字符对应的元素下标
$str .= $mixedArr[$key];//从字库中取得下标为$key的元素值拼接给$str
}
return $str;
}
#分配颜色
private function color($r='', $g='', $b=''){
//初始化三原色
$r = ($r==='') ? mt_rand(0, 255) : $r;//红
$g = ($g==='') ? mt_rand(0, 255) : $g;//绿
$b = ($b==='') ? mt_rand(0, 255) : $b;//蓝
//分配颜色
return imagecolorallocate($this->_img, $r, $g, $b);
}
#输出图像的方法
public function output(){
header('Content-type:image/jpeg');//指定一个响应协议项
imagejpeg($this->_img);//直接将图像输出到浏览器
}
}在blog31/public下创建fonts目录,
将F:\home\class\day15\source\font1.ttf复制转移到blog31/public/fonts目录中,
在blog31/conf/define.php中定义一个目录常量,
在blog31/core/App.class.php中的autoload方法中实现对工具类的自动加载,
测试使用工具类,
在blog31/app/admin/controller/UserController.class.php中构建测试方法test,代码如下:
访问test方法,
验证码制作成功。
2. 实现后台分类管理系统
在blog31/app/admin/controller中创建名为CatController.class.php文件,专门用于操作后台分类管理系统各程序,
代码如下:
实现列表页
在blog31/app/admin/controller/CatController.class.php中创建名为showList的方法,渲染后台分类列表页模板,
通过http://www.blog31.com/index.php?p=admin&m=cat&a=showIndex访问后台分类管理系统列表页,发现页面虽然能够展示,但是样式乱了,
于是进一步调整blog31/app/admin/view/Category/categoryIndex.html中引入资源文件的路径,将”../libs”全部替换为”{C(‘URL’)}/public/admin”,如下图所示,代码截取不全,以实际文件中的代码为准,
在blog31/app/model目录下创建CatModel.class.php的文件,
代码如下:
在blog31/app/admin/controller/CatController.class.php文件showList方法中构建如下代码,
调整模板文件回显查询的数据blog31/app/admin/view/Category/categoryIndex.html:
访问后台分类管理系统列表页:
我们进一步调整程序,将所有分类数据进行整理,
实现无限级递归分类
在blog31/app/admin/controller/CatController.class.php文件中创建两个方法,代码和作用如下图所示:
然后在blog31/app/admin/controller/CatController.class.php文件中的showList方法里调整获得所有分类数据的代码,如下图所示将蓝框中的代码改为红框中的代码:
调整模板页面中的代码,在输出分类名称之前还需要输出缩进符,
测试最终效果:
访问后台分类管理系统列表页
实现添加页
在blog31/app/controller/CatController.class.php中创建名为showAd的方法,渲染后台分类添加页模板,
通过http://www.blog31.com/index.php?p=admin&m=cat&a=showAd访问后台分类管理系统添加页,发现页面虽然能够展示,但是样式乱了,
于是进一步调整blog31/app/admin/view/Category/categoryAdd.html中引入资源文件的路径,将”../libs”全部替换为”{C(‘URL’)}/public/admin”,如下图所示,代码截取不全,以实际文件中的代码为准,
实现编辑页
调整blog31/app/admin/view/Category/categoryIndex.html中的编辑按钮链接,
在blog31/app/admin/controller/CatController.class.php中创建名为showUpd的方法,渲染后台分类编辑页模板,
通过从后台分类列表页点击编辑按钮访问后台分类管理系统编辑页,发现页面虽然能够展示,但是样式乱了,
于是进一步调整blog31/app/admin/view/Category/categoryEdit.html中引入资源文件的路径,将”../libs”全部替换为”{C(‘URL’)}/public/admin”,如下图所示,代码截取不全,以实际文件中的代码为准,
在blog31/app/admin/controller/CatController.class.php中的showUpd方法里构建相应的程序功能代码,如下图所示:
调整blog31/app/admin/view/Category/categoryEdit.html中需要回显数据的部分及表单域的相关属性值,
在blog31/app/admin/controller/CatController.class.php构建updh方法,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45//编辑处理方法
public function updh(){
//接收表单提交的数据
$id = $_GET['id'];
$name = trim($_POST['name']);//新的分类名称
$old_name = trim($_POST['old_name']);//老的分类名称
$parent_id = trim($_POST['parent_id']);//新的父级id
$old_parent_id = trim($_POST['old_parent_id']);//老的父级id
//检查是否有数据真的被修改了
$target = [];
if( $name!=$old_name && $name!='' ){//如果新的名称不等于老的名称并且新的名称不为空,则需要修改name值
$target[] = "name='{$name}'";
}
if( $parent_id!=$old_parent_id ){//如果新的父级id不等于老的父级id
$target[] = "parent_id={$parent_id}";
}
if( !empty($target) ){//如果$target不为空,说明有数据需要被更新
$strTarget = implode(', ', $target);// $strTarget="name='xxxx', parent_id=xxxx";
$sql = "update bg_category set {$strTarget} where id={$id}";
//调用模型执行更新操作
$model = \core\App::single('\model\CatModel');
$re = $model->setData($sql);
if( $re ){//更新成功
echo '嘿嘿嘿,运气不错,更新成功咯~';
}else{//更新失败
echo '哈哈哈,你更新失败了!';
}
}else{//否则给出提示没有数据被更新
echo '您当前还没有更新数据哟~';
}
//2秒之后跳转回编辑页
$url = C('URL') . '/index.php?p=admin&m=cat&a=showUpd&id='.$id;
header('Refresh:2; url='.$url);
exit;
}测试使用效果,效果OK,功能成功。
实现删除功能
3. 实现后台博文管理系统
在blog31/app/admin/controller中创建名为ArticleController.class.php文件,专门用于操作后台博文管理系统各程序,
代码如下:
实现添加页
在blog31/app/controller/ArticleController.class.php中创建名为showAd的方法,渲染后台博文添加页模板,
通过http://www.blog31.com/index.php?p=admin&m=article&a=showAd访问后台博文管理系统添加页,发现页面虽然能够展示,但是样式乱了,
于是进一步调整blog31/app/admin/view/Article/articleAdd.html中引入资源文件的路径,将”../libs”全部替换为”{C(‘URL’)}/public/admin”,如下图所示,代码截取不全,以实际文件中的代码为准,
调整无限级递归分类方法的归属
将blog31/app/admin/controller/CatController.class.php文件中如下图所示的方法剪切下来,
将剪切下来的代码全部粘贴到blog31/app/model/CatModel.class.php的类中,
再调整blog31/app/model/CatModel.class.php内的代码,如下图所示将蓝框中的代码改为红框中的代码:
将blog31/app/admin/controller/CatController.class.php中的showUpd和showList方法调用无限级递归分类方法的方式进行调整,如下图中将蓝框部分改为红框部分:
在blog31/app/controller/ArticleController.class.php中showAd方法里添加如下代码:
调整blog31/app/admin/view/Article/articleAdd.html中的表单各成员代码:
在blog31/app/model下创建ArticleModel.class.php的文件,如下图所示:
在blog31/app/controller/ArticleController.class.php中添加adh方法,处理添加功能,
测试使用效果:
在添加页构建如下内容,
点击添加按钮,效果为:
说明添加功能OK。
实现列表页
在blog31/app/admin/controller/ArticleController.class.php中创建名为showIndex的方法,渲染后台博文列表页模板,
通过http://www.blog31.com/index.php?p=admin&m=article&a=showIndex访问后台博文管理系统列表页,发现页面虽然能够展示,但是样式乱了,
于是进一步调整blog31/app/admin/view/Article/articleIndex.html中引入资源文件的路径,将”../libs”全部替换为”{C(‘URL’)}/public/admin”,如下图所示,代码截取不全,以实际文件中的代码为准,
在blog31/app/admin/controller/ArticleController.class.php中的showList方法里在渲染模板之前查询数据,
将查得的数据在blog31/app/admin/view/Article/articleIndex.html中回显,
测试访问效果:
实现编辑页
- 调整blog31/app/admin/view/Category/articleIndex.html中的编辑按钮链接,
- 在blog31/app/controller/ArticleController.class.php中创建名为showUpd的方法,渲染后台博文编辑页模板,
通过从后台博文列表页点击编辑按钮访问后台博文管理系统编辑页,发现页面虽然能够展示,但是样式乱了,
于是进一步调整blog31/app/admin/view/Category/articleUpd.html中引入资源文件的路径,将”../libs”全部替换为”{C(‘URL’)}/public/admin”,如下图所示,代码截取不全,以实际文件中的代码为准,
实现删除功能
4. 整理模板文件
5. 全天总结
制作的页面和功能:
封装验证码工具类
实现后台分类管理系统的列表页和编辑页
实现无限级递归分类
实现博客文章管理系统添加页
实现博客文章管理系统列表页基础功能