https://a.storyblok.com/f/270183/1368x665/5601fd767f/26apr_dev-blog_rapid-api-development.jpg

LaravelとAPI Platformによる迅速なAPI開発

最終更新日 April 28, 2026

所要時間:2 分

筆者の個人的な意見ではあるが、PHP関係者以外のもっと多くの人々が、API Platformについて知るべきだと思う。 APIプラットフォーム.それは 驚くべき 10分でウェブアプリケーションのAPI全体を構成することができ、コンフィグ・スイッチを変更することで、アプリケーション内の認証を変換して処理するような、目まぐるしく変化する機能を備えている。

この記事では、VonageのMessages APIを使用する既存のLaravelアプリケーションを取り上げ、様々な標準の下でWeb APIとして公開します。

APIプラットフォームとは?

さて、ここからは少しわかりにくい話だ:API Platform はPHPフレームワークです、 しかし、そのフレームワークはSymfonyやLaravelの上に乗っています(これらの上に構築される他のフレームワークやプラットフォームも含まれます。 Drupalまたは WinterCMS).データベースのモデリングと設定フォルダに追加できる設定と属性のセットだと考えてください。また、以下のようなAPIツールでテストするための、完全なウェブダッシュボードが組み込まれています。 ポストマンOpenAPI規格に準拠している。

既存のLaravelアプリケーションを起動する

別名。"さっき作ったのはこれだ!"データベース・エンティティが1つしかないアプリケーションを使おう。 ToDo、 これは 前の記事でコーディングした.また Vonage Messages APIを使用して、ToDo項目の1つにチェックが入ったときに、設定されたデバイスにToDoのテキストコンテンツを送信する(通知のように動作する)。これは完全に機能するアプリケーションなので、API Platformを追加する前に、このアプリを起動することから始める。

ソースコードは ソースコードはこちら.

前提条件

  • ギット

  • PHP 8.3 以上

  • Node 23+ & npm

  • 作曲家

  • Vonageアカウント

ウェブアプリのセットアップ

  1. あなたのマシンにリポジトリを取得します: https://github.com/Vonage-Community/blog-messages_native_php

  2. 依存関係をインストールします: composer install

  3. コマンドラインでマイグレーションを実行する: php artisan migrate

  4. コマンドラインでnpmを実行する: npm i

  5. コマンドラインで、Viteを次のように実行する。 npm run dev

  6. コマンドラインでデータベース・シーダーを実行し、データをアプリに取り込む: php artisan db:seed

  7. 例をコピーする .envをコピーして .env にする: cp .env.example .env

  8. Vonageの認証情報を .envファイルに追加します。

このアプリケーションは Vonage Messages API を使って ToDo が完了したときに SMS を送信するので、Vonage アカウントを作成し、Vonage アプリケーションを作成する必要があります。アプリケーションを作成する際、Messages 機能を選択し、Webhooks フィールドにダミーデータを入力します。 application_id作成時にを移動します。 private.keyをプロジェクトのファイルのルートに移動します。

  • アプリケーションを作成するには アプリケーションの作成ページでアプリケーションの名前を定義します。

  • Webhooksを使用するAPIを使用する場合は、秘密鍵が必要です。Generate public and private key "をクリックすると、自動的にダウンロードが始まります。この鍵は紛失すると再ダウンロードできません。この鍵は紛失しても再ダウンロードできません。 private_<あなたのアプリID>.key.この鍵はAPIコールの認証に使用できます。 注意:アプリケーションを保存するまで、キーは機能しません。

  • 必要な機能(Voice、Messages、RTCなど)を選択し、必要なWebhook(イベントURL、応答URL、受信メッセージURLなど)を提供します。これらはチュートリアルで説明します。

  • 保存してデプロイするには、"Generate new application "をクリックして設定を確定します。これでアプリケーションはVonage APIで使用する準備が整いました。

この .envファイルにコンフィギュレーションを追加する必要がある:

VONAGE_APPLICATION_ID="<YOUR_APPLICATION_ID_HERE>"
VONAGE_PRIVATE_KEY_PATH="./private.key"
VONAGE_TO="<YOUR-NUMBER-HERE>"

ただし VONAGE_PRIVATE_KEY_PATHアプリはルート・レベルであなたの秘密鍵を読み込むことを解決するので、上記の値を常に持つ必要があります。

VONAGE_TOはSMS通知を送りたい番号です。

アプリを提供する必要があります。私は Laravel Herd.インストール方法は インストール手順は.あるいは、コマンドラインから組み込みのPHPサーバーを実行することもできます: php artisan serve

Screenshot showing the main page of the ToDo appApp up and running!

難問:MVCからAPIへ

アプリケーションは、Laravel Livewireの提供するフロントエンドのマジックを散りばめた、古典的なModel-View-Controllerアプリケーションとして書かれています。しかし、2つのシナリオを考えてみましょう:

  1. 外部ツールをアプリケーションにプラグインしたいので、APIを公開する必要がある。

  2. マス・スケーリングとは、フロントエンドとバックエンドを切り離す必要があることを意味する。つまり、SvelteやVueのような別のJavaScriptフレームワークを用意し、公開されたAPIにデータを消費したり送信したりするのだ。

信じられないようなAPIプラットフォーム体験

いよいよAPI Platformをインストールする。ターミナルを開き、以下を追加する:

composer require api-platform/laravel

ターミナルのまま、コンソールでインストールを終了する。

php artisan api-platform:install

インストールは以上だ。信じられない? あなたのプロジェクトのURLに /api:

Screenshot of the API Platform landing pageWe've certainly done -something-EloquentのORMモデルが1つあります、 Todo.アプリではこのようになっています:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Todo extends Model
{
   /**
    * The attributes that are mass assignable.
    *
    * @var array<int, string>
    */

   protected $fillable = [
       'title',
       'completed',
   ];

   /**
    * The attributes that should be cast.
    *
    * @var array<string, string>
    */

   protected $casts = [
       'completed' => 'boolean',
   ];
}

準備はいいですか?次のステップですべてが変わるので、その後に何が起こるか説明しよう。この属性を追加します:

<?php

namespace App\Models;

use ApiPlatform\Metadata\ApiResource;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

#[ApiResource]
class Todo extends Model
{
   use HasFactory;

   /**
    * The attributes that are mass assignable.
    *
    * @var array<int, string>
    */

   protected $fillable = [
       'title',
       'completed',
   ];

   /**
    * The attributes that should be cast.
    *
    * @var array<string, string>
    */
   protected $casts = [
       'completed' => 'boolean',
   ];
}

OK。 #ApiResource]を追加した。.それで、何をするのか?を更新する。 /を更新します。ダッシュボードを更新します:

Screenshot showing HTTP routes for a ToDo entityAn OpenAPI document renders our new magic APIえー、いいですか?じゃあ、今は完全なRESTルートのセットがあるんだね?確認してみよう。データベースには10個のフィクスチャがあります。 HTTPieを使って GET{id}エンドポイントを発行してエントリー5を取得するとどうなるか見てみましょう。

A screenshot of HTTPie returning a 200 of a ToDo entity in JSON-LD formatAbsolute cinema!え?私のためにAPIを作ってくれたの?タイトルの編集リクエストを PATCHタイトルを編集する

Screenshot showing that the ToDo app now has REST API endpoints with an API response in HTTPieSuddenly, a wild REST API appearsオーケー。コードを2行追加して、APIができた。かなりワイルドだ。

さらに深く:API標準とページネーション

目の肥えた方ならお気づきかもしれないが、API Platformはデータ構造パターンをデフォルトにしている。 コンテキストid.しかし、なぜこのようなフィールドになっているのだろうか?

