И в целом, вот первая же ссылка в гугле с уровнем кода на две головы выше чем у автора https://codeshack.io/shopping-cart-system-php-mysql/
1. нажал полсотни раз неожиданных результатов не увиделА то двойное нажатие back приводит к неожиданным результатам.
Я всё еще надеюсь, что ТС действительно изучает РНР. Иначе зачем качать готовый скрипт корзины если можно скачать готовый магазин.ссылка в гугле с уровнем кода на две головы выше чем у автора
<?php
/**
* Model
*/
// регистратор ошибок
function addError($text): void
{
$_SESSION['error'][] = $text;
}
function getError(): array
{
return $_SESSION['error'] ?? [];
}
function clearError(): void
{
unset($_SESSION['error']);
}
/**
* Функции корзины
*/
// инициализация корзины
function basketInit($product): array
{
if (!empty($_COOKIE['basket'])) {
$basket = json_decode(base64_decode($_COOKIE['basket']), true);
if (!empty($basket['item'])) {
$moveUpItem = [];
// проверка доступности товара
foreach ($basket['item'] as $itemCode => &$item) {
$item['available'] = $item['quantity'];
$inStockProduct = getStockProduct($product, $itemCode);
if (empty($inStockProduct)) {
$item['available'] = 0;
$moveUpItem[$itemCode] = $item;
unset($basket['item'][$itemCode]);
} else if ($item['quantity'] > $inStockProduct) {
$item['available'] = $inStockProduct;
}
}
unset($item);
$basket['item'] = $moveUpItem + $basket['item'];
return $basket;
}
}
return [
'basket_id' => uniqid('', true),
'date_create' => date('Y-m-d H:i:s'),
'currency' => 'руб',
'item' => [],
];
}
// добавление товара в корзину
function addItem($basket, $itemCode, $quantity = 1): array
{
if (isset($basket['item'][$itemCode])) {
$basket['item'][$itemCode]['quantity'] += $quantity;
$basket['item'][$itemCode]['update_timestamp'] = time();
} else {
$basket['item'][$itemCode]['quantity'] = $quantity;
$basket['item'][$itemCode]['add_timestamp'] = $basket['item'][$itemCode]['update_timestamp'] = time();
}
return $basket;
}
// удаление товара из корзины
function removeItem($basket, $itemCode): array
{
if (isset($basket['item'][$itemCode])) {
unset($basket['item'][$itemCode]);
}
return $basket;
}
function getStockProduct($product, $itemCode): int
{
return $product[$itemCode]['stock'];
}
// количество товаров в корзине
function countItem($basket): int
{
return count($basket['item']) ?? 0;
}
// общее количество товарных единиц в корзине
function countAllQuantityItem($basket): int
{
return array_sum(array_column($basket['item'], 'available'));
}
// общая стоимость корзины
function getBasketPrice($basket, $product): float
{
$allProductPrice = [];
$productBasket = array_intersect_key($product, $basket['item']);
foreach ($productBasket as $productCode => $productItem) {
$allProductPrice[] = $productItem['price'] * $basket['item'][$productCode]['available'];
}
return array_sum($allProductPrice);
}
// идентификатор корзины
function getBasketId($basket): string
{
return $basket['basket_id'];
}
// валюта корзины
function getBasketCurrency($basket): string
{
return $basket['currency'];
}
// сохранение корзины
function saveBasket($basket): void
{
$basket = base64_encode(json_encode($basket));
setcookie('basket', $basket, time() + 360000, '/');
}
// удаление корзины
function deleteBasket($basket): void
{
saveBasket($basket);
}
function getProduct(): array
{
return [
1000 => [
'code' => 1000,
'stock' => 10,
'name' => 'Калькулятор',
'price' => 699.99,
'currency' => 'руб',
],
2000 => [
'code' => 2000,
'stock' => 5,
'name' => 'Ручка шариковая',
'price' => 12.05,
'currency' => 'руб',
],
3000 => [
'code' => 3000,
'stock' => 20,
'name' => 'Набор карандашей',
'price' => 56.99,
'currency' => 'руб',
],
4000 => [
'code' => 4000,
'stock' => 132,
'name' => 'Тетрадь общая',
'price' => 32.50,
'currency' => 'руб',
],
];
}
function addItemAction($basket, $product): void
{
$itemCode = (int)$_POST['add_item'];
if (!isset($product[$itemCode])) {
addError('Попытка добавления в корзину несуществующего товара');
return;
}
$quantity = (int)($_POST['quantity'][$itemCode] ?? 1);
if ($quantity < 1) {
addError('Количество товара добавляемого в корзину должно быть положительным числом');
} elseif ($product[$itemCode]['stock'] === 0) {
addError('[' . $product[$itemCode]['code'] . '] "' . $product[$itemCode]['name'] . '" недоступен к покупке.');
addError('Товар не может быть добавлен в корзину (<a href="">подобрать замену</a>)');
} elseif ($product[$itemCode]['stock'] >= $quantity + ($basket['item'][$itemCode]['available'] ?? 0)) {
$basket = addItem($basket, $itemCode, $quantity);
} else {
$quantityNew = $product[$itemCode]['stock'] - ($basket['item'][$itemCode]['available'] ?? 0);
if ($quantityNew > 0) {
$basket = addItem($basket, $itemCode, $quantityNew);
addError(
'[' . $product[$itemCode]['code'] . '] "' . $product[$itemCode]['name'] . '" в наличии '
. $product[$itemCode]['stock'] . ' шт. В корзине '
. ($basket['item'][$itemCode]['available'] ?? 0) . ' шт.');
addError('В корзину добавлено максимальное количество товара доступное к покупке.');
} else {
addError(
'[' . $product[$itemCode]['code'] . '] "' . $product[$itemCode]['name'] . '" в наличии '
. $product[$itemCode]['stock'] . ' шт. В корзине '
. ($basket['item'][$itemCode]['available'] ?? 0) . ' шт.');
}
}
useAction($basket);
}
function changeQuantityItemAction($basket, $product): void
{
$itemCode = (int)$_POST['change_quantity'];
if (!isset($basket['item'][$itemCode])) {
addError('Попытка изменения количества несуществующего товара');
return;
}
$quantity = (int)($_POST['basket_quantity'][$itemCode] ?? 0);
if ($quantity > 0) {
if ($product[$itemCode]['stock'] >= $quantity + ($basket['item'][$itemCode]['available'] ?? 0)) {
$basket = addItem($basket, $itemCode, $quantity);
} else {
$quantityNew = $product[$itemCode]['stock'] - ($basket['item'][$itemCode]['available'] ?? 0);
if ($quantityNew > 0) {
$basket = addItem($basket, $itemCode, $quantityNew);
addError(
'[' . $product[$itemCode]['code'] . '] "' . $product[$itemCode]['name'] . '" в наличии '
. $product[$itemCode]['stock'] . ' шт. В корзине '
. ($basket['item'][$itemCode]['available'] ?? 0) . ' шт.');
addError('Установлено максимальное количество товара доступное к покупке.');
} else {
addError(
'[' . $product[$itemCode]['code'] . '] "' . $product[$itemCode]['name'] . '" в наличии '
. $product[$itemCode]['stock'] . ' шт. В корзине '
. ($basket['item'][$itemCode]['available'] ?? 0) . ' шт.');
}
}
} elseif ($quantity < 0) {
if ($basket['item'][$itemCode]['quantity'] > abs($quantity)) {
$basket = addItem($basket, $itemCode, $quantity);
} else {
$quantityNew = $quantity + ($basket['item'][$itemCode]['available'] ?? 0);
if ($basket['item'][$itemCode]['quantity'] > abs($quantity) && $quantityNew !== 0) {
$basket = addItem($basket, $itemCode, $quantityNew);
} else {
$quantityNew = -($basket['item'][$itemCode]['quantity'] ?? 0) + 1;
$basket = addItem($basket, $itemCode, $quantityNew);
addError(
'[' . $product[$itemCode]['code'] . '] "' . $product[$itemCode]['name'] . '" в корзине '
. ($basket['item'][$itemCode]['available'] ?? 0) . ' шт.');
addError(
'Установлено минимальное количество товара для заказа.');
}
}
}
useAction($basket);
}
function removeItemAction($basket): void
{
$itemCode = (int)$_POST['remove_item'];
$basket = removeItem($basket, $itemCode);
useAction($basket);
}
function deleteBasketAction($basket): void
{
$basket['item'] = [];
deleteBasket($basket);
useAction($basket);
}
function useAction($basket): void
{
if (empty(countItem($basket))) {
deleteBasket($basket);
} else {
saveBasket($basket);
}
header('Location:/basket.php');
exit();
}
/**
* Controller
*/
session_start();
// товары
$product = getProduct();
// инициализация корзины
$basket = basketInit($product);
// если нажата ссылка "в корзину"
if (!empty($_POST['add_item'])) {
addItemAction($basket, $product);
}
// если нажата кнопка "изменить"
if (!empty($_POST['change_quantity'])) {
changeQuantityItemAction($basket, $product);
}
// если нажата ссылка "удалить"
if (!empty($_POST['remove_item'])) {
removeItemAction($basket);
}
// если нажата ссылка "очистить корзину"
if (!empty($_POST['delete_basket'])) {
deleteBasketAction($basket);
}
// переменные используемые в html
$basketId = getBasketId($basket);
$currency = getBasketCurrency($basket);
$totalPrice = getBasketPrice($basket, $product);
$countItem = countItem($basket);
$allQuantity = countAllQuantityItem($basket);
// добавим несуществующий товар для проверки
$code = 5000;
$product[$code] = [
'code' => $code,
'stock' => 0,
'name' => 'Несуществующий товар',
'price' => 00.00,
'currency' => 'руб',
];
/**
* View
*/
?>
<html lang="ru">
<head>
<meta charset="utf-8">
<title>Корзина</title>
<!-- CSS only -->
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"
crossorigin="anonymous">
<style>
.icon-red {
fill: red;
}
.icon-gray {
fill: gray;
}
</style>
</head>
<body>
<div class="container">
<figure class="text-end">
<blockquote class="blockquote">
<p>Простой скрипт корзины (хранение корзины на стороне клиента)</p>
</blockquote>
<figcaption class="blockquote-footer">
с использованием cookie<br />
Обсуждение скрипта на форуме
<a href="https://phpclub.ru/talk/threads/Как-обновить-количество-товара-в-корзине.87820/page-3#post-780660" target="_blank">
https://phpclub.ru/talk/threads/Как-обновить-количество-товара-в-корзине.87820/
</a>
</figcaption>
</figure>
<h2>Товары</h2>
<div class="col text-end">
<svg class="<?= !empty($totalPrice) ? ' icon-red' : ' icon-gray' ?>" width="30" height="30" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M2 4c0-.55228.44772-1 1-1h2c.48884 0 .90603.35341.98639.8356L6.18046 5H17c.5523 0 1 .44772 1 1v3.85094c0 1.26646-.9125 2.34866-2.1607 2.56266l-8.87438 1.5216a1.0211 1.0211 0 01-.1507.0143 1.0052 1.0052 0 01-.14982.0369c-.54477.0908-1.06-.2772-1.15079-.822L4.15287 5H3c-.55228 0-1-.44772-1-1zm5.32127 7.8449L6.51379 7H16v2.85094c0 .29226-.2106.54196-.4986.59136l-8.18013 1.4026zM9 16.5c0 .8284-.67157 1.5-1.5 1.5S6 17.3284 6 16.5 6.67157 15 7.5 15s1.5.6716 1.5 1.5zm7 0c0 .8284-.6716 1.5-1.5 1.5s-1.5-.6716-1.5-1.5.6716-1.5 1.5-1.5 1.5.6716 1.5 1.5z"></path>
</svg>
<?php if (!empty($totalPrice)) { ?>
<a href=""><span class="info-text">Корзина</span></a>
<span class="goods-count"><b><?= $countItem ?></b>(<?= $allQuantity ?>) шт</span>
<span class="all-price"><b><?= $totalPrice ?></b> <?= $currency ?></span>
<?php } ?>
</div>
<form id="product" action="/basket.php" method="post">
<table class="table">
<tr>
<th class="col col-1 text-end">Код</th>
<th class="col">Наименование товара</th>
<th class="col col-1 text-end">Цена</th>
<th class="col col-1 text-end">Доступно</th>
<th class="col col-1">Количество</th>
<th class="col col-1"></th>
<th class="col col-1">в корзине</th>
</tr>
<?php foreach ($product as $item) { ?>
<tr>
<td class="text-end"><?= $item['code'] ?></td>
<td><?= $item['name'] ?></td>
<td class="text-end"><?= $item['price'] ?> <?= $item['currency'] ?></td>
<td class="text-end"><?= $item['stock'] ?> шт</td>
<td>
<input class="form-control" size="3" type="number" name="quantity[<?= $item['code'] ?>]" value="1"/>
</td>
<td>
<button class="btn btn-info btn-sm" name="add_item" value="<?= $item['code'] ?>">
в корзину
</button>
</td>
<td><?= !empty($basket['item'][$item['code']]) ? $basket['item'][$item['code']]['available'] . ' шт'
: '' ?></td>
</tr>
<?php } ?>
</table>
</form>
<?php if (!empty(getError())) { ?>
<div class="alert alert-danger" role="alert">
<ul>
<li><?= implode('</li><li>', getError()) ?></li>
</ul>
</div>
<?php }
clearError(); ?>
<?php if (!empty($basket['item'])) { ?>
<h2>Корзина</h2>
<figure class="text-end">
<figcaption class="blockquote-footer">
идентификатор корзины <?= $basketId ?>
</figcaption>
</figure>
<table class="table">
<tr>
<th class="col col-1 text-end">Код</th>
<th>Наименование товара</th>
<th class="col col-1 text-end">Цена за шт</th>
<th class="col col-1 text-end">Количество</th>
<th class="col col-1 text-end">Сумма</th>
<th class="col col-1"></th>
<th class="col col-1" colspan="2">
<form action="/basket.php" method="post">
<button class="btn btn-sm btn-link" name="delete_basket" value="Y">
очистить корзину
</button>
</form>
</th>
</tr>
<form id="basket" action="/basket.php" method="post">
<?php foreach ($basket['item'] as $itemCode => $item) { ?>
<tr>
<?php if (empty($item['available'])) { ?>
<td class="text-end text-danger"><?= $itemCode ?></td>
<td class="text-danger"><?= $product[$itemCode]['name'] ?></td>
<td class="text-end text-danger" colspan="3">товар недоступен</td>
<td class="text-end" colspan="2"><a href="">подобрать замену</a></td>
<?php } else { ?>
<td class="text-end"><?= $itemCode ?></td>
<td><?= $product[$itemCode]['name'] ?></td>
<td class="text-end"><?= $product[$itemCode]['price'] ?> <?= $product[$itemCode]['currency'] ?></td>
<td class="text-end"><?= $item['quantity'] === $item['available']
? '<span class="text-success">' . $item['quantity'] . '</span>'
: '<span class="text-danger">' . $item['quantity']
. '</span> | <span class="text-success">' . $item['available'] . '</span>' ?> шт
</td>
<td class="col col-1 text-end"><?= $product[$itemCode]['price']
* $item['available'] ?> <?= $product[$itemCode]['currency'] ?></td>
<td class="col col-1">
<input class="form-control" size="3" type="number" name="basket_quantity[<?= $itemCode ?>]" value=""/>
</td>
<td class="col col-1">
<button class="btn btn-info btn-sm" name="change_quantity" value="<?= $itemCode ?>">
изменить
</button>
</td>
<?php } ?>
<td class="col col-1">
<button class="btn btn-close btn-sm" aria-label="Удалить товар" name="remove_item" value="<?= $itemCode ?>"></button>
</td>
</tr>
<?php } ?>
</table>
<div class="text-end">
<p>Количество товаров: <b><?= $countItem ?></b>(<?= $allQuantity ?>) шт</p>
<p>Сумма: <b><?= $totalPrice ?></b> <?= $currency ?></p>
</div>
<hr/>
<div class="text-end">
<button class="btn btn-success" name="add_order" value="<?= $basket['basket_id'] ?>">Оформить заказ
</button>
</div>
</form>
<h2>Задания</h2>
<ul>
<li>Вынести функции модели работы с корзиной в отдельный файл <b>basket_model_function.php</b>.</li>
<li>Разделить товары и корзину по отдельным страницам сайта (<b>product.php</b> и <b>basket.php</b>).</li>
</ul>
<?php } ?>
</div>
</body>
</html>
Привет! Благодарю! Занесение корзины в БД и вывод из БД вечером сделаю, а вот changeQuantityItem() - до сих пор не понял, как это осуществить. Буду пробовать.arhat78, написал для тебя пример работы простейшей корзины http://x90421ax.beget.tech/basket.php
1. нажал полсотни раз неожиданных результатов не увидел
По аналогии с добавлением addItem()а вот changeQuantityItem() - до сих пор не понял, как это осуществить
У меня на такую констркции function : void, :array выдаёт ошибку уже в текстовом редакторе. И раньше я не встречался с такими.... Но как я поняли из описания, не обязательно же так объявлять тип?Чем больше замечаний тем лучше. Там и на отдельные файлы разделить надо и ajax не помешает добавить, вобщем много места для творчества, хоть сутки себе удлиняй до 36 часов
Сегодня с БД уже не успеваю поработать. Код изучаю, много неизвестных мне ранее функций,смотрю их действия. Благодарю!arhat78, значит у тебя версия РНР старая. Если хочешь отстрели типизацию, тем более, что в аргументах её нет.
Ну, в ваших мордорах вроде продлили все лицензии до октября, не? Ну и если надо помочь с оплатой лицензии (и если это имеет смысл для тебя), то ты вполне в числе людей, которым я готов с этим помочьСейчас есть только один полноценный редактор под php. В наших мордорах он больше не продаётся, но есть ознакомительная версия https://www.jetbrains.com/ru-ru/phpstorm/nextversion/
Я в курсе, что нужен $_POST, с этим то и сам справлюсьНемного подправил скрипт $_GET -> $_POST
если бы я был против вопросов, я бы не сидел на этом (и других) форуме(ах)по позже сформулирую и задам, если не против
Чем корзина в сессии лучше корзины в кукисах?Это лишнее.
Лучше сессиями.