27.05.2015, 19:01
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,989
|
|
Функции, которые применяю изучаете?
Пусть имеется в корзине товары и пришел запрос выбранных товаров от пользователя, и содержание этих массивов будет таким:
//корзина
$_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. Если трудно разобраться в строке с кучей функций, ну так можно расписать каждую операцию поэтапно, для "разобраться".
Последний раз редактировалось laimas, 27.05.2015 в 19:05.
|
|
27.05.2015, 19:18
|
Аспирант
|
|
Регистрация: 06.04.2015
Сообщений: 52
|
|
Я так до сих пор и не разобрался, как в этой сессии получить эти данные?:
$_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>";
}
?>
Последний раз редактировалось arhat78, 27.05.2015 в 19:22.
|
|
27.05.2015, 19:35
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,989
|
|
Я не знаю что в вашей корзине, да и разбираться с ней не хочу, о чем уже говорил, так как ее структура никак не подходит к задаче, которую вы сами же и поставили - возможность выбора не только товара, но и его размеров. А как я понял, у каждого из товаров это его характеристика, а не отдельной описанный в базе товар.
Вы непосильную для начинающего задачу пытаетесь решить. Или же для начала упрощайте структуру данных, например нет размеров, написав код рабочий. Появятся знания и какой-то опыт, тогда усложнять задачу. Если нет и охота сразу и масштабно, будьте добры изучать язык, по другому не получится.
Ведь магазин, это не "добавить в корзину" и можно потирать руки. Если размеры, значит вполне возможно, что придется и их проверять на отсутствие "вредного", а это уже зависит от бизнес-модели магазина. Одни торгуют по запросам и наличию, и, если нет товара, то принимают заказ, а исполняют при доставке его. Другие ведут учет товаров на складе и у них нельзя заказать товар, которого на текущий момент нет. А это означает запрос в базу "за наличием".
Надо представлять всю эту бизнес-модель и каждые ее конкретные задачи. А каждая из них в свою очередь делиться на более мелкие.
У вас же нет такого представления, а значит и корзина не то, и как набирает товар покупатель, и что этот выбор из себя представляет для РНР....
Учитесь на простых примерах - как добавить в массив новые значения, как обновить в массиве имеющиеся значения, и т.п. А уж потом познания эти применять в более сложном.
|
|
28.05.2015, 07:16
|
Профессор
|
|
Регистрация: 23.10.2010
Сообщений: 2,718
|
|
Сообщение от 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 и получаем все что есть со всем что связано как доктор прописал.
Блеать это насколько каноничная схема, что даже думать не надо как сделать обычный каталог.
|
|
28.05.2015, 07:20
|
Профессор
|
|
Регистрация: 23.10.2010
Сообщений: 2,718
|
|
Проблемы начинаются когда начинается оптимизация. Типа списочные таблицы все одинаковые, а нельзя ли их все засунуть в одну. - Можно. Сделали деревянную таблицу (иерархическую) - засунули. Вдруг оказывается какой-то список выпадает из шаблона. Блин... Начинается поиск еще более универсального метода хранения индивидуальных свойств... premature optimization is evil.
Я вам на картинке покажу. Сколько там списков? Я сам посчитаю - 8 штук. Именно столько раз надо сделать left join со списочной таблицей чтобы получить полный фарш по товару. Поэтому полный фарш выдается на фронт только в продуктовой странице, там 1 товар, можно все собрать. И в админке нужно все собрать для товара, чтобы увидеть все его свойства на человеческом языке, а не id каким-то там. Ну вот, стало быть надо сделать 8 запросов чтобы загрузить 8 списков и затем найти в них тот id, который записан в кортеже товара и показать именно ту опцию.
Так вот, кажется все монструозным и страшным. А на самом деле как только у вас появился 1 список - вы их можете размножать сколько угодно. Интерфейс и логика абсолютно одинаковые для всех, разные только данные.
Последний раз редактировалось kostyanet, 28.05.2015 в 07:31.
|
|
28.05.2015, 07:37
|
Профессор
|
|
Регистрация: 23.10.2010
Сообщений: 2,718
|
|
Таблица размеров вам нужна потому что обувь измеряется дискретными шаблонами, а не континуальными миллиметрами. Но это и будет обычный список. А товары будут заводиться как товары.
ИД - Ботинок А 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:41.
|
|
28.05.2015, 07:51
|
Профессор
|
|
Регистрация: 23.10.2010
Сообщений: 2,718
|
|
Почему простые списки хорошо хранить в одной иерархической таблице - потому что у каждой проперти появлятся свой уникальный ид и вы можете однозначно по любой из них отождествить товары или товар. Если списки хранятся в разных таблицах, то ид пропертей могут совпадать и потребуется префикс, 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 в 07:54.
|
|
28.05.2015, 08:10
|
Профессор
|
|
Регистрация: 23.10.2010
Сообщений: 2,718
|
|
Теперь для всех кто читает. На примере той же обуви, хотя разницы нет.
Если у товара нет личного наименования, типа там сапоги Ольга, или кроссовки Игорь, то продуктовая таблица будет состоять из голимых списков. Входящий артикул - это список "коллекций", на том самом снимке это поле cid - collection id. Такой же обычный список, только не из пропертей-фильтров, а из отдельной таблицы связанной по collection.id=prods.cid. В этой таблице collection - поле title - уникальное. Нельзя завести двух Игорей или двух Олек. Именно эта таблица определяет тот самый уникальный ассортимент, но сама по себе она всего лишь - список и может работать как фильтр.
И вот тут есть переход. Страна на самом деле должна относиться к коллекции, к уникальным записям, равно как и бренд. Тогда в "коллекциях" в самих уже добавляется country_id и brand_id которые линкуются к таблицам country и brand. Запрос на полный фарш чуть усложняется, но не так, чтобы голову свернуть, все как обычно.
Так вот, самая мякотка в том, что вы заколебетесь делать из всех этих пропертей для сегрегации и фильтрации - нормальное человеческое наименование товара. Выведя параметры по-инженерному получите типа
размер 44
сезон лето
пол мужской
возраст взрослый
итп
Для SEO - такой вывод - полное гавно. Нихера оно не индексируется, релевантности не повышает, потому что выглядит и читается не по-человечески.
А чтобы сделать наименование Летние мужские ботинки для взрослых 44 размера - что манна для поиска и для людей - вам придется загонять весь словарь в бд и мудохаться с переводом машинных опций на русский язык.
Поэтому те, кто хочет чтоб у них покупали, не экономят свои силенки, а прямо в наименование товара пишут: Летние мужские ботинки 44 размера.
Тогда оно найдется и поиском в инете и поиском на сайте и именно найдется. А фильтры-шмильтры - это чисто для тех, кто умеет ими пользоваться.
Последний раз редактировалось kostyanet, 28.05.2015 в 08:13.
|
|
28.05.2015, 08:38
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,989
|
|
Сообщение от kostyanet
|
Это какой laimas вам такую бредовую хрень подсказал?
|
Опять ты под ногами скачешь пес шелудивый, брысь щенок под лавку. Обосрал зараза своим поносом каждую вторую тему форума. Пес смердячий
|
|
28.05.2015, 10:31
|
Профессор
|
|
Регистрация: 23.10.2010
Сообщений: 2,718
|
|
Ну хотя бы бабки у него кончились.
В общем по проектированию баз данных надо ходить на спец-форумы. Программисты в этом ничерта не понимают. Хуже всего что понимают, но по-своему, через одно место.
|
|
|
|