monogatari-php / remote-storage
一个用于实现 Monogatari.io RemoteStorage 端点的库。
Requires
- php: >=8.0
- psr/http-factory: ^1.0
- psr/http-message: ^1.0
Requires (Dev)
- codeception/codeception: ^4.1
- codeception/module-asserts: ^1.0.0
- codeception/module-webdriver: ^2.0
- guzzlehttp/psr7: ^2.1
- phpstan/phpstan: ^1.3
- phpunit/php-code-coverage: ^9.2
README
为 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 实现,包括文件系统、mysql、postgres 和 sqlite。如果您需要其他存储解决方案,实现 StorageInterface 应该很简单。有关更多详细信息,请参阅 StorageEngine 文件夹 中的源代码。
生命周期
请求处理的基本生命周期从形成 StorageRequest
开始。您可以使用函数 Controller::requestFromEnvironment
或编写自己的。
然后,请求将被喂送到 StorageFactoryInterface
实现中(例如 SimpleStorageFactory
)。工厂将确定加载哪个 StorageInterface
。
然后控制器将使用 StorageInterface
处理 RESTful 请求。
扩展库
Controller::requestFromEnvironment
的请求只针对一个非常狭窄的使用案例(基于 PHP_INFO
的路由)。它可以在喂给控制器实例之前重写或附加。
需要覆盖的 2 个主要接口是
StorageFactoryInterface
:使用提供的StorageRequest
初始化StorageInterface
的对象。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);
完整示例
许可证
本库采用 MIT 许可证(副本附在此处 此处)。