[unity2019.LTS]最も簡単なデータベース通信 – (4)PHP でテーブルを更新

前回の記事はこちら →
(1)サーバーにデータベースを用意
(2)データベースにテーブルを用意
(3)PHP でテーブルを取得

データベースの値を用意したり、FTP のアクセスは前回と変わらないので、そちらをご参照ください。

プログラムを書く

以下の部分を自分の情報に置き換えてください。ファイル名は update.php とします。
GET ではなく POST の方がパラメータの隠蔽が出来るのでいいのですが、今回はブラウザでテストしたいので、GET で進めます。

[[データベースホスト名]]
[[データベース名]]
[[ユーザー名]]
[[パスワード]]

<?php

{
	update();
}

function update()
{
	try
	{
		if (isset($_GET['name']) == false || isset($_GET['val']) == false)
		{
			echo 'error: parameter';
			return;
		}
		$name = $_GET['name'];
		$val  = $_GET['val'];

		$dsn = 'mysql:host=[[データベースホスト名]];dbname=[[データベース名]];charset=utf8mb4';
		$username = '[[ユーザー名]]';
		$password = '[[パスワード]]';

		$pdo = new PDO($dsn, $username, $password);
		$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
		$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

		$stmt = $pdo->prepare('SELECT * FROM test_table WHERE field_name = :name');
		$stmt->bindValue('name', $name, PDO::PARAM_STR);
		$stmt->execute();

		while ($row = $stmt->fetchObject())
		{
			$stmt = $pdo->prepare('UPDATE test_table SET field_count = :val WHERE field_name = :name');
			$stmt->bindValue('name', $name, PDO::PARAM_STR);
			$stmt->bindValue('val',  (int)$val,  PDO::PARAM_INT);
			$stmt->execute();
		}

		echo 'success';
	}
	catch (PDOException $e)
	{
		echo "error: ". $e->getMessage(). "\n";
		exit();
	}
}

?>

FTP にアップロード

(3) と同じ場所にアップロードします。

public_html/create-forever.games/test/update.php

実行してみる

ブラウザで実行します。

https://www.create-forever.games/test/update.php?name=Japan&val=1123

update.php?name=Japan&val=1123

field_name Japan の行を探して、field_count 1123 を入れる、という内容です。
本当に変わったか、phpMyAdmin で確認してみます。

1123 に変更されました!
もちろん、Japan 以外を変更することもできます。

https://www.create-forever.games/test/update.php?name=France&val=-150

テーブルにない場合はスルーします。

https://www.create-forever.games/test/update.php?name=Amigo&val=0
なにも変わらない

パラメータがおかしければエラーを出力します。

https://www.create-forever.games/test/update.php
https://www.create-forever.games/test/update.php?mame=Japan&val=1123

なお、わかりやすくするために「ユーザーが受け取れるログ」を出力していますが、実際に運用する場合は以下のような形にしておけば、悪意のあるユーザーにヒントを与えずに済むので、いいと思います。

  • サーバーにファイルログ(等)を出力する(サイズの肥大化に注意!)
  • ユーザーには何も返さない

また、今回は GET で引数渡しを行いましたが、unity でアクセスするときには POST にしようと思います。

PHP の簡単な解説

ざっくり解説です。

更新パラメータを確認

if (isset($_GET['name']) == false || isset($_GET['val']) == false)
{
	echo 'error: parameter';
	return;
}
$name = $_GET['name'];
$val  = $_GET['val'];

パラメータ name=Japan&val=1123 が存在するか確認し、あれば変数に代入しています。

接続

$dsn = 'mysql:host=[[データベースホスト名]];dbname=[[データベース名]];charset=utf8mb4';
$username = '[[ユーザー名]]';
$password = '[[パスワード]]';

$pdo = new PDO($dsn, $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

ここは前回と同じですね。更新するにも問い合わせは必要です。

行の存在を確認する

$stmt = $pdo->prepare('SELECT * FROM test_table WHERE field_name = :name');
$stmt->bindValue('name', $name, PDO::PARAM_STR);
$stmt->execute();

このやり方は効率が悪いかもしれませんが、field_name に名前が一致する行があるか確認しています。
存在する場合は fetchObject で行が取れるので更新、存在しなければ fetchObject をスルーするので何も更新されずに終わります。

こんなことをせずに直接 UPDATE でいいような気もしますが…「存在しない行を UPDATE する」というコードをなんとなく気持ち悪いと思ってしまう性を許してください…😢

行を更新する

while ($row = $stmt->fetchObject())
{
	$stmt = $pdo->prepare('UPDATE test_table SET field_count = :val WHERE field_name = :name');
	$stmt->bindValue('name', $name, PDO::PARAM_STR);
	$stmt->bindValue('val',  (int)$val,  PDO::PARAM_INT);
	$stmt->execute();
}

UPDATE クエリでデータを更新します。ここが今回のキモです。

長くなりましたが、次はようやく unity です!

Recommended Blog

(1)サーバーにデータベースを用意
(2)データベースにテーブルを用意
(3)PHP でテーブルを取得
(4)PHP でテーブルを更新
(5)unity で PHP を呼び出す