借助 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 文件中定义其他环境变量,但不能替换上述值。