Javascript-форум (https://javascript.ru/forum/)
-   Серверные языки и технологии (https://javascript.ru/forum/server/)
-   -   Вывод товара в корзине (https://javascript.ru/forum/server/55802-vyvod-tovara-v-korzine.html)

arhat78 15.05.2015 07: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;
}

laimas 15.05.2015 09:14

Нужно менять представление корзины в сессии.

arhat78 15.05.2015 09:18

laimas, а не могли бы по подробнее??? А то так мне не понятно совсем...

laimas 15.05.2015 09:30

Почитайте тут. Не обязательно Ajax, можно и без него. Там описана корзина, ее возможная структура и почему такая выбрана.

arhat78 15.05.2015 13:54

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

laimas 15.05.2015 14:16

Меняйте "свою" корзину, ее представление неудачное, почему, это по ссылке можно понять. Как вложить в вас "понимание", этого я не знаю. )

arhat78 15.05.2015 23:35

Цитата:

Сообщение от laimas (Сообщение 370976)
Меняйте "свою" корзину, ее представление неудачное, почему, это по ссылке можно понять. Как вложить в вас "понимание", этого я не знаю. )

Но нужно же понять, что именно не правильно, и как грамотно нужно поменять этот код. Я же только учусь, и очень тяжело "расшифровать" ваш код и понять, как его применить в моём случае.... Надеюсь, подскажете в каком направлении и как двигаться :thanks:

laimas 16.05.2015 06:54

Я же только учусь, и очень тяжело "расшифровать" ваш код и понять

А вы хотите чтобы я писал код так же как вы? :) Ну понятно, что так:

$_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(), которая описана по ссылке на корзину.

А для полного представления корзины уже нужно будет обходить корзину циклом выводя ее подробное описание в удобном для представления виде.

arhat78 16.05.2015 10:17

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' => 'Туфли')
	   )
	);


Я уже встречал примерно такое построение, но как это применить на практике - примеров не встретил...

laimas 16.05.2015 15:12

Вытаскивать данные из базы в цикле, это очень и очень плохо, и означает насиловать базу. Об этом методе нужно забыть сразу.

Я забыл добавить ключ массиву характеристик в корзине товаров, сделаем это, и пусть на текущий момент корзина, и имеет указанные товары:
$_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(), решить задачу обновления и добавления в массиве корзины.

Нужно учиться на более простых примерах, а не хвататься сразу за написание магазинов. Я не стану укорять за написание магазина вами так - а работает и ладно, а на чем не важно. Но я и не стану вам помогать писать код в том ключе, как это вы делаете, мне это просто не интересно. И объяснять все детали подробно почему это у меня так, а не как у вас, я не буду. На данный момент я не располагаю временем, я и так написал более, чем следовало бы.

arhat78 17.05.2015 16:18

laimas, благодарю и на этом :thanks: Буду изучать новое построение конструкции корзины и всё, что с ней связано. Надеюсь, получится.

arhat78 20.05.2015 11:23

laimas, в общем смотрел я, читал, пытался вникнуть, и понял, что здесь вообще ничего не понял :( Сколько видел уроков с объяснениями, там была моя структура корзины. А здесь, у вас - капец просто. Я уверен, что если грамотно, по вашему корзину построить, то будет всё по науке. Но вот где найти уроки с объяснениями.....?

laimas 20.05.2015 11:56

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

Суть вопроса была такова - есть у меня боты разных размеров и когда добавляется что-то в корзину, все нормально. Но если в корзину добавляют боты другого размера, то прежний добавленный размер теряется.

Будем рассуждать, и для начала забиваем и на РНР, и на все остальные языки, а будем оперировать исключительно блокнотом и карандашом.

Есть магазин, в котором туфли: "Туфли черные", цена 100, размеры 40, 41; "Туфли красные", цена 110, размеры 41, 42; "Туфли белые", цена 150, размер 42.

Выбираем "Туфли черные", одну пару размера 40, и пишет в блокноте:

"Туфли черные": 100 руб., 40 разм., 1 шт.

Затем выбрали еще "Туфли красные", добавляем в блокнот запись и в нем уже будет так:

"Туфли черные": 100 руб., 40 разм., 1 шт.
"Туфли красные": 110 руб., 41 разм., 1 шт.


Затем решили добавить еще "Туфли черные", но 41 размера и две пары. Вопрос - как выгоднее записать этот выбор в блокноте, так:

"Туфли черные": 100 руб., 40 разм., 1 шт.
"Туфли красные": 110 руб., 41 разм., 1 шт.
"Туфли черные": 100 руб., 41 разм., 2 шт.


или так:

"Туфли черные": 100 руб., 40 разм., 1 шт., 41 разм. 2 шт.
"Туфли красные": 110 руб., 41 разм., 1 шт.


?

arhat78 20.05.2015 12:02

Как по мне, то первый вариант....(это я про вывод в корзине)
Цитата:

Сообщение от laimas (Сообщение 371609)
"Туфли черные": 100 руб., 40 разм., 1 шт.
"Туфли красные": 110 руб., 41 разм., 1 шт.
"Туфли черные": 100 руб., 41 разм., 2 шт.

А вот оптимально хорошо выглядит второй вариант.

А уроки про "магазин и корзину" - могу ссылку сбросить :)

