iT邦幫忙

2021 iThome 鐵人賽

DAY 19
0
Software Development

用 PHP 打造專屬於自己的 Telegram 聊天機器人吧!系列 第 19

【PHP Telegram Bot】Day19 - 基礎(8):迴圈、Xdebug

當需要重複做類似的事情時,不需要寫很多行重複的程式,用迴圈就能一次執行很多次

迴圈

while

如果符合小括號中的條件,就執行大括號中的程式,並且執行完後再次檢查條件,直到條件不符合時結束

通常在不知道會執行幾次時使用

例如我想把 1000 以內,所有 2 的次方數印出來

$i = 1;
while (2 ** $i < 1000) {
    echo 2 ** $i, "\n";
    $i++;
}

do while

一樣是不知道會執行幾次時使用,但這次是先做大括號中的程式,才檢查小括號的條件

有時候不管有沒有符合條件,都要執行一次程式,這種方式就很好用

$i = 1;
do {
    echo 2 ** $i, "\n";
    $i++;
} while (2 ** $i < 1000);

for

通常是知道執行幾次時使用,for 會稍微複雜一點,有四個區域,A、B、C 都能留空
https://ithelp.ithome.com.tw/upload/images/20210928/201329169ci75jnB80.png

  1. A:把 0 存進變數 $i
  2. B:邏輯運算,結果如果是 true 就執行大括號中的程式,否則結束迴圈
  3. D:執行大括號中的程式
  4. C:D 結束後會先執行 C,將 $i 增加一
  5. B:之後又回到 2.,就這樣周而復始

其實 while 和 for 是通用的,不管是哪種形式兩者都能修改成另一個,這個就交給你自己試試啦

function a($i, $x) {
    echo $x;
    return $i;
}
for (a($i = 0, 'A'); a($i < 3, 'B'); a($i++, 'C')) {
    a($i, 'D');
}
// ABDCBDCBDCB

foreach

這個比較特別一點,通常會跟陣列做搭配,把陣列中的東西一個個取出來處理

它有兩種寫法,就看要不要使用到陣列的 key

$a = ['a' => 'air', 'b' => 'bag', 'c' => 'cat'];

foreach ($a as $key => $value) {
    echo "key: $key, value: $value\n";
}

foreach ($a as $value) {
    echo "value: $value\n";
}

另外,陣列的值可以使用 & 參考 Call By Reference(鍵不行),改寫原本的陣列

$a = ['a' => 'air', 'b' => 'bag', 'c' => 'cat'];
foreach ($a as &$value) {
    $value = strrev($value);
}
print_r($a);
// [a] => ria
// [b] => gab
// [c] => tac

continue、break

上面四種迴圈都擁有這兩個關鍵字

continue 可以直接跳過接下來的程式

function a($i, $x) {
    echo $x;
    return $i;
}
for (a($i = 0, 'A'); a($i < 3, 'B'); a($i++, 'C')) {
    continue;
    a($i, 'D'); // 不會執行
}
// ABCBCBCB

break 可以結束迴圈,但是只有一層

function a($i, $x) {
    echo $x;
    return $i;
}
for (a($i = 0, 'A'); a($i < 3, 'B'); a($i++, 'C')) {
    break;
    a($i, 'D'); // 不會執行
}
// AB

雙重迴圈

如果想在二維陣列中找東西,就會用到雙重迴圈,但是這樣寫是沒辦法跳出兩層迴圈的

$a = [
    ['0', '1', '2'],
    ['a', 'b', 'c'],
    ['air', 'bag', 'cat']
];
foreach ($a as $b) {
    foreach ($b as $value) {
        echo "\n", $value;
        if ($value === 'b') {
            echo ' 找到 b 了';
            break;
        }
    }
}
// 0
// 1
// 2
// a
// b 找到 b 了
// air
// bag
// cat

有個關鍵字 goto 但不建議使用,我有另一個方法:借用函式和 return

function findValueInMatrix($something, $array) {
    foreach ($array as $b) {
        foreach ($b as $value) {
            echo "\n", $value;
            if ($value === $something) {
                echo " 找到 $something 了";
                return true;
            }
        }
    }
    return false;
}
$a = [
    ['0', '1', '2'],
    ['a', 'b', 'c'],
    ['air', 'bag', 'cat']
];
findValueInMatrix('b', $a);
// 0
// 1
// 2
// a
// b 找到 b 了

Xdebug

Xdebug 是 PHP 的除錯工具,它是一個需要自己下載的擴充元件,可以讓你看清楚程式的執行過程,解決一看到迴圈腦袋就當機的問題

首先要安裝 VS Code 的擴充功能,因為我們要在 VS Code 中執行 Xdebug

然後到 Xdebug 的官網,找到安裝的方法

Ubuntu or Linux

sudo apt install php7.4-xdebug

MacOS

pecl install xdebug

如果是 M1 版本,你可能需要使用以下指令

arch -x86_64 sudo pecl install xdebug

Windows

在官網找出 Windows 載點:https://xdebug.org/download

https://ithelp.ithome.com.tw/upload/images/20210928/20132916Bzb91oClS6.png
選擇對應的 PHP 版本,TS 表示是線程安全(Thread Safe)

