jaspr/mapper
Composer 安装命令:
composer require jaspr/mapper
包简介
JSON API implementation, by annotations or schemas.
README 文档
README
Implementation of JSON API Standard Specification
This project goal is to create easy-to-use library to implement JSON API specification.
Whole project is at the beginning of development. So don't hesitate to help. I'm open to some good ideas how make this more customizable and friendly.
Library only provides wrappers to create valid JSON API document. Controllers and Response is on you.
Issues
You can write email or create issue in gitlab
Installation
Install library via Composer
composer require jaspr/mapper
Basic Usage
For simplicity, we use
$containeras some dependency provider (Dependency Injection).
Describing your objects
You can choose which way you want to describe your object metadata.
With Annotations
Note: If you want to use annotations you have to use
AnnotationDriverinMetadataFactory
How you can see, setting up resource object is quiet easy. Just annotate your getter with `#[Attribute]
or #[Relationship]` annotation.
Schema
The important part is to implement Resource interface. Then fill up static method getSchema.
Note: If you want to use schema you have to use
SchemaDriverinMetadataFactory
Polymorphic relationships (abstract targets)
A relationship target may be an abstract base class, letting a single relationship resolve to any of
its concrete subtypes. Annotate the abstract base as a resource and each concrete subtype as its own resource:
#[API\Resource(type: 'payment-method')]
abstract class PaymentMethod
{
#[API\Id] public string $id;
#[API\Attribute] public string $status; // common fields live on the base
}
#[API\Resource(type: 'card-payment')]
class CardPayment extends PaymentMethod { #[API\Attribute] public string $pan; }
#[API\Resource(type: 'wire-payment')]
class WirePayment extends PaymentMethod { #[API\Attribute] public string $iban; }
class Order
{
#[API\Id] public string $id;
// target is the abstract base; the related resource may be any concrete subtype
#[API\Relationship(PaymentMethod::class)] public PaymentMethod $method;
}
Requirements and behavior:
- The abstract base must declare a common
#[Id]; any#[Attribute]/#[Relationship]declared on it are the common fields shared by all subtypes. - Concrete subtypes are discovered by inheritance, so they must live under the paths scanned by
MetadataFactory. An abstract base with no registered concrete subtype logs a warning at build time. - Encoding/decoding is polymorphic: the concrete
typeis used. Writing a relationship whosetypeis not one of the allowed concrete subtypes is rejected with a validation error. - Filtering through a polymorphic relationship is restricted to the common fields declared on the abstract base (subtype-only fields are not addressable).
- OpenAPI: the relationship
dataidentifiertypeis an enum of the concrete subtypes, and related/include schemas expand to the concrete subtypes. No standalone CRUD path is generated for the abstract base — it is a relationship target only. - TypeScript: the relationship is emitted as a union of the concrete subtype interfaces
(e.g.
ToOneRelationship<CardPayment | WirePayment>); the abstract base is not emitted as an interface and its common fields are inlined into each subtype. - Route registration:
MetadataRepository::getAll()still returns the abstract base. Consumers registering CRUD routes should skip entries whereisAbstract()istrue(abstracts are not instantiable). UsegetSubTypes(string $type)/getConcreteByClass(string $className)to resolve the concrete subtypes.
Note: interfaces as targets are not supported yet — use an abstract class.
MetadataRepository
To create MetadataRepository we must use MetadataFactory.
Usage
<?php
/** @var $container Psr\Container\ContainerInterface */
// This is cache instance implements PSR SimpleCache
$cache = $container->get( Psr\SimpleCache\CacheInterface::class);
// This is AnnotationDriver or SchemaDriver, depends on your preferences
$driver = $container->get(\JSONAPI\Driver\Driver::class);
// Paths to your object representing resources
$paths = ['paths/to/your/resources','another/path'];
// Factory returns instance of MetadataRepository
$repository = JSONAPI\Factory\MetadataFactory::create(
$paths,
$cache,
$driver
);
Encoder
Options
| Param | Default | Description |
|---|---|---|
| repository | Instance of MetadataRepository. |
Usage
<?php
// First we need DocumentBuilderFactory
// Let's get MetadataRepository from DI
/** @var $container Psr\Container\ContainerInterface */
$metadataRepository = $container->get(JSONAPI\Metadata\MetadataRepository::class);
$encoder = \JSONAPI\Mapper\Encoding\EncoderFactory::createDefaultEncoder($metadataRepository)
$data = new \JSONAPI\Mapper\Test\Resources\Valid\GettersExample('id');
/** @var \JSONAPI\Mapper\Components\Membership\ResourceObjectIdentifier $identifier */
$identifier = $encoder->identify($data);
/** @var \JSONAPI\Mapper\Components\Membership\ResourceObject $resource */
$resource = $encoder->encode($data);
/** @var \JSONAPI\Mapper\Components\Membership\Document $document */
$document = $encoder->compose($data);
Request Parser
This object works with url, and parse required keywords as described at JSON API Standard
Options
| Param | Default | Description |
|---|---|---|
| baseUrl | URL where you API lays. Must end with / to work properly with relative links. | |
| repository | Instance of MetadataRepository. | |
| pathParser | PathParser | Instance of PathParserInterface. Provides information about path, like resource type, resource ID, relation type, is it collection or is it relationship. |
| paginationParser | OffsetStrategyParser | Instance of PaginationParserInterface. Pagination. |
| sortParser | SortParser | Instance of SortParserInterface. Sort. |
| inclusionParser | InclusionParser | Instance of InclusionParserInterface. Inclusion. |
| fieldsetParser | FieldsetParser | Instance of FieldsetParserInterface. Sparse Fields |
| filterParser | ExpressionFilterParser | FilterParserInterface instance, which is responsible for parsing filter. Filter |
| bodyParser | BodyParser | Instance of BodyParserInterface. |
| logger | NullLogger | LoggerInterface instance, PSR compliant logger instance. |
Filter
As described, specification is agnostic about filter implementation. So I created, more like borrowed, expression filter from OData. So now you can use something like this:
?filter=stringProperty eq 'string' and contains(stringProperty,'asdf') and intProperty in (1,2,3) or boolProperty ne true and relation.property eq null
Or if you have simpler use cases you can try QuatrodotFilter:
?filter=stringProperty::contains::Bonus|boolProperty::eq::true
Pagination
I implement two of three pagination technics
- LimitOffsetPagination
- PagePagination
Includes
https://jsonapi.org/format/#fetching-includes
Sort
https://jsonapi.org/format/#fetching-sorting
Index Page
If you want use JASPR SDK to its full potential, consider expose index page.
<?php
$doc = new JSONAPI\Mapper\IndexDocument(self::$mr, self::$url);
$response = json_encode($doc);
which returns something like this:
{
"jsonapi": {
"version": "1.0"
},
"links": {
"relation": "https:\/\/unit.test.org\/relation",
"getter": "https:\/\/unit.test.org\/getter",
"meta": "https:\/\/unit.test.org\/meta",
"prop": "https:\/\/unit.test.org\/prop",
"third": "https:\/\/unit.test.org\/third"
},
"meta": {
"title": "JSON:API Index Page",
"baseUrl": "https:\/\/unit.test.org/"
}
}
And if your front-end use jaspr/client-js library, then you can use useJsonApiWithIndex factory to enjoy RESTful
experience.
Open API Schema
This library provides lightweight wrapper around OAS. It can generate OAS v3.0.3 schema in json, so you can provide doc for your api easily.
Basic Example
$factory = new OpenAPISpecificationBuilder(
$metadataRepository,
'https://your.api.url'
);
$info = new Info('JSON:API OAS', '1.0.0');
$info->setDescription('Test specification');
$info->setContact(
(new Contact())
->setName('Tomas Benedikt')
->setEmail('tomas.benedikt@gmail.com')
->setUrl('https://gitlab.com/jaspr')
);
$info->setLicense(
(new License('MIT'))
->setUrl('https://gitlab.com/jaspr/mapper/-/blob/5.x/LICENSE')
);
$info->setTermsOfService('https://gitlab.com/jaspr/mapper/-/blob/5.x/CONTRIBUTING.md');
$oas = $factory->create($info);
$oas->setExternalDocs(new ExternalDocumentation('https://gitlab.com/jaspr/mapper/-/wikis/home'));
$json = json_encode($oas);
For more examples, try look at tests
jaspr/mapper 适用场景与选型建议
jaspr/mapper 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 15.77k 次下载、GitHub Stars 达 0, 最近一次更新时间为 2022 年 06 月 16 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「annotations」 「php」 「json」 「rest」 「serialization」 「api」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 jaspr/mapper 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 jaspr/mapper 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 jaspr/mapper 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
A collection of helpers for PHPUnit to ease testing Tarantool libraries.
Kinikit - PHP Application development framework MVC component
ext-json wrapper with sane defaults
A package to cast json fields, each sub-keys is castable
The last validation library you will ever need!
swagger-php - Generate interactive documentation for your RESTful API using phpdoc annotations
统计信息
- 总下载量: 15.77k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 19
- 依赖项目数: 1
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2022-06-16