PHPでJSONを返すだけのAPIを実装する

# 経緯

APIの右も左も分かっていなかったので、理解を深める為に実装した時のやつ。

~~HTTPステータスコードも返さないし、headerも返さない。~~
~~jsonだけ返す。~~
<2019/8/28追記>
嘘。明示的にHTTPステータスコードを指定しなくとも問題なければ200が返るし、下記で返るのはHEADERを指定していないので、HTMLのBodyにJSONっぽい何かが入ったResponseが返る。JSONとして受け取り側に認識させたいならば、`Content-Type: application/json`をResponseHeaderに付与してやる。あと多分`json_encode`で`JSON_UNESCAPED_UNICODE`オプションを指定してやらないとマルチバイト文字がunicodeで表示されてしまう問題が発生するはずなので注意。

## サーバーサイド（API）

### コード

```php
<?php
// 連想配列用意
$array = [
	'tokyo' => [
		'品川',
		'五反田',
		'三軒茶屋',
		'四谷'
	],
	'kanagawa' => [
		'横浜',
		'相模原',
		'湘南',
		'鎌倉'
	],
	'saitama' => [
		'所沢',
		'狭山',
		'川口',
		'浦和',
		'小手指',
		'飯能'
	]
];

// Origin null is not allowed by Access-Control-Allow-Origin.とかのエラー回避の為、ヘッダー付与
header("Access-Control-Allow-Origin: *");

echo json_encode($array);
```
### コード概要

- Response用のデータを連想配列で用意
- 連想配列をJSON変換
- echoして結果をResponseBodyに吐き出す

~~`header("Access-Control-Allow-Origin: *");`はエラー対策。~~
~~jQueryで$.getJSONしようとした時にエラーが出るので、エラーが出ないようにヘッダー情報を付与。~~
<2019/8/28追記>
[CORS](https://developer.mozilla.org/ja/docs/Web/HTTP/CORS)対策。
[CrossSiteResourceSharing](https://developer.mozilla.org/ja/docs/Web/HTTP/CORS)の略。

>ウェブアプリケーションは、自分のオリジンとは異なるオリジン (ドメイン、プロトコル、ポート番号) からリソースをリクエストするとき、オリジン間 HTTP リクエストを実行します。

とあるようにブラウザで別オリジンのリソースへアクセスしようと場合、セキュリティ上の理由でリクエストが制限されてしまうので、サーバー側のResponseHeaderにCORS許可するよってHeaderを付与してやることでその制限を外すことができる。

他にも自分はやったことがないが、JSONPを使うことでも回避ができるらしい。が、危険という情報もあるのでよく調べたほうがよいかも。

## jQueryを利用したフロント側からAPIへのリクエスト例

フロントでAPIを叩く時のコード（jQuery）

### コード

```js
$(function() {
	$.getJSON('http://localhost/echo_json.php', function(data) {
		Object.keys(data).forEach(function (key) {
			$('#contents').append('<ul id="' + key + '">');
			data[key].forEach(function (value, index, array) {
				$(`#${key}`).append('<li>' + value + '</li>');
			});
		});
	});
});
```

### コード概要

- $.getJSONメソッドを使って、JSONを取ってくる。
- 第一引数はAPIのURL(ローカルだったらjsonを出力するphpのFilePath)
- 第二引数はコールバック関数(処理はコールバック関数の中に書く)
- オブジェクトが返ってくるのでforEachで回す。(オブジェクトは普通にはforEachでは回せないので注意。)

## 上記コードを使ってブラウザで表示

### HTML

```html
<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>サーバー側(PHP)でJSONをechoして、クライアント側(jQuery)で処理してみる</title>
    <script src="https://code.jquery.com/jquery-3.2.1.js" integrity="sha256-DZAnKJ/6XZ9si04Hgrsxu/8s717jcIzLy3oi35EouyE=" crossorigin="anonymous"></script>
</head>
<body>
    <h2>サーバー側(PHP)でJSONをechoして、クライアント側(jQuery)で処理してみる</h2>
    <div id="contents">

    </div>
</body>
</html>
```

### Result

```
サーバー側(PHP)でJSONをechoして、クライアント側(jQuery)で処理してみる

●品川
●五反田
●三軒茶屋
●四谷

●横浜
●相模原
●湘南
●鎌倉

●所沢
●狭山
●川口
●浦和
●小手指
●飯能
```

こんな感じでブラウザに表示されていれば成功

## 参考文献

[load() を使うと Chrome が文句言う](http://tomio2480.hatenablog.com/entry/20120922/1348262110)
[AjaxでAccess-Control-Allow-Originのエラーを回避する方法](https://www.muratayusuke.com/2011/05/28/access-control-allow-origin/)
[コールバック関数とは](https://qiita.com/pocket8137/items/df5afba90b51e90587a5)
[オブジェクトをforEachで回すには](https://qiita.com/nantekkotai/items/6c603b40ac2264e9f6f6)

## 追記 久しぶりに記事編集

大分前の全くわかってなかった時の記事だけど、割と見られるようなので整理。
下記にDockerでさくっと動かせる環境込のソースを用意してみた。
https://github.com/mizumizue/php-simple-api