美思 [PHP] 程式設計教學:基本概念

Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Email

前言

本文會介紹 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.phphttp://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 程式碼擠在一起,這只是自找麻煩的動作。

關於作者

身為資訊領域碩士,美思認為開發應用程式的目的是為社會帶來價值。如果在這個過程中該軟體能成為永續經營的項目,那就是開發者和使用者雙贏的局面。

美思喜歡用開源技術來解決各式各樣的問題,但必要時對專有技術也不排斥。閒暇之餘,美思將所學寫成文章,放在這個網站上和大家分享。