Проблем с jQuery/ajax

noxious

Registered
Понеже не разбирам от jQuery/ajax. Имам проблем с този код. Та, когато отворим прозореца на количката и сме добавили например 3 артикула, и решим да изтрием някой артикул, количката fadeOut-ва (се скрива и трябва отново да се отвори).Също при добавянето на два артикула с един и същ код, но с различен цвят/размер, скрипта го замества, а трябва да го добавя като нов продукт със същия код, но различен цвят/размер.

PHP:
<script type="text/javascript">
	$(document).ready(function() {	
		$(".form-item").submit(function(e) {
			var form_data = $(this).serialize();
			var input_cont = $(this).find('input[type=submit]');

			$.ajax({
				url: "cart_process.php",
				type: "POST",
				dataType: "json",
				data: form_data
			}).done(function(data) {
				$("#cart-info").html(data.items);
				input_cont.val('ДОБАВИ В КОШНИЦАТА');
				//alert("Добавено в кошницата!");
				if($(".shopping-cart-box").css("display") == "block") {
					$(".cart-box").trigger( "click" );
				}
			})
			e.preventDefault();
		});

		// Показване на продуктите в кошницата
		$(".cart-box").click(function(e) {
			e.preventDefault();
			$(".shopping-cart-box").fadeToggle("fast");
			$("#shopping-cart-results" ).load( "cart_process.php", {"load_cart":"1"});
		});

		// Премахване на продукти от кошницата
		$("#shopping-cart-results").on('click', 'a.remove-item', function(e) {
			e.preventDefault(); 
			var pcode = $(this).attr("data-code");
			$(this).parent().fadeOut();
			$.getJSON( "cart_process.php", {"remove_code":pcode} , function(data) {
				$("#cart-info").html(data.items);
				$(".cart-box").trigger( "click" );
			});
		});

	});
</script>

cart_process.php
PHP:
<?php
session_start();
include_once("config.php");

if(isset($_POST["code"])) {
	foreach($_POST as $key => $value) {
		$new_product[$key] = filter_var($value, FILTER_SANITIZE_STRING);
	}
	
	$statement = $mysqli_conn->prepare("SELECT name, price, discount FROM products WHERE code=? LIMIT 1");
	$statement->bind_param('s', $new_product['code']);
	$statement->execute();
	$statement->bind_result($product_name, $product_price, $product_discount);
	
	while($statement->fetch()) {
		$new_product["name"] = $product_name;
		$new_product["price"] = $product_price;
		$new_product["discount"] = $product_discount;
		
		if(isset($_SESSION["products"])) {
			if(isset($_SESSION["products"][$new_product['code']])) {
				unset($_SESSION["products"][$new_product['code']]);
			}			
		}
		$_SESSION["products"][$new_product['code']] = $new_product;
	}
	
	$total_items = count($_SESSION["products"]);
	die(json_encode(array('items' => $total_items)));

}

if(isset($_POST["load_cart"]) && $_POST["load_cart"] == 1) {

	if(isset($_SESSION["products"]) && count($_SESSION["products"]) > 0) {
		$cart_box = "<ul class=\"cart-products-loaded\">";
		$total = 0;
		foreach($_SESSION["products"] as $product) {
			
			$product_name = $product['name'];
			$product_price = $product['price'];
			$product_discount = $product['discount'];
			$percentage = $product_price*($product_discount/100);
			$product_price = $product_price-$percentage;
			$product_price = number_format($product_price, 2);
			$code = $product['code'];
			$sizes = $product['sizes'];
			$colors = $product['colors'];
			
			$cart_box .=  "<li>Код: ".$code." | ".$product_name." (Цвят: ".$colors." | Размер: ".$sizes.") - ".$product_price." ".$currency." <a href=\"#\" class=\"remove-item\" data-code=\"".$code."\">×</a></li>";
			$subtotal = $product_price;
			$total = ($total+$subtotal);
		}
		$cart_box .= "</ul>";
		$cart_box .= "<div class=\"cart-products-total\">Общо без доставката: ".sprintf("%01.2f", $total)." ".$currency."</div>";
		$cart_box .= "<p align=\"center\"><a href=\"viewcart\" class=\"btn btn-primary\" style=\"width: 100%;\" role=\"button\">ПРОДЪЛЖИ</a></p>";
		die($cart_box);
	} else {
		die("Количката е празна.");
	}
}

if(isset($_GET["remove_code"]) && isset($_SESSION["products"])) {
	$product_code = filter_var($_GET["remove_code"], FILTER_SANITIZE_STRING);

	if(isset($_SESSION["products"][$product_code])) {
		unset($_SESSION["products"][$product_code]);
	}
	
	$total_items = count($_SESSION["products"]);
	die(json_encode(array('items' => $total_items)));
}
?>
 
Проблема не е в JS-а, а в PHP-то.
PHP:
if(isset($_SESSION["products"][$new_product['code']])) {
    unset($_SESSION["products"][$new_product['code']]);
}
...
$_SESSION["products"][$new_product['code']] = $new_product;

Тук проверяваш дали съществува масив с индекс равен на кода на продукта, ако съществува - изтрива стария запис, след което създаваш нов масив със същото име за индекс.
Масивите са направени с цел индекса да бъде уникален, т.е. дори да не я правиш тази проверка, при добавяне на запис в масив с индекс, който вече съществува, то новия запис ще презапише стария, което е причината за твоя проблем.

В този си вид кода не може да поддържа два еднакви продукта, макар и с различни параметри (цвят в твоя случай).

