jackytom
@jackytom

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

PHPのforeachで配列が取得できない

Q&A

Closed

PHPで、mariadbの検索結果を配列に格納を試みましたが、SQLの実行結果の最後の1行しか取得できません。

DBのログを見たところ、SQLは問題なく実行されていて、そのSQLをphpAdminで実行したら想定通りの結果でした。

VAR_DUMPで確認したところ、目的の配列格納前の配列では想定通り取得できていて、目的の配列で取得できていないようです。
(添付ソースの96行目の、$timeでは取得できていますが、$timeZoで最後の1件のみです。)

ブラウザのデバッグツールを見ても何もエラーはないため、PHPの不具合を検索してみましたが、それらしいものは出てきませんでした。

原因究明に協力いただければ幸いです。
ソースを添付します。

問題箇所は、96行目です。

<?php
	session_start();
	header('Expires:-1');
	header('Cache-Control:');
	header('Pragma:');
		$token = '';
		if ( isset( $_SESSION[ 'token' ] ) || !empty( $_SESSION[ 'token' ] ) ) {
				$token = $_SESSION['token'];
				} else {
					$token = bin2hex(random_bytes(32));
					$_SESSION['token'] = $token;
					}
	
	function escape($val)
	{
		return htmlspecialchars($val, ENT_QUOTES | ENT_HTML5, 'UTF-8');
	}

	require_once('db_connect.php');

	$button = $_POST['button_culculate'] ?? '';
	$reserveDate = $_POST['reserve_date'] ?? '';
	$timeZone = $_POST['time_zone'] ?? '';
	$serviceId = $_POST['service_id'] ?? '';
	$serviceName = $_POST['service_name'] ?? '';
	$servicePrice = $_POST['service_price'] ?? '';
	$optionPrice = $_POST['option_price'] ?? '';
	$item = $_POST['item'] ?? '';
?>

