#制作環境
Windows 10
XAMPP
PHP : 7.4.3
Visual Studio Code
#はじめに
この記事はプログラミングをはじめたばかりの素人が、メモするのに利用しています。
内容には誤りがあるかもしれません。
当方は2月から2ヶ月間CodeCampのWebマスターコースを受講しました。
CodeCampは、意向により模範解答などを見ることができません。
※理由は、コードの記述に正解がないからだそうです。
他の人のコードを見る事も参考になると思いますので、つたないコード記述ではありますが、合格をもらったコードを掲載します。
良くも悪くも参考になればと思います。
###【追記】
SQLインジェクションの脆弱性があると指摘をいただきました。
講座にない内容ではありますが、重要な内容なのでレッスン等で確認してみて下さい。
#構成
管理ページ tool.php
購入ページ index.php
購入結果ページ result.php
オリジナル関数 functions.php
スタイルシート drink.css
#オリジナル関数 functions.phpについて
エンティティ変換と空白削除の関数を別ファイルで作成し、読み込むようになっていますが、これは後から習うやり方なのでここでは無視してもかまいません。
自分は色々調べる過程でこのやり方を見つけた為、先行してこの方法を使いました。
#課題の内容
####内容
商品の管理・購入ページを作成します。
####合格ライン
・指定要件が全て満たされていること。
・エラーがなく、分かりやすいソースコードになっていること。
####要件
管理ページ tool.php
No. | 内容 |
---|---|
1 | 「ドリンク名」「値段」「在庫数」「公開ステータス」を入力し、商品を追加できる。 |
2 | 商品を追加する場合、「商品画像」を指定してアップロードできる。 |
3 | 追加した商品の一覧情報として、「商品画像」、「商品名」、「値段」、「在庫数」、「公開ステータス」のデータを一覧で表示する。 |
4 | 商品一覧から指定ドリンクの在庫数を入力し、在庫数の変更ができる。 |
5 | 商品一覧から指定ドリンクの公開ステータス「公開」あるいは「非公開」の変更ができる。 |
6 | 商品の追加あるいは指定ドリンク情報(「在庫数」、「公開ステータス」)の変更が正常に完了した場合、完了のメッセージを表示する。 |
7 | 商品を追加する場合、「商品名」「値段」、「在庫数」、「公開ステータス」「商品画像」のいずれかを指定していない場合、エラーメッセージを表示して、商品を追加できない。 |
8 | 商品を追加する場合、「値段」、「在庫数」は、0以上の整数のみ可能とする。0以上の整数以外はエラーメッセージを表示して、商品を追加できない。 |
9 | 商品を追加する場合、公開ステータスは「公開」あるいは「非公開」のみ可能とする。「公開」あるいは「非公開」以外はエラーメッセージを表示して、商品を追加できない。 |
10 | アップロードできる「商品画像」のファイル形式は「JPEG」、「PNG」のみ可能とする。「JPEG」、「PNG」以外はエラーメッセージを表示して、商品を追加できない。 |
11 | 商品一覧から指定ドリンクの在庫数を変更する場合、0以上の整数のみ可能とする。0以上の整数以外はエラーメッセージを表示して、変更できない。 |
購入ページ index.php
No. | 内容 |
---|---|
12 | ステータスが「公開」のドリンク情報(「商品画像」「商品名」「値段」)を一覧で表示する。 |
13 | 金額を投入するテキストボックスを作成する。 |
14 | ドリンクを選択するラジオボタンを作成する。 |
15 | ドリンクの在庫が0の場合、ドリンクを選択するラジオボタンは表示せず、「売り切れ」と表示する。 |
16 | 購入ボタンを押すと購入結果ページへ遷移する。 |
購入結果ページ result.php
No. | 内容 |
---|---|
17 | ドリンクの購入が正常に完了した場合、指定ドリンクの「画像」「商品名」「お釣りの情報」を表示する |
18 | ドリンクの購入が正常に完了した場合、指定ドリンクの在庫を減らす(管理ページの在庫数が減っていること)。 |
19 | 購入ページへ戻るリンクを作成する。 |
20 | 購入するドリンクを指定していない場合、エラーメッセージを表示して、ドリンクを購入することはできない。 |
21 | 投入金額と指定ドリンクを購入するときに必要な金額を比べ、もし投入金額が足りない場合はエラーメッセージを表示して、ドリンクを購入することはできない。 |
22 | 投入金額は0以上の整数のみ可能である。0以上の整数以外の場合は、エラーメッセージを表示して、ドリンクを購入することはできない。 |
23 | 指定ドリンクの在庫を確認し、もし在庫がなかった場合はエラーメッセージを表示して、ドリンクを購入することはできない(確認手順の例は以下になります)。1. 購入ページで、在庫がある商品を表示する。2. もう1つのブラウザで管理ページを表示させて、購入予定の在庫がある商品の在庫数を0に変更する(在庫なしにする)。3. 別のブラウザで開いていた購入ページで、在庫数を0に変更した商品を選択して、購入するボタンを押した場合、エラーメッセージが表示されること |
24 | 指定ドリンクのステータスを確認し、もしステータスが非公開の場合はエラーメッセージを表示して、ドリンクを購入することはできない(確認手順の例は以下になります)。1. 購入ページで、ステータスが公開の商品を表示する。2. もう1つのブラウザで管理ページを表示さて、購入予定のステータスが公開である商品について、ステータスを非公開に変更する(ステータスを非公開にする)。3. 別のブラウザで開いていた購入ページで、ステータスを非公開に変更した商品を選択して、購入するボタンを押した場合、エラーメッセージが表示されること。 |
25 | ドリンクの購入が正常に完了した場合、指定ドリンクと購入日時の情報をデータベースに保存する(※この要件は必須ではなく任意です)。 |
全体
No. | 内容 |
---|---|
26 | 比較は「===」や「!==」を利用していること |
#ソースコード
<?php
// 関連ファイル・フォルダ・DBテーブル
/*
index.php 商品購入ページ
result.php 購入後ページ
functions.php 関数定義ファイル
drink.css ページデザイン定義ファイル
drink_pictureフォルダ 画像ファイル保存フォルダ
drink_info_table 商品情報テーブル
stock_table 在庫情報テーブル
drink_history_table 購入履歴テーブル
*/
$uploaddir = './drink_picture/'; // ファイルのアップ先(フォルダ)の指定
$err_msg = []; // エラーメッセージの格納先
$complete_msg = []; // 操作正常終了時のメッセージ格納先
$host = 'localhost'; // ホスト名
$username = 'xxxxxxxxxxxxx'; // ユーザー名
$passwd = 'xxxxxxxxxxxxx'; // パスワード
$dbname = 'xxxxxxxxxxxxx'; // データベース名
require_once('functions.php'); // 関数呼び出し
date_default_timezone_set('Asia/Tokyo'); // タイムゾーン設定
// DB接続開始
if ($link = mysqli_connect($host, $username, $passwd, $dbname)) {
// 文字化け防止
mysqli_set_charset($link, 'utf8');
// トランザクション開始(オートコミットをオフ)
mysqli_autocommit($link, false);
// ここから新規登録の動作=============================
// メソッドとクエリ内容の確認
if ($_SERVER['REQUEST_METHOD'] === 'POST' && $_POST['sql_kind'] === 'insert') {
// 名前の登録確認と入力情報の格納
if (isset($_POST['new_name']) === TRUE) {
switch (TRUE) {
case (cut($_POST['new_name']) === ''):
$err_msg[] = '商品名を入力してください';
break;
case (cut($_POST['new_name']) === NULL);
$err_msg[] = '商品名を入力してください';
break;
default:
$new_name = cut($_POST['new_name']);
break;
}
}
// 値段の登録確認と入力情報の整数判定と格納
if (isset($_POST['new_price']) === TRUE) {
switch (TRUE) {
case (cut($_POST['new_price']) === ''):
$err_msg[] = '値段を入力してください';
break;
case (cut($_POST['new_price']) === NULL):
$err_msg[] = '値段を入力してください';
break;
case (preg_match('/^[0-9]+$/', cut($_POST['new_price'])) !== 1):
$err_msg[] = '値段は0以上の半角整数を入力してください';
break;
default:
$new_price = (int) cut($_POST['new_price']);
break;
}
}
// 在庫の登録確認と入力情報の整数判定と格納
if (isset($_POST['new_stock']) === TRUE) {
switch (TRUE) {
case (cut($_POST['new_stock']) === ''):
$err_msg[] = '個数を入力してください';
break;
case (cut($_POST['new_stock']) === NULL):
$err_msg[] = '個数を入力してください';
break;
case (preg_match('/^[0-9]+$/', cut($_POST['new_stock'])) !== 1):
$err_msg[] = '在庫は0以上の半角整数を入力してください';
break;
default:
$new_stock = (int) cut($_POST['new_stock']);
break;
}
}
// ファイルの登録確認とファイル情報の判定と格納
if ($_FILES['new_img']['error'] === UPLOAD_ERR_OK) {
if (count($err_msg) === 0) {
// ファイル情報の取得
$chk_picture = getimagesize($_FILES['new_img']['tmp_name']);
// ファイル形式の確認及び拡張子偽装の確認
if ($chk_picture['mime'] === 'image/png' || $chk_picture['mime'] === 'image/jpeg') {
// ファイルサイズの確認
if ($chk_picture[0] <= 500 && ($chk_picture[1] <= 500)) {
// 拡張子の取得
$mime = $chk_picture['mime'];
switch ($mime) {
case 'image/png':
$type = '.png';
break;
case 'image/jpeg':
$type = '.jpg';
break;
}
// ファイル情報の格納 ファイル名は新規作成(セキュリティ対策)
$upload = $uploaddir . date('YmdHis') . rand(0, 10000) . $type;
// 一時フォルダのファイルをアップ先に移動
move_uploaded_file($_FILES['new_img']['tmp_name'], $upload);
} else {
$err_msg[] = 'ファイルは縦と横500px以内にしてください';
}
} else {
$err_msg[] = 'PNGかJPEG形式のファイルをアップロードしてください';
}
}
} else {
$err_msg[] = 'ファイルを選択してください';
}
// ステータスの登録確認と格納
if (isset($_POST['new_status']) === TRUE) {
if ((int) $_POST['new_status'] === 0 || (int) $_POST['new_status'] === 1) {
$new_status = (int) $_POST['new_status'];
} else {
$err_msg[] = 'ステータスは公開か非公開を選択してください';
}
} else {
$err_msg[] = 'ステータスを選択してください';
}
// 現状のエラー数確認
if (count($err_msg) === 0) {
// 作成日時の取得
$new_time = date('Y-m-d H:i:s');
// テーブルに登録する情報を集約し格納
$insert_data_info = [
'drink_name' => $new_name,
'price' => $new_price,
'created_at' => $new_time,
'updated_at' => $new_time,
'status' => $new_status,
'path' => $upload
];
// drink_info_tableへ情報を登録するクエリ
$sql = 'INSERT INTO drink_info_table(drink_name, price, created_at, updated_at, status, path) VALUES (\'' . implode('\',\'', $insert_data_info) . '\')';
// クエリの結果確認
if ($result = mysqli_query($link, $sql) === TRUE) {
// A_Iを取得
$drink_id = mysqli_insert_id($link);
// テーブルに登録する情報を集約し格納
$insert_data_stock = [
'drink_id' => $drink_id,
'stock' => $new_stock,
'created_at' => $new_time,
'updated_at' => $new_time
];
// stock_tableへ情報を登録するクエリ
$sql = 'INSERT INTO stock_table(drink_id, stock, created_at, updated_at) VALUES (\'' . implode('\',\'', $insert_data_stock) . '\')';
// クエリの結果確認
if ($result = mysqli_query($link, $sql) !== TRUE) {
$err_msg[] = 'stock_tableへのデータの登録に失敗しました';
}
} else {
$err_msg[] = 'drink_info_tableへのデータの登録に失敗しました';
}
if (count($err_msg) === 0) {
$complete_msg[] = '追加登録完了!';
}
}
}
// ここから在庫数更新の動作===========================
// メソッドとクエリ内容の確認
if ($_SERVER['REQUEST_METHOD'] === 'POST' && $_POST['sql_kind'] === 'update') {
// 在庫の登録確認と入力情報の整数判定と格納
if (isset($_POST['update_stock']) === TRUE) {
if (preg_match('/^[0-9]+$/', cut($_POST['update_stock'])) === 1) {
$update_stock = (int) cut($_POST['update_stock']);
// 更新日時の取得
$update_time = date('Y-m-d H:i:s');
// 対象商品idの取得
$update_id = $_POST['drink_id'];
// stock_tableの情報を更新するクエリ
$sql = 'UPDATE stock_table SET stock = ' . $update_stock . ', updated_at = \'' . $update_time . '\' WHERE drink_id = ' . $update_id;
if ($result = mysqli_query($link, $sql) === TRUE) {
$complete_msg[] = '在庫数更新完了!';
} else {
$err_msg[] = '在庫数の更新に失敗しました';
}
} else {
$err_msg[] = '0以上の半角整数を入力してください';
}
}
}
// ここからステータス変更の動作=======================
// メソッドとクエリ内容の確認
if ($_SERVER['REQUEST_METHOD'] === 'POST' && $_POST['sql_kind'] === 'change') {
// ステータスの確認と入力情報の格納
if (isset($_POST['change_status']) === TRUE) {
if ((int) $_POST['change_status'] === 0 || (int) $_POST['change_status'] === 1) {
$change_id = $_POST['drink_id'];
$change_status = (int) $_POST['change_status'];
// 変更日時の取得
$change_time = date('Y-m-d H:i:s');
// drink_info_tableの情報を更新するクエリ
$sql = 'UPDATE drink_info_table SET updated_at = \'' . $change_time . '\', status = ' . $change_status . ' WHERE drink_id = ' . $change_id;
if ($result = mysqli_query($link, $sql) === TRUE) {
$complete_msg[] = 'ステータス変更完了!';
} else {
$err_msg[] = 'ステータスの変更に失敗しました';
}
} else {
$err_msg[] = 'ステータスは公開か非公開を選択してください';
}
}
}
// トランザクション成否判定
if (count($err_msg) === 0) {
// 処理確定
mysqli_commit($link);
} else {
// 処理取消
mysqli_rollback($link);
}
// ここから一覧表示の動作=============================
// 登録情報を取得するクエリ
$sql = 'SELECT drink_info_table.drink_id, drink_info_table.drink_name, drink_info_table.price, stock_table.stock, drink_info_table.status, drink_info_table.path FROM drink_info_table LEFT JOIN stock_table ON drink_info_table.drink_id = stock_table.drink_id';
// クエリの結果確認
if ($result = mysqli_query($link, $sql)) {
// 取得した情報の格納
while ($row = mysqli_fetch_array($result)) {
$data[] = $row;
}
} else {
$err_msg[] = 'データの抽出に失敗しました';
}
// DB接続停止
mysqli_free_result($result);
mysqli_close($link);
} else {
$err_msg[] = 'DB接続失敗';
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>自動販売機商品管理</title>
<link rel="stylesheet" href="drink.css">
</head>
<body>
<?php if (count($complete_msg) !== 0) {
foreach ($complete_msg as $complete) { ?>
<p><?php print $complete; ?></p>
<?php }
} ?>
<?php if (count($err_msg) !== 0) {
foreach ($err_msg as $err) { ?>
<p><?php print $err; ?></p>
<?php }
} ?>
<h1>自動販売機管理ツール</h1>
<section>
<h2>新規商品追加</h2>
<form method="post" enctype="multipart/form-data">
<label>名前: <input type="text" name="new_name" size="30" /></label><br>
<label>値段: <input type="text" name="new_price" size="30" /></label><br>
<label>個数: <input type="text" name="new_stock" size="30" /></label><br>
<input type="file" name="new_img" accept="image/jpeg, image/png" /><br>
<select name="new_status"><br>
<option value="0">非公開</option>
<option value="1">公開</option>
</select><br>
<input type="hidden" name="sql_kind" value="insert">
<input type="submit" value="■□■□商品追加■□■□" />
</form>
</section>
<section>
<h2>商品情報変更</h2>
<table>
<caption>商品一覧</caption>
<tbody>
<tr>
<th>商品画像</th>
<th>商品名</th>
<th>価格</th>
<th>在庫数</th>
<th>ステータス</th>
</tr>
<?php if (empty($data) !== TRUE) {
foreach ($data as $list) {
if ((int) $list['status'] === 0) { ?>
<tr class="status_0">
<?php } else { ?>
<tr>
<?php } ?>
<td><img class="image" src="<?PHP print $list['path']; ?>"></td>
<td class="d_name"><?php print html_enc($list['drink_name']); ?></td>
<td class="d_price"><?php print $list['price']; ?></td>
<td>
<form method="post">
<input type="text" class="input_text_width text_align_right" name="update_stock" value="<?php print $list['stock']; ?>">個
<br>
<input type="submit" value="変更">
<input type="hidden" name="drink_id" value="<?php print $list['drink_id']; ?>">
<input type="hidden" name="sql_kind" value="update">
</form>
</td>
<?php if ((int) $list['status'] === 0) { ?>
<td class="d_status">
<form method="post">
<input type="submit" value="非公開 → 公開">
<input type="hidden" name="change_status" value="1">
<input type="hidden" name="drink_id" value="<?php print $list['drink_id']; ?>">
<input type="hidden" name="sql_kind" value="change">
</form>
</td>
</tr>
<?php } else { ?>
<td class="d_status">
<form method="post">
<input type="submit" value="公開 → 非公開">
<input type="hidden" name="change_status" value="0">
<input type="hidden" name="drink_id" value="<?php print $list['drink_id']; ?>">
<input type="hidden" name="sql_kind" value="change">
</form>
</td>
</tr>
<?php }
}
} ?>
</tbody>
</table>
</section>
</body>
</html>
<?php
// 関連ファイル・フォルダ・DBテーブル
/*
tool.php 商品管理ページ
result.php 購入後ページ
functions.php 関数定義ファイル
drink.css ページデザイン定義ファイル
drink_pictureフォルダ 画像ファイル保存フォルダ
drink_info_table 商品情報テーブル
stock_table 在庫情報テーブル
drink_history_table 購入履歴テーブル
*/
$err_msg = []; // エラーメッセージの格納先
$host = 'localhost'; // ホスト名
$username = 'xxxxxxxxxxxxx'; // ユーザー名
$passwd = 'xxxxxxxxxxxxx'; // パスワード
$dbname = 'xxxxxxxxxxxxx'; // データベース名
require_once('functions.php'); // 関数呼び出し
// DB接続開始
if ($link = mysqli_connect($host, $username, $passwd, $dbname)) {
// 文字化け防止
mysqli_set_charset($link, 'utf8');
$sql = 'SELECT drink_info_table.drink_id, drink_info_table.drink_name, drink_info_table.price, drink_info_table.path, stock_table.stock
FROM drink_info_table
JOIN stock_table
ON drink_info_table.drink_id = stock_table.drink_id
WHERE drink_info_table.status = 1';
// クエリの結果確認
if ($result = mysqli_query($link, $sql)) {
// 取得した情報の格納
while ($row = mysqli_fetch_array($result)) {
$data[] = $row;
}
} else {
$err_msg[] = 'データの抽出に失敗しました';
}
// DB接続停止
mysqli_free_result($result);
mysqli_close($link);
} else {
$err_msg[] = 'DB接続失敗';
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>自動販売機</title>
<link rel="stylesheet" href="drink.css">
</head>
<body id="index_body">
<?php foreach ($err_msg as $err) { ?>
<P><?php print $err; ?></P>
<?php } ?>
<h1>自動販売機</h1>
<form class="form" method="post" action="./result.php">
<div>
金額 <input type="text" name="money" />
</div>
<div class="parent">
<?php foreach ($data as $product) { ?>
<div class="product">
<div class="product_picture">
<img class="product_img" src="<?php print $product['path']; ?>"></img>
</div>
<div class="product_name">
<p class="margin"><?php print html_enc($product['drink_name']); ?></p>
</div>
<div class="product_price">
<p class="margin"><?php print $product['price']; ?>円</p>
</div>
<div class="product_buy">
<?php if ((int) $product['stock'] === 0) { ?>
<div class="sold_out"><?php print '売り切れ'; ?></div>
<?php } else { ?>
<input type="radio" name="drink_id" value="<?php print $product['drink_id']; ?>" />
<?php } ?>
</div>
</div>
<?php } ?>
</div>
<div id="submit">
<input type="submit" value="■□■□購入■□■□" />
</div>
</form>
</body>
</html>
<?php
// 関連ファイル・フォルダ・DBテーブル
/*
tool.php 商品管理ページ
index.php 諸品購入ページ
functions.php 関数定義ファイル
drink.css ページデザイン定義ファイル
drink_pictureフォルダ 画像ファイル保存フォルダ
drink_info_table 商品情報テーブル
stock_table 在庫情報テーブル
drink_history_table 購入履歴テーブル
*/
$err_msg = []; // エラーメッセージの格納先
$host = 'localhost'; // ホスト名
$username = 'xxxxxxxxxxxxx'; // ユーザー名
$passwd = 'xxxxxxxxxxxxx'; // パスワード
$dbname = 'xxxxxxxxxxxxx'; // データベース名
require_once('functions.php'); // 関数呼び出し
date_default_timezone_set('Asia/Tokyo'); // タイムゾーン設定
// DB接続開始
if ($link = mysqli_connect($host, $username, $passwd, $dbname)) {
// 文字化け防止
mysqli_set_charset($link, 'utf8');
// トランザクション開始(オートコミットをオフ)
mysqli_autocommit($link, false);
// メソッドとクエリ内容の確認
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// 購入日時の習得
$purchase_time = date('Y-m-d H:i:s');
// drink_idの確認と入力情報の格納
if (isset($_POST['drink_id']) === TRUE) {
switch (TRUE) {
case ($_POST['drink_id'] === ''):
$err_msg[] = 'index.phpからdrink_idを受信できませんでした';
break;
case ($_POST['drink_id'] === NULL):
$err_msg[] = 'index.phpからdrink_idを受信できませんでした';
break;
default:
$drink_id = (int) $_POST['drink_id'];
break;
}
} else {
$err_msg[] = '商品を選択してください';
}
// moneyの確認と入力情報の格納
if (isset($_POST['money']) === TRUE) {
switch (TRUE) {
case ($_POST['money'] === ''):
$err_msg[] = '金額を入力してください';
break;
case ($_POST['money'] === NULL):
$err_msg[] = 'index.phpからmoneyを受信できませんでした';
break;
case (preg_match('/^[0-9]+$/', cut($_POST['money'])) !== 1):
$err_msg[] = '金額は0以上の半角整数を入力してください';
break;
default:
$money = (int) cut($_POST['money']);
break;
}
}
// 現状のエラー数確認
if (count($err_msg) === 0) {
// 商品情報取得のクエリ
$sql = 'SELECT drink_info_table.drink_name, drink_info_table.price, drink_info_table.path, drink_info_table.status, stock_table.stock
FROM drink_info_table
JOIN stock_table
ON drink_info_table.drink_id = stock_table.drink_id
WHERE drink_info_table.drink_id = ' . $drink_id;
if ($result = mysqli_query($link, $sql)) {
// 取得した情報の格納
while ($row = mysqli_fetch_array($result)) {
$data[] = $row;
}
} else {
$err_msg[] = '情報の取得に失敗しました';
}
// 取得した情報の格納
foreach ($data as $info) {
$drink_name = $info['drink_name'];
$price = (int) $info['price'];
$stock = (int) $info['stock'];
$path = $info['path'];
$status = (int) $info['status'];
$remaining_stock = $stock - 1;
$return = $money - $price;
}
// 各種チェック
switch (TRUE) {
case ($return < 0):
$err_msg[] = 'お金が足りません';
break;
case ($remaining_stock < 0):
$err_msg[] = 'この商品は品切れです';
break;
case ($status === 0):
$err_msg[] = 'この商品は選択できません';
break;
}
// stock_tableの更新クエリ
$sql = 'UPDATE stock_table SET stock = ' . $remaining_stock . ', updated_at = \'' . $purchase_time . '\' WHERE drink_id = ' . $drink_id;
if ($result = mysqli_query($link, $sql)) {
// drink_history_tableの追加クエリ
$sql = 'INSERT INTO drink_history_table(drink_id, purchased_at) VALUES (' . $drink_id . ', \'' . $purchase_time . '\')';
if ($result = mysqli_query($link, $sql) !== TRUE) {
$err_msg[] = 'drink_history_tableへの追加に失敗しました';
}
} else {
$err_msg[] = 'stock_tableの更新に失敗しました';
}
}
}
// トランザクション成否判定
if (count($err_msg) === 0) {
// 処理確定
mysqli_commit($link);
} else {
// 処理取消
mysqli_rollback($link);
}
// DB接続停止
mysqli_close($link);
} else {
$err_msg[] = 'DB接続失敗';
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>自動販売機結果</title>
<link rel="stylesheet" href="drink.css">
</head>
<body>
<h1>自動販売機結果</h1>
<?php foreach ($err_msg as $err) { ?>
<p><?php print $err; ?></p>
<?php } ?>
<?php if (count($err_msg) === 0) { ?>
<div class="result">
<img class="result_img" src="<?php print $path; ?>">
<p><?php print 'がしゃん!【' . html_enc($drink_name) . '】が買えました!'; ?></p>
<p><?php print 'おつりは【' . $return . '円】です!'; ?></p>
</div>
<?php } ?>
<a href="index.php">戻る</a>
</form>
</body>
</html>
@charset "UTF-8";
/* tool.php */
table,
tr,
th,
td {
border: solid 1px #000000;
text-align: center;
}
table {
border-collapse: collapse;
}
td {
height: 200px;
}
.image {
width: 200px;
height: 200px;
}
.d_name {
width: 300px;
}
.d_price {
width: 80px;
}
.input_text_width {
width: 60px;
}
.text_align_right {
text-align: right;
}
.d_status {
width: 180px;
}
.status_0 {
background-color: #c0c0c0;
}
/* index.php */
.product {
width: 230px;
text-align: center;
flex: 1;
}
.product_picture,
.product_img {
width: 230px;
height: 230px;
}
.margin {
margin: 0px;
}
.form {
width: 9600px;
}
.parent {
width: 960px;
display: flex;
padding: 0;
flex-wrap: wrap;
}
.product_name,
.product_price,
.product_buy {
width: 230px;
}
.sold_out {
color: #ff0000;
font-weight: bold;
}
.product_price {
color: #0000ff;
font-weight: bold;
}
/* result.php */
.result_img,
.result {
width: 400px;
}
.result_img {
height: 400px;
}
<?php
// 関数を定義
// html変換
function html_enc($text)
{
return htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
}
// 不要スペースの削除
function cut($space)
{
return preg_replace('/\A[\p{C}\p{Z}]++|[\p{C}\p{Z}]++\z/u', '', $space);
}