proresult/php-typescript-rpc-codegen 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

proresult/php-typescript-rpc-codegen

Composer 安装命令:

composer require proresult/php-typescript-rpc-codegen

包简介

Generate typescript rpc from php

README 文档

README

This library/tool is used to expose type annotated php code written in a certain way as rpc functions, and create typescript client code to use the exposed rpc functions in a typesafe manner from the web.

The goal is to make it easy to do type safe requests from typescript code in the browser to a php function running on a server, and get a typesafe response back.

This is currently beta level quality, but is used in production.

High level overview

  1. Define model classes for request + response in a separate source namespace (directory).
  2. Define rpc classes with methods that accept the request model class as a argument (for post requests), and returns the response model class.
  3. Run the code generator. This will create three things:

    • A typescript interface for each model class.
    • A typescript file per rpc class, exporting one function per rpc method.

      The "rpc function" returns a FetchAdapter instance that has all required info for a general typescript client to do the rpc http request for the given rpc method. This makes it easy to perform a typesafe request and get a typesafe response from typescript code in the browser, using the browser fetch api.

    • A php "adapter" class per rpc class. This handles serverside deserialization/serialization of requests/responses, and mapping incoming requests to correct rpc class + method.(By request URL path).

  4. In a request receiving php file, hook the generated php rpc adapter class(es) into the php server request/response cycle by adding it to a RpcRouter instance (defined in proresult/php-typescript-rpc-server). Pass incoming http requests to the RpcRouter and emit it's response back to requester.
  5. Create typescript code that initializes a Client class from the @proresult/php-typescript-rpc library library. Call Client.do method with a FetchAdapter instance created by the generated typescript rpc function to perform rpc requests.

RPC request methods

The default request method is a POST request where all data from client to server is sent json encoded in the request body. The rpc method must then have exactly one argument declared with the request model type.

By annotating a rpc method with the Get attribute defined in php-typescript-server, the request method will be GET. This is handled differently. For "get methods", all data from client to server is sent as query parameters in the url. This kind of rpc method is defined with zero or more arguments limited to these native php types:

  • string
  • int
  • float
  • bool

The response is always a json encoded rpc model class instance.

Example

Look at the test code in this project, or the standalone php-typescript-rpc-demo project for complete example code.

Recommendations

Multiple model source directories

If model classes live in more than one source root, pass all roots with modelInputBaseDir. The argument name is kept for compatibility, but it now accepts either a directory string or an array of directory strings. The generator parses these model directories together and writes TypeScript output for all model classes.

$modelsDir = __DIR__ . '/../src/Proresult/Rpc/Models';
$sharedModelsDir = __DIR__ . '/../../../shared/src/Models';

$codeGenerator = new CodeGen(
    modelInputBaseDir: [$modelsDir, $sharedModelsDir],
    rpcInputBaseDir: $rpcDir,
    typescriptOutputDir: $tsOutDir,
    phpAdapterOutputDir: $phpOutDir,
    pathPrefixAdjustment: $pathAdjust,
    baseRpcPhpNamespace: $baseRpcPhpNamespace,
    phpNamespaceAdjuster: $phpNamespaceAdjuster,
);

For a single model root, pass a string: modelInputBaseDir: $modelsDir.

Output paths and imports are still based on PHP namespaces and the configured ModulePathPrefixAdjustments. Add a path prefix adjustment for the shared model namespace if it should not be generated under its full PHP namespace path.

Date/time fields

Application and shared models may use native PHP date/time types for RPC fields:

public DateTimeImmutable $created;
public ?DateTimeImmutable $deleted;

Codegen maps DateTimeImmutable and DateTimeInterface to the RPC TypeScript date contract:

import { RpcDateTime, deserializeRpcDateTime } from '@proresult/php-typescript-rpc';

Generated TypeScript fields use RpcDateTime, and generated deserializers use deserializeRpcDateTime. The PHP RPC server still normalizes incoming date values through RpcDateTime, preserving the RPC precision and timezone behavior.

Generated constants

Public PHP class constants are exported to TypeScript. Scalar values are emitted as plain TypeScript literals. PHP list arrays are emitted as TypeScript arrays, and associative arrays are emitted as TypeScript object literals with as const.

Be aware that PHP converts numeric string array keys to integer keys. This means codegen cannot distinguish this:

public const FIELD_MAP = ['0' => 'number', '1' => 'customerName'];

from this:

public const FIELD_MAP = ['number', 'customerName'];

Both are PHP lists and will be generated as a TypeScript array. To generate a TypeScript object literal, the PHP array must not be a list after PHP key normalization. For example, legacy ID maps with gaps or keys that do not start at 0 are preserved as objects:

public const FIELD_MAP = ['0' => 'number', '18' => 'validUntilDate'];

generates:

export const FIELD_MAP = {"0": "number", "18": "validUntilDate"} as const;

Request/Response Modelling

When declaring request/response classes, it is recommended, if possible, to have a default initial value for all properties so that a default initialization without values is a valid object instance. This is for forward/backwards compatibility, so that a future or old client don't get BadRequestException because the request is missing a property that is declared in the request class. Naturally, the rpc method being called must also properly handle the default value of the property then.

Development info

When doing development, it can be helpful to include the related dependencies with a symlink, so that one can do required changes in dependencies and see the result immediately. To do this, temporarily add a local repository to the composer.json file.

Example:

"repositories" : {
    "proresult/php-typescript-rpc-server": {
        "type" : "path",
        "url": "../php-typescript-rpc-server",
        "options" : {
            "symlink" : true
        }
    }
}

NB: Remember to remove this again after. Never commit this change.

proresult/php-typescript-rpc-codegen 适用场景与选型建议

proresult/php-typescript-rpc-codegen 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 9.32k 次下载、GitHub Stars 达 0, 最近一次更新时间为 2021 年 06 月 14 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「rpc」 「typescript」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 proresult/php-typescript-rpc-codegen 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 proresult/php-typescript-rpc-codegen 我们能提供哪些服务?
定制开发 / 二次开发

基于 proresult/php-typescript-rpc-codegen 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 9.32k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 10
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2021-06-14