
日期:2006-11-21 作者:喜騰小二 來源:PHPChina
並非所有的站點都包含提要,但是跟進某個地方的所有改動仍然是很有用的。本文將介紹如何使用 Zend_HTTP_Client 模組建立代理,從而將資料提取到提要閱讀器介麵中。在本文中,您將學到:
如何使用 Zend_HTTP_Client 模組載入網站資料。
如何儲存提要條目的全文以及那些不支援提要的網頁的全文。
如何在提要閱讀器介麵中閱讀已儲存提要條目的全文。
在本文的末尾,將完成提要閱讀器應用程式的框架。首先,修改資料庫綱要,其次,更新程式碼以支援新的綱要,然後新增將提要條目和網頁儲存到資料庫中的功能。最後,使用 Zend_HTTP_Client 模組支援使用者有選擇地將條目儲存到資料庫中,並在已更新的線上提要閱讀器中檢視它們。
更新資料庫綱要
為了將提要條目儲存到提要閱讀器介麵中,首先我們需要更新資料庫綱要。在 MySQL 控制臺中鍵入清單 1 中的SQL 陳述式。
清單 1. 變更資料庫綱要
drop table feeds;
create table feeds
(feedname varchar(256), link varchar(512), rss varchar(5));
insert into feeds values
('Fox Sports',
'http://feeds.feedburner.com/foxsports/rss/headlines',
'true'),
('Google News',
'http://news.google.com/?output=rss',
'true'),
('Yahoo News',
'http://rss.news.yahoo.com/rss/topstories',
'true'),
('phpbb',
'http://www.phpbb.com/phpBB/viewforum.php?f=14',
'false'),
('MySQL Forums :: PHP',
'http://forums.mysql.com/list.php?52',
'false'),
('SitePoint Forums :: PHP',
'http://www.sitepoint.com/forums/forumdisplay.php?forumid=34',
'false');
drop table savedentries;
create table savedentries
(username varchar(20), feedname varchar(256), channelname varchar(256),
link varchar(512), entrysaved varchar(5), entrydata varchar(307200));
您能看到 feeds 表新增了一個新的欄位:rss。這個欄位用於辨別該提要是 RSS 提要還是不支援提要的網頁。訂閱清單中新增了另外三個不同 PHP 論壇的提要。請注意,對於第 3 部分中的提要,這個新欄位值為 true,而三條新提要的值則為 false,這幫助它們是網頁,而非 RSS 提要。savedentries 表有兩個新的欄位:entrysaved 和 entrydata。entrysaved 欄位幫助 entrydata 欄位中的資料是有效資料。entrydata 欄位儲存了該文章的全文。新的可訂閱網頁如圖 1 所示。
現在需要回到第 3 部分的程式碼中做一些變更。
更新 IndexController 類
稍後我們將對 viewFeeds 視圖進行更新,這需要當前使用者所訂閱的非 RSS 提要的清單,該清單列出了已訂閱的提要和網頁。在 IndexController 類中變更 indexAction 方法,如下所示。
清單 2. IndexController 類中的 indexAction 方法
public function indexAction()
{
...
$select->where('feeds.feedname=subscribedfeeds.feedname');
$select->where('feeds.rss=?', 'true');
$rssResults = $db->fetchAll($select);
$select = $db->select();
$select->from('subscribedfeeds, feeds', '*');
$select->where('subscribedfeeds.Username = ?', $username);
$select->where('feeds.feedname=subscribedfeeds.feedname');
$select->where('feeds.rss=?', 'false');
$webResults = $db->fetchAll($select);
$view = Zend::registry('view');
$view->username = $username;
$view->rssFeeds = $rssResults;
$view->webFeeds = $webResults;
echo $view->render('viewFeeds.php');
}
}
這裡包含了兩個結果清單:一個包含使用者訂閱的 RSS 提要,而另一個包含當前使用者訂閱的網頁。這些提要隨後被傳送到 viewFeeds 視圖,並被顯示出來。
更新 saveEntryAction 方法
我們需要更新那些可以用來將條目儲存到資料庫中的連結,這樣我們就可以更新這兩個新欄位了。變更 FeedController 類中的 saveEntryAction 方法,如下所示。
清單 3. FeedController 類中的 saveEntryAction 方法
public function saveEntryAction()
{
$filterSession = Zend::registry('fSession');
$username = $filterSession->getRaw('username');
$filterPost = Zend::registry('fPost');
$feedTitle = $filterPost->getRaw('feedTitle');
$channelTitle = $filterPost->getRaw('title');
$channelLink = $filterPost->getRaw('link');
$type = $filterPost->getRaw('type');
$saveFullText = $filterPost->getRaw('saveFullText');
...
$db = Zend::registry('db');
$row = array(
'Username' => $username,
'feedname' => $feedTitle,
'channelname' => $channelTitle,
'link' => $channelLink,
'entrysaved' => $saveFullText ? 'true' : 'false',
'entrydata' => $fullText
);
$table = 'savedentries';
$rowsAffected = $db->insert($table, $row);
if($type == 'webPage')
$this->_redirect("/");
Else
$this->_redirect("/feed/viewChannel?title=$feedTitle");
}
清單 3 中第一段黑體程式碼將資料從 POST 陣列(而不是 GET 陣列)中提取出來,因為這就是請求儲存提要的方式(不想在 URL 中發送文章的全文)。請注意 savedentries 表中的兩個新欄位 type 和 saveFullText 是如何被檢索的。已經檢索的資料被儲存為 savedentries 表中的一個新行,並且,如果儲存了一個網頁,那麼使用者將被轉回到首頁;否則使用者將被轉回到他正在檢視的頻道。
更新 deleteEntryAction 方法
我們更新了從資料庫中移除條目的程式碼。變更 FeedController 類中的 deleteEntryAction 方法,如下所示。
清單 4. FeedController 類中的 deleteEntryAction 方法
public function deleteEntryAction()
{
$filterSession = Zend::registry('fSession');
$username = $filterSession->getRaw('username');
$filterPost = Zend::registry('fPost');
$feedTitle = $filterPost->getRaw('feedTitle');
$channelTitle = $filterPost->getRaw('channelTitle');
$type = $filterPost->getRaw('type');
$db = Zend::registry('db');
$table = 'savedentries';
$where = "username='$username' and feedname='$feedTitle'";
if($type == 'rssFeed')
$where = "$where and channelname='$channelTitle'";
$rowsAffected = $db->delete($table, $where);
$this->_redirect('/feed/viewSavedEntries/');
}
第一段黑體程式碼從 POST 陣列中獲取資料。同樣,也獲得了條目中的 type 欄位。我們可以看到新的 where 子句根據 RSS 提要搜尋比對的 channelname,因為網頁不包含 channelname。
將資料庫變更和新功能新增到視圖中
既然控制器與將傳送給視圖的新資料是一起更新的,那麼我們需要更新該視圖來擷取此資料,並適當地將其展示給使用者。
viewFeeds 視圖
這個視圖嚮已登入使用者展示了已訂閱的提要和 Web 站點。我們需要變更此視圖,以展示使用者當前訂閱的非 RSS Web 站點。所以,讓我們來變更 viewFeeds.php 檔案,如下所示。
清單 5. viewFeeds 視圖
...
echo "".
"$feedTitle
";
}
?>
| Subscribed Web Pages: | Save Entry to Database | Save Full Text |
...
清單 5 中的表顯示了已訂閱的網頁。當我們在每個迴圈遍歷每個條目時,會嵌入了一些包含页面標題、連結和類型(webPage,與 rssFeed 相對)的隱藏輸入項,並且顯示了一個到實際網頁的連結。在這個網頁中,包含了一個帶核取框的用來儲存條目的表單,可透過該核取框支援使用者儲存页面的全文。參見圖 2。
試着儲存 “MySQL Forums :: PHP” 页面條目及其全文,我們稍後就會看到它的樣子。
viewChannel 視圖
更新 viewChannel 視圖,以包含如清單 5 中所示的用於儲存條目的表單。修改 viewChannel 視圖,如下所示。
清單 6. 修改後的 viewChannel 視圖
...
$feedTitle = $this->title;
foreach ($this->rssFeed as $item) {
$entryTitle = $item->title();
$link = $item->link();
echo "
";
}
?>
...
可以看到上麵清單與清單 5 有相似之處,但要注意的是,該隱藏值類型被設定為 rssFeed,而不是 webPage。檢視已更新範例的浏覽器輸出,如圖 3 所示。
viewSavedEntries 視圖
有了與(或不同)全文一起儲存的條目,還需要相應地修改 viewSavedEntries 視圖。為此,請參照下列清單。
清單 7. viewSavedEntries 視圖
...
foreach ($this->entries as $row) {
$link = $row['link'];
$channelTitle = $row['channelname'];
$feedTitle = $row['feedname'];
$entrysaved = '';
if($row['entrysaved'] == 'true')
$entrysaved = 'Full Text';
$title = "$feedTitle";
if($row['channelname'] != ''){
$title = "$title > $channelTitle";
$type = 'rssFeed';
} else {
$type = 'webPage';
}
echo "
";
}
?>
...
將 delete 連結修改成一個帶有 Delete 按鈕的表單。在 foreach 迴圈中,檢視條目是否儲存了全文,如果是,則將 entrysaved 變數設定為 "Full Text "。否則,該變數仍為空。然後設定條目的題及其類型。在表單中,我們嵌入了四個隱藏的輸入項:條目的 feedname、channelname(此值在 webPage 類型時為空)、完整的 link 和 type。隨後我們顯示了到實際網頁的連結、移除條目按鈕以及到已儲存網頁的全文的連結(如果儲存了全文)。請注意,該行為指嚮 /feed/fullText,所以在下一部分中,將在 FeedController 中定義一個新的 fullTextAction 方法。可以在圖 4 中看到修改後的 viewSavedEntries 視圖。
儲存提要條目
有了這個程式碼,使用者就能夠選擇是否要儲存提要條目和網頁的全文,現在惟一餘下的事情是用於抓取網頁的程式碼(使用 Zend_HTTP_Client )。在這一小節中,我們定義了該程式碼和 fullText 行為,該行為用於嚮使用者展示已儲存條目的全文。
使用 Zend_HTTP_Client:saveEntryAction
是時候在 FeedController 類中完成 saveEntryAction 方法了,此方法所對應的行為是透過選中核取框儲存條目的全文來完成的。修改 saveEntryAction 方法,如下所示。
清單 8. FeedController 類中的 saveEntryAction 方法
public function saveEntryAction()
{
$filterSession = Zend::registry('fSession');
$username = $filterSession->getRaw('username');
...
if($saveFullText){
$http = new Zend_Http_Client($channelLink);
$response = $http->get();
if ($response->isSuccessful())
$fullText = $response->getBody();
else{
echo 'Error occurred, full text not saved, '.
'please reload.';
return;
}
}
$db = Zend::registry('db');
...
}
如果核取框指出要儲存條目,則使用 Zend_Http_Client 類抓取它,如上所示。將條目的全文儲存到 fullText 變數中,隨後,該變數在此方法中把全文儲存到資料庫條目中(參見 清單 3)。如果檢索失敗,則將一個錯誤訊息顯示給使用者,使用者可透過重新載入页面來再次嘗試。
檢視已儲存條目的全文
定義 fullTextAction 方法,使用者就能檢視已儲存條目的全文了。定義 FeedController 類中的 fullTextAction 方法,如下所示。
清單 9. FeedController 類中的 fullTextAction 方法
public function fullTextAction()
{
$filterSession = Zend::registry('fSession');
$username = $filterSession->getRaw('username');
$filterGet = Zend::registry('fGet');
$feedTitle = $filterGet->getRaw('feedTitle');
$channelTitle = $filterGet->getRaw('channelTitle');
$db = Zend::registry('db');
$select = $db->select();
$select->from('savedentries', '*');
$select->where("username=?", $username);
$select->where("feedname=?", $feedTitle);
if($channelTitle)
$select->where("channelname=?", $channelTitle);
$sql = $select->__toString();
$fullText = $db->fetchAll($sql);
echo $fullText[0]['entrydata'];
}
從 Session 及 Get 陣列中獲取 username、feedname 和 channelname。隨後搜尋 savedentries 表來獲得比對條目,然後獲取比對條目的全文並顯示給使用者。已儲存的 “MySQL Forums :: PHP” 页面條目的全文如圖 5 所示。
結束語
這樣就完成了提要閱讀器的建立!使用 Zend_HTTP_Client 從網際網路抓取網頁,並將它們儲存到您的提要閱讀器中。您的線上提要閱讀器同樣支援 RSS 提要和網頁。
本係列餘下的部分包含對如何為 Chomp 應用程式加值的介紹。第 5 部分將介紹使用者如何使用 Zend_PDF 模組為已儲存的文章、圖形和搜尋結果建立一個自訂的 PDF。第 6 部分中,將介紹如何使用 Zend_Mail 模組提醒使用者有新的文章發佈。第 7 部分將探討如何搜尋已儲存內容並返回排列好的結果。第 8 部分中,我們將建立自己的混合模組,以新增 Amazon、Flickr 和 Yahoo! 中的資訊。而在第 9 部分中,我們將使用 JavaScript 物件符號為網站新增 Ajax 互動。