govindtomar/extjs-direct

一个基础组件,用于将 Sencha Ext JS Ext.direct 集成到 PHP 应用程序中

dev-master / 5.0.x-dev 2024-08-29 09:07 UTC

This package is auto-updated.

Last update: 2024-09-29 09:22:23 UTC


README

一个基础组件,用于将 Sencha Ext JS Ext.direct 集成到 PHP 应用程序中

Build Status

介绍

这个库提供了一个服务器端实现,用于 Sencha Ext.direct,这是一个 RPC 风格的通信组件,它是 Sencha 的 Ext JSSencha Touch 的一部分。

Ext Direct 是一个平台和语言无关的远程过程调用 (RPC) 协议。Ext Direct 允许 Ext JS 应用的客户端与任何符合该规范的任何服务器平台无缝通信。Ext Direct 无状态且轻量级,支持 API 发现、调用批处理和服务器到客户端事件等特性。

目前这个库仅用作 govindtomar/extjs-direct-bundle 的基础,这是一个将 * Ext.direct* 集成到基于 Symfony 的应用程序的 Symfony 扩展包。我们没有尝试将该库用作独立组件或在 Symfony 环境之外的其他环境中使用,因此以下内容仅从理论上说明它应该如何工作,而没有使用扩展包。我们欢迎任何帮助和贡献,以便使库在扩展包之外更有用。

安装

您可以使用 composer 安装此库

composer require govindtomar/extjs-direct

或直接将包添加到您的 composer.json 文件中。

示例

命名策略决定了如何将 PHP 类名和命名空间转换为与 JavaScript 兼容的 Ext.direct 动作名称。默认命名策略将命名空间分隔符 \ 转换为 .。因此,My\Namespace\Service 转换为 My.namespace.Service。请注意,转换必须是可逆的(My.namespace.Service => My\Namespace\Service)。

$namingStrategy = new GT\ExtDirect\Service\DefaultNamingStrategy();

服务注册表使用来自 jms/metadata 库的元数据工厂以及相关的注释驱动程序(它反过来使用一个 doctrine/annotations 注释读取器)来读取有关可能注释的服务类的元信息。

$serviceRegistry = new GT\ExtDirect\Service\DefaultServiceRegistry(
    new Metadata\MetadataFactory(
        new GT\ExtDirect\Metadata\Driver\AnnotationDriver(
            new Doctrine\Common\Annotations\AnnotationReader()
        )
    ),
    $namingStrategy
);

服务注册表可以通过调用 addServices()addService() 手动填充,或者通过使用 GT\ExtDirect\Service\ServiceLoader 导入服务。默认实现 \GT\ExtDirect\Service\PathServiceLoader 可以从给定路径集中读取类。

事件调度器是可选的,但必须使用诸如参数转换和验证、结果转换的配置监听器等特性。

$eventDispatcher = new Symfony\Component\EventDispatcher\EventDispatcher();

路由器用于将传入的 Ext.direct 请求转换为对正确服务类的 PHP 方法调用。`ContainerServiceFactory` 支持从 Symfony 依赖注入容器中检索服务或实例化没有任何构造函数参数的简单服务。静态服务调用绕过服务工厂。

$router = new GT\ExtDirect\Router\Router(
    new GT\ExtDirect\Router\ServiceResolver(
        $serviceRegistry,
        new GT\ExtDirect\Service\ContainerServiceFactory(
            /* a Symfony\Component\DependencyInjection\ContainerInterface */
        )
    ),
    $eventDispatcher
);

端点对象是所有 Ext.direct 服务器端组件的前端抽象。通过其 createServiceDescription() 方法,可以获得符合标准的 API 描述,而 handleRequest() 接受一个 Symfony\Component\HttpFoundation\Request 并返回一个包含服务调用接收到的 Ext.direct 响应的 Symfony\Component\HttpFoundation\Response

$endpoint = GT\ExtDirect\Service\Endpoint(
    'default', // endpoint id
    new GT\ExtDirect\Description\ServiceDescriptionFactory(
        $serviceRegistry,
        'My.api',
        $router,
        new GT\ExtDirect\Router\RequestFactory(),
        'My.api.REMOTING_API'
    )
);

端点管理器只是一个简单的端点集合,它允许通过端点 ID 检索。这允许轻松公开多个独立的 API。

$manager = new GT\ExtDirect\Service\EndpointManager();
$manager->addEndpoint($endpoint);
$defaultEndpoint = $manager->getEndpoint('default');

$apiResponse = $defaultEndpoint->createServiceDescription('/path/to/router');
$apiResponse->send();

$request = Symfony\Component\HttpFoundation\Request::createFromGlobals();
$response = $defaultEndpoint->handleRequest($request);
$response->send();

可以通过在路由器传入的事件派发器上使用事件监听器来操纵和增强路由过程。该库提供了四个事件订阅者,允许

  • 在调用服务方法之前转换参数
  • 在调用服务方法之前验证参数
  • 在将服务方法调用结果发送回客户端之前转换它
  • 对路由器进行监控以获取时间信息(用于增强Symfony分析器时间线)

