本書實戰性很強,沒有冗長的概念講解,都是實際項目中使用的實用技術,比如驗證碼、文件上傳、圖像處理、調試、安全、緩存等。留言板、博客、論壇、微信公眾平臺開發4個實戰項目案例,使讀者盡快切入ThinkPHP企業級項目開發。
夏磊,目前從事軟件開發工作。精通PHP服務器腳本語言技術,善于把握運用新技術,如LAMP&LNMP平臺以及Node.js平臺下Web軟件的開發、軟件架構、設計模式等。作者博客上大量的PHP相關技術文章,深受讀者好評。
第 12 章
博客系統項目實戰 ?
12.1 項目目的
本博客系統項目目的如下:
記載個人學習、工作、生活上一些值得回味的事情,以及一些值得分享或者探討的技術。
用于社會溝通和交友,和他人分享自己的成功。
自我學習、自我提高。
12.2 需求分析
提到博客,大部分人都不會陌生,畢竟大名鼎鼎的wordpress可是業界神話。本章需要實現的也是一個博客系統。當然,并沒有wordpress那么強大,不過“麻雀雖小、五臟俱全”,一個博客應有的功能還是需要有的。
寫作。博客的核心功能就是寫作,而且是獨自寫作,有寫作就有文章,有文章就涉及文章的分類、發表、編輯、刪除。
評論。既然項目目的中有“用于社會溝通和交友”,那么社會上的讀者如何與作者互動呢?所以,評論功能必不可少。有了評論就需要發表評論、管理評論。
友情鏈接。好文章如何讓別人知道呢?單憑自己的力量是不夠的,所以合理地與他人交換友情鏈接是博客的一種推廣手段。
12.3 功能設計
通過需求分析的結果,可以總結出博客系統需要以下功能:
? 管理員登錄、修改密碼、退出登錄。
? 文章分類添加、編輯、刪除。
? 文章添加、編輯、刪除。
? 發表評論、管理評論。
? 添加友情鏈接、刪除友情鏈接、展示友情鏈接。
12.4 數據庫設計
根據需求分析以及功能設計,設計出如圖12-1所示數據庫模型。
圖12-1
可以看到分類表、文章表、評論表之間存在關系。
12.5 數據庫字典
1. 文章分類(blog_category)
文章分類表設計如表12-1所示。
表12-1
字段名稱 類型 說明
categoryId int(10) 主鍵,自增
name varchar(20) 分類名稱
isNav tinyint(1) 是否顯示在導航欄
total int 文章總數
sort tinyint(4) 排序
2. 文章表(blog_article)
文章表設計如表12-2所示。
表12-2
字段名稱 類型 說明
articleId int(11) 主鍵,自增
Title varchar(40) 文章標題
Description varchar(100) 文章簡介
Image varchar(128) 文章封面
Hits int(11) 點擊數
createdAt int(11) 文章發布時間(時間戳)
updateAt int(11) 文章更新時間
Status tinyint(1) 狀態(發表,不發表)
Sort int 文章排序
Content text 文章正文
categoryId int 分類ID
3. 文章評論表(blog_comment)
文章評論表設計如表12-3所示。
表12-3
字段名稱 字段類型 說明
commentId int 主鍵,自增
nickname varchar(20) 昵稱
createdAt int(11) 評論時間
createdIp varchar(15) 評論IP(只考慮IPV4)
content text 評論內容
articleId int 文章ID
4. 管理員表(blog_admin)
管理員表設計如表12-4所示。
表12-4
字段名稱 字段類型 說明
adminId int 管理員ID
username varchar(20) 用戶名
password char(32) 密碼(md5加密后密文)
createdAt int 賬號添加時間
loginAt int *近登錄時間
loginIp int *近登錄IP
5. 友情鏈接表(blog_link)
友情鏈接表設計如表12-5所示。
表12-5
字段名稱 字段類型 說明
linkId int 主鍵,自增
name varchar(20) 網站名稱
link varchar(100) 鏈接地址
status tinyint(1) 狀態
sort int 排序
12.6 模塊設計
12.6.1 Admin模塊
admin為后臺管理模塊,需要管理文章、分類、評論、友情鏈接等功能。所以根據功能應該分開4個Controller進行處理。Controller如下:
? ArticleController,文章控制器。
? CategoryController,分類控制器。
? CommentController,評論控制器。
? LinkController,友情鏈接控制器。
1. 權限檢測
由于admin模塊屬于受保護的模塊,所以以上4個控制器必須登錄后才能正常訪問,為了不寫重復代碼,需要新建一個控制器處理登錄檢測,以上4個控制器繼承該基本控制器實現統一權限檢測。
在Admin模塊新建BaseController.class.php,添加_initialize方法,代碼如下:
protected function _initialize()
{
if (session('admin.adminId') === null)
{
$this->error('請登錄', U('admin/index/login'));
}
C('LAYOUT_NAME', 'admin');
}
需要進行權限檢測的控制器繼承BaseController即可。
2. 分頁處理
由于該博客系統是一直在線上運行的,所以數據量不可預測,在列表頁需要進行分頁處理。以下是友情鏈接主頁的分頁代碼:
public function index()
{
$model = new Model('Link');
$count = $model->count();
$page = new Page($count);
$show = $page->show();
$list = $model->order('linkId DESC')->limit($page->firstRow . ',' . $page->listRows)->select();
$this->assign('list', $list);
$this->assign('page', $show);
$this->display();
}
3. 文章-分類模型
文章是屬于分類的,所以讀取文章列表的時候需要將分類信息同時查詢處理,這里使用ThinkPHP提供的ViewModel,在Common模塊新建Model文件夾,在Model文件夾下新建ArticleCategoryViewModel.class.php,代碼如下:
namespace Common\Model;
use Think\Model\ViewModel;
class ArticleCategoryViewModel extends ViewModel
{
public $viewFields = array(
'Article' => array('articleId', 'title', 'description', 'image', 'hits', 'createdAt', 'updateAt', 'status', 'sort', 'content'),
'Category' => array('categoryId', 'name', '_on' => 'Article.categoryId=Category.categoryId')
);
}
ViewModel的知識可以在第5章第9節查看。
4. 文件上傳
在設計文章表的時候,有個封面字段,這個字段是用來保存文章封面的,所以需要做一個圖片上傳的功能。為了貫徹“模塊化”的思想,筆者特地將上傳模塊抽象出來,只要在需要上傳的頁面include即可。
在Admin模塊的View文件夾添加Common文件夾,在Common文件夾下添加upload.html,代碼如下:
點擊上傳
該段代碼與一般代碼區別不大,但是重點在于:
uploadCallback && uploadCallback(data.url);
如果當前頁面定義了uploadCallback函數,則將上傳后的結果回調到該函數。
上傳代碼,編輯Admin模塊下的Index控制器,添加upload方法,代碼如下:
public function upload()
{
$upload = new Upload();// 實例化上傳類
$upload->maxSize = 1024 * 1024 * 2;// 設置附件上傳大小
$upload->exts = array('jpg', 'gif', 'png', 'jpeg');// 設置附件上傳類型
$upload->rootPath = __DIR__ . '/../../../upload/'; // 設置附件上傳根目錄
$upload->savePath = ''; // 設置附件上傳(子)目錄
// 上傳文件
$info = $upload->upload();
if (!$info)
{
$this->ajaxReturn(array(
'error' => $upload->getError()
));
}
else
{
$path = $upload->rootPath . $info['file']['savepath'] . $info['file']['savename'];
$image = new Image();
$image->open($path);
$image->thumb(200, 200, Image::IMAGE_THUMB_CENTER)->save($path);
$this->ajaxReturn(array(
'url' => U('/', '', false, true) . 'upload/' . $info['file']['savepath'] . $info['file']['savename']
));
}
}
使用時直接使用以下代碼引入即可(示例代碼在Application/Admin/View/Article/post.html中):
由于回調函數已經寫死了“uploadCallback”,所以目前來說該上傳組件一個頁面只能使用一個。
Admin模塊比較重要的功能就是以上列出來的,其他功能基本上都是添加、編輯、列表、刪除功能,由于篇幅關系這里不再贅述,有需要的讀者可以前往github下載源碼:
https://github.com/xialeistudio/thinkphp-inaction/tree/master/blog
12.6.2 Common模塊
1. 分類處理
Common模塊是公用模塊,其他模塊公用的功能可以放在該模塊下,比如上文中的“文章-分類模型”就是公用Model,所以放在Common/Model下。
博客系統在設計文章分類時有“isNav”字段,該字段用來標識分類是否是導航欄中的分類,所以可以明確出來的需求有:
? 讀取屬于導航欄的分類(status為1)
? 讀取不屬于導航欄的分類(status為0)
? 讀取全部分類
而以上需求返回值都是一致的,也就是分類列表,所以可以將以上三個需求封裝成一個函數,根據傳入的status來決定返回數據。
編輯Application/Common/Common/function.php,添加如下代碼:
/**
* 獲取分類
* @param int $isNav
* @return mixed
……