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


タイトルの通り、C++とPHPとMySQLを用いてデータのやり取りをやってみたのでメモ。

使用したもの

ツール
・VisualStudio2017
Xampp

ライブラリ
Boost (通信するために使用)
Json11 (JSONを解析するために使用)

やりたいこと

流れとしては、
①C++ → ②PHP → ③MySQL → ④PHP → ⑤C++ の順でデータをやり取りしたい。
取りあえず、今回は2つの値を足し算した結果を取得することを目標とする。

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

コード

クライアント:

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」の4つである。
これにより、挿入された順番、入力した値、二つの値の足し算の結果がDBに保存される。

サーバー:

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に「1」、value2に「2」を入力した。
足し算をした結果、ansが「3」となっていることが分かる。

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

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

    id value1 value2    ans
     1      1      2      3

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

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

データベースの中身は以下ようになっている。

まとめ

C++からPHP、PHPからMySQLへの連携は簡単ながら行うことができた。
GET形式をPOST形式にしたり、同期通信を非同期通信にするなどまだやることはある。
また、コードに関してももっと良い書き方があると思う。
今度はこれを応用して何か作りたい。

参考にしたサイト

ネットワーク - TCP
Boost.AsioでHTTP通信
C++11でjsonを扱う方法。json11
C++11でjson扱うならdropbox/json11がよさそう

など。