laimas 20.05.2015 13:37

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

Он не удобен тем, что при подсчетах нужно будет пробегать по всем строкам в блокноте, чтобы найти одни и те же туфли, и если выбор туфлей будет на нескольких его страницах, то такой расчет будет затруднителен. А вот при втором варианте каждая запись, это какие-то одни туфли, для которых описаны различные наборы, и расчет всего, это удобно получить сумму за туфли, затем последовательно суммируя ее с суммой следующей строки. Выискивать записи среди страниц блокнота не придется, а просто перелистываем их когда сумма на текущей просчитана.

Легенда гласит - труд сделал из обезьяны человека, и когда он понял, что считать на косточках не удобно он придумал компьютер. А чтобы компьютер понимал что от него хотят, человек придумал инструкции для него, которые облек в понятие "язык мышления для компьютера". Эти инструкции описывают конкретные представления человека, например, bcdiv(a, b, c) означает - "взять косточку а, разбить ее на b частей, и кроме полученных частей собрать еще и с осколков". А набором таких различных инструкций можно описать задачу, которую и выполнит компьютер, например, сколько литров наваристого борща получится из косточки разделенной на части, включая и осколки.

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

Компьютер выполняет ровно то, что мы от него хотим. А вот если бы наш мир появился не согласно легенде, а в результате большого взрыва (как и вселенной) появились машинные инструкции, которые породили компьютер, которые породили бы нас... Вот тогда все было бы иначе - компьютер бы разбил а на b частей и с осколков, и напечатал - "это борщ, ешь и не гавкай". :-?

Есть такой лозунг - "Мы не рабы, рабы не мы!". Мы не рабы машин, мы управляем ими. Хотя айпады поработили человека, но это из области привычек и потребления, "ум" в айпады все равно человек вложил. Поэтому начинать надо с изначального - с представления того, что я хочу от машины, и только потом облекать желание в инструкции. А тут блокнот и карандаш тоже могут помочь. И вообще, существуют блок-схемы, посредством которых можно описать компьютерную программу. Такие схемы не содержат конкретных функций языка, но они хорошо иллюстрируют алгоритм программы, ее конструкцию, блоки, важные узлы.

Попробуйте с блокнотом, думаю польза будет, а нет, ну тогда не знаю. Расписывать же уроки и некогда, да и не всегда охота писать много. :)

arhat78 21.05.2015 12:10

laimas, вот у меня есть сессия
$_SESSION['cart'] = array()


А мне, получается, нужно записывать этот массив таким образом?
$_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' => 'Туфли')
       )
);


И у меня, получается, много лишнего написано? Этот кэйс :
case('add_to_cart'):
      $id = $_GET['id'];
      $size = $_GET['size'];
      $_SESSION['cart_size'][$id] = $size;
      
      $add_item = add_to_cart($id);
      $_SESSION['total_items'] = total_items($_SESSION['cart']);
      $_SESSION['total_price'] = total_price($_SESSION['cart']);
      header('Location:index.php?view=product&id='.$id);
   break;


