klezbucket/cakephp-klez-api

CakePHP 的 KlezApi 插件

安装: 4

依赖者: 0

建议者: 0

安全: 0

类型:cakephp-plugin

0.5-beta 2019-05-13 01:35 UTC

This package is auto-updated.

Last update: 2024-09-13 13:30:49 UTC


README

欢迎使用 KlezPlugin 的家族。

我们的目标是自动化并简化任何项目的重复部分。扩展框架以提供钩子和设置来实现这一点。

变更日志 v0.5-beta

ImplementationNode 已在此处实现,实现了抽象管道。

变更日志 v0.4-beta

PreflightNode 已在此处实现,准备好服务 CORS 请求。

具体化抽象管道,提取出常见的管道部分。避免配置冗余。

变更日志 v0.3-beta

实现了多管道执行流程。在新的 API 中跨管道跳转。

实现了管道停止。通过新的 API 停止当前管道执行。

变更日志 v0.2-beta

实现了日志功能。

变更日志 v0.1-beta

这是第一次提交。

此包涵盖了项目可能需要的所有 Api 必需品。

格式化支持

  • json
  • xml
  • yml
  • php

安装

您可以使用 composer 将此插件安装到您的 CakePHP 应用程序中。

安装 composer 包的推荐方法是

composer require klezbucket/cakephp-klez-api

路由

您应该在所需的范围内挂钩插件的路由。例如

Router::scope('/', function (RouteBuilder $routes) {
    $routes->scope('/api', [ 'plugin' => 'KlezApi' ], function (RouteBuilder $routes) {
        $routes->loadPlugin('KlezApi');
    });
});

之后,整个 API 都挂在这个路由上

$routes->connect('/:endpoint.:format', ['controller' => 'Webservice', 'action' => 'index' ]);

有效的路由示例:/api/test.json

API 的关键部分是 (端点,格式) 对。上面的例子表示 'test' 端点,以 'json' 数据。

引导

避免使用 config/bootstrap.php 加载插件。

相反,将以下代码放入您的 src/Application.php bootstrap() 方法中。

        $this->addPlugin('KlezApi', [
            'routes' => false,
            'log' => [
                'enabled' => true,
                'maxlength' => 255
            ],
            'config' => [
                'endpoints' => 'endpoints'
            ]
        ]);

config.endpoints 条目表示位于 /config 文件夹中的 CakePHP 配置文件。log 条目表示日志配置。

日志配置

日志引擎需要 KlezCore 的日志适配器。日志的配置有以下选项

  • enabled: boolean,用于启用日志适配器。默认为 false。
  • maxlength: 整数,指定任何给定日志消息的最大长度。默认为 255。
  • file: 字符串,表示日志的文件名。默认为 'klezapi'
  • scopes: 数组,表示日志适配器的任何上下文。默认为 ['klezapi']

端点配置文件

与任何 CakePHP 配置文件一样,它应该返回一个关联数组。

此数组中的每个键应遵循以下约定:'KlezApi.endpoints.{endpoint}',其中 {endpoint} 表示由路由指定的端点名称。

有两种设置,'单个文件' 一种和 '冗余' 一种。

'单个文件' 示例:我们表示一个相对于 /config 文件夹的文件,插件将搜索该文件并从中加载配置。

此文件应遵循 '冗余' 语法。

	"KlezApi.endpoints.test" => "endpoints/test",

'冗余' 示例,我们将一切放入同一个配置文件中。

	"KlezApi.endpoints.test2" => [
		"config" => [
			"increment" => -3,
		],
		"pipeline" => [
			0 => "KlezApi\\Controller\\Node\\CounterNode",
			1 => "KlezApi\\Controller\\Node\\CounterNode",
			2 => "KlezApi\\Controller\\Node\\CounterNode",
			3 => "KlezApi\\Controller\\Node\\CounterNode",
			4 => "KlezApi\\Controller\\Node\\CounterNode",
			5 => "KlezApi\\Controller\\Node\\FormatterNode",
		],
	],

关键组件是配置和管道数组。

'配置' 表示端点可能需要的所有硬编码设置,作为附加输入。

'管道' 表示插件应按顺序执行以处理和生成输出的 '节点' 集合。

'pipeline' 键对应于主要管道,表示端点执行流的入口点。然而,也可以跨管道跳转。

