第 04 章 - 迴圈與陣列初探
上次更新日期 2020/04/05
我們在第二章講到複選,那個複選的勾選項目是變動的,並非固定值。這個就得要使用陣列配合迴圈來處理! 否則,很不容易抓出需要的項目!另外,有時候,我們也很容易在網頁上面應用許多迴圈,產生我們所需要的環境! 例如網頁配色等等~這一章,就讓我們來嘗試玩一玩迴圈與陣列吧!
學習目標:
- 利用 for 迴圈
- 利用 while 迴圈
- 了解陣列在網頁上的應用
- 了解陣列的排序
4.1: 使用 for 迴圈
迴圈很有趣啊!它可以將需要重複進行的動作,透過小小的元件控制,就能夠讓我們的系統幫我們『重複』進行多次! 這樣對於規律的行為,就會變得很有幫助!一般來說, for 迴圈的語法是這樣的:
<?php for ( $i = 1; $i <= 10; $i++ ) { echo $i ; } for ( 初始值; 結束條件; 步階 ) { 在此條件底下要被執行的指令; } ?>
最重要的就是起始值、結束值與每個條件的步階 (step) 設定!舉例來說,像我們繳交作業的網頁那樣,如果你需要針對『學號』的資料來排列, 然後共有 50 個學號時,可以這樣嘗試看看:
- 先建立一個新檔案,檔名就稱為 /www/php/unit04-1-1.php,後續將程式碼寫入 body 當中 ;
- 檔案最上方需要載入 functions.php 喔!
- 在 ul 裡面塞入一段 PHP 程式碼,程式碼裡面需要有:
- 給予一個變數 $mystart 為 1
- 給予一個變數 $myend 為 50
- 使用 for 迴圈,規範變數 $i 從 $mystart 到 $myend 為止
- for 迴圈內部只要顯示『 <li>4070C0${i}</li> 』之類的資訊即可
- 最終將程式碼寫入到後面的 pre 當中,以備查驗
- 在 /www/php/index.php 加入這個程式的連結
很簡單的就將我們需要的學號清單列出來了!這就是迴圈的功能!相當簡單又方便!現在,讓我們來思考一下, 早期有一種網頁顏色稱為『網頁安全色 (請看參考資料)』,這種網頁安全色可以讓網頁開發商在進行某些特殊螢幕的開發時, 會有比較好的效果 (顏色會一樣),雖然目前已經不再需要了。所謂的安全色,就是以 51 數值為步階,在 rgb() 函數裡面使用的顏色, 例如底下的顏色:
- rgb(0,0,0)
- rgb(0,0,51)
- rgb(0,51,0)
- rgb(51,0,0)
總數會有 0, 51, 102, 153, 204, 255 六個濃度,rgb 三種顏色各有六種濃度,因此得到 6x6x6=216 種色碼!如果要你手動輸入這些色碼, 那你總會手殘的...此時,透過迴圈來處理即可。先來看看,如果要列出 rgb(0,0,0) 到 rgb(0,0,255) 時,要怎麼做?透過表格喔!
- 先建立一個新檔案,檔名就稱為 /www/php/unit04-1-2.php,後續將程式碼寫入 body 當中 ;
- 檔案最上方需要載入 functions.php 喔!
- 建立一個表格,以及一個表格橫列 (tr),在橫列裡面建立一隻 PHP 程式
- 使用 for 迴圈,裡面的 $i 值從 0 到 5 喔,步階就給 1 吧!
- 先由 $i * 51 計算出 $b1 的變數,然後將變數傳給表格欄位內的色碼塊
- 在迴圈內輸出『 <td tyle='background-color: rgb(0,0,$b1)'>rgb(0,0,$b1)</td> 』
- 最終將程式碼寫入到後面的 pre 當中,以備查驗
- 在 /www/php/index.php 加入這個程式的連結
唉啊~上面的表格內容實在很糟糕!基本上,我們可以使用所謂的『對比色』來處理背景與前景的顏色~上面只有背景 (background-color) 而已, 如果想要加上前景 (color) 時,怎麼設計呢?基本上,如果是 rgb(0,0,0),對比色就是 rgb(255,255,255),也就是三種顏色分別使用 255 去減它, 就會得到該顏色的對比色~因此,請用對比色的概念重新處理上面的範例:
- 直接取出 /www/php/unit04-1-2.php 的內容來修改
- 在 PHP 的程式碼裡面,增加 color 的 style ,內部的 rgb 都使用 255 去減。
- 最終將程式碼寫入到後面的 pre 當中,以備查驗
- 在 /www/php/index.php 加入這個程式的連結
接下來,我們在上面的基礎上,再加一層迴圈,這次迴圈先使用 RGB 的 G 顏色,亦即 rgb(0,0,0)... rgb(0,51,0)...的格式。 那我們知道每一橫列都需要 tr 才對~所以,在新的一層資料中,就得要將第二組顏色另外使用一個變數來處理,假設為 $j 來處置好了!
- 將 /www/php/unit04-1-2.php 另存新檔成為 unit04-1-4.php,然後進行修改
- 先將原本的 PHP 程式碼圈選之後,按下 [tab] 按鈕往後推一格
- 在原本的 PHP 程式碼前,加上一個 for 迴圈,使用 $j 為變數,且與 $i 相同,都從 0 到 5,步階為 1
- 增加一個變數名 $g1,其內容為 51*$j 計算出 Green 的顏色濃度
- 增加一個變數名 $g2,其內容為 255-$g1,計算出 Green 的對比色濃度
- 修改輸出的結果,讓 rgb 內的資料成為含有 $g1 與 $g2 的資料格式
- 最終將程式碼寫入到後面的 pre 當中,以備查驗
- 在 /www/php/index.php 加入這個程式的連結
既然兩層色碼的問題都解決了,那麼 3 層網頁安全色的色碼也就能夠順利處理掉才對!
- 將 /www/php/unit04-1-4.php 另存新檔成為 unit04-1-5.php,然後進行修改
- 先將原本的 PHP 程式碼圈選之後,按下 [tab] 按鈕往後推一格
- 在原本的 PHP 程式碼前,加上一個 for 迴圈,使用 $k 為變數,且與 $i, $j 相同,都從 0 到 5,步階為 1
- 增加一個變數名 $r1,其內容為 51*$k 計算出 Red 的顏色濃度
- 增加一個變數名 $r2,其內容為 255-$r1,計算出 Red 的對比色濃度
- 修改輸出的結果,讓 rgb 內的資料成為含有 $g1 與 $g2 的資料格式
- 最終將程式碼寫入到後面的 pre 當中,以備查驗
- 在 /www/php/index.php 加入這個程式的連結
簡簡單單的幾個式子,就可以將你需要的整個網頁安全色的 216 個顏色通通顯示出來!而且還能夠使用 table 的樣式來展示, 這樣就會相當愉快!立刻就能處理妥當了!這也是為啥連寫網頁也是需要一些基礎程式設計的能力,會讓你減少很多不必要的工作!
4.2: 使用 while 迴圈
有時候,我們可能會透過迴圈進行某件行為,而這個行為得要透過某個事件才能夠截止。這種情境並不是『固定次數的迴圈』樣式, 因此,使用 for 迴圈會怪怪的。你當然可以持續使用 for 迴圈,然後在程式碼內加上判斷式,不過,那樣的語法不夠直覺,會怪怪的。 所以,此時可能就得要用到 while 迴圈了!while 迴圈的預設語法是這樣的:
<?php while (某個條件發生時才進行) { 在此條件下會被觸發的程式碼; } ?>
來玩個假設,如果你想要從 1~100 之間抽出一個幸運數字,這個幸運數字必須要是 30 才行,那抽數字會抽幾次呢? 讓我們來測試一下:
- 先建立一個新檔案,檔名就稱為 /www/php/unit04-2-1.php,後續將程式碼寫入 body 當中 ;
- 檔案最上方需要載入 functions.php 喔!
- 建立一個 PHP 的程式碼,並且先給予一個 $i 的變數,假設為 0 整數好了;
- 設定一個名為 $myluck 的變數,內容先指定為 0 好了
- 設計 while 迴圈,當 $myluck 為 30 時,就給予停止
- 在當中的程式碼: (1) $i=$i+1; (2) $mylock = rand(1,100); (3)清單類型的顯示次數與 $myluck 數值
- 最終將程式碼寫入到後面的 pre 當中,以備查驗
- 在 /www/php/index.php 加入這個程式的連結
上面的範例是計算抽到 30 這個數值的次數,那能不能轉過來,例如很多時候都要有抽籤的活動,能不能抽出 3 個幸運觀眾!? 就是抽三次,從一定的範圍內抽出來~那應該是可以的:
- 先建立一個新檔案,檔名就稱為 /www/php/unit04-2-2.php,後續將程式碼寫入 body 當中 ;
- 檔案最上方需要載入 functions.php 喔!
- 先在 body 當中顯示一個表單,此表單要傳送給自己操作,使用 post 的方法,表單名稱就寫 myform
- 表單內建立三個變數,第一個是 mystart 變數,使用 text 類型,第二個是 myend 變數,使用 text 類型, 第三個則是 mynu 變數,同樣使用 text 類型。它們分別是開始、結束與個數的相關資訊。
- 建立一個 submit 的按鈕,可以填寫『開始抽獎』之類的文字說明
- 這個部份完成之後的半成品,應該是有點類似這樣:
- 開始從表單將資料抓出來!在最上方使用 $_REQUEST 將三個變數嘗試抓出來!
- 先建立一個變數,名為 $myact ,預設內容為 no
- 使用條件判斷,若存在 $_REQUEST['mystart'] 時,就抓下 $mystart, $myend, $mynu 變數,並將 $myact 設定為 yes。
- 撰寫完畢之後,你可以使用 echo 的方式,將上面的變數顯示到網頁上,並且執行一次上傳的動作看看結果如何。
- (option)可以的話,使用條件判斷,將三個 input 的上傳值,重新填回表單中 (value="")
- 最後,就開始使用 rand 來抽獎咯!
- 使用條件判斷,當 $myact 為 yes 時,才進行所有動作:
- 顯示開始抽獎的 h2 標題
- 顯示 ul 清單
- 設定 $i 為 0
- 使用 while 迴圈,條件有兩個,兩個都成立才會跑。一個是 $i 要小於 $mynu,另一個則是防呆用, $i 要小於 100 !這兩個條件同時成立 (&&) 時, 就進入迴圈階段
- 讓 $i 長大 ($i++ 或 $i=$i+1)
- 顯示清單項目,類似:『echo "<li>" . (rand($mystart, $myend)) . "</li>";』
- 脫離迴圈之後,最後顯示 /ul 的清單結束。
- 最終將程式碼寫入到後面的 pre 當中,以備查驗
- 在 /www/php/index.php 加入這個程式的連結
為了避免使用者惡搞,通常我們在設計程式的時候,都會預先想到一些『防呆』的機制。以上面的設計來說,當使用者輸入要找尋 10000 個使用者資訊時, 我們就只會輸出前面 100 筆,因為程式有防呆!擔心使用者來惡搞啊!這些都是需要考慮的!避免到時候系統被亂用喔!
4.3: 使用陣列功能
以上面的範例來說,我要找出幾筆數據,那如果這幾筆數據有重複怎麼辦?例如,抽獎的結果,兩個人重複怎麼辦?另外, 一般來說,人名或者是學號,可能不會重複啊~那怎麼用 rand 來抽?有問題啊!此外,我們第二章提到的複選,不是也有一堆資料要輸出? 如果不使用陣列,恐怕還很難輸出正確的資訊哩!
- 陣列的使用
基本上,就如同之前說得,陣列跟我們國中時候學的 f(x) = y 有關,在 PHP 的情境下,所謂 f() 就是陣列, x 就是索引值,y 就是每個索引對應的內容。 一般來說,索引值通常是從 0 開始編號,不過,索引也能夠使用字串來代替!這相當有趣!那陣列如何設定呢?使用底下的語法就可以設定一維陣列:
// 底下的方式會產生 $array[0], $array[1] 與 $array[2] 的陣列 $array[] = 1; $array[] = 2; $array[] = 3; // 底下的方式直接給予索引值 $array[1] = 1; $array[2] = 2; $array[3] = 3;
也就是說,索引不見得一定要從 0 開始!不過,最好還是從 0 開始編號 (如果是數值的話),這樣在處理上面比較好解決。 現在,讓我們回到第二章點餐的那個習題,搞一下如何使用簡易的陣列吧!
- 先建立一個新檔案,檔名就稱為 /www/php/unit04-3-1.php,後續將程式碼寫入 body 當中 ;
- 檔案最上方需要載入 functions.php 喔!
- 建立名為 $myfood 的 PHP 陣列,然後設定至少 5 個以上的餐點名稱;
- 建立一個表單,表單使用 post 方法,傳送給自己處理,名稱就定為 myform
- 在表單內建立一個 for 或 while 迴圈皆可,將所有的陣列內容列出,注意, checkbox 需要有 value 以及 name 喔! name 可以都指定為 myfood[] 即可。
- 增加一個 submit 的送出按鈕
- 最終將程式碼寫入到後面的 pre 當中,以備查驗
- 在 /www/php/index.php 加入這個程式的連結
因為在底下的資料是重複輸出的 (input 的部份),所以未來要修改內容時,只要處理最上方的陣列內容,一切就搞定了! 相當舒服啊~那麼,如何將資料上傳後讀出呢?也是 OK 的!
- 將 /www/php/unit04-3-1.php 另存新檔成為 unit04-3-2.php,然後進行修改
- 在 $myfood 陣列之後增加一個名為 $myact 的變數,預設值為 no ,作為是否運作資料下載的依據
- 提供一個條件判斷,若有 myfood 的上傳變數存在時,就進行
- 將 $myact 設定為 yes;
- 使用 $myselect 變數,設定內容為取得 myfood 的資料。
- 在表單後面增加一個條件判斷,當確認 $myact 為 yes 時,就進行
- 顯示標題『你的選擇』
- 顯示 ol 項目
- 設定迴圈,迴圈設定為 $i 從 0 到 $i 小於 $myselect 陣列個數,步階為 1
- 迴圈內執行顯示清單,清單項目為 $myselect[$i] 這樣的內容
- 最終顯示 /ol 結束即可。
- 最終將程式碼寫入到後面的 pre 當中,以備查驗
- 在 /www/php/index.php 加入這個程式的連結
上面的問題是,並沒有顯示你之前勾選的複選項目,這樣我無法確認之前是否勾選該項目啊~那可以在 checkbox 的顯示過程中, 增加判斷是否有該項目的功能嘛?應該也是可以的:
- 將 /www/php/unit04-3-2.php 另存新檔成為 unit04-3-3.php,然後進行修改
- 在表單的 for 迴圈內,新增一個變數,名稱為 $mycheck,預設值為空值;
- 增加一個 for 迴圈,使用 $j 變數,預設為 0 到小於 $myselect 陣列個數,步階為 1
- 在迴圈內判斷,若 $myfood[$i] 相等於 $myselect[$j] 時,就將 $mycheck 重新設定為 "checked='checked'" 這樣
- 在輸出 input 的程式碼中,增加 $mycheck 在 input 標記內
- 最終將程式碼寫入到後面的 pre 當中,以備查驗
- 在 /www/php/index.php 加入這個程式的連結
如果今天你是想要從幾個項目中選出一個來食用呢?這個時候,你就可以透過亂數隨機的方式來產生唯一的項目了!
- 將 /www/php/unit04-3-3.php 另存新檔成為 unit04-3-4.php,然後進行修改
- 將原本你的選擇的部份修改掉,增加一變數,假設為 $i 好了,內容為 0 到 myseleclt 陣列數少 1 的範圍 (0,個數-1)
- 秀出 $myselect[$i] 即可!
- 最終將程式碼寫入到後面的 pre 當中,以備查驗
- 在 /www/php/index.php 加入這個程式的連結
其實意思很簡單,就是你勾選的項目有幾個,從那幾個挑選一個出來的意思!就這麼簡單喔! ^_^!
4.4: 使用 PHP 陣列排序
大略知道怎麼設計迴圈與陣列之後,再來就是需要進行一些有趣的設計了!在很多場合,我們都會推派代表。 代表的名單都有個號碼,那麼,如何抽出這些號碼呢?可以透過 4-2-2 的範例來修改!畢竟那個也是抽出幸運數字! 概念上差不多!另外,任何時刻考慮使用者可能是個白痴或者想要故意玩你的高手,都是個好習慣!因此,我們同樣設計一個防呆。
- 使用 break 離開迴圈
我們可能會使用到 for 迴圈,但是 for 迴圈裡面並不像 while 可以透過條件控制來離開迴圈,因此,這時我們就要主動加入一個 break 的語法, 強迫跳出迴圈!基本語法是這樣的:
<?php for ( ... ) { ...; break; } ?>
當程式碼遇到 break 時,就會離開 for 或者是某個迴圈,而直接跳脫出去!可以避免被迴圈搞死喔!
- 將 /www/php/unit04-2-2.php 另存新檔成為 unit04-4-1.php,然後進行修改
- 將表單的部份,號碼的部份改為開始座號、結束座號、抽出個數等等,其餘不變!
- 在按下送出之後,來到檔案的最上方的 PHP 部份,原本的項目為直接丟入 rand 的亂數結果,這次, 我們透過一個名為 $myok[] 陣列,將所有的抽籤名單通通放入這個陣列裡面。因為人數是固定的, 所以 (1)使用 for 迴圈,規範次數由 0 到 $mynu - 1 次; (2)將抽籤的結果帶入陣列內 (3)如果次數超過 100 次, 就予以離開 (請用上 break 喔!)。
- 最終判斷有 $myact 時,就直接以 for 迴圈,將抽籤到的次數貼到螢幕上即可,這部份與例題 4-2-2 相同!
- 最終將程式碼寫入到後面的 pre 當中,以備查驗
- 在 /www/php/index.php 加入這個程式的連結
- 用陣列在子迴圈裡面進行比對與排除
上面這個案例基本上跟 4-2-2 完全一樣!只是帶入了陣列的用法而已~沒什麼了不起。但是,如果你重複執行幾次這個腳本, 會發現到,慘了!怎麼名單會重複!尤其越少座號時,名單的重複情況會越嚴重!那有沒有辦法克服呢? 可以的!就透過子迴圈 (雙重迴圈) 來處理即可。但是,子迴圈總是需要有個比對的基準,那就是剛剛紀錄下來的陣列的功能了!
- 將 /www/php/unit04-4-1.php 另存新檔成為 unit04-4-2.php,然後進行修改
- 在抽籤的最外層 for 迴圈,重新更改一下相關的項目:
- A. 先設定好,若次數大於 100 次時,就脫離外部迴圈
- B. 設定好一個變數,假設名為 $mygo,目的是用在底下的 while 迴圈當中
- C. 設定 while 迴圈,條件為 $mygo 為 yes 就進行內部的迴圈條件
- C.1. 先設定好一個變數,假設為 $mytemp 好了,這個變數的目的是為了抽籤!
- C.2. 再來開始測試,如果 $myok 的次數不是 0 ,就進行 C.3 的動作,否則就進行 C.4 的動作
- C.3.a. 設定一個判斷條件的變數,假定為 $mycheck,而且預設值為 yes,亦即沒有與既有的名單重複的意思
- C.3.b. 設定內部迴圈,條件使用 for 迴圈,透過 $j=0 到 $j<count($myok) 來判斷是否要處理
- C.3.c. 如果 $mytemp 有等於任何一個 $myok[$j] 時,就設定 $mycheck 為 no
- C.3.d. 離開 for 迴圈之後,增加一個條件判斷式,(1)如果 $mycheck 為 yes 時,就設定 $myok[$j] 為 $mytemp, (2)同時設定 mygo 為 no,並且 (3)break 掉這次的 while 迴圈
- C.4. 因為還沒有設定過 $myok,所以設定 $myok[0] 為 $mytemp 囉!
- 最終將程式碼寫入到後面的 pre 當中,以備查驗
- 在 /www/php/index.php 加入這個程式的連結
- 陣列的排序
若程式語言沒有提供陣列的排序時,過去有所謂的泡沫排序法、插入排序法等等,那都需要一些程式碼的運作,才有辦法將陣列的內容進行排序。 不過,PHP 已經有提供陣列的排序功能,簡單排序功能有這些函數:
- sort($array):可以進行數字的增加排序、或者是文字的遞增排序
- rsort($array):可以進行數字或文字的遞減排序
我們還沒有講到陣列的索引 (index),所以這裡先知道 sort 與 rsort 即可!現在,讓我們修改上面的案例,增加排序的行為,讓最終輸出時,可以將名單排列整齊
- 將 /www/php/unit04-4-2.php 另存新檔成為 unit04-4-3.php,然後進行修改
- 只要將最後的 $myok 的結果,丟改 sort 處理即可。
- 最終將程式碼寫入到後面的 pre 當中,以備查驗
- 在 /www/php/index.php 加入這個程式的連結
當然啦,須不需要進行排序是因人而異,畢竟有時候我們需要抽出的是有幸運順序的情況,那就不能用座號排序囉! 如果只是要抽出一群人,並沒有比重的原因,那用這方案,還挺方便的! ^_^
4.5: 小小挑戰題
以迴圈的方法列出九九乘法表的樣式,基本上,你可以列出 2~9 共 8 個方塊,這 8 個方塊格式可以固定。 在每個方塊裡面再以表格的方式條列出 99 乘法表的乘法結果,就可以得到還不錯的效果了。檔名請設定為 unit04-5-1.php, 做完請在 PHP 首頁增加一個連結喔!
4.6: 參考資料
- Wiki 的網頁安全色說明:https://zh.wikipedia.org/wiki/网页颜色
- PHP 的陣列排序函數:https://www.w3schools.com/php/php_arrays_sort.asp