<html lang=ja>
	<head>
		<meta charset="utf-8">
		<title>予約登録画面</title>
		<meta name="description" content="ヘッドセラピーを中心としたセラピーのサービスを提供しております。">
		<!--リセットcss-->
		<link rel="stylesheet" href="https://unpkg.com/ress/dist/ress.min.css">
		<!--css-->
		<link href="css/reserve_style.css" rel="stylesheet">
		<!--レスポンシブ対応-->
		<meta name="viwport" content="width=device-width, initial-scale=1">
		<!--Googleフォント-->
		<link href="https://fonts.googleapis.com/css2?family=Sawarabi+Gothic&display=swap" rel="stylesheet">
		<link href="https://fonts.googleapis.com/css2?family=Shippori+Mincho:wght@500&display=swap" rel="stylesheet">
	</head>
	<body>
		<?php require_once('header.php')?>
		<h1 class="title">予約登録画面</h1>
		<h2 class="sub">(確認のクリック前に金額計算をクリックします。)</h2>
		<form method="post" name="reserve" class="reserve" id="reserve" action="?">
			<div class="last_name">
				<label for="sei"></label>
				<input type="text" name="sei" class="sei" id="sei" value=
				"<?php
					if(isset($_SESSION['customer'])){
						echo $_session['customer']['last_name'];
					}
				?>"
				<?php
					if(isset($_SESSION['customer'])){
						echo 'readonly="readonly"';
					}
				?>
				>
			</div>
			<div class="mei">
				<label for="mei"></label>
				<input type="text" name="mei" class="mei" id="mei" value=
				"<?php
					if(isset($_SESSION['customer'])){
						echo $_session['customer']['first_name'];
					}
				?>"
				<?php
					if(isset($_SESSION['customer'])){
						echo 'readonly="readonly"';
					}
				?>
				>
			</div>
			<div class="r_date">
				<label for="reserve_date">予約日</label>
				<input type="date" name="reserve_date" class="reserve_date" id="reserve_date" value="<?="$reserveDate"?>">
			</div>
			<div class="time">
				<label for="time_zone">時間帯</label>
				<select name="time_zone" class="time_zone" id="time_zone">
					<?php
						$sql = ('select * from time_zone where status = :status1 or status = :status2 order by level');
						$stmt = $pdo->prepare($sql);
						$stmt -> bindValue(':status1',0);
						$stmt -> bindValue(':status2',2);
						$stmt -> execute();
						$time = $stmt->fetchAll(PDO::FETCH_ASSOC);
						
						foreach($time as $timeZo){
							if($timeZo['time_zone_id'] === $timeZone){
							$zone = "";
							$zone .= "<option value='" . $timeZo['time_zone_id'];
    						$zone .= "' selected>" . $timeZo['time_zone'];
    						$zone .= "</option>";
    						} else {
    							$zone = "";
								$zone .= "<option value='" . $timeZo['time_zone_id'];
	    						$zone .= "'>" . $timeZo['time_zone'];
	    						$zone .= "</option>";
    						}
    					}
    						echo $zone;
					?>
				</select>
			</div>
			<div class="service">
				<label for="servise_name">サービス</label>
				<select name="service_name" class="service_name" id="service_name">
					<?php
						$sql = ('select * from service where status = :status');
						$stmt = $pdo->prepare($sql);
						$stmt -> bindValue(':status',0);
						$stmt -> execute();
						$service = $stmt->fetchAll(PDO::FETCH_ASSOC);
						
						foreach($service as $serviceNa):
							if($serviceNa === $serviceId){
								$serviceTitle = "";
								$serviceTitle .= "<option value='" . $serviceNa['service_id'];
	    						$serviceTitle .= "'selected>" . $serviceNa['service_name'] . "</option>";
	    						}
	    						else {
	    							$serviceTitle = "";
									$serviceTitle .= "<option value='" . $serviceNa['service_id'];
		    						$serviceTitle .= "'>" . $serviceNa['service_name'] . "</option>";
		    						} 
		    				echo $serviceTitle;
						endforeach;
					?>
				>
				</select>
			</div>
			<div class="option">
				<label for="item">オプション</label>
				<select name="item" class="item" id="item">
					<?php
						$sql = ('select * from option where status = :status');
						$stmt = $pdo->prepare($sql);
						$stmt -> bindValue(':status',0);
						$stmt -> execute();
						$row = $stmt->fetchAll(PDO::FETCH_ASSOC);
						
						foreach($row as $data):
							$item = "";
							$item .= "<option value='" . $data['option_id'];
    						$item .= "'>" . $data['option_name'] . "</option>";
    						echo $item;
						endforeach;
					?>
				</select>
			</div>
			<div class="price_1">
				<label for="servise_price">金額(サービス)(表示のみ)</label>
				<input type=text name="service_price" id="service_price" readonly="readonly" value=
					"<?php
					if(isset($button)){
						$sql = ('select * from service where service_id = ?');
						$stmt = $pdo->prepare($sql);
						$stmt -> execute([escape($serviceId)]);
						$row = $stmt->fetchAll(PDO::FETCH_ASSOC);
						
						foreach($row as $data):
							echo $data['price'];
						endforeach;
						}

					?>"
					>
			</div>
			<div class="price_2">
				<label for="option_price">金額(オプション)(表示のみ)</label>
				<input type=text name="option_price" id="option_price" readonly="readonly" value=
					"<?php
						if(isset($button)){
							$sql = ('select * from option where option_id = ?');
							$stmt = $pdo->prepare($sql);
							$stmt -> execute([escape($item)]);
							$row = $stmt->fetchAll(PDO::FETCH_ASSOC);
							
							foreach($row as $data):
								echo escape($data['price']);
							endforeach;
						}
					?>"
					>
			</div>
			<div class="total">
				<label for="total_amount">合計金額(表示のみ)</label>
				<input type=text name="total_amount" class="total_amount" id="total_amount" readonly="readonly" value=
					"<?php
						if(isset($servicePrice) && isset($optionPrice)){
							if(isset($button)){
								echo (int)escape($servicePrice) + (int)escape($optionPrice);
								}
							}
					?>"
				>
			</div>
			<div class="buttons">
				<button type="button" class="button_b" name="button_re" id="button_re" onclick="history.back()">戻る</button>
				<button type="submit" form="reserve" class="button_b" name="button_culculate" id="button_commit" value="calculate">金額計算</button>
 				<button type="submit" class="button_b" name="button_conf" id="button_commit" formaction="reserve_conf.php" value="confirm">確認</button>
			</div>
		</form>
	</body>
	<?php var_dump($timeZo);?>
	<?php var_dump($time);?>
	<?php require_once('footer.php')?>
</html>


0

1Answer

最後のデータのoptionタグしか表示されない、という状況でしたら納得できるコードではあります。
つまりデータは正しく取れていて、その後の処理に問題があるように見えます。

変数$zoneはループの最初で初期化しているので、データはループのたびに上書きされていきます。
なのでループが終わって表示する段階では、最後のデータしか入っていないと思います。

foreach($time as $timeZo) {
	if($timeZo['time_zone_id'] === $timeZone){
		$zone = ""; // ループのたびに初期化している
		$zone .= "<option value='" . $timeZo['time_zone_id'];
		$zone .= "' selected>" . $timeZo['time_zone'];
		$zone .= "</option>";
	} else {
		$zone = ""; // ループのたびに初期化している
		$zone .= "<option value='" . $timeZo['time_zone_id'];
		$zone .= "'>" . $timeZo['time_zone'];
		$zone .= "</option>";
	}
}
echo $zone; // ループの最後に入れたデータしか入っていない

解決方法としては、ループの中で表示する、あるいはデータをすべて結合して最後にechoするような方法が考えられます。

例)ループの中で表示する
foreach ([1, 2, 3] as $n) {
    $r = $n;
    echo $r;
}
// 123
例)データをすべて結合して最後に表示する
$r = '';
foreach ([1, 2, 3] as $n) {
    $r .= $n;
}
echo $r;
// 123
0Like

Comments

  1. @jackytom

    Questioner

    回答ありがとうございます。
    よくわかりました。
    後はどうするか考えます。
    本件はクローズとさせていただきます。

Your answer might help someone💌