И вот это, функция добавления в корзину:
function add_to_cart($id, $size)
{
    if(isset($_SESSION['cart'][$id]))
     {
        $_SESSION['cart'][$id]++;
        return true;
     }       
    else
    {
        $_SESSION['cart'][$id] = 1;
        return true;
    }
        return false; 
}


А как же быть с этими функциями подсчёта общего количества и общей суммы?:

function total_items($cart)
{
    $num_items = 0;
    
    if(is_array($cart))
    {
        foreach($cart as $id => $qty)
        {
            $num_items +=  $qty;
        }
        return $num_items;
    }
}



function total_price($cart)  
{
    $total_price = '0.00';
    
    global $link;
    
    if(is_array($cart))
    {
        foreach($cart as $id => $qty)
        {           
            $result = $link->query("SELECT price FROM products WHERE id='$id' ");
                       
            if($result)
            {
                $item_price = mysqli_fetch_assoc($result);
                $total_price +=  $item_price['price'] * $qty;
            }          
        }
        return $total_price;         
    }
}


В общем, что делать???? Как исправляться???? Неужели потратил год в пустую????

laimas 21.05.2015 19:02

Кто задавал вопрос о различных размерах ботинок? Если размеры различные и при этом это один ID товара, то каким образом можно узнать что заказаны те или иные его размеры поступая вот таким образом $_SESSION['cart'][$id]++; ?
Если же каждый ID товара может описывать только один размер, тогда да можно было бы так поступать - нет такого ID в корзине, значит добавляем, есть, значит увеличиваем его количество.

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

arhat78 21.05.2015 22:27

Я понимаю, что здесь прибавляется в корзине только определённый товар - $_SESSION['cart'][$id]++; А можно в эту сессию добавить каким то образом идентификатор или ключ размера?

laimas 22.05.2015 01:21

Добавляйте, а каким-то каким образом, понятия не имею, попробуйте "как-то". :)

Я описывал структуру корзины, которая описывает наборы не только товаров, но и учитывает их характеристики, в данном случае размеры, а могут быть еще и цвет, и другое. Чем эта структура не устраивает ваш магазин?

arhat78 22.05.2015 17:46

laimas, сейчас для меня эта структура без пошаговых объяснений, как переводчику заглянуть в учебник по термоядерной динамике :lol:

Пробовал вот такой составной ключ:
$add_item = add_to_cart(sprintf('id%ds%d', $id, $size));

но здесь, когда добавляю один ботинок с двумя разными размерами, в корзине выводится этот ботинок двумя отдельными строчками, но без количества, размеров.....

Ещё пробовал такую проверку в корзине, но от этой проверки толка нет...:

if ($product !== get_product($id)) 
      {
       echo $_GET('id');
      }
     if ($b['size'] !== $_SESSION['cart_size'][$id]) 
      {
       echo $_GET['size'];
      }

laimas 22.05.2015 18:26

Вот это лучшее представление данных в данному случае?:
"Туфли черные": 100 руб., 40 разм., 1 шт.
"Туфли красные": 110 руб., 41 разм., 1 шт.
"Туфли черные": 100 руб., 41 разм., 2 шт.

Бог с ним, хотя это и не лучшее, но хотя бы уже это представление попытаться описать массивов и подумать, как его можно использовать. А это - sprintf('id%ds%d', $id, $size), билиберда полнейшая.

Пока не будет изучен раздел РНР руководства "Справочник языка -> Типы -> Массивы" и "Расширения, относящиеся к переменным и типам -> Массивы" даже и разговаривать не о чем.

arhat78 25.05.2015 14:28

laimas, перелопатил "ворохи" материала. Очень интересно по данным вами функциям - в отдельности, а вот как их собирать в одну систему??? Вот например, начнём с самого начала - есть у меня
$_SESSION['cart'] = array();

Вот как в него заносить данные, чтобы он получил вот этот ваш тип:
$_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' => 'Туфли')
       )
);
???????

laimas 25.05.2015 20:16

Это хорошо, что перелопачено, только плохо, что за лопатой не замечено главного, то, что к программированию отношения не имеет.

