PHP 5 运行时环境

借助 App Engine,您可以使用 PHP 编程语言构建网页应用。您的 PHP 应用可在 Google 的可扩展基础架构上运行,并可使用大规模的永久性存储空间和服务。

如需了解如何使用 PHP 和 App Engine 开发网络应用,请参阅 PHP 入门指南

选择 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 脚本的顶部使用 includerequire 语句。

默认情况下,自动类加载仅适用于 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
  • 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 实现动态加载。

要启用这些扩展程序,请在 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_SELFSCRIPT_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"
    

    则您可以使用 includeinclude_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 与您的应用关联的 Cloud 项目 ID。
PORT 接收 HTTP 请求的端口。

您可以app.yaml 文件中定义其他环境变量,但不能替换上述值。