🌐 言語: 🇻🇳 Tiếng Việt · 🇬🇧 English · 🇯🇵 日本語(現在)
GP247 で正しく API を作成するガイド
はじめに
このドキュメントでは、GP247 の標準に沿って API エンドポイントを自作(新規作成)する方法を説明します。 対象は、独自の API で GP247 サイトを拡張したい開発者です(例:モバイルアプリ向けのデータ出力、 外部の管理ソフト、サードパーティ連携)。読み終えると、コードをどこに置くか、ルートをどう宣言するか、 コントローラー/ミドルウェア/認証をどう使うかがわかります。コピーしてすぐ動く完全な例も載せています。 既存の API を呼び出すだけ(自作しない)なら、先に GP247 API 入門 をお読みください。
ℹ️ GP247 の黄金ルール: コアのコード(
vendor/gp247/*)は変更しません。特定のサイト向けに独自の API を 追加するときは、プラグイン(app/GP247/Plugins/フォルダー)か、app/GP247/を使ったオーバーライドの 仕組みで行います。core/front/shopパッケージに直接追加するのは、そのパッケージの主要メンテナーだけです。
1. 書く前に API のアーキテクチャを理解する
GP247 の API は、既存のいくつかの部品を組み合わせてできています。部品を理解すると、正しい場所にコードを差し込めます。
1.1. 2 つのグループと接頭辞(prefix)
| グループ | ルートで使う定数 | 値 | 用途 |
|---|---|---|---|
| Core(管理) | GP247_API_CORE_PREFIX |
api/core |
システム管理(管理者トークンが必要) |
| Front(ストアフロント) | GP247_API_FRONT_PREFIX |
api/front |
ストアのデータと顧客アカウント |
この 2 つの定数は vendor/gp247/core/src/Library/Const.php で固定的に宣言されています。ルートでは必ず定数を使ってください
("api/core" という文字列を手書きしない)。将来接頭辞が変わっても、あなたのコードが自動的に追従します。
1.2. API モードを有効にする
API は GP247_API_MODE フラグがオンのときだけ動作します。サイトの .env ファイルを確認してください。
GP247_API_MODE=true
このフラグがオフの場合、API のルートは一切読み込まれません(vendor/gp247/core/src/routes.php を参照)。
1.3. API ルートが自動で読み込まれる仕組み
GP247_API_MODE=true のとき、コアは次のフォルダー内のすべてのファイルを自動で走査して読み込み、
すべてをミドルウェアグループ GP247_API_MIDDLEWARE で包みます。
vendor/gp247/core/src/Routes/Api/*.phpvendor/gp247/shop/src/Routes/Api/*.phpvendor/gp247/front/src/Routes/Api/*.php
GP247_API_MIDDLEWARE = ['api', 'api.extend'] です。api.extend は GP247 のミドルウェアグループで、
config('gp247-config.api.middleware') で定義されています。
| 順序 | ミドルウェア | 役割 |
|---|---|---|
| 1 | json.response |
すべてのレスポンスを JSON にする(ヘッダー Accept: application/json を設定) |
| 2 | api.connection |
任意のアプリケーション用の鍵(apiconnection/apikey)— 設定でオン/オフ |
| 3 | throttle: 1000 |
1 サイクルあたり 1000 回の呼び出しに制限(不正利用の防止) |
⚠️ 注意: この順序は固定です。変更しないでください。 config に明記された規約です。
👉 プラグインにとって重要な結果: core/shop/front の
Routes/Api/に置いたルートには、上の 3 つのレイヤーが 自動で付きます。しかしプラグインから追加したルートは別の場所(セクション 4)で読み込まれるため、 自動では付きません。自分で包む必要があります。
1.4. Laravel Sanctum による認証
GP247 は Sanctum(Bearer 形式のトークン)を使います。2 つの独立した「ガード」(ログインの入口)があります。
| ガード | プロバイダー | 対象 | トークンを発行する場所 |
|---|---|---|---|
admin-api |
admin_provider |
管理者 | api/core/login |
customer-api |
customer_provider |
顧客/会員 | api/front/login |
各トークンには、できることを制限する**権限の範囲(scope/ability)**も付きます。スコープは
config('gp247-config.api.auth') から取得します(.env で変更可能)。
| 設定キー | 既定値 | 意味 |
|---|---|---|
api_scope_admin |
admin |
通常の管理者 |
api_scope_admin_supper |
admin-supper |
上位の管理者(administrator ロール) |
api_scope_user |
user |
有効化済みの会員 |
api_scope_user_guest |
user-guest |
未有効化の会員/ゲスト |
ログインが必要なルートを保護するには、次のミドルウェアの組み合わせを使います。
'middleware' => [
'auth:admin-api', // Front API の場合は 'auth:customer-api'
'ability:admin,admin-supper', // 許可するスコープ
]
1.5. ヘルパー gp247_namespace() — オーバーライドを可能にする仕組み
GP247 のルートでは、コントローラーを Controller::class と直接書かず、
gp247_namespace() で包みます。
$productController = gp247_namespace(\GP247\Shop\Api\Admin\AdminProductController::class);
Route::get('list', $productController.'@getProductList');
このヘルパーは自動で確認します。app/GP247/... にオーバーライド用のファイルがあればアプリ側を使い、
なければ vendor 内のものを使います。これにより、エンドユーザーは vendor を変更せずにコントローラーをオーバーライドできます。
GP247\... パッケージのコントローラーをルートで指すときは、必ずこのヘルパーを使ってください。
2. 命名規則とレスポンスの形式
新しい API をシステムの他の部分と揃えるため、次の規則を守ってください。
-
リソースごとにまとめる:データのグループごとに 1 つの
Route::group(['prefix' => 'product'], ...)にします。 -
2 つの標準アクション:
list(一覧)とdetail/{id}(1 件の詳細)。 -
コントローラーのメソッド名:
get<Resource>Listとget<Resource>Detail(例:getProductList、getProductDetail)。 -
必ず JSON を返す:
response()->json(...)を使います。 -
成功時:データをそのまま返します(オブジェクトまたはページ分割された一覧)。
-
失敗時/見つからない場合:共通の形式でエラーオブジェクトを返します。
return response()->json([ 'error' => 1, 'msg' => 'Not found', 'detail'=> 'Product not found or no permission!', ], 200); -
ページ分割:一覧を返すときは
->get()の代わりにマクロ->jsonPaginate()(導入済みのパッケージspatie/laravel-json-api-paginate)を使います。標準のページ分割構造 (data、current_page、totalなど)を返し、ページサイズはリクエストで制御できます。
3. 例 A — 自分がメンテナンスするパッケージ(core/front/shop)にエンドポイントを追加する
あなたがパッケージのメンテナー(vendor/gp247/<package> を直接編集する)の場合に使います。
例として、公開の Front API api/front/review/list を追加します。次の順序どおりに進めてください。
-
コントローラーを作成します。場所は
vendor/gp247/<package>/src/Api/...です。Front のデータならRootFrontControllerを、管理のデータならRootAdminControllerを継承します。ファイル
src/Api/Front/ReviewController.phpを作成します。<?php namespace GP247\Shop\Api\Front; use GP247\Front\Controllers\RootFrontController; use Illuminate\Http\Request; use GP247\Shop\Models\ShopProductReview; class ReviewController extends RootFrontController { /** * Get the public review list. * * @return \Illuminate\Http\JsonResponse * * @aidlc-unit shop-api * @aidlc-story US-shop-api-review-list */ public function getReviewList(Request $request) { $reviews = (new ShopProductReview) ->where('status', 1) ->jsonPaginate(); return response()->json($reviews, 200); } } -
ルートファイルを作成します。場所は
src/Routes/Api/review.phpです(Routes/Api/フォルダーに置くだけで コアが自動で読み込みます。ほかの場所で宣言する必要はありません)。<?php use GP247\Shop\Api\Front\ReviewController; use Illuminate\Support\Facades\Route; Route::group([ 'prefix' => GP247_API_FRONT_PREFIX, // => api/front ], function () { $reviewController = gp247_namespace(ReviewController::class); Route::group(['prefix' => 'review'], function () use ($reviewController) { Route::get('list', $reviewController.'@getReviewList'); }); }); -
ルートが読み込まれたか確認します。Artisan コマンドを使います(サイトのルートフォルダーで実行)。
php artisan route:list --path=api/front/review成功すると
GET | api/front/review/listの行が表示されます。表示されない場合は、.envのGP247_API_MODE=trueを確認し、ルートキャッシュを削除してください:php artisan route:clear。 -
試しに呼び出します(公開エンドポイントなのでトークンは不要です)。
curl -X GET "https://shop.example.com/api/front/review/list" -H "Accept: application/json"
管理用エンドポイント(ログインが必要)の場合は、パッケージの
src/Routes/Api/にルートを置き、prefix => GP247_API_CORE_PREFIXとともにミドルウェアグループauth:admin-api+ability:...で包みます (vendor/gp247/shop/src/Routes/Api/admin.phpのサンプルを参照)。
4. 例 B — プラグインから API を追加する(個別サイトにおすすめ)
vendor を変更できない状態で特定のサイトに API を追加するときの、標準に沿った方法です。プラグインは
app/GP247/Plugins/<PluginName>/ に置かれ、その Route.php ファイルはコアが自動で読み込みます。
⚠️ 注意: 重要な違い: プラグインのルートは API のミドルウェアグループ(セクション 1.3)の外側で読み込まれます。 そのため
GP247_API_MIDDLEWAREで自分で包み、prefixも自分で設定する必要があります。忘れると、 API は JSON を強制せず、api.connectionレイヤーも通らず、レート制限もかかりません。
-
プラグイン内にコントローラーを作成します。例:
app/GP247/Plugins/MyApi/Api/Front/StatusController.php<?php namespace App\GP247\Plugins\MyApi\Api\Front; use GP247\Front\Controllers\RootFrontController; use Illuminate\Http\Request; class StatusController extends RootFrontController { /** * Return a simple health-check payload for external monitors. * * @return \Illuminate\Http\JsonResponse * * @aidlc-unit myapi-plugin * @aidlc-story US-myapi-plugin-status */ public function getStatus(Request $request) { return response()->json([ 'error' => 0, 'status' => 'ok', 'time' => gp247_time_now(), ], 200); } } -
app/GP247/Plugins/MyApi/Route.phpでルートを宣言し、API のミドルウェアグループで自分で包みます。<?php use App\GP247\Plugins\MyApi\Api\Front\StatusController; use Illuminate\Support\Facades\Route; // Only register when the API mode is on, matching core behaviour. if (config('gp247-config.env.GP247_API_MODE')) { Route::group([ 'middleware' => GP247_API_MIDDLEWARE, // ['api','api.extend'] — 必ず自分で追加する 'prefix' => GP247_API_FRONT_PREFIX, // => api/front ], function () { $statusController = gp247_namespace(StatusController::class); Route::group(['prefix' => 'myapi'], function () use ($statusController) { Route::get('status', $statusController.'@getStatus'); }); }); } -
キャッシュを削除してルートを確認します。
php artisan route:clear php artisan route:list --path=api/front/myapi成功すると
GET | api/front/myapi/statusが表示されます。 -
試しに呼び出します。
curl -X GET "https://shop.example.com/api/front/myapi/status" -H "Accept: application/json"期待される結果:
{ "error": 0, "status": "ok", "time": "2026-07-30 10:00:00" }
5. ログインが必要なエンドポイントを作る(トークンで保護)
API が非公開のデータ(顧客の注文、管理データなど)を返す場合は、対応する Sanctum のガードで包む必要があります。
コントローラーでは、ログイン中のユーザーを $request->user() で取得します。
ログインが必要な管理用ルートの例:
Route::group([
'prefix' => GP247_API_CORE_PREFIX, // => api/core
'middleware' => [
'auth:admin-api',
'ability:'.config('gp247-config.api.auth.api_scope_admin')
.','.config('gp247-config.api.auth.api_scope_admin_supper'),
],
], function () {
$ctrl = gp247_namespace(\App\GP247\Plugins\MyApi\Api\Admin\ReportController::class);
Route::get('report/sales', $ctrl.'@getSalesReport');
});
クライアントは、login で取得したトークンをヘッダーに付けて送る必要があります。
Authorization: Bearer <access_token>
トークンの発行(
createToken)とトークンの失効(logout)は、core/shop のログイン用コントローラーにすでに 用意されています。トークンの取得にはapi/core/login/api/front/loginエンドポイントを再利用するだけで十分です。 特別な要件がない限り、ログイン部分を自作する必要はありません。
6. 「完了」とする前のチェックリスト
- 定数
GP247_API_CORE_PREFIX/GP247_API_FRONT_PREFIXを使い、文字列をハードコードしていない。 - コントローラーを
gp247_namespace(...)経由で指定し、オーバーライドを可能にしている。 - プラグインのルートは
GP247_API_MIDDLEWARE+prefixで自分で包んでいる(セクション 4)。 - すべての入力に
$request->validate([...])がある。SQL を文字列連結で組み立てない(Eloquent を使う)。 - 一覧は
->jsonPaginate()を使い、すべてのレスポンスはresponse()->json(...)を通している。 - 非公開エンドポイントには
auth:admin-api/auth:customer-api+ 正しいスコープのability:...がある。 -
vendor/gp247/*を変更していない(そのパッケージのメンテナーである場合を除く)。 - 各メソッドに英語の PHPDoc と
@aidlc-unit/@aidlc-storyタグがある(coding-style に従う)。 -
php artisan route:clearを実行し、php artisan route:listにルートが表示されることを確認した。
よくある質問(Q&A)
Q1: API はどこに追加すべきですか — vendor ですか、プラグインですか?
→ ほとんどの場合はプラグイン(app/GP247/Plugins/)か、app/GP247/ によるオーバーライドです。
vendor/gp247/* を直接編集するのは、そのパッケージの主要メンテナーの場合だけです。
vendor 内の変更は composer update で失われるためです。
Q2: 新しいルートが表示されないのはなぜですか?
→ よくある原因は 3 つです。(1) .env で GP247_API_MODE=true を設定していない。(2) キャッシュを削除していない —
php artisan route:clear を実行してください。(3) プラグインの場合、ファイル名が正確に Route.php で、
プラグインが有効になっている必要があります。
Q3: プラグインの API が JSON を返さない/レート制限がかからないのはなぜですか?
→ プラグインのルートは API のミドルウェアグループの外側で読み込まれるためです。セクション 4 のように
'middleware' => GP247_API_MIDDLEWARE で自分で包む必要があります。プラグインから API を追加するときに最も多い間違いです。
Q4: jsonPaginate() は Laravel の paginate() と何が違いますか?
→ jsonPaginate()(パッケージ spatie/laravel-json-api-paginate のもの)は、JSON:API 標準に適したページ分割構造を返し、
クライアントがパラメーターでページサイズを制御できます。GP247 の既存 API と揃えるため、一覧エンドポイントではこれを使ってください。
Q5: 標準に沿ってエラーを返すには?
→ response()->json(...) でオブジェクト {'error': 1, 'msg': '...', 'detail': '...'} を返します。
認証エラーは Sanctum が自動で 401 を返すのに任せます。HTML や素の文字列は返さないでください。
Q6: 自分の API 用に独自のスコープ/権限が必要ですか?
→ 既存のスコープ(admin、admin-supper、user、user-guest)を再利用できます。新しいスコープが必要な場合は、
トークン作成時に付与し、ミドルウェア ability:<your-scope> で確認します。
Sanctum と並行する独自の権限の仕組みを作るのは避けてください。
Q7: apiconnection/apikey レイヤーは新しい API に必須ですか?
→ コードで決めるものではありません。管理画面の設定 api_connection_required で全体としてオン/オフします。
ルートが GP247_API_MIDDLEWARE グループの中にあれば、管理者がオンにしたときにこのレイヤーが自動で適用されます。
Q8: ログイン/トークン発行のエンドポイントを自作する必要がありますか?
→ ありません。api/core/login(管理者)または api/front/login(顧客)を再利用してトークンを取得し、
新しいエンドポイントを auth:admin-api/auth:customer-api で保護してください。
独自のログインを書くのは、特殊な認証フローがある場合だけです。
Q9: API のコントローラーはどのクラスを継承すべきですか?
→ 管理データなら GP247\Core\Controllers\RootAdminController を継承します。Front/ストアのデータなら
GP247\Front\Controllers\RootFrontController を継承します。どちらも、それぞれの側に適したコンテキストが設定済みです。
Q10: 新しい API にテストを書く必要がありますか?
→ あります。testing.md に従い、エンドポイントの feature test を書きます(tests/ リポジトリに置きます)。
少なくとも、ステータスコード、JSON の構造、非公開エンドポイントでトークンがないときにアクセスが拒否されることを確認してください。
📅 最終更新: 2026-10-22 · ✍️ 作成者 (Author): GP247