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

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, время: 13:44.