簡単なRESTful APIサーバーを作ってみる
RESTful APIって?
標準的なWebAPIの設計方式。
リソースに対するURLを1つだけ用意し、HTTPメソッドの切り替えで操作を表す。
例
- 読書リストのうち、ID「0001」の本を取得する
- (URL)https://xxxxx/readinglist/0001
- (HTTPメソッド) GET
- 読書リストのうち、ID「1000」の本を削除する
- (URL)https://xxxxx/readinglist/1000
- (HTTPメソッド) DELETE
RESTful APIはステートレスであるべき
ステートレス = WebAPIサーバはセッション変数を持つべきではない。
サーバ間で共有ができなくなる。などの問題があるから。
スケーラビリティの問題。(今後サーバを増やしたいときとか)
PHPでRESTfulAPIサーバ、クライアントの作成
環境
macOS BigSur 11.0.1
PHP 7.3.22
MAMP 5.7
サーバサイドのPHPファイルを作成
<?php declare(strict_types=1); // GET function getMessage() { $res = [ 'status' => 'success', 'message' => 'ユーザ: ' . $_GET['userName'] . 'の好きな食べ物は、' . $_GET['food'] . 'です。', ]; return $res; } //POST function postMessage() { $res = [ 'status' => 'success', 'message' => 'ユーザ: ' . $_POST['userName'] . 'の好きな食べ物を、' . $_POST['food'] . 'に登録しました。', ]; return $res; } // PUT function putMessage() { parse_str(file_get_contents('php://input'), $putRequest); $res = [ 'status' => 'success', 'message' => 'ユーザ: ' . $putRequest['userName'] . 'の好きな食べ物を、 ' . $putRequest['food'] . 'に変更しました。', ]; return $res; } // DELETE function deleteMessage() { parse_str(file_get_contents('php://input'), $deleteRequest); $res = [ 'status' => 'success', 'message' => 'ユーザ: ' . $deleteRequest['userName'] . 'の好きな食べ物、' . $deleteRequest['food'] . 'を削除しました。', ]; return $res; } switch (strtolower($_SERVER['REQUEST_METHOD'])) { case 'get': echo json_encode(getMessage()); break; case 'post': echo json_encode(postMessage()); break; case 'put': echo json_encode(putMessage()); break; case 'delete': echo json_encode(deleteMessage()); break; }
クライアントサイドのPHPファイルを作成
cUEL関数を使用。
curl_init()
でURLを指定。cURLハンドルを取得。curl_setopt()
でオプションの指定。curl_exec()
でハンドルを渡し、リクエストを送信。レスポンスを取得。curl_close()
でハンドルを閉じる。
GET
<?php declare(strict_types=1); $params = [ 'userId' => 1001, 'userName' => "kona", 'food' => '抹茶', ]; $url = "http://localhost:8888/server.php?" . http_build_query($params); $handle = curl_init($url); curl_setopt($handle, CURLOPT_RETURNTRANSFER, true); $apiResponse = json_decode(curl_exec($handle), true); curl_close($handle); echo "サーバからの応答:\n"; print_r($apiResponse);
実行結果
サーバからの応答: Array ( [status] => success [message] => ユーザ: konaの好きな食べ物は、抹茶です。 )
http_build_query()
で連想配列をパラメータ文字列へ。
$params = [ 'userId' => 1001, 'userName' => "kona", 'food' => '抹茶', ];
↓
userId=1001&userName=kona&food=抹茶(Unicodeに変換される)
POST
<?php declare(strict_types=1); $params = [ 'userId' => 1001, 'userName' => "kona", 'food' => '抹茶', ]; $opt = [ CURLOPT_URL => 'http://localhost:8888/server.php', CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POSTFIELDS => $params, CURLOPT_RETURNTRANSFER => true, ]; $handle = curl_init(); curl_setopt_array($handle, $opt); $apiResponse = json_decode(curl_exec($handle), true); curl_close($handle); echo "サーバからの応答:\n"; print_r($apiResponse);
実行結果
サーバからの応答: Array ( [status] => success [message] => ユーザ: konaの好きな食べ物を、抹茶に登録しました。 )
curl_setopt_array()
で配列で指定した設定を適応できる。
PUT
<?php declare(strict_types=1); $params = [ 'userId' => 1001, 'userName' => "kona", 'food' => '抹茶アイス', ]; $opt = [ CURLOPT_URL => 'http://localhost:8888/server.php', CURLOPT_CUSTOMREQUEST => 'PUT', CURLOPT_POSTFIELDS => http_build_query($params), CURLOPT_RETURNTRANSFER => true, ]; $handle = curl_init(); curl_setopt_array($handle, $opt); $apiResponse = json_decode(curl_exec($handle), true); curl_close($handle); echo "サーバからの応答:\n"; print_r($apiResponse);
実行結果
サーバからの応答: Array ( [status] => success [message] => ユーザ: konaの好きな食べ物を、 抹茶アイスに変更しました。 )
DELETE
<?php declare(strict_types=1); $params = [ 'userId' => 1001, 'userName' => "kona", 'food' => '抹茶アイス', ]; $opt = [ CURLOPT_URL => 'http://localhost:8888/server.php', CURLOPT_CUSTOMREQUEST => 'DELETE', CURLOPT_POSTFIELDS => http_build_query($params), CURLOPT_RETURNTRANSFER => true, ]; $handle = curl_init(); curl_setopt_array($handle, $opt); $apiResponse = json_decode(curl_exec($handle), true); curl_close($handle); echo "サーバからの応答: \n"; print_r($apiResponse);
実行結果
サーバからの応答: Array ( [status] => success [message] => ユーザ: konaの好きな食べ物、抹茶アイスを削除しました。 )
参考書籍
PHP本格入門[下] ~オブジェクト指向設計、セキュリティ、現場で使える実践ノウハウまで
- 作者:大家 正登
- 発売日: 2020/08/03
- メディア: 単行本(ソフトカバー)