197日目 APIの実装【準備編】（バックエンド）

仕事でAPIをさわる機会があり、APIってすごいな！と思ったので今後APIをさわる機会がある方が少しでもAPIへの理解が早くできるように初心者ながらにまとめていきたいと思います！

１つにまとめきれないくらい情報があるので分けていきます！
今回は「APIとは？」「環境設定で必要なもの」「ルーティング設定」についてまとめましたので誰かの力になればなによりです！

## 第１話《APIってなんぞやッ！？》

API（Application Programming Interface）は、アプリケーション同士が通信し、データや機能をやり取りするためのインターフェース（仕組み）です。
APIを使うことで、異なるシステムやサービスが相互に連携し、データや機能を共有できるようになります。

**１．データアクセス**
・システムやデータベースに保存されているデータにアクセスし、外部からリクエストに応じてそのデータを提供します。
例：商品情報、ユーザー情報、注文履歴などを取得するためにAPIを呼び出す。

わかりやすく言うと、`フロントとバックを繋げる橋渡し的な役割`です。

**２．機能の理由**
・特定の機能や処理を外部から利用できるようにします。これにより、他のシステムが機能を再利用することができます。
例：支払い処理、画像の加工、通知送信などの機能をAPIを通じて実行。

**３．データ送信・更新**
・外部システムからデータを送信して、システム内のデータを取得・作成・更新・削除することができます。
例：ユーザー登録、新しい注文の作成、商品情報の更新。

### APIの種類

**１．REST API**
・Web APIの最も一般的な形式です。HTTPリクエストを使って、サーバー上のリソースにアクセスし、操作します。
リクエスト方法には、GET（取得）、POST（作成）、PUT（更新）、DELETE（削除）などがあります。

`例`
・GET　/products：商品一覧を取得するAPI
・POST　/orders：新しい注文を作成するAPI

**２．SOAP API**
・XMLベースのプロトコルを使用するAPIで、主にエンタープライズシステムで利用されます。REST APIよりも厳密な規約に従います。

`例`
・金融機関や大規模な業務システムで使用されることが多い。

**３．GraphQL**
・クライアントが必要なデータをリクエストに応じて柔軟に指定できるAPI。RESTに比べて効率的にデータを取得できる点が特徴です。


今回はREST APIで実装していきます。

### API設計について

実装に先立って、APIの設計を行います。
これは、APIがどのような機能を提供するか、どのデータを送受信するか、どのエンドポイントが必要かどうかなどを定義するフェーズです。

設計段階では、以下の項目を明確にします。

**・リクエスト/レスポンス形式**
APIのリクエストおよびレスポンスのデータ形式を決めます。よく使用される形式は、JSONやXMLです。
    
**・エンドポイント**
APIのURLパスやパラメータを定義し、どのエンドポイントがどの機能を提供するかを整理します。
    
**・HTTPメソッド**
GET,POST,PUT,DELETEなどのHTTPメソッドを使用して、データの取得(GET)、作成(POST)、更新(PUT)、削除(DELETE)の操作を行います。


### サーバーサイドの実装

APIサーバーは、クライアントからのリクエストを受け取り、データベースや他のバックエンドシステムとの通信を行い結果を返します。
このために、以下のような要素を実装します。

**・ルーティング**
APIが提供する各エンドポイントに対するリクエストを処理するためのルート（URLパスとHTTPメソッドの組み合わせ）を設定します。

**・コントローラー**
リクエストを受け取ってビジネスロジックを実行する部分です。
たとえば、ユーザーが「/users」にGETリクエストを送信した場合、データベースからユーザー情報を取得しレスポンス返す処理を行います。

**・モデル**
データベースのテーブルやレコードとプログラムを対応させる部分です。
データベースとのやり取りを抽象化し、データの保存や更新を簡単にします。


## API実装におけるバックエンドの役割

API実装におけるバックエンドの仕事は、システムの「裏側」でデータ処理やビジネスロジックの実行、外部サービスとの連携を行い、クライアント（フロントエンド）に対して必要なデータや機能を提供することです。
APIはそのインターフェースとして機能し、バックエンドはそれを支える全体の仕組みを構成しています。

### バックエンドとサーバーサイドの違い

バックエンドとサーバーサイドは、どちらもAPIの動作の「裏側」に関係していますが、次の点で使い分けられることがあります。

**・バックエンドは広い概念**
バックエンドは、サーバーサイド処理だけでなく、データベースや外部システムとのやり取り、インフラ管理など、アプリケーション全体の裏側を指します。
バックエンドは、アプリケーションが動作するために必要なサーバー、データベース、ファイルシステムなど全体を含む大きな領域を表します。

