Делал такое, геморроя много. Остановился на варианте с тремя таблицами.
таблица items:
id_товара | название | цена и тд...
таблица options:
id_опции | название опции | влияние на цену
таблица items-options:
id_товара | id_опций через запятую | название связки
Таким образом, грузим из items базовую информацию, грузим items-options, получаем от туда примерно такое:
1 | 1,2,3,4 | Цвет
Значит, что у товара 1 есть возможность выбора цвета...
Прогружаем options с айди 1,2,3 и 4. Получаем, например:
1 | Красный | 0
2 | Синий | +100
3 | Белый | -20
4 | Чёрный | 0
Значит, что товар с красным и чёрным цветом будет стоить базовую цену, синего цвета на 100 рублей дороже, а белого уже на 20 дешевле.
В корзину записывать всё в формате:
id_товара | id_выбранных_опций_через_запятую | количество
Если посетитель добавит некий товар 1 двух разных цветов, то в корзине будет две записи:
1 | 1,2 | 1
1 | 3,4 | 1
Опции можно комбинировать. В моём случае это были межкомнатные двери, нужно было учитывать размер полотна, цвет и наличие базовых аксессуаров (петли, ручка, наличники и прочее..). Соответственно, если посетителю нужна дверь 200х100см и такая же 190х90см, то разумнее это в корзине представить как два разных товара. Так он сможет совершенно спокойно заказать две двери первого размера и, допустим, семь дверей второго размера.
Понимаю, что в каком-то плане моя реализация костыльная, но зато она работает и работает очень просто.