PHP仿博客園,個人博客(2)

先謝謝大傢的鼓勵與支持,這是第2篇瞭。也是這個博客系統最核心的東西。這個博客寫完後,我會把它放在我的博客網站。這裡也有我的一個簡歷。
廢話不多說瞭,上一篇有個核心概念就是 give action do something !
這篇我就用代碼來解釋這個概念是啥意思,先看我的 post.class.php . 這個文件是我們的數據層處理類。

簡單介紹一下這個model 類,它繼承瞭一個伺服器基類來做crud 等常用操作, 每次初始化時就會初始化一個伺服器對象 $db. 我們就用這個對象來操作我們的數據。
對於數據操作有2個重要方法 storePostFormValues( ) , storeDiaryFormValues( ),它們2個方法是數據流的開始。
還有2個方法很有意思,addChildNumber( ), reduceChildNumber( ),  它們負責在插入或刪除文檔時的 一個暗箱操作。因為我的文檔可以用多個分類,所以在操作文檔的時候,要考慮到一個問題,就是 category 表中有個字段 記錄瞭該分類下的 文檔數量。所以要動態地改變這些數目的值。
 
下面配合 post.php 控制器,我們就可以開始我們數據的流程瞭(我的控制器還不是一個類,所以無法生成API文檔。因為這還不是真正地MVC架構。)所以在MVC之前,這個也能更利於的理解MVC到底是神馬東東,以及你自己如何去應用,寫出自己的MVC。
以下的情形都是假設:
$action = "天上掉下個女朋友給我吧!"; 讓我們傳入這個控制器看會發生神馬事情。
 
require_once( "config/config.php" );
session_start( );
$action = isset( $_GET['action'] ) ? $_GET['action'] : "";
$username = isset( $_SESSION['username'] ) ? $_SESSION['username'] : "";

 if( !$username )
 {
    header("Location: index.php?action=login");
    exit;
 }
 
這裡我們有個重要流程控制語句 switch , 這個單詞是 開關的意思; 所以當上面那個 $action = "天上掉下個女朋友給我吧!"; 傳入 switch 時,隻有2種可能,一種是開,一種是關。這裡有點雙關地意思,有些同學可能看出來瞭。嘿嘿!
言歸正傳:看看我們的 switch 是如何開關這些 $action , 很明顯 天上不會掉個女朋友給我,因為控制器裡沒有這個開關,所以隻能還是說說代碼的事。
 
switch( $action )
 {
    case "newPost" :
        newPost( );
    break;
   
    case "delete" :
        delete( ) ;
    break;
   
    case "updatePost":
        updatePost( );
    break;
   
    case "IsDraft":
        listDraft( );
    break;
   
    case "logout" :
        logout( );
     break;
    
     case "isPost":
        listPost( );
    break;
   
    case "diffentCategoryPost":
        diffentCategoryPost( );
    break;
   
    case "unCategory":
        unCategory( );
    break;
   
    default :
        listPost( );
    break;
 }
 
 
