PHP, MySQL — Сопоставление флажка с выпадающим списком

#php #mysql #html #drop-down-menu #associative-array

#php #mysql #HTML #выпадающее меню #ассоциативный массив

Вопрос:

У меня возникла проблема с попыткой добавить «количество» к продукту, который заказывает пользователь. У меня есть таблица Products, таблица orders, таблица order_item (которая представляет собой таблицу «многие ко многим», содержащую идентификаторы как продуктов, так и заказов). У меня есть выпадающее окно слева, в котором указано нужное вам количество. Максимальное значение — это запас, доступный в системе.

Вот как выглядит форма:

введите описание изображения здесь

 <form name ="order_form" method="post" action="add_order_action.php" enctype="multipart/form-data">
                    <table border=1 cellpadding=2 cellspacing=2>
                        <caption>Order Form</caption>
                        <tr>
                            <th align="right"> Property </th>

                            <th align="left"> Value </th>
                        </tr>
                        <tr>
                            <td class="col1"> Name </td>
                            <td class="col2"> <input type="text" name="customer" id ="customer" size=30> </td>
                        </tr>
                        <tr>
                            <td class="col1"> Address </td>
                            <td class="col2"> <input type="text" name="address" id ="address" size=30> </td>
                        </tr>
                        <tr>
                            <td class="col1"> Products </td>
                            <td class="col2">

                                <!-- Interests is an array of all interests in the database-->
                                {foreach $products as $product}
                                <select name="products[{$product.id}][quantity]" id ="quantities">
                                        {section name=quantities start=0 loop=$product.stock   1 step=1}
                                        <option value="{$smarty.section.quantities.index}">{$smarty.section.quantities.index}</option>
                                        {/section}
                                </select>
                                <input type="checkbox" name="products[{$product.id}][is_checked]" value="1">{$product.name}<br>
                                {/foreach}
                            </td>
                        </tr>
                        <tr>
                            <td colspan=2 align="center">
                                <input type="submit" name="submit" value="Submit">
                                <input type="reset"  name="reset"  value="Reset">
                            </td>
                        </tr>
                    </table>
                </form>
  

Названия продуктов и номера запасов взяты из таблицы products:

 create table if not exists SEProducts
(
    id int not null auto_increment primary key,
    price double not null,
    name varchar(30) not null,
    stock int not null,
    original_stock int not null,
    sold_stock int not null
)ENGINE=INNODB;
  

Теперь, что я делаю, так это создаю массив из названий продуктов, которые отмечены. Что я хочу сделать, так это связать значения из выпадающих меню, НО ТОЛЬКО ЕСЛИ ОНИ ЯВЛЯЮТСЯ ОДНИМ ИЗ ОТМЕЧЕННЫХ ЗНАЧЕНИЙ. Кроме того, если значение установлено, количество не может быть равно 0. Вероятно, я делаю это крайне неприятным способом, но это то, что я считал лучшим. Я мог бы создать текстовое поле, но тогда вам пришлось бы очищать пользовательский ввод. Это было бы нормально, если бы это работало, в отличие от этого, которое не работает =/

Я добавляю заказы, получая массив product:

 <?php
include "includes/defs.php";

$customer = $_POST['customer'];
$delivery_address = $_POST['address'];
if (isset($_POST['products'])) 
{
    $products = $_POST['products'];
} 
else 
{
    $error = "An order must consist of 1 or more items.";
    header("Location: list_inventory.php?error=$error");
    exit;
}

$id = add_order($customer, $delivery_address, $products);

header("Location: order.php?id=$id");
exit;
?>
  

Тогда моя функция добавления заказа работает следующим образом:

 function add_order($customer, $delivery_address, $products)
{
    $connection = mysql_open();
    $customer = mysql_escape_string($customer);
    $delivery_address = mysql_escape_string($delivery_address);

    $query = "insert into SEOrders (name, address, status) " .
             "values ('$customer', '$delivery_address', 'New')";
    $result = mysql_query($query, $connection) or show_error();

    $id = mysql_insert_id();

foreach ($products as $product)
    {
        if ($product['is_checked'] != 0 amp;amp; $product['quantity'] != 0)
        {
            $query2 = "insert into SEOrder_items (order_id, product_id, quantity) " .
                    "values ('$id', '$product.id', '$product.quantity')";
            $result2 = mysql_query($query2, $connection) or show_error();
        }
    }

mysql_close($connection) or show_error();
return $id;
}
  

