Функции, которые применяю изучаете?
Пусть имеется в корзине товары и пришел запрос выбранных товаров от пользователя, и содержание этих массивов будет таким: //корзина $_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. Если трудно разобраться в строке с кучей функций, ну так можно расписать каждую операцию поэтапно, для "разобраться". |
Я так до сих пор и не разобрался, как в этой сессии получить эти данные?:
$_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>"; } ?> |
Я не знаю что в вашей корзине, да и разбираться с ней не хочу, о чем уже говорил, так как ее структура никак не подходит к задаче, которую вы сами же и поставили - возможность выбора не только товара, но и его размеров. А как я понял, у каждого из товаров это его характеристика, а не отдельной описанный в базе товар.
Вы непосильную для начинающего задачу пытаетесь решить. Или же для начала упрощайте структуру данных, например нет размеров, написав код рабочий. Появятся знания и какой-то опыт, тогда усложнять задачу. Если нет и охота сразу и масштабно, будьте добры изучать язык, по другому не получится. Ведь магазин, это не "добавить в корзину" и можно потирать руки. Если размеры, значит вполне возможно, что придется и их проверять на отсутствие "вредного", а это уже зависит от бизнес-модели магазина. Одни торгуют по запросам и наличию, и, если нет товара, то принимают заказ, а исполняют при доставке его. Другие ведут учет товаров на складе и у них нельзя заказать товар, которого на текущий момент нет. А это означает запрос в базу "за наличием". Надо представлять всю эту бизнес-модель и каждые ее конкретные задачи. А каждая из них в свою очередь делиться на более мелкие. У вас же нет такого представления, а значит и корзина не то, и как набирает товар покупатель, и что этот выбор из себя представляет для РНР.... Учитесь на простых примерах - как добавить в массив новые значения, как обновить в массиве имеющиеся значения, и т.п. А уж потом познания эти применять в более сложном. |
Цитата:
Вообще как можно было допереть совать id товара в какой-то там список свойств товара? Ну то есть это какой степенью перверсии логики надо обладать тому советчику? Как говорят блондинки "он больной на всю голову". Вот типичная нормализованная схема где у каждого продукта есть страна изготовления: table prods id name country_id table country id name чтобы получить название страны в кортеже продукта Код:
select prods.*, country.name То же самое по размерам, добавляем списочную таблицу размеров table sizes id size а в таблицу продуктов добавляем связанное поле table prods id name country_id size_id и тогда чтобы получить размер в кортеже наименования Код:
select prods.*, country.name,sizes.size Блеать это насколько каноничная схема, что даже думать не надо как сделать обычный каталог. |
Вложений: 1
Проблемы начинаются когда начинается оптимизация. Типа списочные таблицы все одинаковые, а нельзя ли их все засунуть в одну. - Можно. Сделали деревянную таблицу (иерархическую) - засунули. Вдруг оказывается какой-то список выпадает из шаблона. Блин... Начинается поиск еще более универсального метода хранения индивидуальных свойств... premature optimization is evil.
Я вам на картинке покажу. Сколько там списков? Я сам посчитаю - 8 штук. Именно столько раз надо сделать left join со списочной таблицей чтобы получить полный фарш по товару. Поэтому полный фарш выдается на фронт только в продуктовой странице, там 1 товар, можно все собрать. И в админке нужно все собрать для товара, чтобы увидеть все его свойства на человеческом языке, а не id каким-то там. Ну вот, стало быть надо сделать 8 запросов чтобы загрузить 8 списков и затем найти в них тот id, который записан в кортеже товара и показать именно ту опцию. Так вот, кажется все монструозным и страшным. А на самом деле как только у вас появился 1 список - вы их можете размножать сколько угодно. Интерфейс и логика абсолютно одинаковые для всех, разные только данные. |
Таблица размеров вам нужна потому что обувь измеряется дискретными шаблонами, а не континуальными миллиметрами. Но это и будет обычный список. А товары будут заводиться как товары.
ИД - Ботинок А 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 записей в тех самых списках. |
Почему простые списки хорошо хранить в одной иерархической таблице - потому что у каждой проперти появлятся свой уникальный ид и вы можете однозначно по любой из них отождествить товары или товар. Если списки хранятся в разных таблицах, то ид пропертей могут совпадать и потребуется префикс, namespace для каждого id и тогда халява 13-8-26 кончится и будет примерно так ?stl=13&mat=8&shp=26 или типа того.
В этом нет ничего плохого, просто будет адрес длиннее. Ну вот, когда с размерами разберетесь, все остальное пойдет по накатанной: сезонность - список сезонов: id-name, половая id-name, возрастная - id-name, материал id-name, модельная группы id-name и так далее. Для цвета тоже можно завести список. |
Теперь для всех кто читает. На примере той же обуви, хотя разницы нет.
Если у товара нет личного наименования, типа там сапоги Ольга, или кроссовки Игорь, то продуктовая таблица будет состоять из голимых списков. Входящий артикул - это список "коллекций", на том самом снимке это поле cid - collection id. Такой же обычный список, только не из пропертей-фильтров, а из отдельной таблицы связанной по collection.id=prods.cid. В этой таблице collection - поле title - уникальное. Нельзя завести двух Игорей или двух Олек. Именно эта таблица определяет тот самый уникальный ассортимент, но сама по себе она всего лишь - список и может работать как фильтр. И вот тут есть переход. Страна на самом деле должна относиться к коллекции, к уникальным записям, равно как и бренд. Тогда в "коллекциях" в самих уже добавляется country_id и brand_id которые линкуются к таблицам country и brand. Запрос на полный фарш чуть усложняется, но не так, чтобы голову свернуть, все как обычно. Так вот, самая мякотка в том, что вы заколебетесь делать из всех этих пропертей для сегрегации и фильтрации - нормальное человеческое наименование товара. Выведя параметры по-инженерному получите типа размер 44 сезон лето пол мужской возраст взрослый итп Для SEO - такой вывод - полное гавно. Нихера оно не индексируется, релевантности не повышает, потому что выглядит и читается не по-человечески. А чтобы сделать наименование Летние мужские ботинки для взрослых 44 размера - что манна для поиска и для людей - вам придется загонять весь словарь в бд и мудохаться с переводом машинных опций на русский язык. Поэтому те, кто хочет чтоб у них покупали, не экономят свои силенки, а прямо в наименование товара пишут: Летние мужские ботинки 44 размера. Тогда оно найдется и поиском в инете и поиском на сайте и именно найдется. А фильтры-шмильтры - это чисто для тех, кто умеет ими пользоваться. |
Цитата:
|
Ну хотя бы бабки у него кончились.
В общем по проектированию баз данных надо ходить на спец-форумы. Программисты в этом ничерта не понимают. Хуже всего что понимают, но по-своему, через одно место. |
Часовой пояс GMT +3, время: 13:44. |