提供的参数和结果转换器使用jms/serializer库来提供扩展的(反)序列化功能,而默认参数验证器则利用symfony/validator库。

$eventDispatcher->addSubscriber(
    new GT\ExtDirect\Router\EventListener\ArgumentConversionListener(
        new GT\ExtDirect\Router\ArgumentConverter(/* a JMS\Serializer\Serializer */)
    )
);
$eventDispatcher->addSubscriber(
    new GT\ExtDirect\Router\EventListener\ArgumentValidationListener(
        new GT\ExtDirect\Router\ArgumentValidator(/* a Symfony\Component\Validator\Validator\ValidatorInterface */)
    )
);
$eventDispatcher->addSubscriber(
    new GT\ExtDirect\Router\EventListener\ResultConversionListener(
        new GT\ExtDirect\Router\ResultConverter(/* a JMS\Serializer\Serializer */)
    )
);
$eventDispatcher->addSubscriber(
    new GT\ExtDirect\Router\EventListener\StopwatchListener(
        /* a Symfony\Component\Stopwatch\Stopwatch */
    )
);

服务注解

要通过Ext.direct API公开的服务必须用适当的元信息装饰。目前这只能通过注解(类似于Doctrine、Symfony或其他现代PHP库中已知的注解)来实现。

每个将被公开为Ext.direct操作的服务类都必须用GT\ExtDirect\Annotation\Action注解。对于既不是静态的也不能使用无参构造函数实例化的服务,Action注解可以可选地接受一个服务id参数。

use GT\ExtDirect\Annotation as Direct;

/**
 * @Direct\Action()
 */
class Service1
{
    // service will be instantiated using the parameter-less constructor if called method is not static
}

/**
 * @Direct\Action("app.direct.service2")
 */
class Service2
{
    // service will be retrieved from the dependency injection container using id "app.direct.service2" if called method is not static
}

此外,每个将被公开在Ext.direct操作上的方法都必须用GT\ExtDirect\Annotation\Method注解。该Method注解可以可选地接受true来指定该方法为表单处理器(接受常规表单提交)或false来指定该方法为常规的Ext.direct方法(这是默认值)。

/**
 * @Direct\Action("app.direct.service3")
 */
class Service3
{
    /**
     * @Direct\Method()
     */
    public function methodA()
    {
        // regular method
    }

    /**
     * @Direct\Method(true)
     */
    public function methodB()
    {
        // form handler method
    }
}

Ext.direct规范中描述的扩展特性,如命名参数和严格命名参数,目前无法通过注解系统公开。

可以通过注解方法参数来应用参数验证,以便将参数传递到通过Ext.direct请求调用的方法中。这要求将GT\ExtDirect\Router\EventListener\ArgumentValidationListener注册到适当的事件派发器。

use Symfony\Component\Validator\Constraints as Assert;

/**
 * @Direct\Action("app.direct.service4")
 */
class Service4
{
    /**
     * @Direct\Method()
     * @Direct\Parameter("a", { @Assert\NotNull(), @Assert\Type("int") })
     *
     * @param int $a
     */
    public function methodA($a)
    {
    }
}

如果被调用方法的签名公开了具有对Symfony\Component\HttpFoundation\Request和/或GT\ExtDirect\Router\Request类型提示的参数,则自动将传入的Symfony HTTP请求和/或原始的Ext.direct请求注入到方法调用中。这对于表单处理方法尤为重要,因为这是访问传入HTTP请求参数(表单提交)的唯一方式。

一旦启用GT\ExtDirect\Router\EventListener\ArgumentConversionListener,就可以在服务方法上使用严格类型对象参数。这些参数将自动从传入的JSON请求反序列化,并将注入到方法调用中。

对于从服务方法调用返回的对象也是如此。如果启用GT\ExtDirect\Router\EventListener\ResultConversionListener,则返回值将自动序列化为JSON,即使它们是非平凡的对象也不例外。

参数和返回值转换都基于Johannes Schmitt的优秀jms/serializer库。有关更多信息,请参阅文档

规范

Ext Direct规范可以在Sencha的文档网站上找到

许可证

MIT许可证(MIT)

版权所有(c)2015 TEQneers GmbH & Co. KG

本软件及其相关文档文件(以下简称“软件”)的使用权在此免费授予,任何获取软件副本的个人均可自由处理该软件,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或出售软件副本,并允许软件提供方进行此类操作,前提是遵守以下条件:

上述版权声明和本许可声明应包含在软件的所有副本或实质性部分中。

软件按“原样”提供,不提供任何形式的保证,无论是明示的还是暗示的,包括但不限于适销性、特定用途适用性和非侵权性保证。在任何情况下,作者或版权所有者均不对任何索赔、损害或其他责任承担责任,无论这些责任是基于合同、侵权或其他原因,这些责任源于、因之产生或与软件或软件的使用或其他操作有关。