Пусть есть две бизнес модели - первая авто дилер, вторая магазин обуви. Покупка машины дело серьезное и не через корзину, это может быть только заказ услуги у дилера - показать выбранные модели или приготовить к продаже их. Вряд ли машины будут покупать как ботинки по несколько пар, а значит $_SESSION['id']++ вполне достаточно. У богатых свои причуды, если для жены покупает одну модель ВАЗа, не обломится дважды щелкнуть на Лексусе для любовницы или трижды на Майбах для любимой собачки.

Но для для интернет магазина обуви вполне норма покупать по несколько пар, и если в нем выбор как $_SESSION['id']++ в реальном бы означало - выбрали одну пару, сбегали на кассу уведомили, сбегали за второй, опять на кассу, и так пока нужное не наберем. А значит набор товара в корзину в данном случае должен быть иной, да еще учитывать и размеры. В реальном не проблема - взяли пару одного размера, еще пару иного и понесли их на кассу, в руках ли, в сумке ли, кому как удобнее. Но для интернет магазина нужно описать "несем в руках/сумке" форматом, который поймет машина, и только потом будем думать как добавлять этот выбор в корзину. Это определено?

А на большую часть вопроса добавления в корзину дает ответ сам тип данных - Array.

kostyanet 26.05.2015 21:39

Тему не читал, ибо баянище. Если уже расжевали, еще раз вкратце:

Цитата:

Сообщение от arhat78
Вот как поменять код, какой применить принцип, чтобы в корзину добавлялся ботинок одного id, но с разными выбранными размерами?


У каждого размера, цвета, оттенка, отделки и тп - свой собственный артикул. Такие требования вытекают хотя бы из обычной бухгалтерской практики.

В интерфейсе каталога или витрины вы можете изображать один артикул разных цветов, но когда начнете бить чеки, вам на каждый товар потребуется _собственный уникальный идентификатор_ и желательно как число. В принципе и текст потянет, но тогда вам придется так и выбивать - зеленые шнурки фабрики Шнурок полиэстер 90 хлопок 20 г.Мск - 3 шт, красные шнурки фабрики Шнурок полиэстер 90 хлопок 20 г.Мск - 5 шт...

kostyanet 26.05.2015 21:45

Цитата:

Сообщение от arhat78
$_SESSION['cart'] = array();

Сессия сдохнет как только браузер закроют. Вся работа ведется с куками или как я недавно узнал сейчас модно - с localStorage.

kostyanet 26.05.2015 21:49

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

Блин я даже не могу представить сколько нужно иметь извилин, чтобы взять 2 коробки с ботинками разного цвета и убедиться что баркод у них разный.

Две? Или одну?

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

kostyanet 26.05.2015 22:03

Цитата:

Сообщение от arhat78
Буду изучать новое построение конструкции корзины и всё,

Капец блин, какая там структура? Нет никакой структуру у телеги.

Ладно, что там наплел специалист по "термоядерной динамике" я не читал, но когда вы хотите показать товар то как это делаете? В урл что ли пишите весь этот Array с цветом размером и длиной шнурков? Коню ясно - пишите какой-то идентификатор по которому товар однозначно отождествляется и добывается из бд.

Так вот корзина это просто коллекция таких id, или артикулов, или индексов - чего угодно. Любой можно открыть как продуктовую страницу, а чтобы открыть все, можно или перечислить через or все идентификаторы, или запузырить их в in();

select * from prods where id in(join(',',$ids));

и все - раскручивайте в фориче обычные тумбы или таблицу или что там - и вот вам телега.

kostyanet 26.05.2015 22:07

Цитата:

Сообщение от arhat78
когда добавляю один ботинок с двумя разными размерами

Самое прикольное что все нужные id у него есть, просто он не мыслит такими категориями как счет-фактура и баркод. Откуда вообще возьмется другой размер или цвет в бд? ну надо сделать запись. Если запись сделана и было предусмотрено поле с автоинкрементом - появился и тот самый id. Бери, сохраняй, добывай, показывай.

В чем проблема-то? Или вы где держите сведения о размерах и цвете?

arhat78 27.05.2015 17:59

kostyanet, не ругайтесь так..... Я же только учусь. Чисто для себя, без всякой коммерческой подоплёки. А вот здесь , с размерами, застрял как в болоте по шею, и не туда, и не сюда..........

