
日期: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 交互。