baraja-core / structured-api
用于定义结构化API端点的复杂库,作为带有模式的类。
Requires
- php: ^8.1
- ext-iconv: *
- ext-json: *
- ext-mbstring: *
- baraja-core/serializer: ^1.0
- baraja-core/service-method-invoker: ^2.2.1
- baraja-core/url: ^1.1
- nette/application: ^3.1
- nette/caching: ^3.1
- nette/di: ^3.0
- nette/http: ^3.1
- nette/robot-loader: ^3.3
Requires (Dev)
- baraja-core/cas: ^1.0
- baraja-core/localization: ^2.0
- phpstan/extension-installer: ^1.1
- phpstan/phpstan: ^1.0
- phpstan/phpstan-deprecation-rules: ^1.0
- phpstan/phpstan-nette: ^1.0
- phpstan/phpstan-strict-rules: ^1.0
- roave/security-advisories: dev-master
- spaze/phpstan-disallowed-calls: ^2.0
- tracy/tracy: ^2.8
- dev-master
- v4.1.1
- v4.1.0
- v4.0.3
- v4.0.2
- v4.0.1
- v4.0.0
- v3.5.1
- v3.5.0
- v3.4.0
- v3.3.3
- v3.3.2
- v3.3.1
- v3.3.0
- v3.2.1
- v3.2.0
- v3.1.2
- v3.1.1
- v3.1.0
- v3.0.6
- v3.0.5
- v3.0.4
- v3.0.3
- v3.0.2
- v3.0.1
- v3.0.0
- v2.5.0
- v2.4.6
- v2.4.5
- v2.4.4
- v2.4.3
- v2.4.2
- v2.4.1
- 2.4.0
- v2.3.2
- v2.3.1
- v2.3.0
- v2.2.1
- v2.2.0
- v2.1.3
- v2.1.2
- v2.1.1
- v2.1.0
- v2.0.10
- v2.0.9
- v2.0.8
- v2.0.7
- v2.0.6
- v2.0.5
- v2.0.4
- v2.0.3
- V2.0.2
- v2.0.1
- v2.0.0
- v1.2.0
- v1.1.2
- v1.1.1
- v1.1.0
- v1.0.12
- v1.0.11
- v1.0.10
- v1.0.9
- v1.0.8
- v1.0.7
- v1.0.6
- v1.0.5
- v1.0.4
- v1.0.3
- v1.0.2
- v1.0.1
- dev-imgbot
- dev-renovate/configure
- dev-restyled/renovate/configure
- dev-dependabot/add-v2-config-file
This package is auto-updated.
Last update: 2024-09-09 20:56:01 UTC
README
BRJ 组织
PHP中的结构化REST API
完全兼容由模式定义的智能结构化API。
- 定义完整的类型提示输入参数,
- 通过模式验证返回的数据,
- 完全兼容Nette框架,
- 通过
#[Inject]
属性(或旧的@inject
注解语法)在公共属性中注入依赖。
📦 安装 & 基本用法
此包可以使用PackageRegistrator安装,它也是Baraja 沙盒的一部分。如果您不使用它,您必须手动按照此指南安装包。
模型配置可以在包根目录中的common.neon
文件中找到。
要手动安装包,请调用Composer并执行以下命令
$ composer require baraja-core/structured-api
🛠️ API端点
API端点是包含操作方法和依赖项的简单类。为了最佳舒适度,请使用您自定义的BaseEndpoint,并声明所有必需的依赖项。
简单示例
<?php declare(strict_types=1); namespace App\Model; final class MyAwesomeEndpoint extends BaseEndpoint { /** * This is test API endpoint as demonstration of inner logic. * * @param string $hello some user-defined parameter. */ public function actionDefault(string $hello = 'world'): MyAwesomeResponse { // The endpoint response can be simply returned as an simple array or typed object. // A type object is much better because it will be used as the basis for documentation. // It will be automatically converted to JSON. return new MyAwesomeResponse( name: 'Test API endpoint', hello: $hello, ); } // or use old syntax: /** * This is test API endpoint as demonstration of inner logic. * * @param string $hello some user-defined parameter. */ public function actionDefault(string $hello = 'world'): void { $this->sendJson([ 'name' => 'Test API endpoint', 'hello' => $hello, ]); } // or return simple array directly: /** * @param array<mixed, mixed> $data */ public function postCreateUser(array $data): array { return [ 'state' => 'ok', 'data' => $data, ]; } }
方法actionDefault
用于格式为/api/v1/test
的请求,并带有查询参数?hello=...
。
方法postCreateUser
将在包含所有数据的POST请求中被调用。
始终直接将端点的响应作为方法的返回类型返回。这使得其他工具(例如,检查代码完整性或生成文档)的静态分析变得更容易。仍然支持sendJson()
、sendOk()
和sendError()
方法,但将来可能会将其标记为已弃用。
📝 端点注册
如果您使用Nette框架,所有端点都将自动注册。这为DIC提供了一种扩展。
要自动注册,只需继承BaseEndpoint
或实现Baraja\StructuredApi\Endpoint
接口。
🌐 HTTP方法
该库支持REST API的所有HTTP方法。HTTP方法的选择是通过方法名解决的。
您可以在方法名开头指定HTTP方法,或使用别名
final class MyAwesomeEndpoint extends BaseEndpoint { public function getDefault(): void { // this logic will be called as GET. } public function actionDefault(): void { // this logic will be called as GET too, // because `action` prefix is alias for GET. } public function postDetail(string $id, string $name, ?string $description = null): void { // this logic will be called as POST. } }
别名列表(别名是可选的)
action
作为GET
update
作为PUT
create
作为POST
💾 获取原始数据
对于处理复杂的数据结构,获取数据的原始原始形式可能很有用。
该库保留键变量array $data
,它始终包含来自用户的原值,无论是否经过验证。
例如
final class OrderEndpoint extends BaseEndpoint { public function postProcessOrder(array $data): void { // variable $data contains all raw data from user. } }
✅ 验证
在运行时调用方法时,将传递的参数与方法定义和数据类型进行验证。这确保端点永远不会用错误的数据调用。
该库保证您将始终获得请求的数据类型。如果您需要定义更复杂的数据类型,您可以使用注释注解。
组合示例
final class ArticleEndpoint extends BaseEndpoint { /** * @param string|null $locale in format "cs" or "en" * @param int $page real page number for filtering, 1 => first page ... "n" page * @param int $limit in interval <0, 500) * @param string|null $status matching constant self::STATUS_* (null, all, published, trash) * @param string|null $query smart search query * @param string|null $filterFrom find all articles from this date * @param string|null $filterTo find all articles to this date * @param string|null $sort sort by supported field * @param string|null $orderBy direction by `ASC` or `DESC` */ public function actionDefault( ?string $locale = null, int $page = 1, int $limit = 32, ?string $status = null, ?string $query = null, ?string $filterFrom = null, ?string $filterTo = null, ?string $sort = null, ?string $orderBy = null, ): void { } }
该库充分利用了PHP 7并始终检查数据类型。如果数据以错误类型传递(例如,布尔值不能通过GET方法传递),它将执行自动转换或抛出错误。
如果参数包含默认值,则它会被自动标记为可选。如果用户没有传递值,将使用默认值。所有必需参数必须始终传递,如果不传递,则不会调用您的逻辑。
🙋 智能响应
该库包含一系列内置方法,用于优雅地处理所有重要返回状态。
例如,如果我们想通过ID获取文章的详细信息并将其从数据库中返回,使用方法是完全直观的
final class ArticleEndpoint extends BaseEndpoint { public function actionDetail(string $id): void { // your logic for fetch data from database // your response $this->sendJson([ 'id' => $id, 'title' => 'My awesome article', 'content' => '...', ]); } }
每个方法都可以通过 send
方法返回输出,或者直接作为类型对象返回。一种更现代的方法是返回整个对象,因为这为我们提供了类型检查以及自动生成文档的基础。
警告:如果您不通过方法或返回语句传递任何输出,端点处理将失败。
在处理操作时,返回成功或错误信息是一个好主意
final class ArticleEndpoint extends BaseEndpoint { public function createDetail(string $title, string $content, ?string $perex = null): void { try { // creating in database... $this->sendOk([ 'id' => 123, ]); } catch (\Exception $e) { $this->sendError('Can not create article because ...'); } } }
🔒 权限
🚩警告:如果您根本不设置权限,则默认所有端点都是私有的,您必须登录才能调用它们!👮
所有API请求都在运行时进行验证。如果您想允许所有用户访问您的端点,请向类中添加 #[PublicEndpoint]
属性。
例如(此端点将是公开的)
#[PublicEndpoint] final class ProductEndpoint extends BaseEndpoint { }
要限制权限,在类或方法上定义一个 #[Role]
属性。
例如(只有管理员和版主可以调用此端点)
#[Role(roles: ['admin', 'moderator'])] final class ArticleEndpoint extends BaseEndpoint { }
权限设置也可以组合使用。例如,在公开端点中,仅限制特定方法的权限
#[PublicEndpoint] final class SitemapEndpoint extends BaseEndpoint { #[Role(roles: 'admin')] public function actionClearCache(): void { // your secured implementation } }
🔒 检查API令牌
如果您想向外部合作伙伴提供API或与另一个应用程序提供安全通信,使用所有请求通过API令牌进行身份验证是一个好主意。为此,有一个官方扩展 structured-api-token-authorizer。
🗺️ 项目端点文档
在开发真实应用程序时,您通常会需要在后端和前端之间传递工作。
为了描述所有端点,该包提供了一个可选扩展,该扩展根据实际代码扫描自动生成文档。
尝试使用 Structured API Documentation。
📄 许可证
baraja-core/structured-api
采用MIT许可证。有关更多详细信息,请参阅 LICENSE 文件。