**・サーバーサイドはバックエンドの一部**
サーバーサイドは、バックエンドの中でも特に、サーバー上で行われる処理に焦点を当てた言葉です。
つまり、APIリクエストの受信やレスポンスの生成、ビジネスロジックの実行など、サーバー内部での処理に関係します。


## API実装の具体例 【準備編】

**実装の開発環境**

`言語`：php

`API`：REST API

`APIデザイン中心の開発プラットフォーム`：APIDOG

`プラットフォーム`：Docker

`Gitクライアントソフトウェア`：Sourcetree

`テキストエディター`：VSCode

`DB管理ツール`：Adminer

`adm`（管理・アドミン）
`フレームワーク：Laravel`

（admとは管理者向けの機能を提供する部分です。主に、システムやデータの管理、運用保守に関する操作を行うためのエリアです。）
マイグレーションファイルというものを作成するとAdminerにテーブルやカラムが登録できます。
詳しくは別の記事に記載してますので、そちらをご確認ください。

[Laravel(php)マイグレーションファイルについて](https://https://qiita.com/QiiTaro_/items/c50bd133319f9bd86354)

`api`
`フレームワーク（Phalcon）`

（apiとは通常エンドユーザーや他のサービスがアクセスするためのAPIを指します。これが一般的なAPIエンドポイントで、アプリケーションの機能やデータにアクセスさせるためのインターフェースを提供します。）
コントローラー・モデルなどを操作するところがこちらです。


## API実装の具体例【参考テーブル作成編】

オンラインショッピングサイトのAPIを例にして、商品テーブル、ユーザーテーブル、注文テーブル、およびカートテーブルを作成する際のカラム名、データ型、コメントの詳細を設定して説明します。

**１．商品テーブル(Products)**
商品情報を管理するテーブルです。

|  カラム名  |  データ型  |  コメント  |
| ---- | ---- | ---- |
|  id  |  bigint(20) unsigned 連番  |  内部ID  |
|  name  |  varchar(255)  |  商品名  |
|  price  |  int(11)  |  商品の価格  |
|  stock  |  int(11) NULL  |  在庫数  |
|  description  |  text  |  商品の説明  |
|  category  |  varchar(255)  |  カテゴリ  |
|  created_at  |  timestamp NULL [CURRENT_TIMESTAMP]	  |  作成日  |
|  created_by  |  bigint(20) unsigned NULL  |  作成者  |
|  updated_at  |  timestamp NULL [CURRENT_TIMESTAMP]	  |  更新日  |
|  updated_by  |  bigint(20) unsigned NULL  |  更新者  |
|  deleted_at  |  timestamp NULL  |  削除日  |
|  deleted_by  |  bigint(20) unsigned NULL  |  削除者  |


**２．ユーザテーブル(users)**
ユーザー情報を管理するテーブルです。

|  カラム名  |  データ型  |  コメント  |
| ---- | ---- | ---- |
|  id  |  bigint(20) unsigned 連番  |  内部ID  |
|  username  |  varchar(50)  |  ユーザー名  |
|  password  |  varchar(255)  |  パスワード  |
|  email  |  varchar(100)  |  在庫数  |
|  created_at  |  timestamp NULL [CURRENT_TIMESTAMP]	  |  作成日  |
|  created_by  |  bigint(20) unsigned NULL  |  作成者  |
|  updated_at  |  timestamp NULL [CURRENT_TIMESTAMP]	  |  更新日  |
|  updated_by  |  bigint(20) unsigned NULL  |  更新者  |
|  deleted_at  |  timestamp NULL  |  削除日  |
|  deleted_by  |  bigint(20) unsigned NULL  |  削除者  |


**３．注文テーブル(orders)**
注文履歴を管理するテーブルです。

|  カラム名  |  データ型  |  コメント  |
| ---- | ---- | ---- |
|  id  |  bigint(20) unsigned 連番  |  内部ID  |
|  user_id  |  bigint(20) unsigned  |  注文をしたユーザーのID（外部キー）  |
|  total_price  |  int(10)  |  合計金額  |
|  order_date  |  timestamp NULL  |  注文日時  |
|  status  |  smallint(6)  |  発送済みかどうか(0 or 1)  |
|  created_at  |  timestamp NULL [CURRENT_TIMESTAMP]	  |  作成日  |
|  created_by  |  bigint(20) unsigned NULL  |  作成者  |
|  updated_at  |  timestamp NULL [CURRENT_TIMESTAMP]	  |  更新日  |
|  updated_by  |  bigint(20) unsigned NULL  |  更新者  |
|  deleted_at  |  timestamp NULL  |  削除日  |
|  deleted_by  |  bigint(20) unsigned NULL  |  削除者  |


**４．カートテーブル**
カートの情報を管理するテーブルです。カートには複数の商品が含まれる可能性があるので、商品情報も関連付けます。

|  カラム名  |  データ型  |  コメント  |
| ---- | ---- | ---- |
|  id  |  bigint(20) unsigned 連番  |  内部ID  |
|  user_id  |  bigint(20) unsigned  |  カートを所有するユーザーのID  |
|  product_id  |  int(11)  |  カートに入っている商品のID  |
|  quantity  |  int(11)  |  商品の数量  |
|  added_at  |  timestamp NULL  |  カートに追加された日時  |
|  created_at  |  timestamp NULL [CURRENT_TIMESTAMP]	  |  作成日  |
|  created_by  |  bigint(20) unsigned NULL  |  作成者  |
|  updated_at  |  timestamp NULL [CURRENT_TIMESTAMP]	  |  更新日  |
|  updated_by  |  bigint(20) unsigned NULL  |  更新者  |
|  deleted_at  |  timestamp NULL  |  削除日  |
|  deleted_by  |  bigint(20) unsigned NULL  |  削除者  |


**外部キーの設定**

userテーブルやproductsテーブルとの関連を作るために、**外部キー(Foreign Key)**を設定します。

１．`orders.user_id`と`users.id`を外部キーで関連付けます。
２．`cart.user_id`と`users.id`を外部キーで関連付けます。
３．`cart.product_id`と`products.id`を外部キーで関連付けます。

これで、オンラインショッピングサイトの主要なテーブルが設定できました。
これらの設定により、商品、ユーザー、注文、カートに関連するデータを効率的に管理できるようになります。


### API実装の具体例 【実装編】

では、前述のテーブル(products, users, orders, cart)を使って、オンラインショッピングサイトのAPI実装例を詳しく説明します。
各APIのリクエストパラメータ、URL、成功レスポンスの例も含めて示します。

### １．ルーティング設定（router.php）

まずルーティングを設定するファイルを作っていきます。
先ほども記述しましたがもう一度説明します。
ルーティングとは、URIエンドポイント（ベースURL（https\://など）の後に続く部分）からパラメータを抽出し、リクエストを受け取るモジュールやコントローラー、アクションを判断する処理です。

**ルーティング設定**
・各エンドポイント（例：商品リスト取得、カートへの商品追加）を設定しています。
・それぞれのエンドポイントは、リクエストメソッド（GET, POST, PUT, DELETE）に基づいて処理されます。

**コントローラーとアクション**
・各ルートには、対応するコントローラーとアクション（メソッド）を指定しています。これにより、クライアント側からのプリフライトリクエストに対応します。
※プリフライトリクエストとは、実際のリクエストを送信する前にそのリクエストが安全かどうか、前もってOPTIONSリクエストを送信して確かめる仕様

〈例〉
・URL： `/api/online-shop/products`
・メソッド： `GET`　`POST`
・パラメータ： 一部Pathパラメータ有り

```php:router.php
<?php

use Phalcon\Mvc\Router;

// ルーターをインスタンス化
$router = new Router();

// 商品リスト取得
$router->add('/online-shop/products',
    ['namespace' => 'App\Contoroller', 'controller' => 'onlineShop', 'action' => 'getProductList'],
    ['GET', 'OPTIONS']
);

// 特定の商品情報取得
$router->add('/online-shop/products/{product_id}', // {product_id}はPathパラメータ
    ['namespace' => 'App\Contoroller', 'controller' => 'onlineShop', 'action' => 'getProductById'],
    ['GET', 'OPTIONS']
);

// ユーザー登録
$router->add('/online-shop/users',
    ['namespace' => 'App\Contoroller', 'controller' => 'user', 'action' => 'postUser'],
    ['POST', 'OPTIONS']
);

// カートに商品を追加
$router->add('/online-shop/cart',
    ['namespace' => 'App\Contoroller', 'controller' => 'cart', 'action' => 'postToCart'],
    ['POST', 'OPTIONS']
);

// カートを確認
$router->add('/online-shop/cart/{user_id}',
    ['namespace' => 'App\Contoroller', 'controller' => 'cart', 'action' => 'getCartByUserId'],
    ['GET', 'OPTIONS']
);

// 注文を確定
$router->add('/online-shop/order',
    ['namespace' => 'App\Contoroller', 'controller' => 'order', 'action' => 'postOrder'],
    ['POST', 'OPTIONS']
);

// ルーターを返す
return $router;

```

今回はルーティング設定までしました。
コントローラーやモデルまでまとめるととんでもなく長くなりますので次回に持ち越したいと思います！

### 【次回！本格的に実装に取り掛かるぞッ！】

**TO BE CONTINUED...**