Два оператора foreach с одним запросом MySQL?

Это единственный способ использовать два оператора foreach с массивами, входящими в базу данных MySQL?

Первый обновит поле ot_hours , а второй foreach обновит поле lieu_hours . Я попытался объединить оба, чтобы сделать один запрос, но он постоянно обновлялся с неправильными значениями.

Это то, что я имею прямо сейчас, что работает, но уродлив.

 foreach($_POST['overtimehours'] as $key => $value) { dbQuery("UPDATE $TABLE SET ot_hours='$value', ot_status=1, ot_submitdate='$ot_submitdate' WHERE trans_num=$key AND uid='$contextUser' AND (ot_status=0 OR ot_status=1 OR ot_status=3)"); } foreach($_POST['lieutimehours'] as $key2 => $value2) { dbQuery("UPDATE $TABLE SET lieu_hours='$value2', ot_status=1, ot_submitdate='$ot_submitdate' WHERE trans_num=$key2 AND uid='$contextUser' AND (ot_status=0 OR ot_status=1 OR ot_status=3)"); } 

Я уверен, что есть намного лучшие способы сделать это. Вот почему я надеюсь, что кто-то может мне помочь 🙂

Спасибо заранее за все ответы

Применительно к вашему делу, вот адаптированный ответ Дэнни :

 <?php //first query: $arrk = array_keys($_POST['overtimehours']); $arrv = array_values($_POST['overtimehours']); $id_list = implode(',', $arrk); $whens = implode( "\n ", array_map( function ($id, $value) { return "WHEN {$id} THEN {$value}"; }, $arrk, $arrv ) ); $sql1 = " UPDATE $TABLE SET ot_hours = CASE trans_num {$whens} END, ot_status=1, ot_submitdate='$ot_submitdate' WHERE id IN ({$id_list}) AND uid='$contextUser' AND (ot_status=0 OR ot_status=1 OR ot_status=3) "; //second query: $arrk = array_keys($_POST['lieutimehours']); $arrv = array_values($_POST['lieutimehours']); $id_list = implode(',', $arrk); $whens = implode( "\n ", array_map( function ($id, $value) { return "WHEN {$id} THEN {$value}"; }, $arrk, $arrv ) ); $sql2 = " UPDATE $TABLE SET lieu_hours = CASE trans_num {$whens} END, ot_status=1, ot_submitdate='$ot_submitdate' WHERE id IN ({$id_list}) AND uid='$contextUser' AND (ot_status=0 OR ot_status=1 OR ot_status=3) "; //now use pdo to run sql1 and sql2 ?> 

По крайней мере, вы готовы изучать новые вещи, это хорошо.

  • Не предполагайте, что все, что вы ожидаете, будет опубликовано.

