使用 Firestore 处理会话

本教程介绍了如何在 App Engine 上处理会话。

许多应用需要处理身份验证和用户偏好设置的会话。PHP 附带基于内存的实现可实现此功能。但此实现不适用于可以通过多个实例提供的应用,因为各实例之间记录的会话可能不同。

目标

  • 编写应用。
  • 在本地运行应用。
  • 在 App Engine 上部署应用。

费用

本教程使用 Google Cloud 的以下收费组件:

您可使用价格计算器根据您的预计使用量来估算费用。 Google Cloud 新用户可能有资格申请免费试用

完成本教程后,您可以删除所创建的资源以避免继续计费。如需了解详情,请参阅清理

准备工作

  1. 登录您的 Google 帐号。

    如果您还没有 Google 帐号,请注册一个新帐号

  2. 在 Cloud Console 的项目选择器页面上,选择或创建 Cloud 项目。

    转到项目选择器页面

  3. 确保您的 Google Cloud 项目已启用结算功能。 了解如何确认您的项目已启用结算功能

  4. 启用 Firestore API。

    启用 API

  5. 安装并初始化 Cloud SDK
  6. 配置 gcloud 工具以使用您的新 Google Cloud 项目:
    # Configure gcloud for your project
    gcloud config set project PROJECT_ID
    PROJECT_ID 替换为您之前创建或选择的 Google Cloud 项目 ID。

设置项目

  1. 在终端窗口中,从您选择的目录启动,并创建一个名为 sessions 的新目录。本教程的所有代码均位于 sessions 目录内。

  2. 切换到 sessions 目录:

    cd sessions
    
  3. 安装依赖项:

    composer require google/cloud-firestore
    

在本教程结束时,最终文件结构类似于以下内容:

sessions
├── app.yaml
└── composer.json
├── index.php

编写应用

  • 在终端窗口中,使用以下内容创建名为 index.php 的文件:

    <?php
    /*
     * Copyright 2019 Google LLC
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *   http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    require_once __DIR__ . '/vendor/autoload.php';
    
    use Google\Cloud\Firestore\FirestoreClient;
    
    $projectId = getenv('GOOGLE_CLOUD_PROJECT');
    // Instantiate the Firestore Client for your project ID.
    $firestore = new FirestoreClient([
        'projectId' => $projectId,
    ]);
    
    $handler = $firestore->sessionHandler(['gcLimit' => 500]);
    
    // Configure PHP to use the the Firebase session handler.
    session_set_save_handler($handler, true);
    session_save_path('sessions');
    session_start();
    
    $colors = ['red', 'blue', 'green', 'yellow', 'pink'];
    /**
     * This is an example of a front controller for a flat file PHP site. Using a
     * Static list provides security against URL injection by default.
     */
    switch (@parse_url($_SERVER['REQUEST_URI'])['path']) {
        case '/':
            if (!isset($_SESSION['views'])) {
                $_SESSION['views'] = 0;
                $_SESSION['color'] = $colors[rand(0, 4)];
            }
            printf(
                '<body bgcolor="%s">Views: %s</body>',
                $_SESSION['color'],
                $_SESSION['views']++
            );
            break;
        default:
            http_response_code(404);
            exit('Not Found');
    }
    

此应用为每位用户显示不同语言的问候语。回访用户始终会收到同一种语言的问候语。

多个应用窗口显示不同语言的问候语。

在应用存储用户偏好设置之前,您需要存储会话中当前用户的相关信息。此示例应用使用 Firestore 来存储会话数据。

您可以通过 Firestore session handler 来使用 Firestore 处理 PHP 会话。

下图说明了 Firestore 如何处理 App Engine 应用的会话。

架构图:用户、App Engine、Firestore。

设置 session_set_save_handler 之后,每个请求都有一个 $_SESSION 全局变量供您访问会话。会话数据存储在 Firestore 中。

在本地运行

  1. 启动内置 PHP Web 服务器:

    php -S localhost:8080
    
  2. 在网络浏览器中查看应用:

    Cloud Shell

    在 Cloud Shell 工具栏中,点击 Web 预览 Web 预览,然后选择在端口 8080 上预览

    本地机器

    在浏览器中,转到 http://localhost:8080

    您会看到五个问候语之一:“Hello World”、“Hallo Welt”、“Hola mundo”、“Salut le Monde”或“Ciao Mondo”。如果您使用其他浏览器或无痕模式打开网页,语言会更改。您可以在 Google Cloud Console 中查看和修改会话数据。

    Cloud Console 中的 Firestore 会话。

  3. 要停止 HTTP 服务器,请在终端窗口中按 Control+C

在 App Engine 上部署并运行

通过 App Engine 标准环境,您可以构建和部署在繁重负载和大量数据的压力下仍能可靠运行的应用。

本教程使用 App Engine 标准环境来部署服务器。

  1. 在您的终端窗口中,创建一个 app.yaml 文件并复制以下内容:

    runtime: php73
    
  2. 在 App Engine 上部署应用:

    gcloud app deploy
    
  3. 如需查看实际应用,请输入以下网址:

    https://PROJECT_ID.REGION_ID.r.appspot.com

    替换以下内容:

现在,问候语由在 App Engine 实例上运行的 Web 服务器提供。

删除会话

PHP 会执行会话垃圾回收 (GC),根据您的 php.ini 配置移除旧会话和过期会话。默认情况下,Firestore 会话处理程序不会清理会话,但您可以在创建会话处理程序时传递 gcLimit 选项,以将该处理程序配置为执行此操作:

$handler = $firestore->sessionHandler(['gcLimit' => 500]);

系统会使用基于概率的会话 GC 移除会话,您也可以显式调用 session_gc 函数来移除会话。

调试应用

如果您无法连接到 App Engine 应用,请检查以下内容:

  1. 检查 gcloud 部署命令是否已成功完成,并且未输出任何错误。如果存在错误(例如 message=Build failed),修复问题,然后再次尝试部署 App Engine 应用
  2. 在 Cloud Console 中,转到日志查看器页面。

    转到“日志查看器”页面

    1. 最近选择的资源下拉列表中,点击 App Engine 应用,然后点击所有 module_id。您将看到访问您的应用时的请求列表,如果您未发现请求列表,请确认您是否已从下拉列表中选择所有 module_id。如果您发现 Cloud Console 出现错误消息,请检查应用代码是否与“编写 Web 应用”相关部分中的代码匹配。

    2. 确保已启用 Firestore API。

清理

删除项目

  1. 在 Cloud Console 中,转到管理资源页面。

    转到“管理资源”页面

  2. 在项目列表中,选择要删除的项目,然后点击删除
  3. 在对话框中输入项目 ID,然后点击关闭以删除项目。

删除 App Engine 实例

  1. 在 Cloud Console 中,转到 App Engine 的版本页面。

    转到“版本”页面

  2. 选中要删除的非默认应用版本对应的复选框。
  3. 点击删除 以删除应用版本。

后续步骤