Recommended
PDF
PDF
PDF
PDF
Laravel における Blade 拡張のツラミ
PDF
PDF
Laravel で API バージョニングを実装するなら
PDF
PPTX
PDF
PDF
PhpStormを使おう --高槻からは快速急行が早くなります #jbugj
PDF
Laravelのパッケージのテストに便利なパッケージ
PDF
こんなに使える!今どきのAPIドキュメンテーションツール
PDF
PDF
今、最もイケてるPHPフレームワークLaravel4
PDF
脆弱性もバグ、だからテストしよう PHPカンファンレス2015
PDF
flyingV Laravel & AWS 經驗分享
PDF
PDF
Javaで1から10まで書いた話(sanitized)
PDF
PPTX
PDF
PDF
PPT
今、最もイケてるPHPフレームワークLaravel4
PDF
PDF
PDF
PDF
PDF
PPTX
PDF
More Related Content
PDF
PDF
PDF
PDF
Laravel における Blade 拡張のツラミ
PDF
PDF
Laravel で API バージョニングを実装するなら
PDF
PPTX
What's hot
PDF
PDF
PhpStormを使おう --高槻からは快速急行が早くなります #jbugj
PDF
Laravelのパッケージのテストに便利なパッケージ
PDF
こんなに使える!今どきのAPIドキュメンテーションツール
PDF
PDF
今、最もイケてるPHPフレームワークLaravel4
PDF
脆弱性もバグ、だからテストしよう PHPカンファンレス2015
PDF
flyingV Laravel & AWS 經驗分享
PDF
PDF
Javaで1から10まで書いた話(sanitized)
PDF
PPTX
PDF
PDF
PPT
今、最もイケてるPHPフレームワークLaravel4
PDF
PDF
PDF
PDF
PDF
Similar to LaravelでAPI定義を管理する
PPTX
PDF
PDF
PDF
AWS Black Belt Tech シリーズ 2015 - Amazon API Gateway
PDF
ochacafe#6 人にもマシンにもやさしいAPIのエコシステム
PDF
Amazon product advertising apiで遊んでみた
PDF
PDF
Hypermedia: The Missing Element to Building Adaptable Web APIs in Rails (増補日本語版)
PPT
PDF
Laravelを用いたゲームサーバーのチューニング
PDF
PPT
OSC2008 Tokyo/Spring REST勉強夜会
PDF
50分で掴み取る ASP.NET Web API パターン&テクニック
More from Kenjiro Kubota
PDF
PDF
アイスタイル特設サイトにおけるVue.js導入事例(再演)
PDF
PDF
アイスタイル特設サイトにおけるVue.jsの導入事例
PDF
PDF
フロントエンドエンジニアが知るべきFirebaseの世界
PDF
PHP,Go,Elasticsearchによる、@cosmeを5倍速くする取り組み
PDF
カメラを利用したアプリを作って約1000人で遊んだ話
PDF
PDF
introducing vue-wait-component
PDF
PDF
2017: A CSS Design Odyssey
PDF
Introducing hhvm hack-async
PDF
PDF
PDF
LaravelでAPI定義を管理する 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. <?php
namespace AppHttpActionApi;
final class GetThisWeeksGameSoftwareRelease
{
private $service;
public function __construct(ThisWeeksGameSoftwareRelease $service)
{
$this->service = $service;
}
public function __invoke(GetThisWeeksGameSoftwareReleaseRequest $request): Responder
{
$validated = $request->validated();
$limit = $validated['limit'] ?? 3;
$offset = $validated['offset'] ?? 0;
$collection = $this->service->getCollection((int) $limit, (int) $offset);
return new GetThisWeeksGameSoftwareReleaseResponder($collection);
}
}
16. class RouteServiceProvider extends ServiceProvider
{
public function register()
{
parent::register();
/** @var Router $router */
$router = $this->app['router'];
$router->group(['prefix' => 'api'], function (Router $router) {
$router->get(
'/game_software/release/week',
['uses' => GetThisWeeksGameSoftwareRelease::class]
);
});
}
}
17. 18. 19. 20. 21. 22. <?php
namespace AppHttpResponderApi;
use AppHttpResponderHateoasResponder;
use IlluminateContractsSupportResponsable;
use AppDomainCollectionGameSoftwareCollection;
class GetThisWeeksGameSoftwareReleaseResponder implements Responsable
{
use HateoasResponder;
private $resource;
public function __construct(GameSoftwareCollection $collection)
{
$this->resource = $collection;
}
public function toResponse($request): IlluminateHttpResponse
{
return $this->hal($this->resource);
}
}
23. 24. 25. REST API Model
Level 0
HTTPを用いてXMLレスポンスを返却すること
Level 1
URLでリソースを表すこと
Level 2
HTTPメソッドを正しく使い分けること
Level 3
ハイパーメディアコントロール
26. 27. 28. 29. 30. 31. 32. Add Annotation
/**
* Class GameSoftware
* @package AppDomainEntity
* @HateoasRelation(
* "self",
* href = "expr('/api/game_software/' ~ object.getId())"
* )
* @HateoasRelation(
* "page",
* href = "expr('/game_software/' ~ object.getId())"
* )
*/
class GameSoftware implements EntityInterface, HateoasResource
{
33. /**
* @var string
* @Accessor("getReleaseDate")
*/
protected $releaseDate;
/**
* @var int
* @Type("int")
*/
protected $price;
public function getId(): int
{
return $this->id;
}
public function getReleaseDate(string $format = "Y-m-d H:i:s"): string
{
return (new DateTime($this->releaseDate))->format($format);
}
34. <?php
namespace AppHttpResponder;
use HateoasHateoas;
use HateoasHateoasBuilder;
use IlluminateHttpResponse;
use HateoasUrlGeneratorCallableUrlGenerator;
trait HateoasResponder
{
protected function hal(
HateoasResource $resource,
int $status = 200,
array $headers = []
): Response
{
return new Response(
$this->builder()->serialize($resource, 'json'),
$status,
array_merge(['Content-Type' => 'application/hal+json'], $headers)
);
}
35. protected function builder(): Hateoas
{
return HateoasBuilder::create()
->setUrlGenerator(
null,
new CallableUrlGenerator(function ($route, array $parameters) {
return route($route, $parameters);
})
)
->build();
}
}
36. <?php
namespace AppHttpResponderApi;
use AppHttpResponderHateoasResponder;
use IlluminateContractsSupportResponsable;
use AppDomainCollectionGameSoftwareCollection;
class GetThisWeeksGameSoftwareReleaseResponder implements Responsable
{
use HateoasResponder;
private $resource;
public function __construct(GameSoftwareCollection $collection)
{
$this->resource = $collection;
}
public function toResponse($request): IlluminateHttpResponse
{
return $this->hal($this->resource);
}
}
37. こんな感じのレスポンスになります。
{
"id": 1,
"title": "スーパーマリオオデッセイ",
"description": "マリオ、世界の旅へ。Nintendo Switch向けソフトに新作3Dマリオが登場します。…",
"release_date": "2017-10-27 00:00:00",
"price": 5545,
"retail_price_desired": 6458,
"platform": "Nintendo Switch",
"thumbnail": "https://images-na.ssl-images-amazon.com/images/I/….jpg",
"_links": {
"self": {
"href": "/api/game_software/1"
},
"page": {
"href": "/game_software/1"
}
}
}
38. 39. public function findReleaseThisWeek(int $limit, int $offset): GameSoftwareCollection
{
$data = $this->criteria->getReleaseThisWeek($limit, $offset);
$collection = new GameSoftwareCollection();
foreach ($data as $item) {
$hydrator = new ReflectionHydrator();
$namingStrategy = new CompositeNamingStrategy([
'release_date' => new MapNamingStrategy([
'release_date' => 'releaseDate'
]),
'retail_price_desired' => new MapNamingStrategy([
'retail_price_desired' => 'retailPriceDesired'
]),
]);
$hydrator->setNamingStrategy($namingStrategy);
$gameSoft = $hydrator->hydrate(
$item,
new GameSoftware()
);
$collection->add($gameSoft);
}
return $collection;
}
40. 41. 42. 44. 45. 46. 47. 48. HATEOASで利用したアノテーション登録でSwagger PHPのアノテーシ
ョン @SWG のClassが見つからないエラーが発生するのでこのアノテーシ
ョンはIgnoreさせる
class AnnotationRegisterServiceProvider extends ServiceProvider
{
public function register()
{
$loader = require base_path().'/vendor/autoload.php';
AnnotationRegistry::registerLoader([$loader, 'loadClass']);
AnnotationReader::addGlobalIgnoredNamespace('SWG'); // Add
}
}
49. Modelの定義
/**
* Class GameSoftware
* @package AppDomainEntity
* @HateoasRelation(
* "self",
* href = "expr('/api/game_software/' ~ object.getId())"
* )
* @HateoasRelation(
* "page",
* href = "expr('/game_software/' ~ object.getId())"
* )
* @SWGDefinition(
* type="object",
* @SWGXml(name="GameSoftware")
* )
*/
class GameSoftware implements EntityInterface, HateoasResource
50. 51. /**
* @SWGProperty(
* property="_links",
* type="object",
* @SWGProperty(
* property="self",
* type="object",
* @SWGProperty(
* property="href",
* type="string"
* )
* ),
* @SWGProperty(
* property="page",
* type="object",
* @SWGProperty(
* property="href",
* type="string"
* )
* )
* )
*/
52. Collectionの定義
/**
* Class GameSoftwareCollection
* @package AppDomainCollection
* @SWGDefinition(
* type="object",
* @SWGXml(name="GameSoftwareCollection")
* )
*/
class GameSoftwareCollection implements EntityCollectionInterface, HateoasResource
{
/**
* @var GameSoftware[]
* @SerializedName("game_software")
* @SWGProperty(
* property="game_software",
* @SWGXml(name="GameSoftware", wrapped=true)
* )
*/
protected $entities = [];
53. Responseの定義
(ResponderClass)
/**
* @param IlluminateHttpRequest $request
* @return IlluminateHttpResponse
* @SWGResponse(
* response="GetThisWeeksGameSoftwareReleaseResponder",
* description="今週発売のゲームを返す",
* @SWGSchema(ref="#/definitions/GameSoftwareCollection")
* )
*/
public function toResponse($request): IlluminateHttpResponse
{
return $this->hal($this->resource);
}
54. RequestParameterの定義
/**
* @SWGParameter(
* parameter="GetThisWeeksGameSoftwareReleaseRequest_limit",
* name="limit",
* description="取得件数",
* in="query",
* required=false,
* type="integer",
* format="int32"
* )
* @SWGParameter(
* parameter="GetThisWeeksGameSoftwareReleaseRequest_offset",
* name="offset",
* description="取得位置",
* in="query",
* required=false,
* type="integer",
* format="int32"
* )
*/
public function rules(): array
55. Endpointの定義
/**
* Class GetThisWeeksGameSoftwareRelease
* @package AppHttpActionApi
* @SWGGet(
* path="/game_software/release/week",
* summary="今週発売のゲームソフト",
* description="",
* consumes={"application/json"},
* produces={"application/hal+json"},
* @SWGParameter(ref="#/parameters/GetThisWeeksGameSoftwareReleaseRequest_limit"),
* @SWGParameter(ref="#/parameters/GetThisWeeksGameSoftwareReleaseRequest_offset"),
* @SWGResponse(
* response="default",
* ref="#/responses/GetThisWeeksGameSoftwareReleaseResponder"
* )
* )
*/
final class GetThisWeeksGameSoftwareRelease
56. swagger.jsonの生成
$ php artisan l5-swagger:generate
開発環境にデプロイする際に実行
もしくは config/l5-swagger.php の 'generate_always' => true にすることで
SwaggerUIにアクセスするたびに生成されます。
/api/documentation にアクセスするとSwaggerUIが展開される。
エンドポイントを変更したい場合は config/l5-swagger.php の
'api' => 'api/documentation', の項目から変更できます。
57. 58.