要指定另一个管道,只需给它一个不同的名称并将其节点集合放入同一个关联数组中,例如

	"KlezApi.endpoints.test2" => [
		"config" => [
			"increment" => -3,
		],
		"pipeline" => [
			0 => "YourApp\\Controller\\Node\\SomeJumpingNode",
			1 => "KlezApi\\Controller\\Node\\FormatterNode",
		],
		'another_pipeline' => [
			0 => "KlezApi\\Controller\\Node\\CounterNode",
			1 => "KlezApi\\Controller\\Node\\CounterNode",
			2 => "KlezApi\\Controller\\Node\\CounterNode",
			3 => "KlezApi\\Controller\\Node\\CounterNode",
			4 => "KlezApi\\Controller\\Node\\CounterNode",
		]
	],

在这个例子中,指定了 'another_pipeline'。

管道和节点

每个端点至少有一个节点集合,称为管道。每个节点应实现 'Node' 接口,以遵守其管道指定的执行流。

该管道在每一个节点之间提供了一个公共缓冲区,数据可以通过它进行存储和转换。

缓冲区API在节点接口内包含了read()、write()、overwrite()和delete()方法。

跨管道跳转

在上面的示例中,指定了另一个管道。

为了跳转到这个新管道,主管道上的节点必须调用jump()方法。此方法的参数必须是所需管道的名称。

        $this->jump('another_pipeline');

如果管道未指定到端点的关联数组中,它将被解析为空管道而不是引发错误。

为了进一步解释,调用jump()的管道将被称为“调用管道”。

停止当前管道

如果出于某种原因不希望继续当前管道的执行,halt()方法将停止进一步的节点评估。

        $this->halt();

注意,如果您在Node中调用halt()后立即调用jump(),则此跳转不会产生任何效果,因为当前管道正在停止。

停止当前管道会将执行流程回溯到调用管道(如果有的话)。

抽象管道

有时几个端点可能有共同的执行路径,复制粘贴节点应该可以工作,但并不那么优雅。

可以使用抽象管道来指定此类共同路径。此外,这些抽象管道不会暴露在API路由中,因此它们在具体化之前保持隐藏。

concretize()方法允许这样做。它需要一个参数,即抽象管道的名称。

        $this->concretize('my_abstract_pipeline');

抽象管道的配置与常规管道完全相同,但它们通过端点的关联数组中的KlezApi.abstract.{$name}键进行指定。

    "KlezApi.abstracts.triple_sum_by_eleven" => [
        "config" => [
            "increment" => 11,
        ],
        "pipeline" => [
            0 => "KlezApi\\Controller\\Node\\CounterNode",
            1 => "KlezApi\\Controller\\Node\\CounterNode",
            2 => "KlezApi\\Controller\\Node\\CounterNode",
        ],
    ],
    "KlezApi.endpoints.abstract" => [
        "config" => [
            'preflight' => [
                'Access-Control-Allow-Origin' => 'klezkaffold3.klez'
            ],
            'concretize' => 'triple_sum_by_eleven'
        ],
        "pipeline" => [
            0 => "KlezApi\\Controller\\Node\\PreflightNode",
            1 => "KlezApi\\Controller\\Node\\ConcretizeTestNode",
            2 => "KlezApi\\Controller\\Node\\FormatterNode",
        ],
    ],

在上面的示例中,指定了一个名为'triple_sum_by_eleven'的抽象管道。还指定了抽象端点。请注意,端点管道中的'ConcretizeTestNode'调用concretize(),并在其配置中指定了'concretize'参数。因此,'triple_sum_by_eleven'抽象被具体化并跳转进去。

如果抽象中指定了多个替代管道,它们也会被具体化,但跳转是在主管道上执行的。

核心节点

我们将尝试提供一些基本的节点,这些节点可以解决任何web服务开发中的许多常见问题。

在提供的Node套件中,还有一些许多在web服务开发上下文中没有意义但在测试中非常有用的测试节点。

格式化节点

如上例中管道的最后一个元素所示,'FormatterNode'是一个核心节点。其主要功能是提供输出,格式化方式由其路由指定的'format'决定。

此节点将其当前缓冲区序列化为所需的格式,然后再发送输出。

跳转方法节点