Для размеров у меня отдельная таблица sizes, где есть id, boot_id (здесь id ботинка соответствует определённому размеру), и size - сам размер.

arhat78 27.05.2015 18:05

laimas, чем больше погружаюсь в ваши коды, тем больше понимаю, что нихр... не понимаю...... Пробовал отдельно размер в массив занести - не получается..... С этой выборкой:
$sql = 'SELECT id, name, price FROM table_name WHERE id IN('.implode(',', array_keys(array_diff_key($order, $basket))).')';
- одни сплошные ошибки и предупреждения.

$order никак не идентифицируется. Может это не правильно или не в том месте размещаю:
if($order = array_intersect_key($_POST['order'], array_flip(array_diff(array_map('intval', array_keys($_POST['order'])), array(0))))) {
    //работаем с корзиной
}

И на все функции ..._array - предупреждения...... :(

laimas 27.05.2015 19:01

Функции, которые применяю изучаете?
Пусть имеется в корзине товары и пришел запрос выбранных товаров от пользователя, и содержание этих массивов будет таким:
//корзина
$_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' => 'Туфли')
       ),
       180 => array(
          'count' => 4,
          'price'  => 1000,
          array('size'=>array(40 => 2, 41 => 2), 'name' => 'Туфли')
       )
);
$basket = &$_SESSION['cart']; //используем ссылку на массив корзины
//полученный массив
$_POST['order'] = array(
    144 => array(41=>1),
    222 => array(40=>1, 42=>2),
    209 => array(41=>1)
);
//array_keys($_POST['order']) получает ключи POST массива
//array_map('intval' ... приводит полученные ключи к integer
//array_diff вычисляет расхождение массивов по их значениям, и удаляит из полученных ключей те, которые будут равных 0 после приведения к integer
//это действие как раз и отсекает "вредности", ибо могут вместо ключей прислать и строку с sql-запросом, а это уже попытка инъекции базы
//array_flip меняет местами ключи и значения массива, это нужно потому, что далее будет использована функция пересечения массивов по их ключам
//а до array_flip ключи были значениями
//array_intersect_key выберет из POST массива только те ключи и их значения, что вернутся после array_flip
//попробуйте в $_POST['order'] замечить один или все ключи на строки, посмотрите результат 
if($order = array_intersect_key($_POST['order'], array_flip(array_diff(array_map('intval', array_keys($_POST['order'])), array(0))))) {
    //$order (POST массив) не пустой, вот что получаем
    print_r($order);
    //работаем с корзиной
    //надо выяснить какие товары в массиве $order уже есть, а каких нет, чтобы для вновь добавляемых получить их параметры в базе
    //для этого опять вычислим расхождение массивов (запрошенного формой и корзины), но уже по их ключам, функцией array_diff_key
    //полученные ключи обеденим в строку значений раздленных запятой, как того требует IN()   
    $sql = 'SELECT id, name, price FROM table_name WHERE id IN('.implode(',', array_keys(array_diff_key($order, $basket))).')';
    //вот что получилось
    echo $sql;
    //как видно, запрос будет только для ID 144 и 222, так как ID 209 уже есть в корзине, и его нужно обновлять 
}

И выполняется без ошибок. Если у вас есть ошибки при исполнении, то их нужно анализировать и устранять их причины, которые могут быть связаны с чем угодно на вашем сервере.

Если вам кто-то показывает код, то разбирайтесь в том, что же он делает, вот это и будет тогда "учеба". А просто копировать не задумываясь, не изучать функции в нем применяемые, да и вообще не изучать функций языка, так какая же это учеба.

PS. Если трудно разобраться в строке с кучей функций, ну так можно расписать каждую операцию поэтапно, для "разобраться".

arhat78 27.05.2015 19:18

Я так до сих пор и не разобрался, как в этой сессии получить эти данные?:
$_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' => 'Туфли')
       ),
       180 => array(
          'count' => 4,
          'price'  => 1000,
          array('size'=>array(40 => 2, 41 => 2), 'name' => 'Туфли')
       )
);


У меня в корзине вывод очень прост:
Array ( [2] => 2 [1] => 1 )
, где [2] - это порядковый номер ботинка в корзине (от большего к меньшему), а 2 - это количество...... Пытался хотя бы размер в массив занести - всё мимо....:

$result = $link->query("SELECT size FROM sizes WHERE `sizes`.`id_boot`='$id' ");
$b = mysqli_fetch_assoc($result);
$s = array();
do{
    $s[]=$b['size'];
    
}
while ($b = mysqli_fetch_assoc($result));
{
        
      echo  "<option   value='".$b['size']."'>"   .$b['size'].  " </option>";
      $s[] = $b['size'];       
}

print $b;


Было так:

$result = $link->query("SELECT size FROM sizes WHERE `sizes`.`id_boot`='$id' ");

while ($b = mysqli_fetch_assoc($result))
{
      echo  "<option   value='".$b['size']."'>"   .$b['size'].  " </option>";
}
?>

laimas 27.05.2015 19:35

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

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

Ведь магазин, это не "добавить в корзину" и можно потирать руки. Если размеры, значит вполне возможно, что придется и их проверять на отсутствие "вредного", а это уже зависит от бизнес-модели магазина. Одни торгуют по запросам и наличию, и, если нет товара, то принимают заказ, а исполняют при доставке его. Другие ведут учет товаров на складе и у них нельзя заказать товар, которого на текущий момент нет. А это означает запрос в базу "за наличием".

Надо представлять всю эту бизнес-модель и каждые ее конкретные задачи. А каждая из них в свою очередь делиться на более мелкие.

У вас же нет такого представления, а значит и корзина не то, и как набирает товар покупатель, и что этот выбор из себя представляет для РНР....

Учитесь на простых примерах - как добавить в массив новые значения, как обновить в массиве имеющиеся значения, и т.п. А уж потом познания эти применять в более сложном.

kostyanet 28.05.2015 07:16

Цитата:

Сообщение от arhat78
Для размеров у меня отдельная таблица sizes, где есть id, boot_id

Это какой laimas вам такую бредовую хрень подсказал? Ну естественно вы ничего не сделаете толком, имея БД спроектированную через жопу.

Вообще как можно было допереть совать id товара в какой-то там список свойств товара? Ну то есть это какой степенью перверсии логики надо обладать тому советчику? Как говорят блондинки "он больной на всю голову".

Вот типичная нормализованная схема где у каждого продукта есть страна изготовления:

table prods
id
name
country_id

table country
id
name

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

Код:

select prods.*, country.name
from prods
left join country
on country.id=prods.country_id

Теперь представьте что вы пихаете id продукта в таблицу стран... странно, как минимум, а вообще скажут - идиотизм.

То же самое по размерам, добавляем списочную таблицу размеров

table sizes
id
size

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

table prods
id
name
country_id
size_id

и тогда чтобы получить размер в кортеже наименования

Код:

select prods.*, country.name,sizes.size
from prods
left join country on country.id=prods.country_id
left joint sizes on sizes.id = prods.size_id

Сколько списков понадобится - столько их делаем и столько добавляем связанных полей и столько раз делаем join и получаем все что есть со всем что связано как доктор прописал.

Блеать это насколько каноничная схема, что даже думать не надо как сделать обычный каталог.

kostyanet 28.05.2015 07:20

Вложений: 1
Проблемы начинаются когда начинается оптимизация. Типа списочные таблицы все одинаковые, а нельзя ли их все засунуть в одну. - Можно. Сделали деревянную таблицу (иерархическую) - засунули. Вдруг оказывается какой-то список выпадает из шаблона. Блин... Начинается поиск еще более универсального метода хранения индивидуальных свойств... premature optimization is evil.

Я вам на картинке покажу. Сколько там списков? Я сам посчитаю - 8 штук. Именно столько раз надо сделать left join со списочной таблицей чтобы получить полный фарш по товару. Поэтому полный фарш выдается на фронт только в продуктовой странице, там 1 товар, можно все собрать. И в админке нужно все собрать для товара, чтобы увидеть все его свойства на человеческом языке, а не id каким-то там. Ну вот, стало быть надо сделать 8 запросов чтобы загрузить 8 списков и затем найти в них тот id, который записан в кортеже товара и показать именно ту опцию.

Так вот, кажется все монструозным и страшным. А на самом деле как только у вас появился 1 список - вы их можете размножать сколько угодно. Интерфейс и логика абсолютно одинаковые для всех, разные только данные.

