monogatari-php/remote-storage

一个用于实现 Monogatari.io RemoteStorage 端点的库。

v1.0 2022-02-04 11:31 UTC

This package is auto-updated.

Last update: 2024-09-28 11:48:57 UTC


README

CI badge-coverage Packagist

为 Monogatari 可视小说引擎提供的 RemoteStorage 实现。

使用方法

要使用远程存储解决方案,首先应在 options.js 中配置 Monogatari 的 存储 设置

// Define what storage engine should be used to save the game data. *
// Adapters Available:
// - LocalStorage: This one is used by default
// - SessionStorage: Same as LocalStorage but will be cleared when the page
//                   is closed.
// - IndexedDB: The information is saved using the IndexedDB web API
// - RemoteStorage: The information will be sent and retrieved from a given
//                  URL Endpoint providing a REST API.
'Storage': {
    'Adapter': 'RemoteStorage',
    'Store': 'MyStore',
    'Endpoint': '/gameSave.php/'
},

然后您需要安装该库。您可以从 Packagist 安装它

composer require monogatari-php/remote-storage

最后,您可以编写 PHP 代码来提供配置中提到的 Endpoint(例如 /gameSave.php

use GuzzleHttp\Psr7\HttpFactory;
use Monogatari\RemoteStorage\Http\Controller;
use Monogatari\RemoteStorage\StorageEngine\FileSystemStorage;
use Monogatari\RemoteStorage\StorageEngine\SimpleStorageFactory;

require_once 'vendor/autoload.php';

$httpFactory = new HttpFactory();
$controller = new Controller(
    new SimpleStorageFactory(fn () => (new FileSystemStorage('./gameSave.json'))),
    $httpFactory, // StreamFactoryInterface implementation
    $httpFactory, // ResponseFactoryInterface implementation
);
Controller::emit($controller->handleRequest(Controller::requestFromEnvironment()));

我们在示例中使用了 Guzzle 库来展示功能。但我们并没有将支持限制在只有 Guzzle。函数 Controller::handleRequest 返回 PSR-7 兼容的 ResponseInterface。在任何现代 PHP 框架中都应该安全使用。

该库包含多个 StorageEngine 实现,包括文件系统、mysqlpostgressqlite。如果您需要其他存储解决方案,实现 StorageInterface 应该很简单。有关更多详细信息,请参阅 StorageEngine 文件夹 中的源代码。

生命周期

请求处理的基本生命周期从形成 StorageRequest 开始。您可以使用函数 Controller::requestFromEnvironment 或编写自己的。

然后,请求将被喂送到 StorageFactoryInterface 实现中(例如 SimpleStorageFactory)。工厂将确定加载哪个 StorageInterface

然后控制器将使用 StorageInterface 处理 RESTful 请求。

扩展库

Controller::requestFromEnvironment 的请求只针对一个非常狭窄的使用案例(基于 PHP_INFO 的路由)。它可以在喂给控制器实例之前重写或附加。

需要覆盖的 2 个主要接口是

  1. StorageFactoryInterface:使用提供的 StorageRequest 初始化 StorageInterface 的对象。
  2. StorageInterface:创建、加载、保存和删除值的对象。

应该非常灵活地扩展。

高级示例

此示例演示了如何使用 PSR-7 ServerRequest(通常由如 Symfony、Laravel 和 Druapl 的 PHP Web 框架实现和使用)与库一起使用。

use GuzzleHttp\Psr7\HttpFactory;
use GuzzleHttp\Psr7\ServerRequest;
use Monogatari\RemoteStorage\Http\Controller;
use Monogatari\RemoteStorage\Http\StorageRequest;
use Monogatari\RemoteStorage\StorageEngine\DatabaseStorage\MySqlStorage;
use Monogatari\RemoteStorage\StorageEngine\SimpleStorageFactory;

require_once 'vendor/autoload.php';

// Connect to database
$pdo = new \PDO('mysql:host=127.0.0.1;port=3306;dbname=test', 'test_user', 'test_password');

// Prepare Controller
$httpFactory = new HttpFactory();
$controller = new Controller(
    new SimpleStorageFactory(
        fn (StorageRequest $request) => new MySqlStorage(
            $pdo,
            'monogatari_storage',
            $request->store_name,
            $request->context['username'] ?? '',
        ),
    ),
    $httpFactory, // StreamFactoryInterface implementation
    $httpFactory, // ResponseFactoryInterface implementation
);

// Parse StoreRequest from PSR-7 ServerRequest
$request = ServerRequest::fromGlobals();
if (!preg_match('/\/gameSave\.php(|\/((?<store_name>.+)\/|)(?<key>.*?))$/', $request->getUri()->getPath(), $uriVariables)) {
    throw new \Exception('Unable to parse uri: ' . $request->getUri()->getPath());
}
$uriVariables += ['store_name' => null, 'key' => null];
preg_match('/^(?<username>.+?)(|:(?<password>.*))$/', $request->getUri()->getUserInfo() ?? '', $userContext);
$userContext += ['username' => '', 'password' => ''];
$storageRequest = new StorageRequest(
    $request->getMethod(),
    $uriVariables['store_name'],
    $uriVariables['key'],
    ($request->getQueryParams()['keys'] ?? null) === 'true',
    $request->getBody(),
    $userContext,
);

// Generate PSR-7 Response
$response = $controller->handleRequest($storageRequest);

// Emit the Response
Controller::emit($response);

完整示例

  1. 基本示例:使用 FileSystemStorage 的简单示例。
  2. 高级示例:使用 MySqlStorage 和 PSR-7 ServerRequest 的更完整示例。

许可证

本库采用 MIT 许可证(副本附在此处 此处)。