C++とPHPとMySQLの連携を試してみた

タイトルの通り、C++とPHPとMySQLを用いてデータのやり取りをやってみたのでメモ。
#使用したもの
<b>ツール</b>
・VisualStudio2017
・[Xampp](https://www.apachefriends.org/jp/index.html)

<b>ライブラリ</b>
・[Boost](https://www.boost.org/users/download/) (通信するために使用)
・[Json11](https://github.com/dropbox/json11) (JSONを解析するために使用)
#やりたいこと
流れとしては、
①C++ → ②PHP → ③MySQL → ④PHP → ⑤C++ の順でデータをやり取りしたい。
取りあえず、今回は2つの値を足し算した結果を取得することを目標とする。

①　足し算したい2つの値を入力し、GET方式で送る。
②　足し算を行い、MySQLに計算結果を送る。
③　結果を保存する。
④　今までの計算結果を受け取り、JSON形式で送る。
④　JSON形式で計算結果を受け取り、それらを表示する。

#コード
<b>クライアント：</b>

```C++(cpp):main.cpp
#include <iostream>
#include <iomanip>
#include <boost/asio.hpp>
#include <boost/algorithm/string.hpp>
#include <vector>
#include "json11.hpp"

using namespace std;
namespace asio = boost::asio;
namespace ip = asio::ip;
using namespace json11;

int main()
{
	//足し算する値の入力
	int value1, value2;
	cout << "value1を入力 : ";	cin >> value1;
	cout << "value2を入力 : ";	cin >> value2;
	cout << '\n';

	//リクエストに対するレスポンス
	string allRes = "";

	//通信を開始
	try {
		asio::io_service io_service;

		//TCPソケットを作成する
		ip::tcp::socket sock(io_service);

		//名前解決（ホスト名からIPアドレスに変換）する
		ip::tcp::resolver resolver(io_service);
		ip::tcp::resolver::query query("127.0.0.1", "http");

		//ホスト情報を設定する
		ip::tcp::endpoint endpoint(*resolver.resolve(query));

		//ソケットへ接続
		sock.connect(endpoint);

		//メッセージを送信
		asio::streambuf request;
		ostream request_ostream(&request);
		string getRequest = "GET add.php?value1=" + to_string(value1)
			+ "&value2=" + to_string(value2) + " HTTP/1.0\r\n\r\n";
		request_ostream << getRequest;
		asio::write(sock, request);

		//メッセージを受信
		asio::streambuf response;
		boost::system::error_code error;

		while (asio::read(sock, response, asio::transfer_at_least(1), error)) {
			//streambufからstringに変換
			string tmp = asio::buffer_cast<const char *>(response.data());
			allRes += tmp.substr(0, response.size());
		}
	}
	catch (exception& e) {
		cout << e.what() << '\n';
		return 1;
	}

	//二重改行で区切る(レスポンスボディを取得するため)
	vector<string> res;
	res = boost::split(res, allRes, boost::is_any_of("\r\n\r\n"));

	//stringからJsonに変換
	string err;
	const Json jsonData = Json::parse(res[res.size() - 1], err);

	cout << jsonData.dump() << "\n\n";

	//各値を取得
	auto jsonArray = jsonData.array_items();
	cout << "    id value1 value2    ans" << endl;

	for (auto &item : jsonArray) {
		cout << setw(6) << right << item["id"].string_value()     << " ";
		cout << setw(6) << right << item["value1"].string_value() << " ";
		cout << setw(6) << right << item["value2"].string_value() << " ";
		cout << setw(6) << right << item["ans"].string_value()    << '\n';
	}

	return 0;
}
```

MySQLに「calc_db」というデータベースを作り、テーブル名を「result」とした。
カラムは、「id」「value1」「value2」「ans」の４つである。
これにより、挿入された順番、入力した値、二つの値の足し算の結果がDBに保存される。
<br></br>

<b>サーバー：</b>

```php:add.php
<?php

//計算する値を入力
$isInput = TRUE;
if(isset($_GET['value1'])){
	$value1 = intval($_GET['value1']);
}
else {
	$isInput = FALSE;
}
if(isset($_GET['value2'])){
	$value2 = intval($_GET['value2']);
}
else {
	$isInput = FALSE;
}

//DBの設定
$mysql = mysqli_connect('localhost', 'root', '') or die(mysqli_error($mysql));
mysqli_select_db($mysql, 'calc_db');
mysqli_query($mysql, 'SET NAMES UTF8');

//入力があるならデータをDBに追加
if($isInput){
	//結果を計算
	$ans = $value1 + $value2;

	//DBにデータを挿入
	$insert = sprintf('INSERT INTO result SET value1=%d,value2=%d,ans=%d',
			mysqli_real_escape_string($mysql, $value1),
			mysqli_real_escape_string($mysql, $value2),
			mysqli_real_escape_string($mysql, $ans)
	);
	mysqli_query($mysql, $insert) or die(mysqli_error($mysql));
}

//DBからデータを取得
$request = sprintf('SELECT * FROM result');
$result = mysqli_query($mysql, $request) or die(mysqli_error($mysql));

$ansList = array();
while($row = mysqli_fetch_assoc($result)){
	$ansList[] = array(
		'id'=>$row['id'],
		'value1'=>$row['value1'],
		'value2'=>$row['value2'],
		'ans'=>$row['ans']
	);
}

//jsonで出力
$jsonData = json_encode($ansList);
header("Content-Type: application/json; charset=utf-8");
echo $jsonData;
?>
```
#出力結果
value1に「１」、value2に「２」を入力した。
足し算をした結果、ansが「３」となっていることが分かる。

```
value1を入力 : 1
value2を入力 : 2

[{"ans": "3", "id": "1", "value1": "1", "value2": "2"}]

    id value1 value2    ans
     1      1      2      3
```
次に、value1に「２」、value2に「３」を入力した。
ansは「５」となり、表にはこれまでの計算結果が表示されている。

```
value1を入力 : 2
value2を入力 : 3

[{"ans": "3", "id": "1", "value1": "1", "value2": "2"}, {"ans": "5", "id": "2", "value1": "2", "value2": "3"}]

    id value1 value2    ans
     1      1      2      3
     2      2      3      5
```
データベースの中身は以下ようになっている。
<img width="497" alt="DB足し算.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530813/17a6b839-a3b2-15aa-6b51-7441df677b56.png">
#まとめ
C++からPHP、PHPからMySQLへの連携は簡単ながら行うことができた。
GET形式をPOST形式にしたり、同期通信を非同期通信にするなどまだやることはある。
また、コードに関してももっと良い書き方があると思う。
今度はこれを応用して何か作りたい。

#参考にしたサイト
・[ネットワーク - TCP]
(https://boostjp.github.io/tips/network/tcp.html)
・[Boost.AsioでHTTP通信]
(https://nekko1119.hatenablog.com/entry/2013/10/02/145532)
・[C++11でjsonを扱う方法。json11]
(https://qiita.com/YukiMiyatake/items/497e2fe807d09141e000)
・[C++11でjson扱うならdropbox/json11がよさそう]
(https://kyokomi.hatenablog.com/entry/2014/05/10/233613)

など。