Используйте тройную операцию и функцию isset, чтобы проверить, действительно ли ваши сообщения находятся на месте:

 $overTimeHours = isset($_POST['overtimehours']) ? $_POST['overtimehours'] : false; $lieuTimeHours = isset($_POST['lieutimehours']) ? $_POST['lieutimehours'] : false; if($overTimeHours != false && $lieuTimeHours != false) { // Proceed ; checkpoint #1 } else { // The values were not posted, do some error handling. } 

Итак, в этот момент внутри контрольной точки № 1 вы будете делать следующее:

 foreach($overTimeHours as $key => $value) { dbQuery("UPDATE $TABLE SET ot_hours='$value', ot_status=1, ot_submitdate='$ot_submitdate' WHERE trans_num=$key AND uid='$contextUser' AND (ot_status=0 OR ot_status=1 OR ot_status=3)"); } foreach($lieuTimeHours as $key2 => $value2) { dbQuery("UPDATE $TABLE SET lieu_hours='$value2', ot_status=1, ot_submitdate='$ot_submitdate' WHERE trans_num=$key2 AND uid='$contextUser' AND (ot_status=0 OR ot_status=1 OR ot_status=3)"); } 
  • Вы, вероятно, не найдете уродливым, чтобы пробежать один цикл, если у вас был только один массив для синтаксического анализа.

Теперь у вас есть два массива (очевидно), поэтому, если минимальное количество циклов для одного массива – одно для цикла, то минимальное количество циклов, которое вам нужно для двух массивов, должно быть два. Массивы UNRELATED, поэтому вы не можете использовать их, чтобы упростить синтаксический анализ другого.

Анализ через $ overTimeHours с

 $overTimeHours as $key => $value 

предполагая, что вам действительно нужны ключи и значения внутри массива, это самая короткая вещь, которую вы можете сделать. Та же история идет о lieuTimeHours

  • Ваш код доступен для SQL-инъекций.

Не вставляйте переменные в свой запрос следующим образом:

 SET lieu_hours='$value2' 

Порядочный программист (или 12-летний ребенок) может легко ввести что-то подобное в вашу базу данных:

 yo';DROP TAbLE users;-- 

Или что-то подобное, чтобы удалить данные из вашей базы данных. Вы должны использовать подготовленные инструкции, чтобы предотвратить атаку с помощью базовых SQL-инъекций.

Подготовленные утверждения доступны в большинстве ситуаций, но я настоятельно рекомендую использовать либо PDO, либо синтаксис mysqli.

Вот пример того, как вы можете создать PDO-соединение:

 // Usage: $db = connectToDatabase($dbHost, $dbName, $dbUsername, $dbPassword); // Pre: $dbHost is the database hostname, // $dbName is the name of the database itself, // $dbUsername is the username to access the database, // $dbPassword is the password for the user of the database. // Post: $db is an PDO connection to the database, based on the input parameters. function connectToDatabase($dbHost, $dbName, $dbUsername, $dbPassword) { try { return new PDO("mysql:host=$dbHost;dbname=$dbName;charset=UTF-8", $dbUsername, $dbPassword); } catch(PDOException $PDOexception) { exit("<p>An error ocurred: Can't connect to database. </p><p>More preciesly: ". $PDOexception->getMessage(). "</p>"); } } 

Теперь вы можете инициализировать переменные базы данных:

 $host = 'localhost'; $user = 'root'; $databaseName = 'databaseName'; $pass = ''; 

Теперь вы можете получить доступ к своей базе данных через

 $db = connectToDatabase($host, $databaseName, $user, $pass); // You can make it be a global variable if you want to access it from somewhere else. 

Теперь вы можете создать запрос, который принимает подготовленные инструкции:

 $query = "UPDATE :table SET ot_hours=:ot_hours, ot_status=1, ot_submitdate=:ot_submitdate WHERE trans_num=:key AND uid=:contextUser AND (ot_status=0 OR ot_status=1 OR ot_status=3);"; 

И теперь вы можете легко подготовить его, выполнить переменные INTO в запросе БЕЗ того, чтобы быть vonurable для SQL-инъекций (различие действительно: незаготовленные запросы выполняются COMMANDS, между тем готовые являются простыми STRINGS):

 $statement = $db->prepare($query); // Prepare the query. $success = $statement->execute(array( ':table' => $TABLE, ':ot_hours' => $ot_hours, ':ot_submitdate ' => $ot_submitdate , ':key' => $key, ':contextUser' => $contextUser )); // Here you insert the variable, by executing it 'into' the prepared query. if($success) { // Update was successful. ] else { // Update was not successful, feel free to catch an PDOException $PDOexception } 

Также я отмечаю, что добавил «;» в конце вашего скрипта, который НЕ ЗАПРЕЩЕН, но я чувствую, что это безопаснее, чтобы убедиться, что ваше исполнение завершено, и вы не хотите, чтобы что-то имело отношение к нему (хотя это не от вас).

Надеюсь, что я ответил на ваш вопрос / и (и, надеюсь, дальше), я надеюсь, что вы рассмотрите то, что я сказал 🙂 Не стесняйтесь спрашивать, есть ли какие-либо вопросы.

Кроме того, не стесняйтесь исправить меня, если я, возможно, что-то неправильно сказал, написав этот ответ.

Я бы рекомендовал вам использовать подготовленный отчет. Вы должны хотя бы правильно кодировать другие используемые вами переменные ( $TABLE , …)

 $firstUpdate = "UPDATE $TABLE SET ot_hours=:value, ot_status=1, ot_submitdate='$ot_submitdate' WHERE trans_num=:key AND uid='$contextUser' AND (ot_status=0 OR ot_status=1 OR ot_status=3)"; $secondUpdate = "UPDATE $TABLE SET lieu_hours=':value', ot_status=1, ot_submitdate='$ot_submitdate' WHERE trans_num=:key AND uid='$contextUser' AND (ot_status=0 OR ot_status=1 OR ot_status=3)"; $db = PDO(...); // I assume here a connection managed by PDO $stmt = $db->prepare($firstUpdate); foreach($_POST['overtimehours'] as $key => $value) { $stmt->execute(array(":key"=>$key,":value"=>$value); } $stmt = $db->prepare($secondUpdate); foreach($_POST['lieutimehours'] as $key => $value) { $stmt->execute(array(":key"=>$key,":value"=>$value); } 

На мой взгляд, первое, что вам нужно сделать, это уменьшить количество открытий соединений с БД, как показано ниже:

 $query = ""; foreach($_POST['overtimehours'] as $key => $value) { $query .="UPDATE $TABLE SET ot_hours='$value', ot_status=1, ot_submitdate='$ot_submitdate' WHERE trans_num=$key AND uid='$contextUser' AND (ot_status=0 OR ot_status=1 OR ot_status=3) ; "; } foreach($_POST['lieutimehours'] as $key2 => $value2) { $query .= "UPDATE $TABLE SET lieu_hours='$value2', ot_status=1, ot_submitdate='$ot_submitdate' WHERE trans_num=$key2 AND uid='$contextUser' AND (ot_status=0 OR ot_status=1 OR ot_status=3); "; } if ($query) dbQuery($query); 

во-вторых, и это важно, как вы сказали, объединить два массива в одну попытку и отладить ваш код до тех пор, пока вы не добьетесь успеха.