Решение е да махнеш този код, който проверява за съществуващ продукт, а добавянето да става без задаване на индекс
PHP:
$_SESSION["products"][] = $new_product;

След което преди
PHP:
foreach($_SESSION["products"] as $product) {
Добавяш
PHP:
$uniqueProducts = array_unique($_SESSION['products'], SORT_REGULAR);
Което ще премахне напълно идентичните продукти и евентуално заменяш $_SESSION['products'] с $uniqueProducts във foreach-а.
 
Стана, но премахването на продукт от количката не работи

PHP:
// Премахване на продукти от кошницата
			$("#shopping-cart-results").on('click', 'a.remove-item', function(e) {
				e.preventDefault();
				var pcode = $(this).attr("data-code");
				$(this).parent().fadeOut();
				$.getJSON( "cart_process.php", {"remove_code":pcode}, function(data) {
					$("#cart-info").html(data.items);
					$(".cart-box").trigger( "click" );
				});
			});

или това


if(isset($_GET["remove_code"]) && isset($_SESSION["products"])) {
	$product_code = filter_var($_GET["remove_code"], FILTER_SANITIZE_STRING);

	if(isset($_SESSION["products"][$product_code])) {
		unset($_SESSION["products"][$product_code]);
	}
	
	$total_items = count($_SESSION["products"]);
	die(json_encode(array('items' => $total_items)));
}
 
PHP:
if(isset($_SESSION["products"][$product_code])) {
    unset($_SESSION["products"][$product_code]);
}
Би станало
PHP:
$productIndex = array_search($product_code, array_column($_SESSION['products'], "code"));
if ($productIndex) {
    unset($_SESSION['products'][$productIndex];
}
Но така ще изтриеш всички продукти с този код.

Решение е вместо да добавяш data-code, да промениш
PHP:
foreach($uniqueProducts as $product) {
На
PHP:
foreach($uniqueProducts as $index => $product) {
След което променяш data-code на data-index със стойност $index. Променяш си навсякъде в кода свързан с триенето на продукти, както в JS, така и PHP.
Така ще имаш индекса на всеки продукт в списъка и при желание да се изтрие, изпращаш data-index и в PHP-то става
PHP:
/*Използвам $product_code, за да разбереш за коя променлива става на въпрос,
по-удачно би било да се преименува, понеже вече не изпращаме кода, а индекс, например $productIndex*/
if (array_key_exists($product_code, $_SESSION['products']) {
    unset($_SESSION['products'][$product_code];
}
 
Супер, стана! Само когато се добавя продукт със същото име, той се показва като един както и трябва да е. Предполагам, че презаписва текущия с новия и показва един от двата, но по-горе където показва колко артикула са добавени в количката се увеличава +1, а не трябва. И ако съм добавил да речем един и същ продукт 3 пъти (еднакви данни като код, име, цвят, размер, абсолютно всичко) и след това цъкна да го изтрия, трябва да цъкна 3 пъти на него, за да се изтрие, защото 3 пъти съм го добавил, въпреки че го показва като един.

PHP:
<li><a href="#" class="cart-box" title="Виж количката"><img src="images/cart-icon.png" style="width: 16px; height: 16px;" /> <span class="badge badge-danger"><span id="cart-info"><?php 
if(isset($_SESSION["products"])) {
	echo count($_SESSION["products"]); 
} else {
	echo 0;
}
?></span></span></a></li>
 
Пробвай да замениш
PHP:
$uniqueProducts = array_unique($_SESSION['products'], SORT_REGULAR);
С
PHP:
$_SESSION['products'] = array_unique($_SESSION['products'], SORT_REGULAR);
Като евентуално замениш $uniqueProducts със $_SESION['products'] навсякъде в кода.
 
Стана това за триенето, с изключение на това горе в навигацията. То отброява +1 артикул, а не трябва. Иначе при триенето стана само с един клик :)

Код:
<li><a href="#" class="cart-box" title="Виж количката"><img src="images/cart-icon.png" style="width: 16px; height: 16px;" /> <span class="badge badge-danger"><span id="cart-info"><?php 
if(isset($_SESSION["products"])) {
        echo count($_SESSION["products"]); 
} else {
        echo 0;
}
?></span></span></a></li>

Това в същност отчита +1 артикул като се добави вече съществуващ продукт.

Edit: В същност, когато е отворен прозореца на количката и се цъкне отново на "Добави в количката" това се refresh-ва и не отброява +1 вече съществуващите, но не и иначе.
 
Все още е така

PHP:
<li><a href="#" class="cart-box" title="Виж количката"><img src="images/cart-icon.png" style="width: 16px; height: 16px;" /> <span class="badge badge-danger"><span id="cart-info"><?php 
if(isset($_SESSION["products"])) {
	echo count(array_unique($_SESSION['products'], SORT_REGULAR));
} else {
	echo 0;
}
?></span></span></a></li>

Също забелязах, че като се отвори количката и се добави съществуващия вече продукт, то го добавя още веднъж горе при брояча, а щом съществува не трябва да го добавя. А, докато не е отворена количката колкото пъти се кликне на добавяне на съществуващ продукт то си ги отчита +1 на всеки клик. И ако изпразня количката и през това време тя е отворена, и реша да кликна на този продукт 2 пъти, то го добавя 2 пъти и след това не го добавя, горе в брояча в навигацията.
 
Edit: Оправих го!
Код:
$_SESSION["products"][] = $new_product;
$_SESSION['products'] = array_unique($_SESSION['products'], SORT_REGULAR);

+1, @SVTerziev.
 

Горе