每個switch都應該定義默認的 開關,這樣當沒有女朋友的時候,可以確保我們還有基友。
如何傳入 action 呢?
來看這樣一個url,也就是我們的後臺框架的導航, post.php?action=isPost  這個是一個標準的action, 我們每個url 其實都是由這些action組成的,也可以加入其他的一些參數到我們的url 中, 這樣我們可以在控制器定義的方法中 GET (得到這些變量的值),然後我們可以多些控制。
好瞭,當這個url 到達我們的控制器後,我們接收判斷,然後打開一個 isPost 的開關,這樣我們就可以調用後面的方法瞭,想想 開關燈,開關電腦,開關就是我們經常做的事。
這裡我們隻是換瞭一個地方。
ok 。 來看看這個開關的下面的方法。
 
 function listPost( )
{
    $results = array( );
    $results['pageTitle'] = "Post List" ;
    $results['path'] = "<a href='?action=isPost' >隨筆</a>";
    // set the message
    if ( isset( $_GET['error'] ) )
    {
        if ( $_GET['error'] == "InsertedFailed" ) $results['errorMessage'] = "文檔添加失敗";
        if ( $_GET['error'] == "postDeleteFailed" ) $results['errorMessage'] = "文檔刪除失敗";
    }
    if ( isset( $_GET['status'] ) )
    {
        if ( $_GET['status'] == "changesSaved" ) $results['statusMessage'] = "文檔保存瞭!";
        if ( $_GET['status'] == "Deleted" ) $results['statusMessage'] = "文檔刪除瞭!";
        if ( $_GET['status'] == "Inserted" ) $results['statusMessage'] = "你添加瞭新的文檔!";
        if ( $_GET['status'] == "SaveToDraft" ) $results['statusMessage'] = "文檔保存到瞭草稿箱!";
    }
   
    // 文檔的分類瀏覽
    $db = MySQL::getInstance( );
    $pagination = new Pagination;
    $cat = new Category;
    $results['categories'] =  $cat->getCategoryList("post");
   
    $pagination->countSQL = "select * from post where type = 'post' " ;
    $db->Query( $pagination->countSQL );
    $pagination->totalRecords = $db->RowCount( );
    $records = $db->HasRecords( $pagination->rebuiltSQL( ) );
    if( $records )
    {
        $results['posts'] = $db->QueryArray( $pagination->rebuiltSQL( ) );
        require_once(TEMPLATE_PATH . "/post/post_list.php");
    }
    else
    {
        require_once(TEMPLATE_PATH . "/post/post_list.php");
    }
   
 }
 

我們定義瞭一個數組,$results = array( ); 這個數組的作用明顯,它將保存我們從 model 中獲取的任何數據,也可以保存從url上 GET 的特殊參數。然後將在我們下面require_once(*****) 包含的模版中顯示出來, 路徑定義在瞭 path 變量中。
同時我們會接收2個提示參數,
error , 表示操作出現錯誤,任何人都在所難免,包括電腦,誰都會犯錯,關鍵是去承認,電腦做的很好,他們勇於承認錯誤。
status; 表示狀態,就是成功的操作。
$pagination = new Pagination;

這個類是我們的分頁類,我們傳入一個 總的數量給它,然後它自己會算出總頁數,每跳轉一個頁面,相當於刷新瞭一次,所以大傢的做法就是,在構造器裡 GET(獲取)url上的page 的值,
讓我們知道是當前那一頁瞭。同時我們重新生成瞭查詢的語句,後面加上一條限制的語句,類似 limit $start(起始的id), $offset(長度); 原理就是從這個id起,往後給我10 條記錄;
我的設定就是 10 條,你也可以更靈活。

$cat = new Category;
這個類後面會詳細說,也是非常重要的分類model。這裡我們就是簡單獲取 這個類型下的所有分類,顯示在側邊欄,我已經完成瞭。有圖有真相!

 