'JumpMethodNote'跳转到当前请求的小写形式指定的http方法所表示的管道。

    "KlezApi.endpoints.test" => [
        "config" => [

        ],
        "pipeline" => [
            0 => "KlezApi\\Controller\\Node\\RandomIncrementNode",
            1 => "KlezApi\\Controller\\Node\\JumpMethodNode",
            2 => "KlezApi\\Controller\\Node\\FormatterNode",
        ],
        'get' => [
            0 => "KlezApi\\Controller\\Node\\BufferCounterNode",
        ],
        'post' => [
            0 => "KlezApi\\Controller\\Node\\BufferCounterNode",
            1 => "KlezApi\\Controller\\Node\\BufferCounterNode",
        ],
        'put' => [
            0 => "KlezApi\\Controller\\Node\\BufferCounterNode",
            1 => "KlezApi\\Controller\\Node\\BufferCounterNode",
            2 => "KlezApi\\Controller\\Node\\BufferCounterNode",
        ],
    ],

在这个例子中,所有的GET请求都将转换为'get'管道,每个在端点关联数组中指定的方法也是如此。如果没有指定方法,则将其解析为空管道,因此不会发生任何事情。

预检节点

当请求OPTIONS方法时,'PreflightNode'提供CORS头。如果检测到该方法,则提供配置的头,如果没有指定,则传递默认值。此节点在提供CORS头时会停止管道。

    "KlezApi.endpoints.cors" => [
        "config" => [
			'headers => [
				'Access-Control-Allow-Headers' => 'Accept,Authorization,Content-Type'
			]
        ],
        "pipeline" => [
            0 => "KlezApi\\Controller\\Node\\PreflightNode",
            1 => "KlezApi\\Controller\\Node\\RandomIncrementNode"
            2 => "KlezApi\\Controller\\Node\\JumpMethodNode",
            3 => "KlezApi\\Controller\\Node\\FormatterNode",
        ],
        'options' => [
            0 => "KlezApi\\Controller\\Node\\BufferCounterNode",
        ],
        'get' => [
            0 => "KlezApi\\Controller\\Node\\BufferCounterNode",
            1 => "KlezApi\\Controller\\Node\\BufferCounterNode",
        ],
    ],

在这个示例中,当请求 OPTIONS 方法时,'PreflightNode' 将服务配置的 'Access-Control-Allow-Headers',并附加默认缺少的头部 'Access-Control-Allow-Methods' 和 'Access-Control-Allow-Origin'。如果需要更多的头部,它们也可以追加到配置关联数组中。之后,管道将停止。因此,指定的 'options' 管道永远不会执行,因为执行流程不会达到 'JumpMethodNode'。

实现节点

'ImplementationNode' 实现了一个抽象管道,它从 config.implements 中读取所需的管道。

    "KlezApi.abstracts.main" => [
        "pipeline" => [
            0 => "KlezApi\\Controller\\Node\\PreflightNode",
            1 => "KlezApi\\Controller\\Node\\ImplementationNode",
            2 => "KlezApi\\Controller\\Node\\FormatterNode",
        ],
    ],
    "KlezApi.abstracts.auth" => [
        "pipeline" => [
            0 => "App\\Controller\\Node\\CaptchaNode",
            1 => "App\\Controller\\Node\\AuthNode",
        ],
    ],
    "KlezApi.endpoints.auth" => [
        "config" => [
            'implements' => 'auth'
        ],
        "pipeline" => [
            0 => "App\\Controller\\Node\\MainNode", // MainNode runs $this->concretize('main');
        ],
    ],

在上面的示例中,'auth' 端点实现了抽象的 'main' 管道,它围绕在公共特征节点之间的另一个 ImplementationNode。这个 ImplementationNode 实现了 'auth' 抽象管道,它包含应用程序的授权逻辑。

这允许创建一个公共管道部分,'main' 抽象管道。然后指定与业务相关的逻辑,'auth' 抽象管道。

命令

生成裸端点

bin/cake KlezApi.generator newstuff

在端点配置文件中创建一个新的端点条目。

上面的示例将以下条目追加到配置数组中

	"KlezApi.endpoints.newstuff" => [
		"config" => [
		],
		"pipeline" => [
			0 => "KlezApi\\Controller\\Node\\FormatterNode",
		],
	],

它检查端点是否已存在。在这种情况下,端点配置不会被替换,命令将失败。