1

一部のコードを古いスタイルの mysql クエリから準備済みに変更するのに問題があります。この問題は、複数の while を使用していて、それぞれが問題を引き起こしている独自のクエリを使用しているため、一度に 1 つの準備済みステートメントしかアクティブにできないことが原因であると想定しています。

編集:誰かが気にするなら、私はそれを2つのループだけで動作させました-

function createDeskMenu()
{
    global $bookingTimes, $dbconn;
    $day0 = mktime(0, 0, 0, date("m")  , date("d"), date("Y"));

    $query = "SELECT location FROM location";
    $result = mysqli_query($dbconn,$query);
    mysqli_num_rows($result);
    while ($row = mysqli_fetch_array($result))
    {
        $location = $row['location'];
        echo "<h3>$location</h3><div>";
        $query = $dbconn -> prepare("SELECT COALESCE( CountDesk, 0 ) total, name, d.desk_id, phone, fax, dock, pc FROM desk d LEFT JOIN (SELECT COUNT(booked.desk_id) CountDesk, desk_id FROM booked WHERE booking_id >=?)b ON d.desk_id = b.desk_id WHERE location=?");
        $query->bind_param("is",$day0, $location);
        $query->execute();
        $query->bind_result($totalCount,$name,$desk_id,$phone,$fax,$dock,$pc);
        while($query->fetch()) {
            $total = count($bookingTimes) * 14 - $totalCount;
            echo '<a href="?page=desk&desk='.$desk_id.'"><div class="desk"><b>'.$name.' 
            ('.$total.' Available Bookings)</b><li>Facilities:';
            if($phone){echo " Phone,";}if($fax){echo " Fax Machine,";}if($dock){echo " Laptop Dock.";}if($pc){echo " Desktop Workstation.";}
            echo '</li></div></a><hr />';
        }
        $query->close();
        echo '</div>';
    }
}
4

1 に答える 1

1

prepare()接続に別のステートメントからのフェッチを待機している行がある間は、ステートメントを実行できません。まず、前の結果セットを閉じるか、そこからすべての行をフェッチする必要があります。

でも...

句がないためlocation 、まったく取得する外部クエリの必要性はわかりません。すべてのWHERE場所を選択しているため、その部分を完全に省略できます。外側のループ for を使用しているのは、場所ごとに for を作成することだけであり、これは非常に無駄です (もともとコードの破損を引き起こすことに加えて)。<h3>

代わりに、1 つのクエリを実行し、フェッチ ループで場所が変更されたかどうかを確認します。変更したら、ヘッダーを出力します

echo "<h3>$location</h3><div>";

そのため、外側のクエリとループを完全に削除し、次のようなパターンを使用して の変更を検出しますlocationORDER BY locationそれらがあなたのためにソートされていることを確認してください。

バインドされたパラメーターは必要ありません。場所はもはや可変ではなく、$day0からのタイムスタンプであることがわかっているため、 query() 呼び出しでこれを行うことができますmktime()

// Substitute a query() call and $day0 can be inserted directly.
// This one query fetches all locations sorted...
$query = $dbconn->query("
  SELECT
   COALESCE( CountDesk, 0 ) total,
   name,
   d.desk_id,
   phone,
   fax,
   dock,
   pc
 FROM 
   desk d
   LEFT JOIN (
     SELECT COUNT(booked.desk_id) CountDesk, desk_id FROM booked WHERE booking_id >= $day0
   )b ON d.desk_id = b.desk_id 
 ORDER BY location");

// Store the last location in a variable which starts empty...
$location = "";

while($row = $query->fetch_assoc()) {
  // on change of $location, update the variable.
  if ($location !== $row['location']) {
    $location = $row['location'];
    // And output the new location value
     echo "<h3>$location</h3><div>";
  }

  // Do the rest of your loop.
  $total = count($bookingTimes) * 14 - $row['total'];
  echo '<a href="?page=desk&desk='.$row['desk_id'].'"><div class="desk"><b>'.$row['name'].' 
  ('.$total.' Available Bookings)</b><li>Facilities:';
  if($row['phone']){
    echo " Phone,";
  }
  if($row['fax']){ 
    echo " Fax Machine,";
  }
  if($row['dock']){
    echo " Laptop Dock.";
  }
  if($row['pc']){
    echo " Desktop Workstation.";
  }
  echo '</li></div></a><hr />';
}
$row->close();
echo '</div>';

失敗した理由は次のとおりです....prepare()前のステートメントまたはクエリからフェッチする行が残っている間は、新しいステートメントを作成できません。最初にすべての行をフェッチするか、ステートメントを で閉じる必要があります$stmt->close()。したがって、事実上、フェッチ ループをネストすることはできません。

より良い方法は、最初にすべての行を配列にフェッチしてから、その配列をループすることです。

while ($row = $first_query->fetch()) {
  // Append all onto an array
  $first_query_rows[] = $row;
}
// Then loop over that
foreach ($first_query_rows as $row) {
  // Do a new query with $row
}

ただし、通常、これは適切な で解決できますJOIN

于 2013-01-14T21:05:18.707 に答える