【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


结尾

基础的部分到今天就结束啦,这八天的东西在程序里只能算是冰山一角

虽然很多东西没讲到(例如:错误处理、测试、物件、设计模式),但这些已经足够写出一只有模有样的机器人了!


<<:  【Day15】数据展示元件 - Carousel

>>:  [Day24] - 介绍 Svelte.js 如何使用

[Day 11] 实作 Ktor i18n 机制

以微框架来说,i18n 不是必备的功能,但如果是想要开发面向一般大众的服务,在这个国际化的时代,i1...

2021 Updated CIS-SIR Exam Questions

Want to pass the CIS-SIR exam on your first attem...

[D09] OpenCV 应用范围

我们现在已经知道 OpenCV 可以拿来处理影像,这样的成效又适用在什麽领域? 或是能对生活有什麽帮...

如何正确选择的高防服务?

如何正确选择高防服务呢?首选是高防CDN。那麽它具备哪些优势呢? 高防CDN的优势   CDN即内容...

[CodeIgniter] 隐藏网址中的index.php

新手发文 Codeigniter如果不调整设定,网址中会自带index.php 为了符合MVC架构,...