iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 2
5
Modern Web

成為 Modern PHPer系列 第 2

Day 02:內置伺服器

  • 分享至 

  • twitterImage
  •  

有時坐擁許多工具,但卻不知如何應用。

前言

PHP 在 5.4.0 之後就內建 Built-in Web Server,這個功能可以在不用安裝 Apache 或 Nginx 的情況下就能順利啟動開發時期專用的網頁伺服器。

在翻閱某些坊間的 PHP 書籍時,還是時常看到花費一到兩個小節的篇幅去安裝 Apache 或 Nginx(或是用 WAMP、WNMP 之類的整合環境),這純粹是浪費時間。

PHP 的繁體中文且非翻譯書基本上都是垃圾

內置伺服器

基礎使用

在安裝 PHP 之後,我們可以利用一個指令啟動 Built-in Web Server

php -S localhost:8000

上述指令會監聽目前所在的資料夾,並且啟動一個可以執行 PHP 的環境。假設存在一個檔案 a.php,便可以透過 curl “localhost:8000/a.php” 去執行該 PHP Script 並且察看結果。

進階應用

前端控制器模式(Front Controller Pattern)

關於前端控制器模式,建議可以參見我前年在 iThome 鐵人賽的發文:設計模式 - 前端控制器模式(Front Controller Pattern)

對於這類「專案根目錄」與「網站入口點」不同的情況,可以利用 -t 參數額外指定運行資料夾

php -S localhost:8000 -t public/

以上假設網站入口點位於 public/ 資料夾下。

address 與 port 的額外指定

只要修改 localhost:8000 中的 8000,即可在不同的 Port 上啟動 Server。這在 Port 佔用或具有多個專案時相當好用。

對於 localhost:8000 中的 localhost 解釋起來較為麻煩,這篇花一點篇幅做解釋:

  • 如果使用 localhost,只有自己本機才能夠存取,通常這已經足夠使用
  • 如果使用 0.0.0.0 表示監聽所有來源
    • 我通常會在 Docker Image 中使用,這樣執行起來的 Container 就能夠接受來自外部的連線
    • 如果要在區域網路中傳遞資料,也可以利用這樣的方式(就像 python 的 SimpleHTTPServer)

內置伺服器的額外設定

使用前端控制器模式後,我們的應用程式可能有些規則:

  • 如果使用者要求的檔案存在,直接使用該檔案
  • 如果使用者要求的檔案不存在,交給應用程式的路由處理

此時,我們會需要撰寫一個 server.php 的設定檔:(這份檔案來自 Laravel 的 server.php,這也是 Laravel 在啟動內置伺服器時的設定檔)

// server.php

$uri = urldecode(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH));

if ($uri !== '/' && file_exists(__DIR__."/public$uri")) {
    // return false 表示請內置伺服器直接存取該檔案,不經過特別處理
    return false;
}

// 其餘的內容交給應用程式的入口點(/public/index.php)處理
require_once __DIR__.'/public/index.php';

之後,使用 php -S localhost:8000 -t public/ server.php 即可依照這個設定檔啟動內置伺服器。

判斷目前是否在內置伺服器

可以利用 PHP_SAPI 這個 const 去取得目前 PHP 運行環境所使用的 API 類型。

if (PHP_SAPI === 'cli-server') {
    // 表示目前使用的是 PHP 內置伺服器
}

註:PHP_SAPIphp_sapi_name() 將會有相同的內容,通常建議用 PHP_SAPI 即可
註:除了 clicli-server 之外,很難利用 PHP_SAPI 去判斷目前的 Web Server 與使用環境,例如 Apache 就有 apache, apache2filterapache2handler 等不同的可能值

注意事項

根據 PHP 官方建議

PHP 內置伺服器僅適用於開發時期(這非常重要)

其理由在於 PHP 內置伺服器是屬於單執行緒,而且長久執行可能存在 Memory Leak 的問題,所以不可用於產品環境。

如果希望像 Node.js 或 Golang 那樣,可以直接啟動一個 Web Server 並且提供正式服務,可以考慮使用 swooleroadrunner,關於這兩個內容我應該會再用其它文章做說明。

後記

在前言的部份,我提到了「PHP 的繁體中文且非翻譯書基本上都是垃圾」,雖然加上了刪除線,不過其實並非開玩笑。

拿個自身經驗來說,在 2012 年初學 PHP 時曾經購買了陳惠貞及陳俊榮當年度撰寫的書籍,直到 2016 年下旬該書雖然不再出版,但僅僅只是改了個名字在內容幾乎沒有變動的情況下再次出版。

先不提 2012 年用根本沒有推出的 PHP 6 作為噱頭的詐騙書名,2016 年的書籍中宣稱自己是 PHP 7 卻仍是把 2012 年的範例程式拿來複製貼上,而且在我的印象中還完全沒有提到 PDO。

很顯然地,並不是只有這個作者、這系列書有這樣的行為。

在數次到實體書店翻閱之後,我認為這算是出版業界一個相當病態的騙錢手段:不在乎出版品質,只在乎能否用聳動的書名、很新潮的技術名詞推銷很快就會過時的垃圾內容。


上一篇
Day 01:什麼是 Modern PHP
下一篇
Day 03:PSR-12 概述
系列文
成為 Modern PHPer30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言