baraja-core/structured-api

该包最新版本(v4.1.1)没有可用的许可证信息。

用于定义结构化API端点的复杂库,作为带有模式的类。


README


BRJ 组织

PHP中的结构化REST API

Integrity check

完全兼容由模式定义的智能结构化API。

  • 定义完整的类型提示输入参数,
  • 通过模式验证返回的数据,
  • 完全兼容Nette框架,
  • 通过#[Inject]属性(或旧的@inject注解语法)在公共属性中注入依赖。

Baraja Structured API debug Tracy panel

📦 安装 & 基本用法

此包可以使用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 文件。