博客项目(三)
在项目中封装文件上传
- 在Lib文件夹下创建Upload.class.php页面
<?php
namespace Lib;
class Upload{
private $path; //文件上传路径
private $size; //文件允许大小
private $type; //文件允许上传的类型
private $error; //保存错误信息
public function __construct(){
$this->path=$GLOBALS[‘config’][‘app’][‘upload_path’];
$this->size=$GLOBALS[‘config’][‘app’][‘upload_size’];
$this->type=$GLOBALS[‘config’][‘app’][‘upload_type’];
}
public function getError(){
return $this->error;
}
/*
* 文件上传的方法
* @param $file array $_FIELS[]
*/
public function uploadOne($file){
if(!$this->checkError($file)){ //验证上传过程是否有误
return false;
}
if(!$this->checkType($file)){ //验证格式
return false;
}
if(!$this->checkSize($file)){ //验证大小
return false;
}
if(!$this->checkHttpPost($file)){ //验证文件是否是http的post上传
return false;
}
//创建文件夹
$foldername=date(‘Y-m-d’); //文件夹名
$folderpath= $this->path.$foldername; //文件夹路径
if(!file_exists($folderpath))
mkdir ($folderpath);
//文件上传
$filename= uniqid(”,true).strtolower(strrchr($file[‘name’],’.’)); //文件名
$filepath= $folderpath.DS.$filename; //文件路径
if(move_uploaded_file($file[‘tmp_name’], $filepath))
return $foldername.’/’.$filename;
else{
$this->error=’文件上传失败’;
return false;
}
}
//检查上传过程中是否有误
private function checkError($file){
//$file[‘error’]!=0表示文件上传有误
if($file[‘error’]!=0){
switch ($file[‘error’]){
case 1:
$this->error=’上传文件超出了PHP配置文件允许的最大值’;
break;
case 2:
$this->error=’上传文件超出了表单允许的最大值’;
break;
case 3:
$this->error=’只有部分文件上传’;
break;
case 4:
$this->error=’上传文件为空’;
break;
case 6:
$this->error=’找不到临时文件’;
break;
case 7:
$this->error=’文件写入失败’;
break;
default:
$this->error=’未知错误’;
}
return false;
}
return true;
}
//验证上传格式
private function checkType($file){
$finfo= finfo_open(FILEINFO_MIME);
$info=finfo_file($finfo, $file[‘tmp_name’]);
$info_array= explode(‘;’, $info); //分割
if(!in_array($info_array[0], $this->type)){
$this->error=’文件类型上传错误,只能允许:’.implode(‘,’, $this->type); //转化字符串
return false;
}
return true;
}
//验证大小
private function checkSize($file){
if($file[‘size’]>$this->size){
$this->error=’文件不能操作’. number_format($this->size/1024,1).’K’;
return false;
}
return true;
}
//验证是否是http的post上传
private function checkHttpPost($file){
if(!is_uploaded_file($file[‘tmp_name’])){
$this->error=’文件必须是HTTP上传’;
return false;
}
return true;
}
}
- 在config.php配置中,配置文件上传的信息
在用户注册中上传头像
完善LoginController控制器中的register()方法
登录成功后显示头像
运行结果
管理员登录后显示用户列表
- 在Controller\Admin文件夹下创建UserController.class.php页面
- 在View/Admin目录下的user_list.html中循环取出普通用户
- 在menu.html中,点击“用户管理”跳转到user_list页面中
- 运行结果
管理员删除普通用户
- 在UserController.class.php页面中,添加接受删除用户的请求
- 在user_list中,点击“删除”
更改个人信息
显示个人信息
模型
无
控制器(UserController)
视图(user_edit.html)
点击menu.html中的“个人设置”
运行结果
更改个人信息
在UserController的edit()方法中,更改个人信息
public function editAction(){
$id=$_SESSION[‘user’][‘user_id’];
$model=new \Model\UserModel();
//更改个人信息
if(!empty($_POST)){
if(!empty($_POST[‘password’])) //更改密码
$data[‘user_pwd’]=md5($_POST[‘password’]);
if($_FILES[‘face’][‘error’]!=4){ //更改头像
$upload=new \Lib\Upload();
if(!$data[‘user_face’]=$upload->uploadOne($_FILES[‘face’]))
$this->error (‘index.php?p=Admin&c=User&a=edit’,$upload->getError ());
//删除原来的头像
$old_face=$GLOBALS[‘config’][‘app’][‘upload_path’].$_SESSION[‘user’][‘user_face’];
if(file_exists($old_face))
unlink ($old_face);
}
//如果有$data就说明需要修改
if(isset($data)){
$data[‘user_id’]=$id;
if($model->update($data)){
session_destroy();
echo ‘<div style=”text-align:center”>修改成功,重新登录</div>’;
echo <<<str
<script type=”text/javascript”>
setTimeout(function(){
top.window.location.href=’index.php?p=Admin&c=Login&a=login’; //top表示框架的最顶端窗口
},3000)
</script>
str;
exit;
}
else
$this->error (‘index.php?p=Admin&c=User&a=edit’, ‘修改失败’);
}
}
//个人设置修改结束
$info=$model->find($id);
$this->smarty->assign(‘info’,$info);
$this->smarty->display(‘user_edit.html’);
}
博客类别模块
多级联动
多级联动在网站开发中非常常见。
思考:如何使用一个表实现无限极联动?
id |
name |
parent_id |
1 |
江苏 |
0 |
2 |
安徽 |
0 |
3 |
苏州 |
1 |
4 |
昆山 |
3 |
5 |
花桥 |
4 |
实现无限极联动主要在于表设计
创建类别表
create table category(
cat_id int unsigned auto_increment primary key comment ‘类别id’,
cat_name varchar(20) not null comment ‘类别名称’,
parent_id int unsigned not null comment ‘父级id’,
sort_order int default 50 comment ‘排序’
)engine=innodb charset=utf8 comment ‘类别表’;
表结构
插入测试数据
insert into category values (null,’计算机’,0,default),(null,’文学’,0,default);
insert into category values (null,’硬件’,1,default),(null,’软件’,1,default);
insert into category values (null,’国内文学’,2,default),(null,’国外文件’,2,default)
insert into category values (null,’PHP’,4,default),(null,’java’,4,default)
查看数据并按层次摆放
通过递归创建多级联动的树形结构
<?php
mysql_connect(‘localhost’,’root’,’root’);
mysql_select_db(‘data’);
mysql_query(‘set names utf8’);
$rs=mysql_query(‘select * from category order by sort_order,cat_id’);
$array=array();
while($rows=mysql_fetch_assoc($rs)) {
$array[]=$rows;
}
header(‘content-type:text/html;charset=utf-8’);
/**
*$list array 需要创建树形结构的数组
*$parent_id int 指定的父级下的元素创建树形结构
*$deep int 当前元素的深度级别
*/
function createTree($list,$parent_id=0,$deep=0) {
static $tree=array();
foreach($list as $rows){
if($rows[‘parent_id’]==$parent_id){
$rows[‘deep’]=$deep;
$tree[]=$rows;
createTree($list,$rows[‘cat_id’],$deep+1);
}
}
return $tree;
}
$tree=createTree($array);
//输出
foreach($tree as $rows) {
echo str_repeat(‘ ’,$rows[‘deep’]*8),$rows[‘cat_name’],'<br>’;
}
运行结果
博客中显示类别列表
- 在Model文件夹中创建CategoryModel.class.php页面
<?php
namespace Model;
class CategoryModel extends \Core\Model{
//获取类别的树
public function getCategoryTree($parent_id=0){
$list= $this->select();
$list= $this->createTree($list,$parent_id);
return $list;
}
//创建树形结构
private function createTree($list,$parent_id=0,$deep=0) {
static $tree=array();
foreach($list as $rows){
if($rows[‘parent_id’]==$parent_id){
$rows[‘deep’]=$deep;
$tree[]=$rows;
$this->createTree($list,$rows[‘cat_id’],$deep+1);
}
}
return $tree;
}
}
- 在Controller\Admin目录下创建CategoryController.class.php页面
- 在menu.html页面中点击“类别管理”
- 在cat_list.html页面中取出类别
运行结果
添加类别
入口位置
显示添加类别
模型
无
控制器(CategoryController)
视图(cat_add.html)
运行结果
实现添加的业务逻辑
模型
无
控制器
视图
无
修改类别
修改入口
显示修改页面
模型
无
控制器
视图(将cat_add.html页面复制一份,改名为cat_edit.html)
执行修改的业务逻辑(CategoryController控制器中实现)
public function editAction(){
$cat_id=(int)$_GET[‘cat_id’];
$model=new \Model\CategoryModel();
//修改业务逻辑
if(!empty($_POST)){
$data[‘cat_name’]=$_POST[‘cat_name’];
$data[‘parent_id’]=$_POST[‘parentid’];
$data[‘sort_order’]=$_POST[‘sort_order’];
$data[‘cat_id’]=$cat_id;
//错误一:指定的父级是自己
if($data[‘parent_id’]==$cat_id){
$this->error (‘index.php?p=Admin&c=Category&a=edit&cat_id=’.$cat_id, ‘自己不能做自己的父亲’);
}
//错误二:指定的父级是自己的后代
$sublist=$model->getCategoryTree($cat_id);
foreach($sublist as $rows){
if($rows[‘cat_id’]==$data[‘parent_id’])
$this->error (‘index.php?p=Admin&c=Category&a=edit&cat_id=’.$cat_id, ‘指定的父级是自己的后代’);
}
//更新操作
if($model->update($data))
$this->success (‘index.php?p=Admin&c=Category&a=list’,’修改成功’);
else
$this->error (‘index.php?p=Admin&c=Category&a=edit&cat_id=’.$cat_id, ‘修改失败’);
}
$info=$model->find($cat_id);
$cat_list=$model->getCategoryTree();
$this->smarty->assign(‘cat_list’,$cat_list);
$this->smarty->assign(‘info’,$info);
$this->smarty->display(‘cat_edit.html’);
}
删除类别
删除入口
模型
视图
无
控制器
作业:
在项目中上传头像,可能这个头像尺寸会很大,在项目中封装一个生成缩略图的方法来处理头像。