需求:
- 商品表的管理:CRUD、搜索、排序、翻頁(yè)
- 考慮SQL注入
- 使用js插件:時(shí)間插件,在線編輯器
- 圖片生成縮略圖,節(jié)省帶寬,加載快
創(chuàng)建一個(gè)控制器完成商品表的操作
namespace Admin\Controller;
use Think\Controller;
class GoodsController extends Controller
{
public function add()
{
// 2.處理表單
if(IS_POST)
{
//3. 先生成模型
// D和M的區(qū)別:D生成我們自己創(chuàng)建的模型對(duì)象,M生成TP自帶的模型對(duì)象
// 這里我們要生成我們自己創(chuàng)建的模型,因?yàn)檫@里要使用我們自己創(chuàng)建的模型中的驗(yàn)證規(guī)則來(lái)驗(yàn)證表單
// 這里用M可以添加成功但是驗(yàn)證表單的功能會(huì)失敗,因?yàn)轵?yàn)證規(guī)則是在我們自己定義的模型中的,而M生成的是TP自帶的模型里沒(méi)有驗(yàn)證規(guī)則
$model = D('Goods');
// 4. a.接收表單中所有的數(shù)據(jù)并存到模型中 b.使用I函數(shù)過(guò)濾數(shù)據(jù) c.根據(jù)模型中定義的規(guī)則驗(yàn)證表單
//5.在create方法時(shí)傳入第二個(gè)參數(shù)標(biāo)記是什么類(lèi)型的表單,其中1:添加,2:修改
if($model->create(I('post.'), 1))
{
// 5. 插入數(shù)據(jù)庫(kù)
if($model->add())
{
// 6. 提示信息
$this->success('操作成功!', U('lst'));
// 7.停止執(zhí)行后面的代碼
exit;
}
}
// 8. 如果上面失敗,獲取失敗的原因
$error = $model->getError();
// 9. 顯示錯(cuò)誤信息,并跳回到上一個(gè)頁(yè)面
$this->error($error);
}
// 1.顯示表單
$this->display();
}
public function edit()
{
// 處理表單
if(IS_POST)
{
$model = D('Goods');
if($model->create(I('post.'), 2))
{
// save方法的返回值是影響的記錄數(shù)(mysql_affected_rows),如果修改時(shí)沒(méi)有修改任何值會(huì)返回0.如果失敗返回FALSE
if(FALSE !== $model->save())
{
$this->success('操作成功!', U('lst?p='.I('get.p')));
exit;
}
}
// 如果失敗顯示錯(cuò)誤信息
$this->error($model->getError());
}
// 接收商品的ID
$id = I('get.id');
// 先從數(shù)據(jù)庫(kù)中取出要修改的記錄的信息
$model = M('Goods');
$info = $model->find($id);
$this->assign('info', $info);
// 顯示修改的表單
$this->display();
}
public function delete()
{
$model = D('Goods');
$model->delete(I('get.id'));
$this->success('操作成功!', U('lst?p='.I('get.p')));
}
// 列表
public function lst()
{
$model = D('Goods');
// 獲取帶翻頁(yè)的數(shù)據(jù)
$data = $model->search();
$this->assign(array(
'data' => $data['data'],
'page' => $data['page'],
));
$this->display();
}
}
創(chuàng)建模型
class GoodsModel extends Model
{
// 在添加時(shí)調(diào)用create方法時(shí)允許接收的字段
protected $insertFields = array('goods_name','price','goods_desc','is_on_sale');
// 在修改時(shí)表單中可以有哪些字段
protected $updateFields = array('id', 'goods_name','price','goods_desc','is_on_sale');
// 定義表單驗(yàn)證的規(guī)則,控制器中的create方法時(shí)用
protected $_validate = array(
array('goods_name', 'require', '商品名稱不能為空!', 1),
array('goods_name', '1,45', '商品名稱必須是1-45個(gè)字符', 1, 'length'),
array('price', 'currency', '價(jià)格必須是貨幣格式', 1),
array('is_on_sale', '0,1', '是否上架只能是0,1兩個(gè)值', 1, 'in'),
);
// TP在調(diào)用add方法之前會(huì)自動(dòng)調(diào)用這個(gè)方法,我們可以把在插入數(shù)據(jù)庫(kù)之前要執(zhí)行的代碼寫(xiě)到這里
// 第一個(gè)參數(shù):就是表單中的數(shù)據(jù)(要插入到數(shù)據(jù)庫(kù)中的數(shù)據(jù))是一個(gè)一維數(shù)組
// 第二個(gè)參數(shù):額外信息,:當(dāng)前模型對(duì)應(yīng)的實(shí)際的表名是什么
// 說(shuō)明:在這個(gè)函數(shù)中要改變這個(gè)函數(shù)外部的$data,需要按鈕引用傳遞,否則修改也無(wú)效
// 說(shuō)明:如果return false是指控制器中的add方法返回了false
protected function _before_insert(&$data, $option)
{
// 獲取當(dāng)前時(shí)間
$data['addtime'] = time();
// 上傳LOGO
if(isset($_FILES['logo']) && $_FILES['logo']['error'] == 0)
{
$rootPath = C('IMG_rootPath');
$upload = new \Think\Upload(array(
'rootPath' => $rootPath,
));// 實(shí)例化上傳類(lèi)
$upload->maxSize = (int)C('IMG_maxSize') * 1024 * 1024;// 設(shè)置附件上傳大小
$upload->exts = C('IMG_exts');// 設(shè)置附件上傳類(lèi)型
/// $upload->rootPath = $rootPath; // 設(shè)置附件上傳根目錄
$upload->savePath = 'Goods/'; // 圖片二級(jí)目錄的名稱
// 上傳文件
$info = $upload->upload();
if(!$info)
{
// 先把上傳失敗的錯(cuò)誤信息存到模型中,由控制器最終再獲取這個(gè)錯(cuò)誤信息并顯示
$this->error = $upload->getError();
return FALSE; // 返回控制器
}
else
{
$logoName = $info['logo']['savepath'] . $info['logo']['savename'];
// 拼出縮略圖的文件名
$smLogoName = $info['logo']['savepath'] . 'thumb_' .$info['logo']['savename'];
// 生成縮略圖
$image = new \Think\Image();
// 打開(kāi)要處理的圖片
$image->open($rootPath.$logoName);
$image->thumb(150, 150)->save($rootPath.$smLogoName);
// 把圖片的表單放到表單中
$data['logo'] = $logoName;
$data['sm_logo'] = $smLogoName;
}
}
}
protected function _before_update(&$data, $option)
{
// 上傳LOGO
if(isset($_FILES['logo']) && $_FILES['logo']['error'] == 0)
{
$rootPath = C('IMG_rootPath');
$upload = new \Think\Upload(array(
'rootPath' => $rootPath,
));// 實(shí)例化上傳類(lèi)
$upload->maxSize = (int)C('IMG_maxSize') * 1024 * 1024;// 設(shè)置附件上傳大小
$upload->exts = C('IMG_exts');// 設(shè)置附件上傳類(lèi)型
/// $upload->rootPath = $rootPath; // 設(shè)置附件上傳根目錄
$upload->savePath = 'Goods/'; // 圖片二級(jí)目錄的名稱
// 上傳文件
$info = $upload->upload();
if(!$info)
{
// 先把上傳失敗的錯(cuò)誤信息存到模型中,由控制器最終再獲取這個(gè)錯(cuò)誤信息并顯示
$this->error = $upload->getError();
return FALSE; // 返回控制器
}
else
{
$logoName = $info['logo']['savepath'] . $info['logo']['savename'];
// 拼出縮略圖的文件名
$smLogoName = $info['logo']['savepath'] . 'thumb_' .$info['logo']['savename'];
// 生成縮略圖
$image = new \Think\Image();
// 打開(kāi)要處理的圖片
$image->open($rootPath.$logoName);
$image->thumb(150, 150)->save($rootPath.$smLogoName);
// 把圖片的表單放到表單中
$data['logo'] = $logoName;
$data['sm_logo'] = $smLogoName;
// 刪除商品的原圖片
// 先根據(jù)商品的ID取出這件商品的圖片的路徑
$logo = $this->field('logo,sm_logo')->find($option['where']['id']);
// 從配置文件取出圖片所在目錄
$rp = C('IMG_rootPath');
// 刪除圖片
unlink($rp . $logo['logo']);
unlink($rp . $logo['sm_logo']);
}
}
}
public function search()
{
/************ 搜索 ****************/
$where = array(); // 默認(rèn)情況下的搜索條件為空
// 商品名稱的搜索
$goodsName = I('get.goods_name');
if($goodsName)
$where['goods_name'] = array('like', "%$goodsName%");
// 價(jià)格的搜索
$startPrice = I('get.start_price');
$endPrice = I('get.end_price');
if($startPrice && $endPrice)
$where['price'] = array('between', array($startPrice, $endPrice));
elseif ($startPrice)
$where['price'] = array('egt', $startPrice);
elseif ($endPrice)
$where['price'] = array('elt', $endPrice);
// 上架的搜索
$isOnSale = I('get.is_on_sale', -1);
if($isOnSale != -1)
$where['is_on_sale'] = array('eq', $isOnSale);
// 是否刪除的搜索
$isDelete = I('get.is_delete', -1);
if($isDelete != -1)
$where['is_delete'] = array('eq', $isDelete);
// 時(shí)間的搜索
$startAddtime = I('get.start_addtime');
$endAddtime = I('get.end_addtime');
if($startAddtime && $endAddtime)
$where['addtime'] = array('between', array(strtotime("$startAddtime 00:00:00"), strtotime("$endAddtime 23:59:59")));
elseif ($startAddtime)
$where['addtime'] = array('egt', strtotime("$startAddtime 00:00:00"));
elseif ($endAddtime)
$where['addtime'] = array('elt', strtotime("$endAddtime 23:59:59"));
/***************** 排序 ******************/
$orderby = 'id'; // 默認(rèn)排序字段
$orderway = 'desc'; // 默認(rèn)排序方式
$odby = I('get.odby');
if($odby && in_array($odby, array('id_asc','id_desc','price_asc','price_desc')))
{
if($odby == 'id_asc')
$orderway = 'asc';
elseif ($odby == 'price_asc')
{
$orderby = 'price';
$orderway = 'asc';
}
elseif ($odby == 'price_desc')
$orderby = 'price';
}
/************ 翻頁(yè) *************/
// 總的記錄數(shù)
$count = $this->where($where)->count();
// 生成翻頁(yè)對(duì)象
$page = new \Think\Page($count, 10);
$page->setConfig('next', '下一頁(yè)');
$page->setConfig('prev', '上一頁(yè)');
// 獲取翻頁(yè)字符串
$pageString = $page->show();
// 取出當(dāng)前頁(yè)的數(shù)據(jù)
$data = $this->where($where)->limit($page->firstRow.','.$page->listRows)->order("$orderby $orderway")->select();
//echo $this->getLastSql();
return array(
'page' => $pageString,
'data' => $data,
);
}
// 在控制器中調(diào)用delete方法之前會(huì)自動(dòng)調(diào)用
protected function _before_delete($option)
{
// 先根據(jù)商品的ID取出這件商品的圖片的路徑
$logo = $this->field('logo,sm_logo')->find($option['where']['id']);
// 從配置文件取出圖片所在目錄
$rp = C('IMG_rootPath');
// 刪除圖片
unlink($rp . $logo['logo']);
unlink($rp . $logo['sm_logo']);
}
}
在師徒模板中,可以不需要使用tp標(biāo)簽輸出變量,循環(huán),判斷,直接用php自身的
<?php foreach($data as $k=>$v): ?>
<?php endforeach; ?>
<?php if(): ?>
<?php endif; ?>
注意
我們?cè)趯?xiě)其他控制器的CRUD時(shí),都可以按照這種方式來(lái)做,提醒一下,向上傳文件顯示圖片的代碼,我們可以封裝到Common/Common/function.php,然后可以直接調(diào)用使用