王汝山 郭俊亮 張洪川
(銅仁職業(yè)技術(shù)學(xué)院 貴州省銅仁市 554300)
隨著學(xué)習(xí)的不斷深入,在完成網(wǎng)頁、數(shù)據(jù)庫等課程的基礎(chǔ)上,綜合運用Web 表單和MySQL 數(shù)據(jù)庫設(shè)計開發(fā)“許愿墻”階段案例,將所學(xué)內(nèi)容運用到實際案例中,達到學(xué)以致用的目的。
隨著網(wǎng)絡(luò)的普及,人們將許愿墻搬上網(wǎng)絡(luò),通過網(wǎng)頁來管理愿望,這便是網(wǎng)絡(luò)“許愿樹”。
在本項目中,對于許愿墻的具體需求如下:
(1)配置虛擬主機;
(2)MySQL 保存數(shù)據(jù);
(3)提供發(fā)布、展示、修改和刪除功能;
(4)提供紅、綠、藍、黃貼紙;
(5)顯示發(fā)布時間;
(6)分頁展示;
(7)密碼保護可選項。
開發(fā)環(huán)境如下:
操作系統(tǒng):Windows 7 旗艦版
Apache:Apache2.4.41
PHP:PHP7.2.27
MySQL:mysql-8.0.19
2.1.1 創(chuàng)建虛擬機
虛擬主機又稱共享主機,通過虛擬主機可在一臺服務(wù)器上部署多個項目。首先,啟用虛擬主機配置文件。打開Apache 配置文件httpd.conf,找到httpd-vhosts.conf 所在的行,取消注釋即可。
其次,配置虛擬主機文件。打開httpd-vhosts.conf 文件進行配置,其中域名如下:
ServerName www.wishingwall.com
最后,配置本地DNS。打開C 盤下的系統(tǒng)文件hosts[2],添加:127.0.0.1 www.wishingwall.com。重啟Apache 服務(wù)確保配置生效,在主目錄文件中編寫測試文件,添加代碼
2.1.2 目錄結(jié)構(gòu)
項目的開發(fā)除必要的PHP 文件外,頁面的前端展示還需要HTML、CSS、JavaScript 等[3]。本項目包括含目錄common、css、js、view,基本文件function.php、init.php、save.php、index.php,自定義模板文件index.php、add.html、edit.html、password.html。其中的index.php 是項目主頁,主要有展示、刪除愿望及密碼驗證等功能,save.php 主要有添加、修改愿望等功能。
2.1.3 連接數(shù)據(jù)庫
連接數(shù)據(jù)庫時使用MySQLi 擴展,打開PHP 配置文件php.ini,找到mysqli 所在行并取消注釋,重啟Apache 服務(wù)即可生效。
在MySQL 中創(chuàng)建數(shù)據(jù)庫,在init.php 文件中使用mysqli_connect()連接數(shù)據(jù)庫。
2.1.4 準備公共函數(shù)
將公共函數(shù)保存在function.php 文件中。input()函數(shù)根據(jù)$method 為get 或post 確定對應(yīng)的超全局變量,根據(jù)$type 的值返回對應(yīng)類型的數(shù)據(jù),例如s 對應(yīng)string,d 對應(yīng)int,a 對應(yīng)數(shù)組,若不存在,使用trigger_error()自定義錯誤。
2.1.5 引入公共文件
為能夠在index.php 和save.php 中使用定義在common 中的init.php 和function.php,使用require 將其引入。
在數(shù)據(jù)庫wish 中創(chuàng)建數(shù)據(jù)表wall,用于保存數(shù)據(jù)。表含有字段id、name、content、time、color、password,數(shù)據(jù)類型分別為int、varchar、varchar、int、varchar、varchar,分別代表id、姓名、內(nèi)容、發(fā)布時間戳、顏色、密碼。其中發(fā)布時間time 使用整型表示,主要用于保存 Unix 時間戳。在命令行使用insert 插入幾條測試數(shù)據(jù)。
2.3.1 查詢顯示所有愿望
在首頁index.php 中使用select 查詢所有愿望貼紙,并使用mysqli_query()執(zhí)行SQL 語句,使用mysqli_fetch_all()取出并顯示所有愿望。
2.3.2 日期格式化
由于表中保存的是Unix 時間戳,為讓其以友好格式顯示,在function.php 中添加format_date()函數(shù),其實現(xiàn)思想是:計算當前時間戳與表中時間戳的差(秒數(shù)),該差值若超過1 天則換算為天數(shù);若不滿一天且超過1 小時則換算為小時數(shù);若不滿1 小時且超過1 分鐘則換算為分鐘數(shù);若不滿1 分鐘且超過1 秒則返回秒數(shù);若不滿1 秒則返回“1 秒”。
其中$format 數(shù)組的鍵為對應(yīng)單位時間內(nèi)的秒數(shù),例如1 天為60*60*24 秒,即86400 秒。為以良好的格式顯示貼紙,可將已取出的數(shù)據(jù)輸出到指定的index.html 模板中。
2.3.3 HTML 模板
打開index.html 文件,依次遍歷取出的$data 數(shù)組并顯示。對于name 和content 字段,由于是用戶輸入數(shù)據(jù),使用htmlspecialchars()函數(shù)進行轉(zhuǎn)義[4];time 字段是自動獲取的系統(tǒng)時間,無需轉(zhuǎn)義,使用format_date()和date()進行格式化輸出;color由單選按鈕提供,也無需轉(zhuǎn)義。
2.4.1 原理
當表中的數(shù)據(jù)越來越多時,頁面無法將其全部顯示,為防止數(shù)據(jù)量過大,可使用分頁功能。分頁功能又分為“假分頁”和“真分頁”。所謂“假分頁”是指一次性查詢出全部數(shù)據(jù),顯示時依次取出部分數(shù)據(jù)?!罢娣猪摗笔侵覆樵儠r限定查詢數(shù)量,將查詢出的數(shù)據(jù)全部顯示[5]。此處利用“真分頁”減輕服務(wù)器負擔(dān)。
MySQL 中的limit 命令用于限定select 命令中記錄的起始位置和數(shù)量。limit 后的第2 個參數(shù)為每次查詢的最大記錄數(shù),第1 個參數(shù)為查詢起始記錄的偏移量。其兩個參數(shù)關(guān)系如下:
第1 個參數(shù) =(頁碼 - 1)*第2 個參數(shù)
由于每頁顯示的最大記錄數(shù)固定,可將第2 個參數(shù)定義為常量,在function.php 中創(chuàng)建函數(shù)返回limit 的兩個參數(shù)。
2.4.2 實現(xiàn)
通過function.php 中的input()函數(shù)確定當前要顯示的頁碼,結(jié)合limit 參數(shù)拼接SQL 語句,通過ORDER 使最新發(fā)布的愿望排在最前面。為防止查詢到空白頁碼,需對流程進行控制,使用header()重定向,并停止腳本執(zhí)行。
2.4.3 分頁導(dǎo)航
實現(xiàn)分頁查詢后,為方便翻頁瀏覽,需提供分頁導(dǎo)航功能,通常包括“首頁”、“上一頁”、“下一頁”、“尾頁”鏈接。首頁的頁碼為1,尾頁的頁碼為最后一頁的頁碼。
使用count(*)獲取總記錄數(shù),總頁數(shù)為總記錄數(shù)/每頁記錄數(shù),若不能整除則向上取整,最小值為1。
打開function.php,將分頁導(dǎo)航代碼封裝到函數(shù)page_html()中,用于返回導(dǎo)航鏈接。其中,若位于首頁時,取消“首頁”和“上一頁”鏈接;若位于“尾頁”時,取消“下一頁”和“尾頁”鏈接。將鏈接輸出到index.html 模板中,通過瀏覽器訪問測試,如圖1所示。
2.5.1 創(chuàng)建表單
使用JS 實現(xiàn)當單擊主頁中的“我要許愿”按鈕時彈出許愿表單,將其保存在add.html 文件中,在HTML 模板文件index.html 使用require 引入即可。
2.5.2 接收并過濾
add 表單會將數(shù)據(jù)提交到save.php 文件,因此在該腳本中使用input()接收變量,同時限制用戶提交數(shù)據(jù)的長度并指定默認值。strlen()函數(shù)對于中、英文字符并不能準確地獲取字符長度,因此需要使用PHP 提供的mb_strlen()函數(shù),使用mb_strimwidth()截取指定寬度的字符串。而該函數(shù)的使用需要在PHP 配置文件中開啟相應(yīng)的擴展,找到mbstring 一行并取消注釋,重啟Apache 服務(wù)即可生效。
2.5.3 保存數(shù)據(jù)
完成對輸入數(shù)據(jù)的過濾后,即可將數(shù)據(jù)保存到數(shù)據(jù)庫中。打開save.php,利用MySQLi 擴展提供的預(yù)處理方式,實現(xiàn)了SQL 語句與數(shù)據(jù)的分離,同時支持批量操作。
PHP 執(zhí)行SQL 的傳統(tǒng)方式是將發(fā)送的數(shù)據(jù)與SQL 語句綁定,每條SQL 都需要經(jīng)過分析、編譯、優(yōu)化,而預(yù)處理方式則是預(yù)先編譯一次用戶提交的SQL 模板,在操作時,直接添加數(shù)據(jù)即可,大大提高了運行效率。保存完畢,使用header()函數(shù)跳轉(zhuǎn)到首頁。
2.6.1 驗證密碼
為防止提交的愿望被隨意修改,在發(fā)布時提供密碼保護可選項。若設(shè)置密碼,則在修改和刪除愿望時需首先驗證密碼。在展示愿望貼紙時,顯示每個愿望的修改鏈接。
單擊超鏈接會為index.php 傳遞愿望id 和當前page 頁碼。打開首頁index.php,使用input()函數(shù)獲取待編輯愿望的id,使用max()確保id 有效。在獲取$id 后,即可根據(jù)$id 判斷是否需要顯示驗證密碼表單。
利用$id 及密碼驗證表單中的密碼即可查詢指定的數(shù)據(jù)記錄是否存在。在首頁index.php 中添加如下代碼:
$checked = isset($_POST['password'])|| empty($edit['password']);
其中的$checked 指明密碼驗證是否成功。當原密碼為空或密碼正確時值為true,密碼不正確時值為false。$tips 保存驗證失敗時的提示信息。為顯示修改表單,在模板中添加如下代碼:
require($checked?'edit':'password').'.html';
圖1:分頁導(dǎo)航
圖2:修改或刪除標記
將index.php 中查詢出結(jié)果集取出,使用函數(shù)mysqli_fetch_assoc()將數(shù)據(jù)保存為關(guān)聯(lián)數(shù)組,并在edit.html 顯示修改愿望表單。
2.6.2 確認更新
save.php 目前只有添加功能,根據(jù)傳遞的id 參數(shù)可以判斷此時是添加還是修改操作。在修改前,同樣需要驗證保護密碼。若數(shù)據(jù)記錄存在且密碼一致,使用預(yù)處理操作修改數(shù)據(jù)記錄。
刪除愿望主要用于發(fā)布者刪除自己的愿望。為防止被別人誤刪,同樣需要進行密碼驗證。添加刪除超鏈接,其中的“action=delete”用于區(qū)分刪除和修改功能,單擊超鏈接會為index.php 傳遞待刪除愿望id 和當前page 頁碼。
當要修改或刪除愿望時,將鼠標移動至愿望貼紙上,即可顯示修改和刪除標記和×,如圖2所示。
本文主要使用Apache+PHP+MySQL 實現(xiàn)“許愿墻”案例。利用Apache 配置虛擬主機,利用MySQL 保存數(shù)據(jù)記錄,使用MySQLi 擴展訪問數(shù)據(jù)庫,實現(xiàn)了Unix 時間戳的友好顯示,實現(xiàn)了分頁顯示功能,為限制修改提供了密碼保護功能。通過該階段性案例,加強了學(xué)生對PHP 基礎(chǔ)知識的理解。