ajax搭配PHP、MySQL輸出動態下拉式選單
動態下拉式選單似乎是詢問度很高的設計需求,jquery甚至還有許多plugin可以選;不過試用過好幾個plugin都不是很順手,後來想想其實動態下拉式選單並不是多難的東西,於是就花了點時間自己寫,順便也測試自己邏輯夠不夠清楚。
動態下拉式選單的邏輯說穿了很簡單:選定第一層選項後(選項可以用html列或是從資料庫拉),第二層選單會根據第一層選項跳出對應的內容(如果有第三層也是同樣的邏輯,只是資料庫的設計會多一層欄位)。
邏輯了解之後,又要如何用程式表達呢?
1. 假設第一層選單是從資料庫拉,那麼首先就要透過PHP先把第一層選單的項目從資料庫裡撈出來
2. 由jquery取得選取的項目,並用ajax傳到後端負責「打撈」的PHP頁面(假設為deal.php)
3. deal.php取得第一層選項,並把對應的第二層項目撈出來、回傳給ajax
4. 最後,ajax的success:function(res){}再把回傳的第二層項目插入第二層select的option
大功告成!
接下來,在開始準備程式前,首先需要把資料庫準備好。舉例來說,我希望第一層是產品的分類項目,第二層是分類項目下的產品型號,那麼在資料庫就需要先建「分類」與「型號」的欄位,簡單規劃如下:
categories | items |
---|---|
TV | 46″ |
TV | 50″ |
Player | BD |
Player | DVD |
Player | VCD |
資料庫建好之後,就可以開始著手頁面了:
1. 建置html選單:
[pastacode lang=”markup” manual=”%3Cdiv%3E%0A%20%20%20%3Cselect%20id%3D’categories’%3E%0A%20%20%20%20%20%20%3Coption%3E%E9%81%B8%E6%93%87%E7%B3%BB%E5%88%97%3C%2Foption%3E%0A%20%20%20%3C%2Fselect%3E%0A%3C%2Fdiv%3E%0A%3Cdiv%3E%0A%20%20%20%3Cselect%20id%3D’items’%3E%0A%20%20%20%20%20%20%3Coption%3E%E9%81%B8%E6%93%87%E7%94%A2%E5%93%81%3C%2Foption%3E%0A%20%20%20%3C%2Fselect%3E%0A%3C%2Fdiv%3E” message=”” highlight=”” provider=”manual”/]
2. 插入PHP語法把categories的項目從資料庫裡撈出來:
[pastacode lang=”php” manual=”%3Cdiv%3E%0A%20%20%20%3Cselect%20id%3D’categories’%3E%0A%20%20%20%20%20%20%3Coption%3E%E9%81%B8%E6%93%87%E7%B3%BB%E5%88%97%3C%2Foption%3E%0A%3C%3F%0A%24sql%20%3D%20%22SELECT%20DISTINCT%20categories%20FROM%20%E8%A1%A8%E6%A0%BC%E5%90%8D%E7%A8%B1%22%3B%2F%2FDISTINCT%E5%8F%AF%E9%81%B8%E5%87%BA%E6%AC%84%E4%BD%8D%E4%B8%AD%E5%85%B7%E6%9C%89%E4%B8%8D%E5%90%8C%E5%90%8D%E7%A8%B1%E7%9A%84%E8%B3%87%E6%96%99%EF%BC%8C%E6%9C%AC%E4%BE%8B%E4%B8%AD%E6%9C%83%E6%8C%91%E5%87%BATV%E8%88%87Player%0A%24result%20%3D%20mysqli_query(%24link%2C%20%24sql)%20or%20die(%22%E8%B3%87%E6%96%99%E9%81%B8%E5%8F%96%E9%8C%AF%E8%AA%A4%EF%BC%81%22.mysqli_error(%24link))%3B%0Awhile(%24data%3Dmysqli_fetch_assoc(%24result))%7B%0A%3F%3E%0A%20%20%20%20%20%20%3Coption%20value%3D%22%3C%3Fecho%20%24data%5B’categories’%5D%3B%3F%3E%22%3E%3C%3Fecho%20%24data%5B’categories’%5D%3B%3F%3E%3C%2Foption%3E%0A%3C%3F%0A%7D%0A%3F%3E%0A%20%20%20%3C%2Fselect%3E%0A%3C%2Fdiv%3E%0A%3Cdiv%3E%0A%20%20%20%3Cselect%20id%3D’items’%3E%0A%20%20%20%20%20%20%3Coption%3E%E9%81%B8%E6%93%87%E7%94%A2%E5%93%81%3C%2Foption%3E%0A%20%20%20%3C%2Fselect%3E%0A%3C%2Fdiv%3E” message=”” highlight=”” provider=”manual”/]
3. 抓取被選取的選項,透過ajax丟到後端deal.php:
[pastacode lang=”javascript” manual=”%24(document).on(‘change’%2C%20’%23categories’%2C%20function()%7B%0A%20%20%20var%20categories%20%3D%20%24(‘%23categories%20%3Aselected’).val()%3B%2F%2F%E6%B3%A8%E6%84%8F%3Aselected%E5%89%8D%E9%9D%A2%E6%9C%89%E5%80%8B%E7%A9%BA%E6%A0%BC%EF%BC%81%0A%20%20%20%24.ajax(%7B%0A%20%20%20%20%20%20url%3A%22deal.php%22%2C%09%09%09%09%0A%20%20%20%20%20%20method%3A%22POST%22%2C%0A%20%20%20%20%20%20data%3A%7B%0A%20%20%20%20%20%20%20%20%20categories%3Acategories%0A%20%20%20%20%20%20%7D%2C%09%09%09%09%09%0A%20%20%20%20%20%20success%3Afunction(res)%7B%09%09%09%09%09%0A%20%20%20%20%20%20%20%20%20%2F%2F%E8%99%95%E7%90%86%E5%9B%9E%E5%90%90%E7%9A%84%E8%B3%87%E6%96%99%0A%20%20%20%20%20%20%7D%0A%20%20%20%7D)%2F%2Fend%20ajax%0A%7D)%3B” message=”” highlight=”” provider=”manual”/]
4. deal.php取得分類選項,從資料庫裡撈對應的型號出來:
[pastacode lang=”php” manual=”%24categories%20%3D%20%24_POST%5B’categories’%5D%3B%0A%24sql%20%3D%20%22SELECT%20items%20FROM%20%E8%B3%87%E6%96%99%E8%A1%A8%E5%90%8D%E7%A8%B1%20WHERE%20categories%20%3D%20’%24categories’%22%3B%0A%24result%20%3D%20mysqli_query(%24link%2C%20%24sql)%20or%20die(%22%E5%8F%96%E5%87%BA%E8%B3%87%E6%96%99%E5%A4%B1%E6%95%97%EF%BC%81%22.mysqli_error(%24link))%3B%0A%24res%20%3D%20%22%22%3B%2F%2F%E6%8A%8A%E6%BA%96%E5%82%99%E5%9B%9E%E5%82%B3%E7%9A%84%E8%AE%8A%E6%95%B8res%E6%BA%96%E5%82%99%E5%A5%BD%0Awhile(%24data%3Dmysqli_fetch_assoc(%24result))%7B%0A%20%20%20%24res%20.%3D%20%22%0A%20%20%20%20%20%20%3Coption%20value%3D’%7B%24data%5B%22items%22%5D%7D’%3E%7B%24data%5B’items’%5D%7D%3C%2Foption%3E%0A%20%20%20%22%3B%2F%2F%E5%B0%87%E5%B0%8D%E6%87%89%E7%9A%84%E5%9E%8B%E8%99%9F%E9%A0%85%E7%9B%AE%E9%81%9E%E8%BF%B4%E5%88%97%E5%87%BA%0A%7D%3B%0Aecho%20%24res%3B%2F%2F%E5%B0%87%E5%9E%8B%E8%99%9F%E9%A0%85%E7%9B%AE%E4%B8%9F%E5%9B%9E%E7%B5%A6ajax” message=”deal.php” highlight=”” provider=”manual”/]
5. 最後一個步驟,將deal.php吐回的項目列表塞回DOM的select裡面:
[pastacode lang=”javascript” manual=”%24(document).on(‘change’%2C%20’%23categories’%2C%20function()%7B%0A%20%20%20var%20categories%20%3D%20%24(‘%23categories%20%3Aselected’).val()%3B%0A%20%20%20%24.ajax(%7B%0A%20%20%20%20%20%20url%3A%22deal.php%22%2C%09%09%09%09%0A%20%20%20%20%20%20method%3A%22POST%22%2C%0A%20%20%20%20%20%20data%3A%7B%0A%20%20%20%20%20%20%20%20%20categories%3Acategories%0A%20%20%20%20%20%20%7D%2C%09%09%09%09%09%0A%20%20%20%20%20%20success%3Afunction(res)%7B%09%09%09%09%09%0A%20%20%20%20%20%20%20%20%20%24(‘%23items’).html(res)%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%7D)%2F%2Fend%20ajax%0A%7D)%3B” message=”” highlight=”” provider=”manual”/]
結束收工!
實際跑過整個流程之後,是不是發現動態下拉式選單真的不複雜,只是若要到三層、四層……,資料庫的設計就要更多欄位而已,說不定反倒是把所有資料輸入資料庫欄位還比較花時間咧!
categories POST給deal.php 沒有值 但是我把deal.php的$sql where 這邊的$categories改成寫死
其實回傳有值的 只是不清楚為什麼$categories沒有值
Hi Steven,
感謝您的分享,讓小弟終於寫出三層動態下拉DB選單
但是小弟遇到一個問題
若是資料都不對等,例如像以下這樣
country categories item
US TV 55
US TV 40
US
JP player VCD
JP TV
UN
像這樣的資料
小弟在第一層選到UN時
第二層會變動,而且只會出現下拉空白
可是第三層卻不會動(還是請選擇)
請問要怎麼去判斷若只有一層資料
第二及第三層都會一起變動只出現下拉空白呢
煩請您指導,謝謝
Hi Peterrabbit,
我的初步想法是從ajax那一段程式去判斷php有沒有回傳值,來決定第二層與第三層的下拉選項,不過最近沒有時間測試,等三月之後的淡季會來試試看!若您有時間測試也歡迎來回覆測試狀況,謝謝喔!
感謝你的這篇備忘,獲益良多!!
ps: 步驟2的 “while($data=mysqli_fetch_assoc($result){” 在 $result 後漏了一個 “)”
Hi Garfield,
感謝回饋與除蟲,程式碼已修正,謝謝!
請問有範例的程式碼嗎?