答えは、API Platformのデフォルトが JSON-LD (JSON For Linking Data) フォーマットです。.ここでは1つのエンティティしか表示されていないかもしれないが、1対多のエンティティ関係があれば、API Platformは自動的に返された結果を処理してくれるだろう。例として、次のような新しいエンティティを追加してみましょう。 SubTask.Eloquentでは、リレーションシップは次のようになります:

   public function subtasks(): HasMany
   {
       return $this->hasMany(Subtask::class);
   }

同じエンドポイントを呼び出すと、以下のようなレスポンスがレンダリングされる。どのフィールドをレンダリングするかを決定するGroups Serializationコードを追加したことに留意してほしい。API Platform Serializationについては を参照してください。を参照してください。 $visible配列の設定を使用して、レンダリングしたいモデルの部分を公開します。

{
    "@context": "/api/contexts/Todo",
    "@id": "/api/todos/5",
    "@type": "Todo",
    "id": 5,
    "title": "sample patch request",
    "completed": false,
    "createdAt": "2026-03-10T13:44:23+00:00",
    "updatedAt": "2026-03-11T11:41:13+00:00",
    "subTasks": [
        {
            "@id": "/api/sub_tasks/1",
            "@type": "SubTask",
            "id": 1,
            "title": "Write request body",
            "completed": true
        },
        {
            "@id": "/api/sub_tasks/2",
            "@type": "SubTask",
            "id": 2,
            "title": "Send PATCH request",
            "completed": false
        },
        {
            "@id": "/api/sub_tasks/3",
            "@type": "SubTask",
            "id": 3,
            "title": "Verify API response",
            "completed": false
        }
    ]
}

API PlatformがAPIデータの面倒を見てくれるなんて、なんてクールなんだろう。変換レイヤーやDTOをすべて捨てる時が来たようだ!

REST開発の標準がJSON-LDではなかったら?そんな時は、設定に向かおう。 configuration/api-platform.php.

<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

use ApiPlatform\Metadata\UrlGeneratorInterface;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Auth\AuthenticationException;
use Symfony\Component\Serializer\NameConverter\SnakeCaseToCamelCaseNameConverter;

