Wanneer een key al bestaat maar een value in die key nog niet, maak een nieuwe key aan met andere na
Via ajax post ik data naar een script dat weer wordt ingeladen in dat mandje.
Ik verstuur een array van het product zelf (titel, prijs e.d.) en een array van de productopties (kleur, grootte, materiaal etc). Beide arrays hebben een artikelid, deze vergelijk ik en wanneer ze gelijk zijn voeg ik ze samen.
Wanneer dat is gebeurd ziet mijn sessie er bijvoorbeeld zo uit:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Array
(
[Badmeubel trend dynasty met ronde kom 60 century oak] => Array
(
[artikelid] => 63
[product] => Badmeubel trend dynasty met ronde kom 60 century oak
[price] => 45
[picture] => cms/images/productgallerijen/badmeubel-trend-dynasty-met-ronde-kom-60-century-oak/badmeubel-trend-dynasty-met-ronde-kom-60-century-o.jpg
[quantity] => 1
[alias] => badmeubel-trend-dynasty-met-ronde-kom-60-century-oak
[catalias] => trendline-60cm
[Formaat] => 60 cm
[Kleur] => century oak
[Materiaal] => kunststof
[prodoptie] => 0
)
)
(
[Badmeubel trend dynasty met ronde kom 60 century oak] => Array
(
[artikelid] => 63
[product] => Badmeubel trend dynasty met ronde kom 60 century oak
[price] => 45
[picture] => cms/images/productgallerijen/badmeubel-trend-dynasty-met-ronde-kom-60-century-oak/badmeubel-trend-dynasty-met-ronde-kom-60-century-o.jpg
[quantity] => 1
[alias] => badmeubel-trend-dynasty-met-ronde-kom-60-century-oak
[catalias] => trendline-60cm
[Formaat] => 60 cm
[Kleur] => century oak
[Materiaal] => kunststof
[prodoptie] => 0
)
)
Nu heb ik een stuk code dat checkt of een product is gepost en dat product al bestaat. Zo nee voeg hem toe aan de array, zo ja tel de geposte quantity bij het bestaande product op.
Dat is deze code (dit staat binnen een check of een product wel is gepost en of productopties zijn gepost):
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//Stop de productnaam in de variabele $prod
$prod = $thisProduct['product'];
//Als er nog geen sessie bestaat, maak deze dan aan
if (!isset($_SESSION['cart'])) {
//en maak er gelijk een array van
$_SESSION['cart'] = [];
}
//Als de productnaam nog niet voorkomt in de sessie, voeg deze dan toe inclusief de overige array waarden
if (!isset($_SESSION['cart'][$prod])) {
$_SESSION['cart'][$prod] = $thisProduct;
}
//Als deze wel voorkomt voeg hem dan niet toe maar tel de quantity op bij het bestaande product
else {
$_SESSION['cart'][$prod]['quantity'] += $thisProduct['quantity'];
}
$prod = $thisProduct['product'];
//Als er nog geen sessie bestaat, maak deze dan aan
if (!isset($_SESSION['cart'])) {
//en maak er gelijk een array van
$_SESSION['cart'] = [];
}
//Als de productnaam nog niet voorkomt in de sessie, voeg deze dan toe inclusief de overige array waarden
if (!isset($_SESSION['cart'][$prod])) {
$_SESSION['cart'][$prod] = $thisProduct;
}
//Als deze wel voorkomt voeg hem dan niet toe maar tel de quantity op bij het bestaande product
else {
$_SESSION['cart'][$prod]['quantity'] += $thisProduct['quantity'];
}
Dat werkt prima. Maar stel dat een persoon hetzelfde product twee keer toevoegd, met verschillende opties. Bijvoorbeeld: product a in kleur geel en product a in kleur blauw, dan vervangt hij de opties en telt de quantity bij elkaar op. Uiteindelijk staat er dus maar één product in het mandje.
Ik wil graag dat er een nieuw product wordt toegevoegd, aangezien mijn script checkt op productnaam en de keys in de array ook de productnamen zijn, zal ik hier misschien een nummer achter moeten zetten. Bijvoorbeeld Badmeubel trend dynasty met ronde kom 60 century oak | 1. En die | 1 er later weer uitfilteren zodat dat niet in de productnamen is te zien door een persoon.
Hoe kan ik dat het beste aanpakken?
Ik post nu prodvarray, hierin zit bijvoorbeeld het volgende:
Code (php)
1
prodvarray: ["\u20ac 55 - ","Formaat: 80 cm","Kleur: grey","Materiaal: graniet","artikelid: 64","prodoptie: 2"]
Dit explode ik tot een bruikbare array en voeg toe aan de sessie aan het juiste product via de volgende code:
(deze code staat samen met bovenstaande code binnen: if($_POST['product'] && $_POST['prodvarray']){ bovenstaande en onderstaande code }
)
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
$postedprodopts = $_POST['prodvarray'];
$postedoptsdecoded = json_decode($postedprodopts);
// Maak de $prodoptiearray array aan
$prodoptiearray = array();
foreach($postedoptsdecoded as $key1 => $opts){
if(strpos($opts, ':')){
$optsexplod = explode(':', $opts);
// Stop de geexplodeerde waardes in de $prodoptiearray array
$prodoptiearray[$optsexplod[0]] = $optsexplod[1];
//$thisProduct[$optsexplod[0]] = $optsexplod[1];
}
}
if(!empty($_SESSION['cart'])){
foreach($_SESSION['cart'] as $cartproductopts){
// Check of het artikelid in de sessiearray gelijk is aan het artikelid wat wordt meegestuurd met de opties,
// zo ja voeg de optie toe aan de sessie array
if($cartproductopts['artikelid'] == $prodoptiearray['artikelid']){
// Anders als de productnaam wel voorkomt maar de optie nog niet
if($_SESSION['cart'][$cartproductopts['product']]['prodoptie'] !== $prodoptiearray['prodoptie']){
//$_SESSION['cart'][] = $prod.'1';
echo 'het product bestaat al maar de optie nog niet';
//$_SESSION['cart'][$cartproductopts['product']] = $_SESSION['cart'][$cartproductopts['product']];
}else{
}
foreach($prodoptiearray as $key2 => $merged){
$_SESSION['cart'][$cartproductopts['product']][$key2] = $merged;
//$prodoptiearray[$key2] = $_SESSION['cart'][$cartproductopts['product']][$key2];
}
}
}
}
$postedoptsdecoded = json_decode($postedprodopts);
// Maak de $prodoptiearray array aan
$prodoptiearray = array();
foreach($postedoptsdecoded as $key1 => $opts){
if(strpos($opts, ':')){
$optsexplod = explode(':', $opts);
// Stop de geexplodeerde waardes in de $prodoptiearray array
$prodoptiearray[$optsexplod[0]] = $optsexplod[1];
//$thisProduct[$optsexplod[0]] = $optsexplod[1];
}
}
if(!empty($_SESSION['cart'])){
foreach($_SESSION['cart'] as $cartproductopts){
// Check of het artikelid in de sessiearray gelijk is aan het artikelid wat wordt meegestuurd met de opties,
// zo ja voeg de optie toe aan de sessie array
if($cartproductopts['artikelid'] == $prodoptiearray['artikelid']){
// Anders als de productnaam wel voorkomt maar de optie nog niet
if($_SESSION['cart'][$cartproductopts['product']]['prodoptie'] !== $prodoptiearray['prodoptie']){
//$_SESSION['cart'][] = $prod.'1';
echo 'het product bestaat al maar de optie nog niet';
//$_SESSION['cart'][$cartproductopts['product']] = $_SESSION['cart'][$cartproductopts['product']];
}else{
}
foreach($prodoptiearray as $key2 => $merged){
$_SESSION['cart'][$cartproductopts['product']][$key2] = $merged;
//$prodoptiearray[$key2] = $_SESSION['cart'][$cartproductopts['product']][$key2];
}
}
}
}
Daarin doe ik het volgende:
Code (php)
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
// Anders als de productnaam wel voorkomt maar de optie nog niet
if($_SESSION['cart'][$cartproductopts['product']]['prodoptie'] !== $prodoptiearray['prodoptie']){
//$_SESSION['cart'][] = $prod.'1';
echo 'het product bestaat al maar de optie nog niet';
//$_SESSION['cart'][$cartproductopts['product']] = $_SESSION['cart'][$cartproductopts['product']];
}else{
}
if($_SESSION['cart'][$cartproductopts['product']]['prodoptie'] !== $prodoptiearray['prodoptie']){
//$_SESSION['cart'][] = $prod.'1';
echo 'het product bestaat al maar de optie nog niet';
//$_SESSION['cart'][$cartproductopts['product']] = $_SESSION['cart'][$cartproductopts['product']];
}else{
}
Oftewel, check of het product al in de sessie bestaat maar de prodoptie (een cijfer waar de gekozen optie aan is gekoppeld) nog niet. De echo laat zich al zien op het juiste moment, wanneer ik voor het eerst een product toevoeg zie ik de echo, als ik daarna hetzelfde product toevoeg met dezelfde optie niet meer, maar voeg ik hetzelfde product toe met een andere optie (prodoptie) dan zie ik hem weer wel.
Hier loop ik alleen vast.. wat kan ik het beste doen?
Onder al deze code staat een loop die de sessie loopt en giet in een mandoverzicht.
Als ik dit soort dingen zie:
Dan krijg ik al het idee dat er ergens een verkeerde afslag is genomen. De naam van een product zou het product niet moeten identificeren. Dit zou dan ook nooit als (identificerende) key in een array gebruikt moeten worden.
Al deze informatie in een sessie opslaan snijdt ook geen hout want al deze informatie is afleidbaar uit het id(entificerend attribuut). Die data hoef je dus ook absoluut niet in een sessie te proppen.
Een sessie is niet bedoeld als een rijdend archief.
Nu terug naar je probleem. Zoals gezegd hangt hoe je dit aanpakt heel erg af van je productconfiguratie. Als je dit niet handig hebt ingericht begin je ongeveer nu stront te krijgen :).
Stel je hebt een product: een lamp genaamd Hennie. Hennie heeft twee uitvoeringen: een gele variant en een blauwe variant. Deze laatste varianten zijn concrete (fysieke) producten. De lamp "Hennie" is geen concreet product want het vertelt je niet of Hennie geel of blauw is.
Idealiter heb je dus een identificerend attribuut voor een gele Hennie en een blauwe Hennie en idealiter zijn dit dus je product-id's zodat je kunt zeggen mja doe mij maar 1 x een gele Hennie en 2 x een blauwe Hennie anders wordt het mogelijk behoorlijk complex allemaal.
Het enige wat je in je sessie komt te staan is een array met product => aantal, dus zoiets:
De rest van deze productinformatie trek je uit de database als je een boodschappenmand of checkout wilt weergeven.
Dus of ik kon alles opnieuw doen, of de bestaande code aanpassen, ik heb voor dat laatste gekozen.
Wat jij zegt is beter maar kan helaas niet aangezien ik bepaalde restricties heb binnen het CMS wat ik gebruik.
Je database is het fundament van je applicatie. Als je hier allerlei dingen op wilt bouwen moet het fundament wel geschikt zijn / voldoende ruimte hiervoor bieden.
Opmerkelijk dat je het CMS noemt waarbinnen je werkt / moet werken. Er is vantevoren toch wel een soort van haalbaarheidsonderzoekje gehouden waarbij ook is onderzocht hoe het productgedeelte ingericht zou moeten worden? En verschillende productuitvoeringen zijn daarbij helemaal niet zo ondenkbaar, ik zou haast zeggen, hoe is het mogelijk dat dat over het hoofd lijkt te zijn gezien?
EDIT: misschien is dit nog op te lossen door hier dus nog een laag bovenop te bouwen waarbij je dus wel eerdergenoemde SKU's (concrete producten) hebt.
Gewijzigd op 19/04/2018 14:52:30 door Thomas van den Heuvel
Ik heb nu de volgende code:
Code (php)
1
2
3
4
5
6
2
3
4
5
6
if(!in_array($prodoptiearray['prodoptie'], array_column($_SESSION['cart'], 'prodoptie'))){
echo 'het product bestaat al maar de optie nog niet';
$_SESSION['cart'][$cartproductopts['product'].rand()] = $_SESSION['cart'][$cartproductopts['product']];
}else{
}
echo 'het product bestaat al maar de optie nog niet';
$_SESSION['cart'][$cartproductopts['product'].rand()] = $_SESSION['cart'][$cartproductopts['product']];
}else{
}
Deze voegt een product nog een keer toe met een random getal in de naam. Dit geeft me de volgende array:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Array
(
[Badmeubel trend dynasty met ronde kom 60 century oak844298890] => Array
(
[artikelid] => 63
[product] => Badmeubel trend dynasty met ronde kom 60 century oak
[price] => 45
[picture] => cms/images/productgallerijen/badmeubel-trend-dynasty-met-ronde-kom-60-century-oak/badmeubel-trend-dynasty-met-ronde-kom-60-century-o.jpg
[quantity] => 1
[alias] => badmeubel-trend-dynasty-met-ronde-kom-60-century-oak
[catalias] => trendline-60cm
)
[Badmeubel trend dynasty met ronde kom 60 century oak1364175603] => Array
(
[artikelid] => 63
[product] => Badmeubel trend dynasty met ronde kom 60 century oak
[price] => 45
[picture] => cms/images/productgallerijen/badmeubel-trend-dynasty-met-ronde-kom-60-century-oak/badmeubel-trend-dynasty-met-ronde-kom-60-century-o.jpg
[quantity] => 2
[alias] => badmeubel-trend-dynasty-met-ronde-kom-60-century-oak
[catalias] => trendline-60cm
[Formaat] => 60 cm
[Kleur] => century oak
[Materiaal] => kunststof
[prodoptie] => 063
)
)
(
[Badmeubel trend dynasty met ronde kom 60 century oak844298890] => Array
(
[artikelid] => 63
[product] => Badmeubel trend dynasty met ronde kom 60 century oak
[price] => 45
[picture] => cms/images/productgallerijen/badmeubel-trend-dynasty-met-ronde-kom-60-century-oak/badmeubel-trend-dynasty-met-ronde-kom-60-century-o.jpg
[quantity] => 1
[alias] => badmeubel-trend-dynasty-met-ronde-kom-60-century-oak
[catalias] => trendline-60cm
)
[Badmeubel trend dynasty met ronde kom 60 century oak1364175603] => Array
(
[artikelid] => 63
[product] => Badmeubel trend dynasty met ronde kom 60 century oak
[price] => 45
[picture] => cms/images/productgallerijen/badmeubel-trend-dynasty-met-ronde-kom-60-century-oak/badmeubel-trend-dynasty-met-ronde-kom-60-century-o.jpg
[quantity] => 2
[alias] => badmeubel-trend-dynasty-met-ronde-kom-60-century-oak
[catalias] => trendline-60cm
[Formaat] => 60 cm
[Kleur] => century oak
[Materiaal] => kunststof
[prodoptie] => 063
)
)
Hij voegt hem dus los toe. Het enige probleem is dat .rand() random is en de volledige keynaam (productnaam + random getal) nergens aan te roepen is. Nu kan ik dus niet checken bij welke key hij de quantity moet optellen, dat doet hij nu altijd maar bij 1 product.
Ik moet dus van dat random getal iets bruikbaars maken, zodat dit overal aan te roepen is..
Dat ik ipv dit:
Zoiets kan doen:
En voor het verwijderen dit:
Code (php)
1
2
3
4
5
6
2
3
4
5
6
$deleteprod = $_POST['remove'];
//Als het geposte product vanuit het remove script bestaat in de array, verwijder deze dan
if(array_key_exists($deleteprod, $_SESSION['cart'])){
unset($_SESSION['cart'][$deleteprod].$getal);
}
//Als het geposte product vanuit het remove script bestaat in de array, verwijder deze dan
if(array_key_exists($deleteprod, $_SESSION['cart'])){
unset($_SESSION['cart'][$deleteprod].$getal);
}
Gewijzigd op 19/04/2018 15:33:07 door Snelle Jaap
Snelle Jaap op 19/04/2018 15:31:09:
Het enige probleem is dat .rand() random is en de volledige keynaam (productnaam + random getal) nergens aan te roepen is.
Dan zoek je het onderscheidende kenmerk dat een unieke key oplevert: product-id + optie-id bijvoorbeeld.
Je lijkt een vorm van een EAV-opzet (entity-attribute-value) te gebruiken. Eventueel kun je er daarvoor dan ook nog de unieke waarde toevoegen aan de key, bijvoorbeeld voor twee verschillende kleuren:
FooBar stoel + kleur + zwart
naast:
FooBar stoel + kleur + wit
Gewijzigd op 19/04/2018 15:55:30 door Ward van der Put
Ward van der Put op 19/04/2018 15:54:42:
Dan zoek je het onderscheidende kenmerk dat een unieke key oplevert: product-id + optie-id bijvoorbeeld.
Je lijkt een vorm van een EAV-opzet (entity-attribute-value) te gebruiken. Eventueel kun je er daarvoor dan ook nog de unieke waarde toevoegen aan de key, bijvoorbeeld voor twee verschillende kleuren:
FooBar stoel + kleur + zwart
naast:
FooBar stoel + kleur + wit
Snelle Jaap op 19/04/2018 15:31:09:
Het enige probleem is dat .rand() random is en de volledige keynaam (productnaam + random getal) nergens aan te roepen is.
Dan zoek je het onderscheidende kenmerk dat een unieke key oplevert: product-id + optie-id bijvoorbeeld.
Je lijkt een vorm van een EAV-opzet (entity-attribute-value) te gebruiken. Eventueel kun je er daarvoor dan ook nog de unieke waarde toevoegen aan de key, bijvoorbeeld voor twee verschillende kleuren:
FooBar stoel + kleur + zwart
naast:
FooBar stoel + kleur + wit
Slim, thanks ik heb het werkend gekregen!
Via jquery vul ik een hidden input veld met het optieid en het artikelid gecombineerd (altijd uniek) deze post ik direct in mijn sessie array als prodoptie, deze heb ik vervolgens achter alle code met productnamen als keys geplakt en dat werkt :)
Thomas van den Heuvel op 19/04/2018 14:07:01:
Het enige wat je in je sessie komt te staan is een array met product => aantal
Ik zou de inhoud van het winkelmandje zelfs helemaal niet in een sessie zetten, maar serverside opslaan in de database. Dat heeft als voordeel dat je op je smartphone kunt beginnen met winkelen en vervolgens afrekenen op je laptop. Of andersom. Of tussendoor even je browser laten crashen. :-)
Nadeel daarvan is dat je ingelogd moet zijn om iets in je winkelmandje te doen, maar dat zou je nog kunnen ondervangen door voor niet-ingelogde gebruikers het mandje te koppelen aan het sessie-id. Wanneer de gebruiker inlogt, kun je dan alsnog de koppeling met het userid maken.
(En je moet af en toe even alle oude winkelmandjes weggooien, want die blijven staan als iemand besluit om de kussentjes toch maar bij de Bijenkorf te gaan kopen.)
$_SESSION kan ook best een implementatie hebben die van de database gebruik maakt. Dus dat is een optie die ik zeker niet op voorhand uitsluit. Maar dit is verder abstractie, aan de "buitenkant" gebruik je gewoon $_SESSION als voorheen. Als het maar op een manier geregeld is.
Gewijzigd op 19/04/2018 19:30:36 door Thomas van den Heuvel
Kan inderdaad maar deze website heeft geen login-systeem. Dus misschien wat voor in de toekomst bij een andere site.