Я думал, что мне, возможно, придется использовать какой-нибудь JavaScript, но я абсолютно профан в этом.

Если бы я не смог объяснить сам: Короче говоря; Мне нужно добавить количества в массив products, но только если продукты проверены и количество равно > 0.

Заранее спасибо, приветствую 🙂

РЕДАКТИРОВАТЬ: Я внес некоторые изменения, но теперь я получаю следующую ошибку: Ошибка 1452: Не удается добавить или обновить дочернюю строку: сбой ограничения внешнего ключа ( db/SEOrder_items , ССЫЛКИ на ОГРАНИЧЕНИЕ SEOrder_items_ibfk_2 ВНЕШНЕГО КЛЮЧА ( product_id ) SEProducts ( id ))

Ответ №1:

В качестве первого шага я бы объединил массивы продуктов и количеств, чтобы количества, флажок и название продукта были в одном массиве:

 <select name="products[{$product.id}][quantity]" id ="quantities">
…
</select>
<input type="checkbox" name="products[{$product.id}][is_checked]" value="1" />
  

приведет к следующему массиву (где 1 и 2 — идентификаторы продуктов, ‘is_checked’ устанавливается только в том случае, если флажок был установлен):

 $_POST['products'] = array(
    [1] => array(
        'quantity' => 3,
        'is_checked' => 1,
    ),
    [2] => array(
        'quantity' => 1,
        // not checked
    ),
);
  

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

 foreach($_POST['products'] as $currentProductId => $currentProductArray)
  

Комментарии:

1. Я внес эти изменения, но теперь, когда я пытаюсь добавить новый порядок, я получаю следующую ошибку: Ошибка 1452: Не удается добавить или обновить дочернюю строку: сбой ограничения внешнего ключа ( db/SEOrder_items , ССЫЛКИ на ОГРАНИЧЕНИЕ SEOrder_items_ibfk_2 ВНЕШНЕГО КЛЮЧА ( product_id ) SEProducts ( id ))

Ответ №2:

Я думаю, вам просто нужно немного подправить вашу логику и ваш шаблон.

Во-первых, вы хотите полностью использовать продукты, доступные на странице заказа, а не продукты, которые возвращаются; это:

 if (isset($_POST['products'])) 
{
    $products = $_POST['products'];
} 
else 
{
    $error = "An order must consist of 1 or more items."
    header("Location: list_inventory.php?error=$error");
    exit;
}
  

Должно выглядеть примерно так:

 $products = the_products_list_that_you_sent_to_the_page();
  

Конечно, если список продуктов большой, то вам придется вытаскивать список продуктов со страницы (и проверять каждый продукт), как вы делаете сейчас. Однако, если список продуктов невелик, то проще начать с известного и допустимого списка.

Суть проблемы заключается в вашем взаимодействии с базой данных и в том, как add_order это работает. Вы add_order получите список продуктов для просмотра в $products . Все, что вам нужно сделать, это:

  • Создайте массив данных для вставки.
  • Пройдите $products , если продукт отмечен и у него есть количество, добавьте его и его количество в список.
  • Проверьте, есть ли что-нибудь в списке заказов после завершения вышеупомянутого цикла:
    • Если в списке заказов что-то есть, add_order можете добавить все это в базу данных.
    • Если в списке заказов ничего нет, add_order может вернуть код ошибки (например, нулевой идентификатор заказа), и вызывающий может пожаловаться пользователю, что вообще ничего не заказывать не имеет смысла.

Основная стратегия заключается в сборе ваших данных и последующем действии с ними, а не в попытке действовать с вашими данными во время их сбора.

Теперь возникает проблема: как нам связать количество с конкретной проблемой? Это легко решить, поскольку у нас есть идентификаторы продуктов; ваши <select> элементы должны быть:

 <!--
  Note that this also avoids the evil of having
  duplicate id attributes in one page
-->
<select name="quantity_{$product.id}">
  

Затем, когда вы ищете количество определенного продукта, вы можете извлечь его прямо из $_POST как скаляр as $q = $_POST['quantity_' . $product_id] .

Я знаю, что мог бы решить корень вашей проблемы, просто посоветовав вам переименовать ваши <select> элементы, но я решил, что по ходу дела разберусь с некоторыми другими вашими возможными проблемами.