15.05.2015, 07:52
|
Аспирант
|
|
Регистрация: 06.04.2015
Сообщений: 52
|
|
Вывод размера товара в корзине
Всем привет! В свободное от работы время изучаю PHP и тренируюсь в создании инет-магазина, и вот возник вопрос: добавляю в корзину ботинок Арт.10001 размер 20 из выпадающего списка, в корзине выводится этот ботинок с размером 20; затем добавляю в корзину этот же ботинок, но с размером 24 - а в корзине уже выводится этот последний ввод с размером 24, т.е размер 24 перезаписывает сверху размер 20. Вот как поменять код, какой применить принцип, чтобы в корзину добавлялся ботинок одного id, но с разными выбранными размерами? У размеров своя таблица в mysql, с id. Заранее благодарен.
Добавление товара в корзину:
<form action="index.php" method="get">
<input type="hidden" name="view" value="add_to_cart">
<input type="hidden" name="id" value="<?=$product['id']?>">
<select name="size" >
<?PHP
$sql="SELECT * FROM sizes WHERE `sizes`.`id_boot`='$id' ";
echo $sql.'<br>';
$a=mysql_query($sql);
while ($b = mysql_fetch_array($a))
{
echo "<option value='$b[2]' > $b[2] </option>";
}
?>
</select>
<input type="submit" value="Добавить в корзину">
</form>
Это вывод в корзине:
foreach ($_SESSION['cart'] as $id => $quantity): $product = get_product($id);
$b['size'] = $_SESSION['cart_size'][$id];
if (!empty($_GET['size'])) {echo $_GET['size'];}
?>
<tr>
<td align="center"><?=$product['title']; ?></td>
<td align="center"> <?=$b['size'];?> </td>
<td align="center"> <?=number_format($product['price'],2); ?> руб</td>
<td align="center"><input type="text" size="2" name="<?=$id; ?>" maxlength="2" value="<?=$quantity; ?>" /></td>
<td align="center"> <?=number_format($product['price'] * $quantity ,2); ?> руб</td>
</tr>
И дальше коды связанные с добавлением в корзину:
case('add_to_cart'):
$id = $_GET['id'];
$size = $_GET['size'];
$_SESSION['cart_size'][$id] = $size;
$add_item = add_to_cart($id, $size);
$_SESSION['total_items'] = total_items($_SESSION['cart']);
$_SESSION['total_price'] = total_price($_SESSION['cart']);
header('Location:index.php?view=product&id='.$id);
break;
session_start();
if(!isset($_SESSION['cart']))
{
$_SESSION['cart'] = array();
$_SESSION['total_items'] = 0;
$_SESSION['total_price'] = '0.00';
}
function add_to_cart($id)
{
if(isset($_SESSION['cart'][$id]))
{
$_SESSION['cart'][$id]++;
return true;
}
else
{
$_SESSION['cart'][$id] = 1;
return true;
}
return false;
}
Последний раз редактировалось arhat78, 15.05.2015 в 14:03.
|
|
15.05.2015, 09:14
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,989
|
|
Нужно менять представление корзины в сессии.
|
|
15.05.2015, 09:18
|
Аспирант
|
|
Регистрация: 06.04.2015
Сообщений: 52
|
|
laimas, а не могли бы по подробнее??? А то так мне не понятно совсем...
|
|
15.05.2015, 09:30
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,989
|
|
Почитайте тут. Не обязательно Ajax, можно и без него. Там описана корзина, ее возможная структура и почему такая выбрана.
|
|
15.05.2015, 13:54
|
Аспирант
|
|
Регистрация: 06.04.2015
Сообщений: 52
|
|
laimas, что то подобное я уже встречал, но как это применить к моей корзине - так и не понял.
|
|
15.05.2015, 14:16
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,989
|
|
Меняйте "свою" корзину, ее представление неудачное, почему, это по ссылке можно понять. Как вложить в вас "понимание", этого я не знаю. )
|
|
15.05.2015, 23:35
|
Аспирант
|
|
Регистрация: 06.04.2015
Сообщений: 52
|
|
Сообщение от laimas
|
Меняйте "свою" корзину, ее представление неудачное, почему, это по ссылке можно понять. Как вложить в вас "понимание", этого я не знаю. )
|
Но нужно же понять, что именно не правильно, и как грамотно нужно поменять этот код. Я же только учусь, и очень тяжело "расшифровать" ваш код и понять, как его применить в моём случае.... Надеюсь, подскажете в каком направлении и как двигаться
|
|
16.05.2015, 06:54
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,989
|
|
Я же только учусь, и очень тяжело "расшифровать" ваш код и понять
А вы хотите чтобы я писал код так же как вы? Ну понятно, что так:
$_SESSION['total_items'] = total_items($_SESSION['cart']);
$_SESSION['total_price'] = total_price($_SESSION['cart']);
я делать не стану, и вот почему. Для программирования необходимо наличие логического мышления, но и не менее полезно уметь абстрагироваться от конкретных конструкций языка программирования. Можно даже сказать так - умение видеть задачу от общего к частному, это первично, а умение воплотить ее в конструкциях языка программирования, это уже вторично. Можно вызубрить наизусть все функции и конструкции языка, но так и не уметь написать что либо стоящее. А вот хорошее представление задачи как раз и позволяет выбрать необходимые инструменты в языке программирования для ее решения.
С какой целью у вас количество товаров в корзине и общая их сумма присваивается двум отдельным переменным - $_SESSION['total_items'] и $_SESSION['total_price']? Это только кажется, что так будет удобно и выгодно, а на самом деле это избыток данных не несущих каких либо преимуществ.
Представьте, что вы работаете в почтовом отделении и выполняете простую работу - нужно лизнуть марку и наклеить ее на конверт. Конверты с марками складывать отдельно. Изначально было выдано 1000 марок и 1000 конвертов. В конце рабочего дня нужно определить сколько осталось марок и конвертов осталось и запомнить. Не сложно, пересчитав конверты с марками, вычитаем это из 1000, получая нужное.
Если код вашей корзину переложить на работу в почтовом отделении, то получается, что вы работали так - марки лежали в одном столе, конверты в другом, а конверты с наклеенными марками вообще относились в другую комнату. При этом нужно было взять марку в одном столе, лизнуть ее, пойти к другому столу, взять конверт, наклеить марку и бежать в другую комнату.
Покупая в магазине товар, вы в уме будет считать общую их сумму, чтобы ориентироваться хватит ли у вас денег в кошельке (скоро считать в уме не надо будет, упаковки снабдят RFID-метками, и дисплей на тележке будет отображать просчитанную автоматически сумму). Всегда можно заглянуть в тележку, что-то убрать из нее, вернув на прилавок, что-то другое добавить, в общем "редактирование". Кассир на кассе также будет проверять товары в тележке, и только после того как товар оплачен, тележка будет пуста.
На все время пока совершалась покупка - от выбора товара на прилавке, до оплаты товаров на кассе, всегда требовалась тележка, то есть, перекладывая это на язык на программирование можно сказать, что на всем этапе использовали один и тот же объект - корзину. На основе содержимого тележки можно всегда знать и характеристики товара, и их количество, и их цену, и общую сумму.
А если представить, что вам "помогают" в покупке сестра и брат - сестра считает и записывает сумму за товары, но находится в отделе косметики, а брат катает тележку, но хочет приобрести перфоратор как месть перфоратору соседа и находится в отделе электрических товаров, а вы бегаете из продуктового отдела с товарами к ним, чтобы положить товар в тележку и узнать сколько же набрано. Понятное дело, что это помощь в кавычках, и сестра с братом лишние звенья.
Ваш код как раз и есть покупка с "помощью" сестры и брата. )
Как и в реальном магазине, так и в виртуальном, корзина требуется на всем этапе приобретения товара - от выбора его, до оформления заказа. Корзина должна быть единственным объектом хранящем все данные о товарах, и на основе которых можно получать те или иные параметры корзины. Разбрасывать эти параметры по другим переменным, это распылять внимание и писать лишний код.
По ссылке описано представление корзины, которое в вашем случае можно описать так:
$_SESSION['cart'] = array(
209 => array(
'count' => 3,
'price' => 1500,
array('size'=>array(42 => 2, 41 => 1), 'name' => 'Галоши')
),
150 => array(
'count' => 2,
'price' => 1000,
array('size'=>array(40 => 1, 41 => 1), 'name' => 'Туфли')
)
);
где 209 и 150, это уникальные идентификаторы товаров, первичный ключ в sql-таблице. Именно он, а не Арт.1001 или иной. Артикулы, это информация для продавцов и, если надо, то и покупателю. Ключ count - хранит количество набранного товара, price - его цену за 1 шт., а в массиве хранится детализация о выборе - название товара и размер как ключ, значением которого будет количество набранного для его покупки. Если Галош выбрали 2 шт. 42-го размера и 1 шт. 41-го, то count равен 3.
Добавляя товар в корзину, нужно помещать его в корзину под его идентификатором, как ключом массива, а в массив детализации помещать размер как ключ, а выбранное количество размера как значение (нельзя запрещать покупать 42 размер в количестве более штуки). Если 42 размер уже был помещен в корзину в количестве 1 шт., а покупатель изменит количество на 2 или иное, то ключ 42 будет переписан с новым значением. Если покупатель выберет 0, или "удаление" 42-го размера, значит 0 он и есть 0, или удаляем.
При всех таких изменениях суммируется значение ключа count.
Узнать же всего товаров в корзине и сумму за них позволяют стандартные функции PHP - current, array_product, array_sum, array_map в функции totalBasket(), которая описана по ссылке на корзину.
А для полного представления корзины уже нужно будет обходить корзину циклом выводя ее подробное описание в удобном для представления виде.
Последний раз редактировалось laimas, 16.05.2015 в 07:27.
|
|
16.05.2015, 10:17
|
Аспирант
|
|
Регистрация: 06.04.2015
Сообщений: 52
|
|
laimas, сразу возникают вопросы. Например, до этого я вытаскивал данные о товаре в цикле из БД, а теперь, если применить этот код
$products = [23 => ['price'=>120, 'name'=>'Товар 1'], 245 => ['price'=>230, 'name'=>'Товар 2'], 39 => ['price'=>150, 'name'=>'Товар 3'], 109 => ['price'=>380, 'name'=>'Товар 4']];
, то получается мне нужно так заполнить переменную $products на 1000 строчек, да ещё каждый раз в ручную редактировать изменения в товаре...... То же самое касается и этого кода:
$_SESSION['cart'] = array(
209 => array(
'count' => 3,
'price' => 1500,
array('size'=>array(42 => 2, 41 => 1), 'name' => 'Галоши')
),
150 => array(
'count' => 2,
'price' => 1000,
array('size'=>array(40 => 1, 41 => 1), 'name' => 'Туфли')
)
);
Я уже встречал примерно такое построение, но как это применить на практике - примеров не встретил...
|
|
16.05.2015, 15:12
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,989
|
|
Вытаскивать данные из базы в цикле, это очень и очень плохо, и означает насиловать базу. Об этом методе нужно забыть сразу.
Я забыл добавить ключ массиву характеристик в корзине товаров, сделаем это, и пусть на текущий момент корзина, и имеет указанные товары:
$_SESSION['cart'] = array(
209 => array(
'count' => 3,
'price' => 1500,
'prop' => array('size'=>array(42 => 2, 41 => 1), 'name' => 'Галоши')
),
150 => array(
'count' => 2,
'price' => 1000,
'prop' => array('size'=>array(40 => 1, 41 => 1), 'name' => 'Туфли')
)
);
Если на страницах покупатель может выбрать количество товара, а также указывать его характеристики, в данном случае размер, то на сервер нужно отправлять массив описывающий такой выбор, в котором под первичным ключом хранится размер/размеры и набранное их количество. Допустим сервер получит заказ на новые товары, а также изменение количества товара ID209 для 41-го размера, и добавления 43-го размера с количеством 1 шт., и передается как $_POST['order'].
Первоочередной задачей будет определить не туфту ли прислали в первичных ключах, обезопасить их для подстановки в запрос, а также определение тех товаров, которых еще нет в корзине, чтобы обратиться к базе для получения их наименования и цены, и уже потом добавить их в базу. А также вычленить товар, который уже есть в корзине, чтобы обновить его параметры.
Вы читали о функция, ссылки на которые я дал? Даю еще на на семь, которые потребуются для решения выше указанных задач. Более ссылок я давать не буду, скачивайте руководство РНР, оно есть на русском, в удобном CHM формате, с примерами к функциям. Изучайте, уясняйте, тем более, что тип данных array, это тип с которым придется сталкиваться постоянно. А ковыряться в этом типе исключительно как for, foreach и т.п., это плодить многоэтажный код, в котором легко и заблудиться.
И так, нам потребуется встроенные РНР функции - intval, implode, array_diff, array_diff_key, array_intersect_key, array_keys, array_flip.
Обрабатываем полученный массив выбрасывая из него "пустышки" если такие есть, и если после этого вернется не пустой массив $order, то выполняем операции с корзиной:
if($order = array_intersect_key($_POST['order'], array_flip(array_diff(array_map('intval', array_keys($_POST['order'])), array(0))))) {
//работаем с корзиной
}
Допустим в результате получим такой массив:
Array (
[209] => Array (
[42] => 3
[43] => 1
)
[186] => Array (
[37] => 1
)
[254] => Array (
[40] => 2
)
)
В нем два новых товара ID186 и ID254. Нужно из массива $order получить эти идентификаторы и получить информацию о них из базы, но не двумя запросами в цикле, а одним запросом используя sql-оператор IN(). Если в таблице поле идентификаторов имеет имя id, то запрос будет типа такого:
$basket = &$_SESSION['cart']; //что такое ссылки, читать в руководстве
$sql = 'SELECT id, name, price FROM table_name WHERE id IN('.implode(',', array_keys(array_diff_key($order, $basket))).')';
В итоге будет сделан всего один запрос к базе и возвращены данные о товарах ID186 и ID254. После этого их можно добавлять в корзину. Товары параметры которых в корзине нужно обновить получаются так:
$upd = array_intersect_key($basket, $order);
А теперь попробуйте сами, зная (желательно бы знать) о функции array_sum(), решить задачу обновления и добавления в массиве корзины.
Нужно учиться на более простых примерах, а не хвататься сразу за написание магазинов. Я не стану укорять за написание магазина вами так - а работает и ладно, а на чем не важно. Но я и не стану вам помогать писать код в том ключе, как это вы делаете, мне это просто не интересно. И объяснять все детали подробно почему это у меня так, а не как у вас, я не буду. На данный момент я не располагаю временем, я и так написал более, чем следовало бы.
Последний раз редактировалось laimas, 16.05.2015 в 15:19.
|
|
|
|