前言
本文會介紹 PHP 程式的基本概念,並開始撰寫第一個 PHP 程式。
PHP 的檔案名稱和副檔名
PHP 不會特別限制檔案名稱,只要簡單易懂即可。一般會以英文來命名檔名,打字會比較方便。不要在檔名中使用空格,以免造成不必要的麻煩。
PHP 腳本的副檔名為 .php 。在 Unix 上寫 PHP 命令列程式時,不需要副檔名,其餘情境則要加上副檔名。
終端機版本的 Hello World 程式
除了一開始練習語法外,必要時也可以用 PHP 來寫命令列程式。像是在 PHP 專案中需要寫個小工具程式,但不想用第二種語言,就可以用 PHP 來寫。
GNU/Linux
在 GNU/Linux 上的 Hello World 程式如下:
#!/usr/bin/env php
<?php
echo "Hello World" . "\n";
第一行不是 PHP 語法,而是 shebang。這項 Unix 特性用來指定腳本所用的直譯器 (interpreter),此處當然是 PHP。第二行開始的語法就是 PHP 的部分。
將上述腳本加上可執行的權限:
$ chmod +x hello
可注意到這個版本的 PHP 腳本沒有副檔名。
執行此腳本即可在終端機印出 Hello World 字串:
$ ./hello
Hello World
Windows
由於 Windows 沒有 shebang 行,所以直接寫 PHP 語法:
<?php
echo "Hello World" . "\n";
執行該腳本的方式是以 PHP 主程式直接執行:
> php.exe hello.php
Hello World
(選擇性) 包裝 PHP 命令列程式
用 PHP 寫命令列程式時,不一定要直接用 PHP 命令稿來寫。可以先用 Batch 腳本或 POSIX shell 腳本當外部指令,再從外部腳本間接呼叫實際運行的 PHP 命令稿。
由於 PHP 是跨平台的程式語言,藉由這種模式,可以很輕易地做出跨平台的命令列程式,而且可以繞過 Windows 無法使用 shebang 的議題。
Unix Wrapper
在 Unix 上建議使用 POSIX shell 或 Bash 做為 wrapper,因為這兩種 shell 較常使用。
以下是一個假想的 POSIX shell wrapper:
#!/bin/sh
#
# A wrapper to a pseudo PHP script.
# Check whether PHP is available on the system.
if ! command -v php 2>&1 >/dev/null;
then
echo "No PHP on the system" >&2;
exit 1;
fi
# Get the directory of the script itself.
cwd=$(dirname $0);
# Get the directory of the PHP script.
libexec="${cwd}/../libexec";
# Run the PHP script and pass command-line arguments to it.
php "${libexec}/program.php" "$@";
讀者可根據自身的需求,修改此 wrapper。
Windows Wrapper
在 Windows 沒有什麼命令列環境可選,當然是用 batch 腳本當成 wrapper:
@echo off
rem A wrapper to a pseudo PHP script.
rem Check PHP is available on the system.
php --version >nul 2>&1 || (
echo No PHP on the system >&2
exit 1
)
rem Get the directory of current batch script.
set cwd=%~dp0
rem Get the directory of the PHP script.
set libexec=%cwd%\..\libexec
rem Run the PHP script and pass command-line arguments to it.
php %libexec%\program.php %*
由於 batch 腳本本身的特性較弱,利用這種方式,可以把實際的工作交由 PHP 來執行。
網頁版本的 Hello World 程式
用 PHP 撰寫網頁時,輸出的不僅是文字,還有 HTML 標籤。以下是網頁版本的 Hello World 程式:
<!DOCTYPE html>
<html>
<head>
<title><?php echo "Hello World"; ?></title>
</head>
<body>
<h1><?php echo "Hello World"; ?></h1>
</body>
</html>
這裡大部分的代碼是 HTML,只有內嵌 (embedding) 少量的 PHP 程式碼。如果讀者覺得閱讀這樣的代碼有困難的話,建議回頭補強一下 HTML 的部分。
實際輸出的結果如下:
$ php hello.php
<!DOCTYPE html>
<html>
<head>
<title>Hello World</title>
</head>
<body>
<h1>Hello World</h1>
</body>
</html>
可以注意到原本 PHP 程式碼的部分已經不見了,替換成一般的字串。瀏覽器不認得 PHP 程式碼,所以 PHP 程式碼不會原封不動地輸出,而會在執行 PHP 腳本時動態轉換。
使用 PHP 內建網頁伺服器 (Built-in Web Server)
雖然直接閱讀輸出的 HTML 代碼也可以確認輸出結果是否正確,畢竟 HTML 代碼不易直接閱讀。可以用 PHP 內建的開發用網頁伺服器運行 PHP 腳本,以觀看上線後輸出的結果。
將工作目錄 (working directory) 移到 PHP 腳本所在的位置,在 GNU/Linux 下輸人以下指令:
$ php -S localhost:3000
在 Windows 下則改輸入以下指令:
> php.exe -S 127.0.0.1:3000
在瀏覽器上輸入 http://localhost:3000/hello.php 或 http://127.0.0.1:3000/hello.php 就可以看到頁面實際輸出的結果。
PHP 網頁程式實際上線時,不是使用內建的網頁伺服器,因為效能太差。還是要使用 Apache 或 Nginx 等真正在生產環境 (production environment) 所使用的網頁伺服器。由於篇幅限制,這裡不討論部署 (deployment) 的議題。
大小寫敏感性 (Case Sensitivity)
PHP 的變數 (variable) 會區分大小寫。$foo
、$Foo
和 $FOO
視為相異的變數。
但 PHP 的保留字 (keyword) 不區分大小寫。大部分 PHP 程式設計者會沿用 C 的習慣,用小寫來寫保留字。而不會像在寫 SQL 般,用全大寫英文來寫指令。
PHP 的函式 (function) 也不區分大小寫。很多 PHP 內建函式使用 C 風格來命名,但按照 PHP 社群的慣例,會用仿 Java 的命名風格來命名函式和類別 (class),即為 CamelCase。
空白 (Space)、縮進 (Indentation)、換行 (End of Line)
PHP 對空白、縮進、換行等排版元素相對自由。除了要用空白區分識別字和語法外,可以自行將程式碼排列整齊,以利閱讀。
PHP 指令 (Instruction)
PHP 指令以敘述為單位。每行敘述後要用 ;
區隔開來。這項特性承襲自 C 和 Perl。按照 PHP 社群的慣例,每行敘述會寫在單獨一行。
PHP 標籤 (Tag)
由於 PHP 是內嵌在 HTML 頁面內的語言,要用一對 <?php
和 ?>
標籤將 PHP 指令的部分包起來。在 PHP 標籤以外的部分則會原封不動地輸出。
若 PHP 腳本不需輸出 HTML 頁面,按照社群慣例,只寫前半的 PHP 標籤即可。如下例:
<?php
function isEven($number)
{
return 0 == ($number % 2);
}
內嵌在 HTML 頁面內的 PHP 指令當然要寫出成對的 PHP 標籤。如下例:
<h1><?php echo "Hello World"; ?></h1>
對於簡短的 PHP 程式碼,可以用一對 <?=
和 ?>
來取代原本的 PHP 標籤:
<h1><?= echo "Hello World"; ?></h1>
實際上可用的 PHP 標籤不只這兩種。目前 PHP 官方文件只推薦這兩種 PHP 標籤 (出處),故不列出其他標籤。
以 PHP 撰寫網頁程式時,會將 PHP 腳本分為純 PHP 腳本和輸出 HTML 頁面 (註) 的腳本。函式、類別等會寫在純 PHP 腳本中,輸出頁面的腳本則專注在輸出頁面。
(註) 實際上不僅是 HTML 頁面、還包括 XML、JSON 等多種格式。
註解 (Comment)
PHP 承襲 C 和 Perl 的慣例,有三種風格的註解。
Perl 風格的註解是單行註解:
# A Perl-style comment.
C 風格的註解則是多行註解:
/* A C-style comment. */
雖然 C 風格的註解相對不易寫,但這種註解可跨越多行或內嵌在 PHP 程式碼內,仍然有其實用性。
C++ 風格的註解也是單行註解:
// A C++-style comment.
引入函式庫
PHP 引入函式庫的語法是 require_once。以下是一個虛擬例子:
require_once "/path/to/library/autoload.php";
這裡使用 require_once
而非 require
是因為前者沒有重覆引入的問題,適用在函式、類別等不能重覆宣告的項目。
主函式 (Main Function)
PHP 沒有主函式的概念,直接把指令寫在腳本頂層即可。函式、類別等則會用特定的區塊 (block) 來區隔。
離開狀態 (Exit Status)
在命令列程式中,使用 exit 函式回傳程式的離開狀態。慣例上,回傳 0
表示程式成功地結束,回傳 1
則是程式有錯。
但在網頁程式中,使用上述函式對網頁沒什麼實質意義。對網頁程式來說,比較有意義的回傳值是 HTTP 狀態碼 (HTTP status code)。回傳 HTTP 狀態碼的函式是 http_response_code。
網頁成功執行的 HTTP 狀態碼是 200。在網頁出錯時,根據不同的錯誤情境會有相異的回傳值。這裡有一份 HTTP 狀態碼的清單。
壓縮輸出的網頁
在撰寫 PHP 腳本時,為了維護方便,會將 PHP 腳本排列整齊。但這樣的腳本所輸出的 HTML 頁面會多出許多不必要的空白。這些空白對瀏覽器來說是沒有實際意義的,平白耗費網路頻寬而已。
所幸,Apache 和 Nginx 等網頁伺服器,都可以壓縮 HTML 頁面。因此,不需要故意將 PHP 程式碼擠在一起,這只是自找麻煩的動作。