对于没有太多基础的我来说,每一次的小进步都让我感到异常兴奋,但我也知道学习的路还很长,我会一直保持着谦虚的态度去学习,去掌握知识。
经过将近一个月的努力,终于把老大布置的‘简单任务’完成的差不多了,简单总结一下我在这个过程中所遇到的问题及解决方法。
在这之前我也看过thinkphp3.13版本的有关学习视频,对mvc架构有了初步了解。我始终认为学习与实践相结合,知识才能学得快,掌握得牢。接到给我的模板后,我就去官网下载了thinkphp3.23的完整核心包。在这之前,我安装了web开发的继承环境phpstudy,所以我把核心包下载解压后,就放在phpstudy创建的www目录下了。然后在单入口文件中修改了项目名称为App(默认为application)接着在地址栏输入localhost/phpmyadmin打开mysql创建名为news的数据库,接着在App/common/conf/config.php里开始配置参数。
return array(
//'配置项'=>'配置值'
'APP_GROUP_LIST' => 'Home,Admin',//开启应用分组
'default_module' => 'Home',//默认模板
'url_model' => '0',//url模式
// 数据库连接参数
'DB_TYPE' => 'mysql',//数据库类型
'DB_HOST' => '127.0.0.1',//地址
'DB_USER' => 'root',//登陆名
'DB_PWD' => 'root',//登陆密码
'DB_NAME' => 'news',//数据库名
'DB_PREFIX' => 'news_',//表前缀
// 去伪静态后缀
'URL_HTML_SUFFIX'=> '',
);
3.23版本的会在初始化时每个目录下生成一个index.php的空的安全文件,可以在单入口index.php中加入define('BUILD_DIR_SECURE', false);(关闭目录安全文件生成)
我先把模板文件放到了自建的Public目录下,在网上找了一个登陆的模板(只有一个登陆页面和一个进入之后的管理页),然后就开始写后台控制器,写在Controller下命名为IndexController.class.php
namespace Admin\Controller;
use Think\Controller;
class IndexController extends Controller {
public function index(){
echo '欢迎来到后台!';
$this->display('login');
}
下面的步骤就不再展示了,就只说说在实现功能是遇到的困难,由于刚开始做,想着就先把功能实现只做了登陆名和密码的验证,I方法默认的过滤类型是htmlspecialchars,而在过滤其他类型的数据时一定要注意过滤的类型,我也简单查找总结了I方法过滤的类型
I函数
I('参数名’,‘默认值’,过滤类型);//字符串函数:md5,strip_tags...等
filter_list:int;boolean;float;validate_regexp;validate_url;validate_email;validate_ip;string;stripped;encoded;special_chars;unsafe_raw;email;url;number_int;number_float;magic_quotes;callback
1、strip_tags:从字符串中去除HTML和 PHP标记
2、mysql_escape_string:转义一个字符串用于 mysql_query
这些函数在防注入方面起到很大的作用.
后来,我又加上了验证码和session
public function verify() {
// 实例化Verify对象
$verify = new \Think\Verify();
// 配置验证码参数
$verify->fontSize = 14; // 验证码字体大小
$verify->length = 4; // 验证码位数
$verify->imageH = 34; // 验证码高度
$verify->useImgBg = true; // 开启验证码背景
$verify->useNoise = false; // 关闭验证码干扰杂点
$verify->entry();
}
在前台验证码的图片属性里增加了onClick="this.src='{:U('verify')}&did=' + new Date().getTime();"用以点击后更新验证码
session_start();
$_SESSION['name'] = I('username',0,);//用session存储登陆后的用户名,用以验证是否已登陆
$name = $session['name'];
if(!isset($_SESSION['name']) || empty($_SESSION['name'])) {
$this->error('非法操作,请先登录!!!',U('Index/index'));
}
然后在后台管理首页写控制器,当记录数太多时需要建立搜索,因此需要在模板文件里添加几个按条件搜索的输入框,然后在后台判断输入是否为空,若部位空则显示按条件搜索结果,若为空则显示所有结果。但是结果在一个页面浏览不太方便,因此,我又添加了分页功能
$db_c = M('con_head');
$count =$db_c->count();
$p = getpage($count,10);
$hd = $db_c->field(true)->order('cid')->limit($p->firstRow, $p->listRows)->select();
$this->assign('page',$p->show());
在公共函数里写
function getpage($count, $pagesize = 10) {
$p = new Think\Page($count, $pagesize);
$p->setConfig('header', '<li style="list-style:none;" class="rows">共<b>%TOTAL_ROW%</b>条记录 第<b>%NOW_PAGE%</b>页/共<b>%TOTAL_PAGE%</b>页</li>');
$p->setConfig('prev', '上一页');
$p->setConfig('next', '下一页');
$p->setConfig('last', '末页');
$p->setConfig('first', '首页');
$p->setConfig('theme', '%FIRST%%UP_PAGE%%LINK_PAGE%%DOWN_PAGE%%END%%HEADER%');
$p->lastSuffix = false;//最后一页不显示为总页数
return $p;
}
前台直接用{$page}就行了
为了实现文章可编辑,我又添加了Ueditor文本编辑器,在官网下载解压后放在Public目录下,然后在模板页引用
<script type="text/javascript" charset="utf-8" src="__PUBLIC__/ueditor/ueditor.config.js"></script>
<script type="text/javascript" charset="utf-8" src="__PUBLIC__/ueditor/ueditor.all.min.js"> </script>
<!--建议手动加在语言,避免在ie下有时因为加载语言失败导致编辑器加载失败-->
<!--这里加载的语言文件会覆盖你在配置项目里添加的语言类型,比如你在配置项目里配置的是英文,这里加载的中文,那最后就是中文-->
<script type="text/javascript" charset="utf-8" src="__PUBLIC__/ueditor/lang/zh-cn/zh-cn.js"></script>
<script type="text/javascript">var ue = UE.getEditor('editor');</script>
在要添加文本编辑的地方添加id="editor"的属性就能用了
在控制器中用正则简单过滤下脚本,这中方法还未能有效防止xss攻击,在以后的学习中,我会进行深入学习了解
$preg = "/<script[\s\S]*?<\/script>/i";
$add['detail'] = preg_replace($preg,"",$add['detail'],3);
哦,还有,我还添加过一个上传图片的功能
public function uploadpic() {
if (!empty($_FILES)) {
$upload = new \Think\Upload();// 实例化上传类
$upload->maxSize = 2048000; //上传文件最大大小
$upload->allowExts = array('jpg','jpeg','gif','png');//允许上传文件类型
$upload->rootPath = "./Public/img/"; //文件保存根目录,可以自定义
$upload->savePath = "uploads/"; //文件保存目录
$upload->replace = 'true'; //可以替换相同名称的文件
$img = getBaseName($_FILES['image']['name']);
$upload->saveName = substr($img,0,strrpos($img, '.'));
$file = $upload->upload($_FILES)['image'];
if(empty($file['savename'])){
$this->error($upload->getError());//获取失败信息
}else {
$url = $file['savepath'].$file['name'];//print_r($url);die;
$img = "./Public/img/".$url;//获取文件上传目录
$add = ['name' => I('name'),'url' => $url];
$db_p = M('con_picture');
if(!empty($add['name']) && !empty($add['url'])) {
$han = $db_p->add($add);
$this->success('添加成功!',U('pic'));
}else {
$this->error('添加失败,请重试!');
}
}
}
$this->assign('name',$img);
$this->display('uploadpic');
}
在这里面有一个getBaseName()的函数需要定义,我写在了公共函数Common/Common/function.php里了,作用是把中文名的编码换成utf8的 防止中文乱码
function getBaseName($filename, $type)
{
//将中文名的编码换成utf8的 防止中文乱码
$basename = basename(iconv("UTF-8","gb2312", $filename), $type);
return $basename;
}
写一个公共类,让后台的其它控制器都继承这个类,防止未登陆就能访问后台其他页面
public function _initialize() {
$name = $session['name'];
if(!isset($_SESSION['name']) || empty($_SESSION['name'])) {
$this->error('非法操作,请先登录!!!',U('Index/index'));
}
}
模板文件都放在view下,通过控制器带调用
以上便是后台大致遇到的重要问题,大致能想到这么多
前台基本上就是调用数据库内容,然后按条件循环输出,
印象深的地方就是用户在登陆时的判断,如果登陆,就可以直接评论,未登录时评论,会跳转到登陆界面,没点击评论直接登陆的,会跳转到留言历史
在这之期间,有些写代码时的规范好处我也领悟了一些,比如用数组来接收一个页面的数据在插入数据库时不容易出错,用assign()将后台处理的数据赋给一个变量在修改时只需要改动后台的变量名即可,将后台与前台分开来,更加方便处理。