這樣 我們的 $results 數組中就儲存瞭我們頁面所需的所有數據。 好的,來看看我們的模版,是怎麼輸出的。
 
  View Code
 
  1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  2 <html>
  3     <head>
  4         <title>
  5             博客後臺管理</title>
  6             <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  7             <link rel="stylesheet" type="text/css" href="assert/css/blog.css" />          
  8     </head>   
  9     <body id="Posts">
 10             <table id="BodyTable" border="0" cellpadding="0" cellspacing="0" width="100%">
 11                 <tr>
 12                     <td id="Header" colspan="2"><p id="SiteNav"></p>           
 13                         <p id="BlogTitle">
 14                             Arist's Blog
 15                         </p>
 16                         <p id="Site Title">
 17                             <b><blockquote>Hinging there, everything will be fine.</blockquote></b>
 18                         </p>
 19                     </td>
 20                 </tr>
 21                 <tr>
 22                     <td>
 23                         <p id="LeftNavHeader">操作</p>
 24                     </td>
 25                     <td class="NavHeaderRow">
 26                         <ul id="TopNav">
 27                             <li><a href="post.php?action=IsPost">隨筆</a></li>
 28                             <li><a href="article.php?action=IsArticle">文章</a></li>
 29                             <li><a href="diary.php?action=IsDiary">日記</a></li>
 30                             <li><a href="comment.php?action=IsComment">評論</a></li>
 31                             <li><a href="photo.php?action=IsPhoto">相片</a></li>                           
 32                         </ul>
 33                         <p id="SubNav">
 34                             當前位置:&nbsp;<?php if( isset( $results['path'] )) echo $results['path']; ?>
 35                         </p>
 36                     </td>
 37                 </tr>
 38                 <tr>
 39                     <td class="NavLeftCell">                       
 40                         <p class="left_nav">
 41                             <ul id="LinksActions">
 42                                 <li><a href="article.php?action=newArticle">&raquo; 添加新文章</a></li>
 43                             </ul>
 44                         </p>
 45                         <p id="CategoriesHeader" class="LeftNavHeader">
 46                             分類
 47                         </p>
 48                         <p class="left_nav">
 49                             <ul id="LinksCategories">
 50                             <li><a href="category.php?action=ListCat&type=article">[編輯分類]</a></li>
 51                             <li><a href="article.php?action=IsArticle">[所有分類]</a></li>
 52                             <li><a href="article.php?action=unCategory">[未分類]</a></li>
 53 <?php
 54 if( isset( $results['categories'] )  && ! empty( $results['categories'] ) ){
 55     foreach( $results['categories'] as $category ){
 56     echo <<<EOB
 57                     <li><a href="article.php?action=diffentCategoryArticle&catID={$category['category_id']}">{$category['name']}({$category['count_child_number']})</a></li>
 58 EOB;
 59     }
 60 }
 61 ?>
 62                             </ul>
 63                         </p>
 64                     </td>
 65                     <td id="Body">
 66                         <p id="Main">
 67                 <p id="Editor_Messages">
 68                 <!– 顯示提示信息 –>
 69                 <?php
 70                     if( isset( $results['statusMessage'] )){echo  $results['statusMessage'];}
 71                     if( isset( $results['errorMessage'] )){echo  $results['errorMessage'];}
 72                 ?>
 73                 </p>
 74 <p id="Editor_Results">
 75     <p id="Editor_Results_Header" class="CollapsibleHeader">
 76         <span id="Editor_Results_headerTitle">文章(主要用於轉載,發佈原創博文要通過“隨筆”)</span>
 77     </p>
 78     <p id="Editor_Results_Contents">    
 79 <?php 
 80     if( isset( $results['posts'] )){
 81     echo <<<EOB
 82             <table id="Listing" class="Listing" cellspacing="0" cellpadding="0" border="0" style='width:98%;'>
 83                 <tr style="text-align: center">
 84                     <th valign="bottom">
 85                         標題
 86                     </th>
 87                     <th width="40" style="text-align: center">
 88                         發佈<br />
 89                         狀態
 90                     </th>
 91                     <th valign="bottom" width="50" style="text-align: center">
 92                         評論
 93                     </th>
 94                     <th width="50" style="text-align: center">
 95                         頁面<br />
 96                         瀏覽
 97                     </th>             
 98                     <th valign="bottom" width="40" style="text-align: center">
 99                         操作
100                     </th>
101                     <th valign="bottom" width="40" style="text-align: center">
102                         操作
103                     </th>
104                 </tr>
105        
106 EOB;
107         foreach( $results['posts'] as $post ){
108             $time = date("Y-m-d H:i:s", $post['create_time']);
109             if( $post['status'] == "1" ){
110                 $post['status']  = "發佈";
111             }    else {
112                 $post['status']  = "<b>未發佈</b>";
113             }
114             echo <<<EOB
115             <tr id="entry_{$post['post_id']}" class="Alt">
116                 <td style="text-align: left">{$post['title']} ({$time})</td>
117                 <td style="text-align: center">{$post['status']}</td>
118                 <td style="text-align: center">{$post['view_count']}</td>
119                 <td style="text-align: center">{$post['comment_count']}</td>
120                 <td style="text-align: center"><a href="article.php?action=editArticle&postID={$post['post_id']}">編輯</a></td>
121                 <td style="text-align: center"><a href="JavaScript:if(confirm('從伺服器中刪除這篇文檔?')==true){window.location='article.php?action=delete&postID={$post['post_id']}';}">刪除</a></td>   
122             </tr>
123 EOB;
124         }
125             echo "</table>";               
126             if( isset( $pagination) ){$pagination->createLinks( ) ;}
127     } else {
128         echo "當前無內容!";
129     }
130
131 ?>  
132
133     </p>
134 </p>
135
136
137 <span id="currentPostId" style="display:none;"></span>
138
139                         </p>
140                     </td>
141                 </tr>
142             </table>
143             <p id="blog_top_nav_block">
144                 <p id="site_nav">
145                 </p>
146                 <p id="login_area">         
147                  <span id="span_userinfo"><b><?php  echo $_SESSION['username']; ?> </b>&nbsp; <a href="?action=logout">logout</a></span>
148                 </p>
149                 <p class="clear"></p>
150             </p>
151             <table id="Footer" border="0" cellpadding="0" cellspacing="0" width="100%">
152                 <tr>
153                     <td colspan="2">
154                         <p>
155                             &copy; <?php echo date("Y", time( ) ); ?> Arist
156                         </p>
157                     </td>
158                 </tr>
159             </table>
160     </body>
161 </html>
 
