tenjuu99 / wp-resta
使用DI(依赖注入)的WordPress REST API开发框架
Requires
- php: >=8.2
- papertower/wp-rest-api-psr7: ^0.8.0
Requires (Dev)
- phpstan/extension-installer: ^1.3
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^11.1
- psr-mock/http-message-implementation: ^1.0
- roots/wordpress: ^6.4
- szepeviktor/phpstan-wordpress: ^1.3
README
Wp\Resta
这是一个用于在WordPress上开发REST API的插件。
该插件的理念和接口受到了BEAR.Sunday 的影响。
如何安装
前提:请确保在WordPress管理面板中将永久链接设置保存为“文章标题”等。
用于自定义主题
$ cd /path/to/theme
$ composer require tenjuu99/wp-resta
在 functions.php
中初始化
以下是从示例目录中读取API的设置示例。
<?php require_once __DIR__ . '/vendor/autoload.php'; (new Wp\Resta\Resta)->init([ 'routeDirectory' => [ [__DIR__ . '/vendor/wp/resta/src/REST/Example/Routes', 'Wp\\Resta\\REST\\Example\\Routes\\', 'example'] ], 'use-swagger' => true, 'schemaDirectory' => [ [__DIR__ . '/vendor/wp/resta/src/REST/Example/Schemas', 'Wp\\Resta\\REST\\Example\\Schemas\\'], ], ]);
作为插件使用
也可以将其作为WordPress插件使用。
以下示例使用 composer/installers
将WordPress插件配置到 wp-content/plugins/
以下。
$ composer config "extra.installer-paths.wp-content/plugins/{\$name}/" "['type:wordpress-plugin']"
$ composer require composer/installers tenjuu99/wp-resta
如果成功展开到wp-content/plugins以下,请从管理面板启用插件。
示例
安装后,管理面板将添加一个名为 REST API doc
的菜单。
此页面使用Swagger UI对API定义进行文档化。
此示例实现位于 src/REST/Example/Routes/
以下。
如何开发
要添加自己的路由定义,请在 functions.php
初始化时编写路由目录的设置代码。
传递给 routeDirectory
的数组是 ['目录名', 'php命名空间', 'api命名空间']
,而 schemaDirectory
是 ['目录名', 'php命名空间']
。
(new Wp\Resta\Resta)->init([ 'routeDirectory' => [ ['wp-content/themes/mytheme/vendor/wp/resta/src/REST/Example/Routes', 'Wp\\Resta\\REST\\Example\\Routes\\', 'example'], + ['src/Routes', 'MyREST\\Routes\\', 'myroute'] ], 'schemaDirectory' => [ ['wp-content/themes/mytheme/vendor/wp/resta/src/REST/Example/Schemas', 'Wp\\Resta\\REST\\Example\\Schemas\\'], + ['src/Schemas', 'MyREST\\Schemas\\'] ], ]);
根据需要,在 composer.json
中添加autoload设置。
"autoload": { + "psr-4": { + "MyREST\\": "src/" + } }
创建 src/Routes/HelloWorld.php
。
<?php namespace MyREST\Routes; use Wp\Resta\REST\AbstractRoute; class HelloWorld extends AbstractRoute { public $body = 'Hello, world!'; }
以下URL将被生成。
$ curl http://example.com/wp-json/myroute/helloworld
请确保返回值为 "Hello, world!"。
URL定义和URL变量
myroute
是在 functions.php
中定义的命名空间,而 helloworld
则直接用作类名。
通过定义 ROUTE
常量来更改URL定义。同时,让我们定义一些URL变量。
<?php namespace MyREST\Routes; use Wp\Resta\REST\AbstractRoute; class HelloWorld extends AbstractRoute { protected const ROUTE = 'hello/[name]'; protected const URL_PARAMS = [ 'name' => 'string', ]; public function callback(string $name) : string { return "Hello, ${name}!"; } }
我们期望生成以下URL。
$ curl http://example.com/wp-json/myroute/hello/amashige
我们期望返回 "Hello, amashige!"。
在 ROUTE
常量中,使用 [var]
和 []
包围即可将参数作为路径参数处理。
变量允许以下模式。
protected const URL_PARAMS = [ 'id' => 'integer', 'id_not_required' => '!integer', 'name' => 'string', 'name_not_required' => '!string', 'ok_or_ng' => '(ok|ng)', 'first_name' => [ 'type' => 'string', 'required' => false, 'regex' => '[a-z]+' ], ];
这些可以通过将 ROUTE
常量定义为 user/[id]
的形式作为URL嵌入变量来定义为路径参数。
未作为路径参数使用的但定义在 URL_PARAMS
中的变量作为查询参数使用。
以下示例展开为 http://example.com/wp-json/myroute/user/2?name=tenjuu99
。
protected const ROUTE = 'user/[id]'; protected const URL_PARAMS = [ 'id' => 'integer', 'name' => '?string', ];
这些变量可以通过回调方法接收。
回调
如果继承自 AbstractRoute
的类有一个名为 callback
的方法,则可以调用此方法以将其用作响应的body。可以作为body返回的是可以被 WP_REST_Response
解析的对象。如果返回了 Psr\Http\Message\ResponseInterface
,则将其直接使用。
callback
方法的参数可以接收URL变量。如果定义了 URL变量
id
,则可以将其定义为 callback(int $id)
。
此外,由于存在简单的DI,因此可以将可解决的类作为参数定义以接收。对于在运行时确定值(例如 WP_REST_Response
)的情况,由于在回调被调用时值已确定,因此可以使用它们。
DI
提供了一个简单的DI。
基本上是自动绑定,在大多数情况下无需设置即可使用。基本上只支持构造函数注入(AbstractRoute::callback
是例外)。
// src/Lib/Foo.php namespace MyREST\Lib; class Foo { private Bar $bar; public function __construct(Bar $bar) { $this->bar = $bar; } public function getBarString(): string { return $this->bar->get(); } } // src/Lib/Bar.php namespace MyREST\Lib; class Bar { public function get(): string { return 'bar'; } } // src/Routes/Sample.php namespace MyREST\Routes; use MyREST\Lib\Foo; class Sample extends AbstractRoute { private Foo $foo; public function __construct(Foo $foo) { $this->foo = $foo; } public function callback() { return $this->foo->getBarString(); } }
Bar::get
的返回值将被解决。
上述内容可以通过DI的自动绑定来解决,但如果是接口注入,则无法自动解决。在这种情况下,需要进行设置。设置可以通过将 dependencies
传递给初始化代码来完成。
(new Wp\Resta\Resta)->init([ 'routeDirectory' => [ ... ], 'schemaDirectory' => [ ... ], + 'dependencies' => [ + PSR\Log\LoggerInterface::class => MonoLog\Logger::class, + ], ]);
此外,自动绑定机制仅解决类或接口的依赖,因此如果构造函数接收类或接口以外的值,则无法解决。在这种情况下,请使用函数。
(new Wp\Resta\Resta)->init([ 'routeDirectory' => [ ... ], 'schemaDirectory' => [ ... ], 'dependencies' => [ PSR\Log\LoggerInterface::class => MonoLog\Logger::class, + WP_Query::class => function () { + return new WP_Query(['post_type' => 'post']); + } ], ]);