閉著眼睛按保留
https://ithelp.ithome.com.tw/upload/images/20210928/20132916lz2QM7nZNr.png

下載後放到 ext 資料夾裡
https://ithelp.ithome.com.tw/upload/images/20210928/20132916MOcZDl53xR.png

之後要設定 php.ini,在最底下貼上這段

[Xdebug]
zend_extension = "path-to-Xdebug.dll"

填上路徑(填你自己的)
https://ithelp.ithome.com.tw/upload/images/20210928/20132916gr8Pzk5qzZ.png

最後按儲存就完成啦


使用 Xdebug

先開啟你的程式檔案,然後在你要停止的行號左邊點一下,就會出現一個小紅點
https://ithelp.ithome.com.tw/upload/images/20210928/20132916YznIHr8wNG.png

在 VS Code 左邊有個像這樣的 Icon,找到它並點下去
https://ithelp.ithome.com.tw/upload/images/20210928/201329168EbpM7PDLD.png

按下「建立 launch.json 檔案」,這樣才不用每次都要重選
https://ithelp.ithome.com.tw/upload/images/20210928/20132916MATNRhHgs5.png

之後就會自動建立一個偵錯的設定檔並且開啟,不用理它直接關掉就對了
https://ithelp.ithome.com.tw/upload/images/20210928/20132916BNVs8oSJPj.png

點開選單,選擇「Launch currently open script」,這個是 CLI 模式時的偵錯,另外兩個是給伺服器用的
https://ithelp.ithome.com.tw/upload/images/20210928/20132916FlB264NJ0y.png

按下這個按鈕(或是按 F5)就會開始偵錯你開啟的那個檔案
https://ithelp.ithome.com.tw/upload/images/20210928/20132916iaiCJuVOQ5.png

停在這裡表示還沒開始執行這一行
https://ithelp.ithome.com.tw/upload/images/20210928/20132916fdVqyUou7U.png

左邊可以看到 $i 還沒被賦值
https://ithelp.ithome.com.tw/upload/images/20210928/20132916XtwwQONs6A.png

按下「逐步執行」(或是按 F11)
https://ithelp.ithome.com.tw/upload/images/20210928/201329162nZ8IyBBEA.png

你可以發現 $i 的值變成 0 了,但程式還是在同一行
https://ithelp.ithome.com.tw/upload/images/20210928/20132916hYtrnEqkXL.png

因為這一行會執行兩個步驟,賦值 $i = 0 和檢查 $i < 10

再次按下「逐步執行」(或是按 F11),才會執行 $i < 10


Xdebug 功能

先看這排按鈕,最左邊是讓你能拖動它的
https://ithelp.ithome.com.tw/upload/images/20210928/20132916IFmNE7wTLH.png

從左到右依序是

按鈕 說明
https://ithelp.ithome.com.tw/upload/images/20210928/20132916i5w6oHmEDe.png 繼續執行程式直到下一個斷點,或是程式結束
https://ithelp.ithome.com.tw/upload/images/20210928/20132916s5PCcwFAon.png 執行一步程式,遇到函式就只當做一步,不會跑進函式
https://ithelp.ithome.com.tw/upload/images/20210928/20132916XW3zsnCuN1.png 執行一步程式,會跑進函式
https://ithelp.ithome.com.tw/upload/images/20210928/20132916GFIOde7xhy.png 直接執行到函式結束,會停在函式後的下一步位置
https://ithelp.ithome.com.tw/upload/images/20210928/20132916OaIjg6qF5p.png 重新執行偵錯,從頭開始執行程式
https://ithelp.ithome.com.tw/upload/images/20210928/20132916HwSUCl8u3i.png 中止偵錯,直接停止程式,不再執行

變數 VARIABLES

顯示當前作用域的變數
https://ithelp.ithome.com.tw/upload/images/20210928/20132916UG8bhzoXNk.png

堆疊 CALL STACK

可以讓你看到現在程式的位置,並且可以查看呼叫這個函式的地方
https://ithelp.ithome.com.tw/upload/images/20210928/20132916yzOCKS0pqB.png

監看 WATCH

在這邊可以對變數做簡單的運算,例如我想知道 $i 的二次方是多少
https://ithelp.ithome.com.tw/upload/images/20210928/20132916tniY2nLdrO.png

斷點 BREAKPOINTS

打勾表示你要停下來的地方,在這邊可以看到哪個檔案有斷點,還有斷點在第幾行
https://ithelp.ithome.com.tw/upload/images/20210928/201329162QZb4G003U.png

甚至可以編輯停止的條件
https://ithelp.ithome.com.tw/upload/images/20210928/20132916PRaem5mcIP.png


結尾

基礎的部分到今天就結束啦,這八天的東西在程式裡只能算是冰山一角

雖然很多東西沒講到(例如:錯誤處理、測試、物件、設計模式),但這些已經足夠寫出一隻有模有樣的機器人了!


上一篇
【PHP Telegram Bot】Day18 - 基礎(7):邏輯運算與流程控制
下一篇
【PHP Telegram Bot】Day20 - sendMessage:發送和轉換 Markdown 訊息
系列文
用 PHP 打造專屬於自己的 Telegram 聊天機器人吧!30

尚未有邦友留言

立即登入留言