nilportugues/haljson-bundle
Composer 安装命令:
composer require nilportugues/haljson-bundle
包简介
HAL+JSON API Transformer Bundle for Symfony 2 and Symfony 3
关键字:
README 文档
README
For Symfony 2 and Symfony 3
- Installation
- Usage
- Outputing API Responses
- Integration with NelmioApiDocBundleBundle
- Quality
- Contribute
- Support
- Authors
- License
Installation
Step 1: Download the Bundle
Open a command console, enter your project directory and execute the following command to download the latest stable version of this bundle:
$ composer require nilportugues/haljson-bundle
Step 2: Enable the Bundle
Then, enable the bundle by adding it to the list of registered bundles
in the app/AppKernel.php file of your project:
<?php // app/AppKernel.php // ... class AppKernel extends Kernel { public function registerBundles() { $bundles = array( // ... new NilPortugues\Symfony\HalJsonBundle\NilPortuguesSymfonyHalJsonBundle(), ); // ... } // ... }
Usage
Creating the mappings
Mapping directory
Mapping files should be located at the app/config/serializer directory. This directory must be created.
It can be also be customized and placed elsewhere by editing the app/config/config.yml configuration file:
# app/config/config.yml nilportugues_hal_json: mappings: - "%kernel.root_dir%/config/serializer/" - @AppBundle/Product/config/Mappings
Mapping files
The HAL+JSON transformer works by transforming an existing PHP object into its JSON representation. For each object, a mapping file is required.
Mapping files must be placed in the mappings directory. The expected mapping file format is .yml and will allow you to rename, hide and create links relating all of your data.
For instance, here's a quite complex Post object to demonstrate how it works:
$post = new Post( new PostId(9), 'Hello World', 'Your first post', new User( new UserId(1), 'Post Author' ), [ new Comment( new CommentId(1000), 'Have no fear, sers, your king is safe.', new User(new UserId(2), 'Barristan Selmy'), [ 'created_at' => (new DateTime('2015/07/18 12:13:00'))->format('c'), 'accepted_at' => (new DateTime('2015/07/19 00:00:00'))->format('c'), ] ), ] );
And the series of mapping files required:
# app/config/serializer/acme_domain_dummy_post.yml mapping: class: Acme\Domain\Dummy\Post alias: Message aliased_properties: author: author title: headline content: body hide_properties: [] id_properties: - postId urls: self: get_post ## @Route name comments: get_post_comments ## @Route name curies: name: example href: http://example.com/docs/rels/{rel}
# app/config/serializer/acme_domain_dummy_value_object_post_id.yml mapping: class: Acme\Domain\Dummy\ValueObject\PostId aliased_properties: [] hide_properties: [] id_properties: - postId urls: self: get_post ## @Route name curies: name: example href: http://example.com/docs/rels/{rel}
# app/config/serializer/acme_domain_dummy_comment.yml mapping: class: Acme\Domain\Dummy\Comment aliased_properties: [] hide_properties: [] id_properties: - commentId urls: self: get_comment ## @Route name curies: name: example href: http://example.com/docs/rels/{rel}
# app/config/serializer/acme_domain_dummy_value_object_comment_id.yml mapping: class: Acme\Domain\Dummy\ValueObject\CommentId aliased_properties: [] hide_properties: [] id_properties: - commentId urls: self: get_comment ## @Route name curies: name: example href: http://example.com/docs/rels/{rel}
# app/config/serializer/acme_domain_dummy_user.yml mapping: class: Acme\Domain\Dummy\User aliased_properties: [] hide_properties: [] id_properties: - userId urls: self: get_user friends: get_user_friends ## @Route name comments: get_user_comments ## @Route name curies: name: example href: http://example.com/docs/rels/{rel}
# app/config/serializer/acme_domain_dummy_value_object_user_id.yml mapping: class: Acme\Domain\Dummy\ValueObject\UserId aliased_properties: [] hide_properties: [] id_properties: - userId urls: self: get_user ## @Route name friends: get_user_friends ## @Route name comments: get_user_comments ## @Route name curies: name: example href: http://example.com/docs/rels/{rel}
Outputing API Responses
It is really easy, just get an instance of the HalJsonSerializer from the Service Container and pass the object to its serialize() method. Output will be valid JSON-API.
Here's an example of a Post object being fetched from a Doctrine repository.
Finally, a helper trait, HalJsonResponseTrait is provided to write fully compilant responses wrapping the PSR-7 Response objects provided by the original JSON API Transformer library.
<?php namespace AppBundle\Controller; use NilPortugues\Symfony\HalJsonBundle\Serializer\HalJsonResponseTrait; use Symfony\Bundle\FrameworkBundle\Controller\Controller; class PostController extends Controller { use HalJsonResponseTrait; /** * @\Symfony\Component\Routing\Annotation\Route("/post/{postId}", name="get_post") * * @param $postId * @return \Symfony\Component\HttpFoundation\Response */ public function getPostAction($postId) { $post = $this->get('doctrine.post_repository')->find($postId); $serializer = $this->get('nil_portugues.serializer.hal_json_serializer'); /** @var \NilPortugues\Api\Hal\HalTransformer $transformer */ $transformer = $serializer->getTransformer(); $transformer->setSelfUrl($this->generateUrl('get_post', ['postId' => $postId], true)); $transformer->setNextUrl($this->generateUrl('get_post', ['postId' => $postId+1], true)); return $this->response($serializer->serialize($post)); } }
Output:
HTTP/1.1 200 OK
Cache-Control: private, max-age=0, must-revalidate
Content-type: application/hal+json
{
"post_id": 9,
"headline": "Hello World",
"body": "Your first post",
"_embedded": {
"author": {
"user_id": 1,
"name": "Post Author",
"_links": {
"self": {
"href": "http://example.com/users/1"
},
"example:friends": {
"href": "http://example.com/users/1/friends"
},
"example:comments": {
"href": "http://example.com/users/1/comments"
}
}
},
"comments": [
{
"comment_id": 1000,
"dates": {
"created_at": "2015-08-13T22:47:45+02:00",
"accepted_at": "2015-08-13T23:22:45+02:00"
},
"comment": "Have no fear, sers, your king is safe.",
"_embedded": {
"user": {
"user_id": 2,
"name": "Barristan Selmy",
"_links": {
"self": {
"href": "http://example.com/users/2"
},
"example:friends": {
"href": "http://example.com/users/2/friends"
},
"example:comments": {
"href": "http://example.com/users/2/comments"
}
}
}
},
"_links": {
"example:user": {
"href": "http://example.com/users/2"
},
"self": {
"href": "http://example.com/comments/1000"
}
}
}
]
},
"_links": {
"curies": [
{
"name": "example",
"href": "http://example.com/docs/rels/{rel}",
"templated": true
}
],
"self": {
"href": "http://example.com/posts/9"
},
"next": {
"href": "http://example.com/posts/10"
},
"example:author": {
"href": "http://example.com/users/1"
},
"example:comments": {
"href": "http://example.com/posts/9/comments"
}
},
"_meta": {
"author": [
{
"name": "Nil Portugués Calderó",
"email": "contact@nilportugues.com"
}
]
}
}
Response objects (HalJsonResponseTrait)
The following HalJsonResponseTrait methods are provided to return the right headers and HTTP status codes are available:
private function errorResponse($json); private function resourceCreatedResponse($json); private function resourceDeletedResponse($json); private function resourceNotFoundResponse($json); private function resourcePatchErrorResponse($json); private function resourcePostErrorResponse($json); private function resourceProcessingResponse($json); private function resourceUpdatedResponse($json); private function response($json); private function unsupportedActionResponse($json);
Integration with NelmioApiDocBundleBundle
The NelmioApiDocBundle is a very well known bundle used to document APIs. Integration with the current bundle is terrible easy.
Here's an example following the PostContoller::getPostAction() provided before:
<?php namespace AppBundle\Controller; use NilPortugues\Symfony\HalJsonBundle\Serializer\HalJsonResponseTrait; use Symfony\Bundle\FrameworkBundle\Controller\Controller; class PostController extends Controller { use HalJsonResponseTrait; /** * Get a Post by its identifier. Will return Post, Comments and User data. * * @Nelmio\ApiDocBundle\Annotation\ApiDoc( * resource=true, * description="Get a Post by its unique id", * ) * * @Symfony\Component\Routing\Annotation\Route("/post/{postId}", name="get_post") * @Sensio\Bundle\FrameworkExtraBundle\Configuration\Method({"GET"}) * * @param $postId * @return \Symfony\Component\HttpFoundation\Response */ public function getPostAction($postId) { $post = $this->get('doctrine.post_repository')->find($postId); $serializer = $this->get('nil_portugues.serializer.hal_json_serializer'); /** @var \NilPortugues\Api\Hal\JsonTransformer $transformer */ $transformer = $serializer->getTransformer(); $transformer->setSelfUrl($this->generateUrl('get_post', ['postId' => $postId], true)); $transformer->setNextUrl($this->generateUrl('get_post', ['postId' => $postId+1], true)); return $this->response($serializer->serialize($post)); } }
And the recommended configuration to be added in app/config/config.yml
#app/config/config.yml nelmio_api_doc: sandbox: authentication: name: access_token delivery: http type: basic custom_endpoint: false enabled: true endpoint: ~ accept_type: ~ body_format: formats: [] default_format: form request_format: formats: json: application/hal+json method: accept_header default_format: json entity_to_choice: false
Quality
To run the PHPUnit tests at the command line, go to the tests directory and issue phpunit.
This library attempts to comply with PSR-1, PSR-2, PSR-4 and PSR-7.
If you notice compliance oversights, please send a patch via Pull Request.
Contribute
Contributions to the package are always welcome!
- Report any bugs or issues you find on the issue tracker.
- You can grab the source code at the package's Git repository.
Support
Get in touch with me using one of the following means:
- Emailing me at contact@nilportugues.com
- Opening an Issue
Authors
License
The code base is licensed under the MIT license.
nilportugues/haljson-bundle 适用场景与选型建议
nilportugues/haljson-bundle 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 789 次下载、GitHub Stars 达 10, 最近一次更新时间为 2015 年 08 月 23 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「symfony」 「json」 「Symfony2」 「api」 「response」 「hal」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 nilportugues/haljson-bundle 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 nilportugues/haljson-bundle 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 nilportugues/haljson-bundle 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Kinikit - PHP Application development framework MVC component
The bundle for easy using json-rpc api on your project
ext-json wrapper with sane defaults
A package to cast json fields, each sub-keys is castable
Bundle Symfony DaplosBundle
Symfony2 Barcode Generator Bundle with Twig function extension
统计信息
- 总下载量: 789
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 10
- 点击次数: 21
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2015-08-23