return [
   'title' => 'API Platform',
   'description' => 'My awesome API',
   'version' => '1.0.0',
   'show_webby' => true,
   'routes' => [
       'domain' => null,
       // Global middleware applied to every API Platform routes
       // 'middleware' => [],
   ],
   'resources' => [
       app_path('Models'),
   ],
   'formats' => [
       'jsonld' => ['application/ld+json'],
       // 'jsonapi' => ['application/vnd.api+json'],
       // 'csv' => ['text/csv'],
   ],

(Copyrightを残しておいたのは ケビン・デュグラス に敬意を表して)。

コンフィグ配列に formatsキーがある。それを変更しよう:

   'formats' => [
       'jsonld' => ['application/ld+json'],
       'jsonhal' => ['application/hal+json'],
   ],

もう一度リクエストを送っても、何も変わらない。JSON-LDのままだ。どうして?

これはAPI PlatformのContent Negotiation実装の一部である。LD-JSONはまだ が最初にキーで、デフォルトのままです。しかし、リクエストヘッダを accept: application/hal+jsonに変更してリクエストを実行する:

Screenshot of the response, but now formatted in HALSuddenly, a wild HAL appearsそのため、API利用者が望むフォーマットをリクエストできるようになり、その力はAPI利用者の手に委ねられることになった。

また、APIの作者であるあなたには、相手のアプリに新しいエンドポイントを作成するような、ある種の強力な権限を与える。 /api/v2,そして 単純に変更することができる。APIをGraphQLのものに変更したい場合はどうすればいいのだろう?そうだ。たった 3ステップだ!

  1. ブラウザでComposerを使用してAPI Platform GraphQLをインストールする

composer require api-platform/graphql
  1. でGraphQLを有効にします。 configuration/api-platform.phpファイル

   'graphql' => [
       'enabled' => true,
       'nesting_separator' => '__',
       'introspection' => ['enabled' => true],
       'max_query_complexity' => 500,
       'max_query_depth' => 200,
       // 'middleware' => null,
   ],
  1. に向かう。 /api/graphqlどうなる?

Screenshot of the built-in API Platform GraphQL sandboxA Built-in GraphQL sandbox, just for youそうだ。あなたのAPIがGraphQLになったのだから、あなたはGraphQLプレイグラウンドを持っているのだ。もし信じないなら

Screenshot of an API call returning a GraphQL responseFrom REST to GraphQL in mere minutesこれでGraphQL API REST APIがある。

ページネーションは、私がいつも実装するのに非常に手間がかかると感じているもののひとつだ。API Platformは、ページネーションの統合プロセスを簡素化することに関して、ばかばかしいにもほどがあるアプローチを持っている。ToDoモデルをもう一度考えてみよう:

<?php

namespace App\Models;

use ApiPlatform\Metadata\ApiProperty;
use ApiPlatform\Metadata\ApiResource;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Symfony\Component\Serializer\Attribute\Groups;

#[ApiResource(normalizationContext: ['groups' => ['read']])]
#[ApiProperty(property: 'title', serialize: [new Groups(['read'])])]
#[ApiProperty(property: 'completed', serialize: [new Groups(['read'])])]
class Todo extends Model
{
   use HasFactory;

   /**
    * Get the subtasks for the todo.
    */
   #[ApiProperty(readableLink: true)]
   #[Groups(['read'])]
   public function subtasks(): HasMany
   {
       return $this->hasMany(Subtask::class);
   }

   /**
    * The attributes that are mass assignable.
    *
    * @var array<int, string>
    */

   protected $fillable = [
       'title',
       'completed',
   ];

   /**
    * The attributes that should be cast.
    *
    * @var array<string, string>
    */
   protected $casts = [
       'completed' => 'boolean',
   ];
}

関係をフォーマットするための新しい属性を追加した。 Subtaskリレーションをフォーマットするための新しい属性を追加しました。ページ分割を追加するために、ページごとに返されるエンティティの数のデフォルトを設定し、次に pageURL クエリ文字列をテストします。次の属性をクラスに追加します:

#[ApiProperty(property: 'title', serialize: [new Groups(['read'])])]
#[ApiProperty(property: 'completed', serialize: [new Groups(['read'])])]
#[ApiResource(
   normalizationContext: ['groups' => ['read']],
   paginationItemsPerPage: 5,
)]
#[ApiProperty(property: 'title', serialize: [new Groups(['read'])])]
#[ApiProperty(property: 'completed', serialize: [new Groups(['read'])])]
class Todo extends Model

それで終わりだ。完了。Todoが10個あるので、1ページに2ページ-5エンティティが返されるはずです。そこで、2ページ目を追加するテストができる:

Screenshot of an API call showing pagination standard fields rendered by API PlatformMagical pagination out of the boxページネーションのリンクも追加された。

結論

私がAPI Platform Conference 2025でAPI Platformのパワーについて話したときに指摘したことのひとつは、このフレームワークを毎日毎日使っているPHP開発者は、おそらくこの種のパワーがどれほど稀なものであるかを知らないだろうということだ。この種の機能を開発者の手元に置き、これほどシンプルにできるものは他にはない。もしあなたがPHPの世界の人でないなら、ぜひ試してみてほしい。

ご質問がある場合、またはあなたが作っているものを共有したい場合は、こちらをクリックしてください。

最新の開発者向けニュース、ヒント、イベント情報をお届けします。

シェア:

https://a.storyblok.com/f/270183/400x385/12b3020c69/james-seconde.png
James SecondeシニアPHPデベロッパー

スタンダップ・コメディーの学位論文を持つ俳優の訓練を受け、ミートアップ・シーンを経てPHP開発に携わるようになった。技術について話したり書いたり、レコード・コレクションから変わったレコードを再生したり買ったりしています。