kostyanet 28.05.2015 07:37

Таблица размеров вам нужна потому что обувь измеряется дискретными шаблонами, а не континуальными миллиметрами. Но это и будет обычный список. А товары будут заводиться как товары.

ИД - Ботинок А 44 размер - выбрали из списка 44 - Сохранили
ИД - Ботинок А 42 размер - выбрали из списка 42 - Сохранили

Как выбрать все ботинки 44 размера если в товаре нет такого числа? Ну надо загрузить список размеров, найти там ИД 44-го, а потом загрузить из каталога where size_id=$id.

Разумеется ничего отдельно грузить не надо - where просто приделывается к тому самому запросу с джойнами, а id размера получаем из интерфейса браузера, куда сперва и был загружен список ид-размер для выбора юзером.

Куда еще проще?

Кстати, гляньте как оно устроено на фронте то, что я показал на снимке с тыла - http://mebmoll.ru/catalog/tables?fls=13-8-26

Вот эти 13-8-26 - это и есть ID записей в тех самых списках.

kostyanet 28.05.2015 07:51

Почему простые списки хорошо хранить в одной иерархической таблице - потому что у каждой проперти появлятся свой уникальный ид и вы можете однозначно по любой из них отождествить товары или товар. Если списки хранятся в разных таблицах, то ид пропертей могут совпадать и потребуется префикс, namespace для каждого id и тогда халява 13-8-26 кончится и будет примерно так ?stl=13&mat=8&shp=26 или типа того.

В этом нет ничего плохого, просто будет адрес длиннее.

Ну вот, когда с размерами разберетесь, все остальное пойдет по накатанной: сезонность - список сезонов: id-name, половая id-name, возрастная - id-name, материал id-name, модельная группы id-name и так далее.

Для цвета тоже можно завести список.

kostyanet 28.05.2015 08:10

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

Если у товара нет личного наименования, типа там сапоги Ольга, или кроссовки Игорь, то продуктовая таблица будет состоять из голимых списков. Входящий артикул - это список "коллекций", на том самом снимке это поле cid - collection id. Такой же обычный список, только не из пропертей-фильтров, а из отдельной таблицы связанной по collection.id=prods.cid. В этой таблице collection - поле title - уникальное. Нельзя завести двух Игорей или двух Олек. Именно эта таблица определяет тот самый уникальный ассортимент, но сама по себе она всего лишь - список и может работать как фильтр.

И вот тут есть переход. Страна на самом деле должна относиться к коллекции, к уникальным записям, равно как и бренд. Тогда в "коллекциях" в самих уже добавляется country_id и brand_id которые линкуются к таблицам country и brand. Запрос на полный фарш чуть усложняется, но не так, чтобы голову свернуть, все как обычно.

Так вот, самая мякотка в том, что вы заколебетесь делать из всех этих пропертей для сегрегации и фильтрации - нормальное человеческое наименование товара. Выведя параметры по-инженерному получите типа

размер 44
сезон лето
пол мужской
возраст взрослый
итп

Для SEO - такой вывод - полное гавно. Нихера оно не индексируется, релевантности не повышает, потому что выглядит и читается не по-человечески.

А чтобы сделать наименование Летние мужские ботинки для взрослых 44 размера - что манна для поиска и для людей - вам придется загонять весь словарь в бд и мудохаться с переводом машинных опций на русский язык.

Поэтому те, кто хочет чтоб у них покупали, не экономят свои силенки, а прямо в наименование товара пишут: Летние мужские ботинки 44 размера.

Тогда оно найдется и поиском в инете и поиском на сайте и именно найдется. А фильтры-шмильтры - это чисто для тех, кто умеет ими пользоваться.

laimas 28.05.2015 08:38

Цитата:

Сообщение от kostyanet
Это какой laimas вам такую бредовую хрень подсказал?

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

kostyanet 28.05.2015 10:31

Ну хотя бы бабки у него кончились.

В общем по проектированию баз данных надо ходить на спец-форумы. Программисты в этом ничерта не понимают. Хуже всего что понимают, но по-своему, через одно место.


Часовой пояс GMT +3, время: 07:19.