借助 App Engine,您可以使用 PHP 编程语言构建 Web 应用。您的 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 团队将使用新版本标识符。在您更改 api_version
设置并上传应用之前,应用将继续使用以前选择的版本。
如需详细了解 app.yaml
文件以及如何将应用部署到 App Engine,请参阅 app.yaml
参考文档和部署 PHP 应用主题。
沙盒
为了让 App Engine 能够跨多个网络服务器分发应用请求,并防止应用之间相互干扰,应用需要在受限制的“沙盒”环境中运行。在此环境中,应用可以执行代码,使用 App Engine 邮件、网址提取服务和用户服务,还可以检查用户的网络请求并做好响应准备。
App Engine 应用不能有以下行为:
对文件系统执行写入操作。PHP 应用可以使用 Google Cloud Storage 来存储永久性文件。应用可以从文件系统中读取内容,并且可以使用随应用上传的所有应用文件。
缓慢响应。向应用发出的 Web 请求必须在数秒内得到处理。需要很长时间才能做出响应的进程将被终止,以免 Web 服务器发生过载。
进行其他类型的系统调用。
自动类加载
系统会在需要时自动加载标准 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());
已启用的扩展程序
PHP 运行时中已为 App Engine 启用以下扩展程序:
- apc
- bcmath
- 日历
- 核心
- ctype
- 日期
- dom
- ereg
- exif
- filter
- ftp
- gd
- hash
- iconv
- json
- libxml
- mailparse
- mbstring
- mcrypt
- memcache
- memcached
- mysql
- mysqli
- mysqlnd
- OAuth
- openssl
- pcre
- PDO
- pdo_mysql
- 反射
- session
- shmop
- SimpleXML
- soap
- sockets(适用于支持结算功能的应用)
- SPL
- 标准
- 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 运行时将使用 MemcacheSessionHandler
类通过 Memcache 存储会话信息。您可以使用 PHP 的 session_set_save_handler()
方法指定自己的会话处理程序,从而调整上述行为。Memcache 可让用户快速保存和检索会话数据,这意味着您的请求开销会被降至最低。不过,App Engine Memcache 中的数据可能会定期清空,届时所有会话信息都将丢失。对于存在时间较长的会话,最好使用其他存储服务,例如 Cloud SQL。
专用 $_SERVER 键
PHP 在请求范围内提供了特殊的 $_SERVER[]
数组。除了标准 CGI 参数,App Engine 还额外添加了一些有用的键。
APPLICATION_ID
- 创建应用时设置的应用的 app_id。例如 my-wordpress。AUTH_DOMAIN
- 通过 Users API 对用户进行身份验证时所使用的网域。在 appspot.com 上托管的应用的 AUTH_DOMAIN 为 gmail.com,这些应用接受任何 Google 账号。使用 Google Workspace 在自定义网域上托管的应用拥有等同于该自定义网域的 AUTH_DOMAIN。CURRENT_VERSION_ID
- 当前正在运行的应用的主要版本和次要版本,例如“X.Y”。主要版本号(“X”)在应用的 app.yaml 文件中指定。次要版本号(“Y”)在应用的每个版本上传到 App Engine 时自动设置。在开发 Web 服务器上,次要版本始终为“1”。DEFAULT_VERSION_HOSTNAME
- 此应用的默认版本的主机名,例如 my-php-app.uc.r.appspot.com。HTTP_X_APPENGINE_CITY
- 发起请求的城市的名称。例如,对于从美国山景城 (Mountain View) 发起的请求,其标头值可能为 mountain view。HTTP_X_APPENGINE_CITYLATLONG
- 发起请求的城市的纬度和经度。对于来自美国山景城的请求,此字符串可能为“37.386051,-122.083851”。HTTP_X_APPENGINE_COUNTRY
- 发起请求的国家/地区,用 ISO 3166-1 二位字母国家/地区代码表示。App Engine 根据客户端的 IP 地址来确定此代码。HTTP_X_APPENGINE_REGION
- 发起请求的地区的名称。此值仅在X-Appengine-Country
中的国家/地区的上下文中有意义。例如,如果国家/地区为“US”,地区为“ca”,则“ca”表示“加利福尼亚州”,而不是加拿大。USER_EMAIL
- 如果已使用 Users API 对用户进行身份验证,则返回用户的电子邮件地址。应用应使用昵称作为可显示名称。USER_ID
- 如果电子邮件地址与 Google 账号关联,并且已使用 Users API 对该用户进行身份验证,则 user_id 会返回用户唯一的永久 ID,该 ID 为一个字符串。无论用户是否更改其电子邮件地址,此 ID 对于用户始终不变。USER_IS_ADMIN
- 如果已登录用户也是应用的管理员,并且已使用 Users API 对该用户进行身份验证,则为 1。否则为 0。USER_NICKNAME
- 对于 Google 账号用户,昵称要么是用户电子邮件地址的“名称”部分(如果电子邮件地址与应用位于同一网域中),要么是用户完整的电子邮件地址。USER_ORGANIZATION
- 使用 Google 账号设置的应用可以确定目前登录的用户使用的是个人 Google 账号,还是由 Google Workspace 网域管理的账号。
1.9.0 中的更新后的 PHP_SELF
和 SCRIPT_NAME
行为
在 $_SERVER['SCRIPT_NAME']
和 $_SERVER['PHP_SELF'
] 的实现方面,1.9.0 之前的版本与 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_callback()
的示例,请参阅 PREG_REPLACE_EVAL
文档。
可以手动启用的函数
以下列表指定了必须在应用的 php.ini 文件中使用 google_app_engine.enable_functions
指令手动启用的 PHP 函数。
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
指令手动停用函数。
需要启用结算功能的函数
以下函数使用套接字,因此仅适用于已启用结算功能的应用。
流支持
支持的 PHP I/O 流封装容器
支持以下 PHP I/O 流包装函数:
- 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
文件中定义其他环境变量,但不能替换上述值。