以上隻是顯示數據,人人都會啊。
 
我們怎麼操作這些數據呢?
操作,就像是一種控制能力。 學生時代踢足球,我對球場有一種很強的控制能力,大學足球比賽拿瞭1次冠軍,1次亞軍,1次季軍,大四沒去,中學更是無數榮譽。
我的位置是中衛,在足球場上,這個位置,你得有統觀全局的能力,也得有很強的個人能力,還有指揮能力;扯的遠瞭,現在天天坐在電腦前,這些東西也早就沒瞭,
就剩下些經驗之談。不過其中滋味,你也須也體驗過。
 
我這個博客有個缺點,每次你對伺服器進行一次讀寫操作,你得刷新啊!我知道這對伺服器的負載很大,但是我覺得如果一個新技術你沒有完全吃透,盲目運用,隻會適得其反。
所以暫時我還是犧牲伺服器的響應時間,內存消耗,來獲得一種相對的穩定!
 
所以我對全局還不是很瞭解,還有很多未知地領域沒有涉入,如深入ajax,深入php,c 。。。 不多說瞭。
好瞭,看看怎麼對數據進行CRUD 吧!
DELETE 刪除
先看這個指令 post.php?action=delete&amp;postID=132
當我們確認要刪除時,這裡有個註意的地方,我們能先要對該文檔所屬的分類下的 count_child_number 這個字段進行 一個減 1 的操作。
為什麼? 因為我也開始犯瞭個邏輯錯誤,刪除後我才調用這個方法,還記得嘛!reduceChildNumber( ) 有趣地地方就是這裡,讓我受益匪淺!也讓我調試瞭N久!
 
所以:當你的語法都沒錯的時候,可能是你的邏輯錯瞭!或是方法錯瞭!這就是我的註釋! 請看:
 
  $post = new Post;
    $filter['post_id'] = isset( $_GET['postID'] ) ? ( int )$_GET['postID'] : "";
   
    //  !important 在數據刪除之前 先將該分類下的文章數量減 1
    // 否則你不知道刪除那個分類下的文章數量
    // 我犯瞭個邏輯錯誤 先刪除瞭 文檔, 然後查該文檔的分類ID;永遠也查不到,因為已經不存在瞭。
    $post->reduceChildNumber( "category", ( int ) $_GET['postID'] );
   
    $result = $post->delete("post", $filter );
 
這裡我們隻要初始化我們文章頭頂的那個 model 就可以輕松調用 delete() 方法。
 
CREATE 插入
先看這個指令 post.php?action=newPost
說實話,我很久沒有插入瞭。呵呵! 看控制方法:
  View Code
 
