透過 App Engine,您可以使用 PHP 程式設計語言建構網路應用程式。您的 PHP 應用程式會採用 Google 的可擴充基礎架構執行,並使用大規模的永久儲存空間和服務。
選取 PHP 執行階段
App Engine 會使用 PHP 5.5.34 版執行 PHP 網路應用程式。注意:在 Linux 上,您也必須在本機安裝 PHP,才能執行 PHP 應用程式。
如要將應用程式設為使用 PHP 執行階段,請在 app.yaml
檔案中新增以下內容:
runtime: php55
api_version: 1
...
第一個元素 runtime
會選取 PHP 執行階段環境。
第二個元素 api_version
會選取要使用的 PHP 執行階段環境版本。截至本文撰寫時,App Engine 只有一個版本的 PHP 環境,即 1
。如果日後有無法回溯相容的變更,則 App Engine 小組將使用新版本 ID。在您變更 api_version
設定並上傳應用程式之前,您的應用程式會繼續使用所選版本。
如要進一步瞭解 app.yaml
檔案,以及如何將應用程式部署至 App Engine,請參閱 app.yaml
參考資料和「部署 PHP 應用程式」主題。
沙箱
如要讓 App Engine 將應用程式要求分散到多部網路伺服器,並且避免應用程式彼此干擾,應用程式會在受到限制的「沙箱」環境中執行。在這個環境中,應用程式可以執行程式碼、使用 App Engine 郵件、網址擷取及使用者服務,以及檢查使用者的網路要求和準備回應。
App Engine 應用程式做不到的事情如下:
寫入檔案系統。PHP 應用程式可以使用 Google Cloud Storage 來儲存永久檔案。您可以從檔案系統讀取,而且可以使用所有以應用程式上傳的應用程式檔案。
慢速回應。應用程式收到的網路要求必須在幾秒內處理完畢。處理序所需的回應時間如果太長,就會終止,以免導致網路伺服器負荷過重。
進行其他種類的系統呼叫。
自動載入類別
標準 PHP 程式庫 (SPL) 類別及任何屬於 App Engine 適用的 SDK 的類別都會在必要時自動載入。也就是說,您不需要在 PHP 指令碼頂端使用 include
或 require
陳述式。
根據預設,自動類別載入作業只會針對位於 App Engine SDK 根目錄根目錄 (以及如果已由 --php_executable_path
指定,則為本機 PHP 安裝) 的檔案中定義的類別執行。
如要新增更多自動載入類別的搜尋路徑,請在 PHP 指令碼中使用 set_include_path
。
set_include_path('my_additional_path' . PATH_SEPARATOR . get_include_path());
啟用的擴充功能
在 App Engine 適用的 PHP 執行階段中已啟用以下擴充功能:
- apc
- bcmath
- calendar
- Core
- ctype
- date
- dom
- ereg
- exif
- filter
- ftp
- gd
- hash
- iconv
- json
- libxml
- mailparse
- mbstring
- mcrypt
- memcache
- memcached
- mysql
- mysqli
- mysqlnd
- OAuth
- openssl
- pcre
- PDO
- pdo_mysql
- Reflection
- session
- shmop
- SimpleXML
- soap
- sockets (適用於已啟用計費功能的應用程式)
- SPL
- standard
- tokenizer
- xml
- xmlreader
- xmlwriter
- xsl
- zip
- zlib
可動態載入的擴充功能
設定 php.ini
後,可動態載入以下擴充功能:
- cURL:這個擴充功能使用通訊端服務發出要求,必須遵循通訊端服務的配額和限制。詳情請參閱「傳出要求」。
- MongoDB - 這個擴充功能允許開發人員連結現有的 MongoDB 執行個體,使用通訊端服務發出要求,必須遵循通訊端服務的配額和限制。
- ImageMagick
- intl
- fileinfo
如要啟用這些擴充功能,請在 php.ini
檔案的 extension
下方新增指令,如下所示:
extension = "curl.so"
extension = "mongo.so"
extension = "imagick.so"
extension = "intl.so"
extension = "fileinfo.so"
工作階段
大部分網路應用程式都需要能有辦法保留要求之間的使用者狀態資訊。PHP 提供便利的工作階段管理層。App Engine 中的工作階段運作方式與任何其他 PHP 應用程式中的工作階段非常類似。
在使用者工作階段中設定變數:
session_start();
$_SESSION['Foo'] = 'Bar';
處理同一使用者發出的後續要求:
session_start();
print $_SESSION['Foo']; // prints Bar
根據預設,App Engine 執行階段將使用 Memcache,透過 MemcacheSessionHandler
類別來儲存工作階段資訊。您可以使用 PHP 的 session_set_save_handler()
方法,指定自用的工作階段處理常式,藉以調整這種行為。Memcache 可以很快地儲存和擷取資料,這表示要求的負擔會非常小。但系統可能會定期清除 App Engine Memcache 中的資料,也就是說,將會失去所有工作階段資訊。對於存在時間較久的工作階段,建議使用替代的儲存空間服務,例如 Cloud SQL。
特殊 $_SERVER 鍵
PHP 會在要求範圍中提供特殊的 $_SERVER[]
陣列。除了標準 CGI 參數外,App Engine 還會新增一些有用的額外鍵。
APPLICATION_ID
- 應用程式的 app_id 是在應用程式建立時設定,例如 my-wordpressAUTH_DOMAIN
:用於透過 Users API 驗證使用者的網域。在 appspot.com 上代管的應用程式具有 gmail.com 的 AUTH_DOMAIN,並接受任何 Google 帳戶。使用 Google Workspace 在自訂網域上代管的應用程式,其 AUTH_DOMAIN 會與自訂網域相同CURRENT_VERSION_ID
- 目前正在執行的應用程式的主要和次要版本,例如「X.Y」。主要版本編號 (「X」) 指定於應用程式的 app.yaml 檔案。次要版本編號 (「Y」) 會在每個版本的應用程式上傳至 App Engine 時自動設定。在開發網路伺服器上,次要版本一律是「1」。DEFAULT_VERSION_HOSTNAME
- 這個應用程式預設版本的主機名稱,例如 my-php-app.uc.r.appspot.com。HTTP_X_APPENGINE_CITY
- 發出要求的來源城市名稱。例如,如果是來自 Mountain View (山景市) 的要求,標頭值可能為「mountain view」。HTTP_X_APPENGINE_CITYLATLONG
- 要求來源城市的經緯度。如果是來自 Mountain View (山景市) 的要求,這個字串可能會是「37.386051,-122.083851」。HTTP_X_APPENGINE_COUNTRY
- 發出要求的來源國家/地區,採用 ISO 3166-1 alpha-2 國家/地區代碼。App Engine 會根據用戶端的 IP 位址決定這個代碼。HTTP_X_APPENGINE_REGION
- 要求來源地區的名稱。這個值必須搭配X-Appengine-Country
中的國家/地區一起理解。舉例來說,如果國家/地區是「US」而地區是「ca」,則「ca」表示「加州」而非加拿大。USER_EMAIL
- 如果已使用 Users API 驗證使用者身分,則傳回使用者的電子郵件地址。應用程式應使用暱稱做為可顯示名稱。USER_ID
- 如果電子郵件地址與 Google 帳戶相關聯,user_id 會傳回使用者的專屬永久 ID (str),如果使用者已使用 Users API 進行驗證。無論使用者是否變更其電子郵件地址,該使用者的 ID 一律相同。USER_IS_ADMIN
- 1:如果登入的使用者也是應用程式的管理員,且已使用 Users API 完成驗證。否則為 0。USER_NICKNAME
- 對於 Google 帳戶使用者,若使用者電子郵件地址所在的網域與應用程式相同,則暱稱為使用者電子郵件地址的「名稱」部分,否則,則為使用者的完整電子郵件地址。USER_ORGANIZATION
- 使用 Google 帳戶設定的應用程式可以判斷目前登入的使用者是使用個人 Google 帳戶,還是由 Google Workspace 網域管理的帳戶。
在 1.9.0 版更新 PHP_SELF
和 SCRIPT_NAME
行為
1.9.0 以下版本的 $_SERVER['SCRIPT_NAME']
和 $_SERVER['PHP_SELF'
] 實作方式與 1.9.0 以上版本的實作方式大不相同。這些變更符合 PHP 應用程式一般預期的 Apache 實作。
以下範例示範這些差異。
1.9.0 之前 | 1.9.0 之後 |
---|---|
app.yaml: - url: /.* script: index.php |
|
REQUEST_URI: / SCRIPT_FILENAME: /path/to/index.php SCRIPT_NAME: / PHP_SELF: / |
REQUEST_URI: / SCRIPT_FILENAME: /path/to/index.php SCRIPT_NAME: /index.php PHP_SELF: /index.php |
REQUEST_URI: /bar SCRIPT_FILENAME: /path/to/index.php SCRIPT_NAME: /bar PHP_SELF: /bar |
REQUEST_URI: /bar SCRIPT_FILENAME: /path/to/index.php SCRIPT_NAME: /index.php PHP_SELF: /index.php |
REQUEST_URI: /index.php/foo/bar SCRIPT_FILENAME: /path/to/index.php SCRIPT_NAME: /index.php/foo/bar PHP_SELF: /index.php/foo/bar |
REQUEST_URI: /index.php/foo/bar SCRIPT_FILENAME: /path/to/index.php SCRIPT_NAME: /index.php PHP_SELF: /index.php/foo/bar |
REQUEST_URI: /test.php/foo/bar SCRIPT_FILENAME: /path/to/index.php SCRIPT_NAME: /test.php/foo/bar PHP_SELF: /test.php/foo/bar |
REQUEST_URI: /test.php/foo/bar SCRIPT_FILENAME: /path/to/index.php SCRIPT_NAME: /index.php PHP_SELF: /index.php |
app.yaml: - url: /.* script: foo/index.php |
|
REQUEST_URI: /bar SCRIPT_FILENAME: /path/to/foo/index.php SCRIPT_NAME: /bar PHP_SELF: /bar |
REQUEST_URI: /bar SCRIPT_FILENAME: /path/to/foo/index.php SCRIPT_NAME: /foo/index.php PHP_SELF: /foo/index.php |
指令與新的初始化預設值
本表指定的指令,其初始化預設值與 php.net 提供的標準 PHP 解譯器所提供的預設值不同。您可以在應用程式的 php.ini 檔案中加入這些預設指令來覆寫這些預設指令。
指令 | App Engine 中的預設值 |
---|---|
detect_unicode |
false |
session.gc_maxlifetime |
600 |
session.cookie_secure |
600 |
session.cookie_httponly |
1 |
session.use_only_cookies |
1 |
display_errors |
0 |
display_startup_errors |
0 |
html_errors |
0 |
log_errors |
1 |
file_uploads |
0 |
upload_max_filesize |
262144 |
max_file_uploads |
0 |
date.timezone |
UTC |
sendmail_path |
null |
allow_url_fopen |
1 |
allow_url_include |
0 |
enable_dl |
0 |
expose_php |
Off |
register_globals |
Off |
magic_quotes_gpc |
0 |
mysqlnd.collect_statistics |
0 |
mysql.allow_local_infile |
0 |
mysqli.allow_local_infile |
0 |
停用的函式
出於安全原因或與 App Engine 執行環境的相容器,部分 PHP 函式已停用。您可以在應用程式的 php.ini 檔案中,明確重新啟用其中的部分函式。
永久停用的函式
以下函式已在 App Engine 中永久停用:
disk_free_space()
disk_total_space()
diskfreespace()
escapeshellarg() and escapeshellcmd()
exec()
highlight_file()
lchgrp(), lchown(), link(), and symlink()
passthru()
pclose() and popen()
proc_close(), prog_get_status(), proc_nice(), proc_open(), and proc_terminate()
set_time_limit()
shell_exec()
show_source()
system()
App Engine 不含 pcntl 擴充功能,因此,在 App Engine 中執行的 PHP 應用程式無法使用 pcntl
所提供的函式。
tempnam()
和 sys_get_temp_dir()
支援
App Engine 應用程式是在不允許寫入本機檔案系統的安全沙箱中執行。因此,App Engine 版本的 tempnam()
會傳回記憶體內的暫存檔,此檔案可稍後寫入永久儲存空間解決方案,例如 Google Cloud Storage 值區。
以下範例說明如何使用 file_put_contents()
和 fwrite()
寫入記憶體內暫存檔案。
<?php
$dir = sys_get_temp_dir();
$tmp = tempnam($dir, “foo”);
file_put_contents($tmp, “hello”)
$f = fopen($tmp, “a”);
fwrite($f, “ world”);
fclose($f)
echo file_get_contents($tmp);
預期的範例輸出如下:
hello world
部分受限函式
PHP 專用的 App Engine 執行階段不支援 preg_replace()
和 mb_ereg_replace()
函式的 /e
模式修飾符。請參閱 PREG_REPLACE_EVAL
說明文件,瞭解淘汰通知,以及如何更新程式碼以改用 preg_replace_callback()
的範例。
可以手動啟用的函式
此清單指定的 PHP 函式必須在應用程式的 php.ini 檔案中,使用 google_app_engine.enable_functions
指令手動啟用。
gc_collect_cycles()
、gc_enable()
、gc_disable()
和gc_enabled()
getmypid()
getmyuid()
和getmygid()
getrusage()
getmyinode()
get_current_user()
libxml_disable_entity_loader()
*parse_str()
phpinfo()
phpversion()
php_uname()
php_sapi_name()
您也可以在應用程式的 php.ini 檔案中使用 disable_functions
指令,手動停用函式。
需要啟用計費功能的函式
以下函式會用到通訊端,因此只適用於啟用計費功能的應用程式。
- 所有網路函式,但
gethostname()
除外 - 所有通訊端函式
- 所有 FTP 函式
- cURL,除非是使用 cURL 精簡版
連結 MySQL 伺服器的 TCP/IP 連線 (Cloud SQL 只能搭配使用 UNIX 通訊端)
串流支援
支援的 PHP I/O 串流包裝函式
系統支援下列 PHP I/O stream 包裝函式:
- php://input
- php://output
- php://memory
- php://temp
串流包裝函式
PHP 中的許多函式 (例如 fopen()
或 file_get_contents()
) 會利用 PHP 的串流介面支援不同的通訊協定。
以下是在 App Engine 執行階段中自動註冊及可供使用的內建串流包裝函式清單。
file://
glob://
http://
(作用與 PHP 的內建 http 串流處理常式類似,但使用 App Engine URLfetch 服務)https://
(使用 App Engine URLfetch 服務)ftp://
gs://
(Google Cloud Storage 的串流處理常式)zlib://
以下是 App Engine 不支援且尚未註冊的內建串流處理常式清單。
data://
expect://
ogg://
phar://
rar://
ssh2://
停用的串流傳輸
以下是已停用的串流傳輸。
ssl
sslv2
sslv3
tcp
tls
udg
udp
unix
純 PHP
PHP 執行階段環境的所有程式碼都必須是純 PHP。App Engine 不允許您上傳自己的 C 擴充功能。
此環境包含 PHP 標準程式庫。部分擴充功能已停用,因為 App Engine 不支援其核心功能,例如網路及寫入檔案系統。
您可以將程式碼放入應用程式目錄 (即包含 app.yaml
檔案的目錄),藉此在應用程式中加入其他純 PHP 程式庫。
例如,您可以在應用程式目錄中建立指向程式庫目錄的符號連結。接著,只要依循這個連結,就能在您將應用程式部署到 App Engine 時,於應用程式中加入這個程式庫。
您也可以指定 php.ini
指令,並在程式碼中加入 PHP include
陳述式,藉此加入 PHP 程式庫。不過,建議您使用 PHP 依附元件管理工具,例如 Composer。
範例:
如果您在
php.ini
檔案的include_path
指令中加入應用程式的根目錄:include_path=".:/[ROOT_DIR]/myapp"
接著,您可以使用
include
或include_once
陳述式,加入與include_path
相關的 PHP 檔案:include_once 'myfile.php';
如果您選擇使用 Composer 來加入純 PHP 程式庫,則只需在安裝依附元件後加入單一檔案即可:
require_once 'vendor/autoload.php';
使用 Composer 安裝應用程式的依附元件時,所有套件都會加入應用程式目錄的
vendor
中,這個子目錄也是autoload.php
檔案產生的位置。
工具
App Engine 適用的 SDK 所含的工具可用來測試應用程式及上傳應用程式檔案。
開發伺服器會在您的本機電腦上執行應用程式,以測試您的應用程式。
gcloud
工具會處理指令列與 App Engine 上執行應用程式的所有互動。您可以使用 gcloud app deploy
將應用程式上傳至 App Engine,或更新個別設定檔。您也可以查看應用程式的記錄資料,以使用自己的工具來分析應用程式效能。
PHP 解譯器原始碼
您可以從 GitHub 的 appengine-php 存放區下載 App Engine 的 PHP 解譯器原始碼。
並行與延遲
應用程式的延遲對提供流量所需的執行個體數量影響最大。若快速處理要求,一個執行個體就能處理許多要求。
環境變數
下列為執行階段設定的環境變數:
環境變數 | 說明 |
---|---|
GAE_APPLICATION
|
App Engine 應用程式的 ID。這個 ID 的前置字串為「region code~」,例如在歐洲部署的應用程式為「e~」。 |
GAE_DEPLOYMENT_ID |
目前部署的 ID。 |
GAE_ENV |
App Engine 環境。設為 standard 。 |
GAE_INSTANCE |
服務目前正在執行的執行個體 ID。 |
GAE_RUNTIME |
app.yaml 檔案中指定的執行階段。 |
GAE_SERVICE |
在 app.yaml 檔案中指定的服務名稱。如果未指定服務名稱,則會設為 default 。 |
GAE_VERSION |
服務目前的版本標籤。 |
GOOGLE_CLOUD_PROJECT |
與應用程式相關聯的 Google Cloud 專案 ID。 |
PORT |
接受 HTTP 要求的通訊埠。 |
您可以在 app.yaml
檔案中定義其他環境變數,但無法覆寫上述的值。