Learning Objectives
- 用 <?php ?> 標籤標出 PHP 程式,說明純 PHP 檔案為什麼省略結尾的 ?>
- 用 <?= ?> 與 if: … endif; 替代語法,把 PHP 與 HTML 混寫在同一個檔案
- 說明敘述以分號結束、大括號組成區塊,並使用三種註解
- 比較 echo 與 print,說出變數名稱區分大小寫、函式名稱與關鍵字不區分
- 看懂 Parse error 的訊息,知道錯誤的行號可能在真正出錯處的下一行
先把規則學好,錯誤訊息就看得懂
每一種程式語言都有自己的語法(syntax):程式要怎麼開始、敘述怎麼結束、註解怎麼寫。 語法錯一個字元,PHP 就完全不執行這個檔案,只給你一行錯誤訊息。
這一課整理 PHP 最基本的寫法規則:
- PHP 程式寫在
<?php和?>之間,外面的內容原樣輸出 - 敘述以分號
;結束,大括號{ }把好幾個敘述組成區塊 - 三種註解、兩種輸出方式(
echo與print) - 哪些名稱區分大小寫、哪些不區分
最後學會讀 Parse error(語法錯誤)的訊息,知道該去哪一行找問題。
PHP 標籤
PHP 檔案裡,只有 <?php 和 ?> 之間的內容會被當成程式執行;標籤外面的內容(通常是 HTML)原樣輸出。
<p>這一行是 HTML,原樣輸出</p>
<?php echo '這一段由 PHP 輸出'; ?>
<p>又回到 HTML</p>
幾個規則:
| 寫法 | 說明 |
|---|---|
<?php … ?> |
標準的 PHP 標籤;<?php 後面一定要有空白或換行 |
<?= $x ?> |
短輸出標籤,等於 <?php echo $x; ?>,在 HTML 裡插入一個值時最好用 |
<? … ?> |
舊式短標籤,可能被伺服器設定(short_open_tag)關閉,不要使用 |
純 PHP 的檔案不寫結尾的 ?>。 如果檔案最後寫了 ?>,後面不小心多了一個空白或換行,那個空白也會被輸出;
這會讓之後要送出的 HTTP 標頭(轉址、Cookie)失敗,出現「headers already sent」的警告(第 11、16 課)。
官方手冊建議:檔案以 PHP 程式結尾時,省略結尾標籤。只有檔案後面還有 HTML 時才需要 ?>。
還有兩個細節:
?>會「吃掉」緊接在它後面的一個換行,所以<?php echo 'A'; ?>下一行的文字會接在 A 的後面- 結尾標籤本身就代表敘述結束,所以
?>前面最後一個敘述可以不寫分號(但習慣上還是寫)
PHP 與 HTML 混寫
PHP 最常見的用法是一個檔案裡 HTML 與 PHP 交錯:大部分是固定的 HTML,在需要變化的地方插入值。
需要「依條件輸出不同的 HTML」時,用 if 的替代語法:把 { 換成 :,把 } 換成 endif;,
每一段都放在自己的 <?php ?> 裡,中間夾著 HTML。
<?php if ($isOpen): ?>
<p>報名中</p>
<?php else: ?>
<p>報名已截止</p>
<?php endif; ?>
和大括號的寫法意思相同,只是在一大段 HTML 裡比較好讀,不會看到一個孤零零的 <?php } ?> 不知道對應哪裡。
for、foreach、while、switch 也有替代語法(endfor;、endforeach;、endwhile;、endswitch;)。
if 的完整用法在第 05 課,這裡先看它怎麼和 HTML 搭配。
HTML 原樣輸出,PHP 填入值
注意動畫只會停在 PHP 程式的那幾行,HTML 是直接輸出的。$isOpen 是 true,所以第 9 行的 HTML 會輸出、第 11 行的「報名已截止」被跳過,動畫不會停在第 11 行。看最後的輸出:PHP 標籤全部消失,只剩下 HTML。
敘述、區塊與註解
敘述(statement)是程式的一個步驟,例如一次指派、一次輸出。PHP 的每個敘述都以分號 ; 結束:
- 一行可以寫好幾個敘述:
$a = 3; $b = 4; - 一個敘述也可以跨好幾行,PHP 讀到分號才認定結束;換行和多餘的空白對 PHP 來說都只是分隔
- 大括號
{ }把好幾個敘述組成一個區塊(block),用在if、迴圈、函式後面
註解(comment)是寫給人看的說明,PHP 會略過:
| 寫法 | 範圍 |
|---|---|
// 說明 |
單行註解:到這一行結尾 |
# 說明 |
單行註解(較少用);注意 #[ 開頭是 PHP 8 的屬性(attribute)語法,不是註解 |
/* 說明 */ |
多行註解:從 /* 到第一個 */,可以跨很多行;不能巢狀,裡面再放一個 /* */ 會提早結束 |
單行註解遇到
?>也會結束,後面的文字會被當成 HTML 輸出。所以不要在//註解裡寫?>。
註解寫「為什麼這樣做」比寫「這一行在做什麼」更有用;也可以暫時把一段程式註解掉,先不執行。
分號決定敘述在哪裡結束
第 3 行有兩個敘述,動畫會在這一行停兩次。第 7、8 行是一個跨兩行的敘述,動畫只停一次。第 4 到 6 行的註解完全不會執行,動畫直接跳過。
想一想:標籤與註解
下面的檔案會輸出什麼?(注意每個 ?> 後面的換行)
<?php echo 'A'; ?>
B
<?= 'C' ?>
D
下面的程式會輸出什麼?
<?php
// 印出 A ?>B
echo 'C';
echo 與 print
echo 和 print 都用來輸出,它們是語言結構(language construct)而不是一般的函式,所以後面的括號可以省略。
echo |
print |
|
|---|---|---|
| 一次輸出幾個值 | 可以用逗號接好幾個:echo 'A', 'B'; |
只能一個 |
| 回傳值 | 沒有(不能放在運算式裡) | 一定回傳 1,可以寫 $r = print 'x'; |
| 常見程度 | 最常用 | 較少用 |
要把幾段文字接成一個字串,用串接運算子 .(第 04 課):echo 'Hello' . ' ' . 'PHP';。
在 HTML 裡插入值時,用短輸出標籤 <?= $x ?> 最簡潔。
echo 與 print 的差別
第 6 行把 print 的回傳值存進變數:print 先輸出文字,再回傳 1。echo 就沒辦法這樣寫。
大小寫與空白
| 名稱 | 區分大小寫嗎 | 例子 |
|---|---|---|
| 變數 | 區分 | $name、$Name、$NAME 是三個不同的變數 |
| 常數 | 區分(第 03 課) | MAX 和 max 不同 |
| 函式名稱 | 不區分(英文字母) | strtoupper()、STRTOUPPER() 是同一個函式 |
| 關鍵字 | 不區分 | echo、ECHO、Echo 都可以;true、TRUE 也一樣 |
雖然函式與關鍵字不區分大小寫,請一律照官方的寫法(函式與關鍵字小寫),程式才一致、好讀。 變數的大小寫打錯,是初學者常見的錯誤:PHP 會當成另一個不存在的變數,印出「Undefined variable」警告。
空白、縮排與空行,PHP 都不在乎(字串裡的除外)。縮排是寫給人看的:區塊裡的程式縮排 4 個空白,是 PHP 社群最常見的風格(PSR-12)。
變數區分大小寫,函式不區分
第 3、4 行建立了兩個不同的變數,左邊的變數區可以看到 $name 與 $Name 並存。第 8 行讀取 $NAME:這個變數不存在,PHP 印出 Warning(警告)。警告不會讓程式停下來,第 9 行照常執行。
看懂 Parse error
PHP 執行一個檔案前,會先把整個檔案讀過一遍、檢查語法。只要有一個語法錯誤,整個檔案一行都不會執行,只印出:
Parse error: syntax error, unexpected variable "$qty" in /var/www/html/index.php on line 4
| 部分 | 意思 |
|---|---|
Parse error |
語法錯誤(還沒開始執行) |
syntax error, unexpected variable "$qty" |
在這裡讀到一個「不應該出現」的東西:變數 $qty |
in /var/www/html/index.php |
哪一個檔案 |
on line 4 |
PHP 發現錯誤的那一行 |
PHP 回報的是「發現錯誤」的位置,不一定是「犯錯」的位置。少了分號時,PHP 讀到下一行開頭才發現「這裡應該要有分號」,
所以行號常常是下一行;括號、引號沒有配對時,行號甚至可能在檔案的最後一行(unexpected end of file)。
看到 Parse error,先看那一行,沒問題就往前一行找。
常見的語法錯誤:
| 錯誤 | 訊息常見的樣子 |
|---|---|
| 少了分號 | unexpected variable "$x"、unexpected token "echo",行號在下一行 |
| 字串的引號沒有關 | 錯誤出現在很後面,因為後面的程式都被當成字串內容 |
| 大括號沒有配對 | unexpected end of file(少了 })或 unexpected token "}"(多了 }) |
在終端機可以用 php -l 檔名 只檢查語法、不執行,沒有錯誤時印出 No syntax errors detected in 檔名。
少一個分號,整個檔案都不執行
第 3 行少了分號。注意第 5 行的「開始計算」沒有被印出來:Parse error 在執行之前就發生了,所以一行都沒有執行。錯誤訊息說的是第 4 行,但要修改的是第 3 行。
想一想:輸出、大小寫與語法錯誤
下面的程式會印出什麼?
<?php
$x = print 'Hi';
echo $x;
下面的程式執行的結果是什麼?
<?php
echo 'start';
echo 'A'
echo 'B';
下面的程式會印出什麼?(?? 表示左邊的變數不存在時改用右邊的值,第 03 課介紹)
<?php
$Lang = 'php';
echo STRTOUPPER($Lang), "\n";
echo $lang ?? '沒有 $lang';
動手做:修好三個語法錯誤
下面的程式有三個語法錯誤。先直接執行,看 Parse error 指出哪一行,修好一個再執行一次,直到印出:
考試:期中考
教室:E1-101
時間:9:00
重點回顧
- PHP 程式寫在
<?php與?>之間,標籤外的內容原樣輸出;<?= $x ?>是<?php echo $x; ?>的簡寫 - 純 PHP 檔案省略結尾的
?>,避免多出的空白被輸出;?>會吃掉緊接的一個換行 - 在 HTML 裡依條件輸出,用替代語法
<?php if (…): ?> … <?php else: ?> … <?php endif; ?> - 每個敘述以
;結束;一行可以有多個敘述,一個敘述也可以跨多行;{ }組成區塊 - 註解:
//、#、/* */;/* */不能巢狀,單行註解遇到?>會結束 echo可以輸出多個值、沒有回傳值;print只輸出一個值、回傳 1- 變數名稱區分大小寫;函式名稱與關鍵字不區分,但一律照官方寫法用小寫
- Parse error 代表整個檔案都沒執行;行號是 PHP 發現錯誤的位置,少了分號時往前一行找