function newPost( )
 {
    $results['action'] = "newPost" ;
    $results['pageTitle'] = " Add New post" ;
    $results['newPost'] = "true";
    $results['path'] = "<a href='?action=isPost' >隨筆</a>&raquo; <span>添加隨筆</span>" ;
    $post = new Post;
    $cat = new Category;
    $results['categories'] =  $cat->getCategoryList( "post");
    // 新建文檔
    if( isset( $_POST['saveChanged'] ))
    {   
        $post-> storePostFormValues( $_POST );
        $result = $post->insertPost( );
        if( $result )
        {
            $post->addChildNumber( "category", $_POST['category'] );
            header("Location: post.php?action=isPost&status=Inserted");
        }
        else
        {
            header("Location: post.php?action=isPost&error=InsertedFailed");
        }
        // 保存到草稿箱
    } else if( isset( $_POST['saveDraft']) )
    {
        $post = new Post;
        $post-> storePostFormValues( $_POST );
        $post->saveDraft( );
        header("Location: post.php?action=isPost&status=postSaveToDraft");
        // cancel
    } else if( isset( $_POST['cancel'] ))
    {
        header("Location: post.php?action=isPost");
    }
    else
    {
        require_once(TEMPLATE_PATH . "/post/post_edit.php");
    }
 }
 
 
我們使用一個模版來同時進行文檔的插入和更新。關鍵就是 isset( ),當我們調用控制器的 newPost 方法時,我們並沒有往模版中傳入文檔。
所以在模版中,我們用 isset() 來做判斷時,我們獲得瞭空值,是個好東西;這樣我們不會輸出任何內容到模版中去。這樣,我們等待用戶提交表單,在這裡,我為瞭省事,暫時沒有對表單進行過濾,不過我留瞭個後門以後來更新。 好的,假設我們的表單被提交瞭,(也被你基本的過濾瞭)。

我們調用 post model中 的 storePostFormValues( ) , storeDiaryFormValues( ); 記得嘛,這個方法把所有的表單內容放入一個數組,在做瞭基本的類型檢查之後,
到這裡已經成功一半瞭。下面就是 insert***()。 這就是mysql 萬能伺服器操作類的好處,它能幫你處理各種表單,各種類型。當然你如果要求更細,更多,你可以繼承它,擴展
它的方法,或新建方法。 到這裡離完成還有一步,addChildNumber( )。 當你為你的文檔選擇分類時,同時也要在相應的分類表中的 count_child_number中加 1 。
如果用戶選擇將文檔放入草稿箱的話,隻需插入一個 type = PostDraft 的文檔記錄。
 
UPDATE 更新
先看這個指令 post.php?action=updatePost&amp;postID=132
更新首先就要獲得這個文檔的數據,postID, 同樣是 GET方法得到。 這樣我們就可以初始化表單中的 value 值瞭。 isset( ) 在這裡起瞭關鍵作用,不是嘛?
後面的部分大同小異, storePostFormValues( ) , storeDiaryFormValues( ); 然後你調用 post model update***( ) 。
看代碼:
  View Code
 
function updatePost( )
 {
    $results['action'] = "updatePost";
    $results['pageTitle'] = "Edit post";
    $post = new Post;
    $cat = new Category;
    $results['categories'] =  $cat->getCategoryList("post");
    if( isset( $_POST['saveChanged'] ))
    {
        // do update
        $post->storePostFormValues( $_POST );
        $post->updatePost( );
        header("Location: post.php?action=isPost&status=changesSaved") ;                   
    } else if( isset( $_POST['cancel'] ) )
    {
        header("Location: post.php?action=isPost&status=Cancel");
    }else
    {
        // get the post    
        $postID = isset( $_GET['postID'] ) ?  $_GET['postID'] : " ";
        $results['post'] = $post->getPostByID( $postID );
        require_once(TEMPLATE_PATH . "/post/post_edit.php");
    }
   
 }
 
 
 
到這裡就差不多瞭,我們實現瞭幾乎所有的基本操作。
幾點說明,這些action 有的是導航,有的是生成的,大部分是固定的。自己看著用吧。 下篇說說 分類的事!還有就是這篇博客寫完後會放在一個網站上 www.anyui.net
你如果想要源碼學習的話,我會提供下載。謝謝你花這麼長時間聽我嘮叨, 看到這句的人,祝你們 昨天 6,1 快樂,嘿嘿。

 

摘自 warcraft

You May Also Like