Wanneer een key al bestaat maar een value in die key nog niet, maak een nieuwe key aan met andere na

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Snelle Jaap

Snelle Jaap

19/04/2018 12:39:16
Quote Anchor link
Ik heb een winkelmand waar producten aan toegevoegd kunnen worden.

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)
PHP script in nieuw venster Selecteer het PHP script
1
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
        )

)


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)
PHP script in nieuw venster Selecteer het PHP script
1
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'];
}


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)
PHP script in nieuw venster Selecteer het PHP script
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)
PHP script in nieuw venster Selecteer het PHP script
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
$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];
            }
        }
    }
}




Daarin doe ik het volgende:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
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{

}


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.
 
PHP hulp

PHP hulp

23/04/2024 20:20:25
 
Adoptive Solution

Adoptive Solution

19/04/2018 13:35:13
Quote Anchor link
Voor dat soort vraagstukken hebben ze SKU bedacht

https://www.marketingtermen.nl/begrip/sku
 
Thomas van den Heuvel

Thomas van den Heuvel

19/04/2018 14:07:01
Quote Anchor link
Los van hoe je dit implementeert, je oplossing wordt voor een groot deel bepaald door je productconfiguratie.

Als ik dit soort dingen zie:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
Array
(
    [Badmeubel trend dynasty met ronde kom 60 century oak] => Array
        (
            ...
        )

)

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:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
array(
    11 => 1, // 1 x gele Hennie (id 11)
    88 => 2, // 2 x blauwe Hennie (id 88)
)

De rest van deze productinformatie trek je uit de database als je een boodschappenmand of checkout wilt weergeven.
 
Snelle Jaap

Snelle Jaap

19/04/2018 14:34:48
Quote Anchor link
Ik ben het met je eens dat het op deze manier niet optimaal is. Helaas bleek achteraf pas dat die productopties noodzakelijk waren toen de rest van de code al klaar was.

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.
 
Thomas van den Heuvel

Thomas van den Heuvel

19/04/2018 14:51:01
Quote Anchor link
Het is jouw verantwoordelijkheid om te beslissen of je wilt voortborduren op dit (m.i.) slecht ontwerp, en de vraag is ook of je niet steeds vaster komt te staan in de modder. Ik zou daar dan ook bijval voor vragen of op zijn minst overleggen of en hoe verder te gaan.

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
 
Snelle Jaap

Snelle Jaap

19/04/2018 15:31:09
Quote Anchor link
Klopt maar ik weet zeker dat het zo moet lukken. Volgens mij ben ik er bijna.

Ik heb nu de volgende code:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
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{

}


Deze voegt een product nog een keer toe met een random getal in de naam. Dit geeft me de volgende array:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
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
        )

)


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:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
$_SESSION['cart'][$prod]['quantity'] += $thisProduct['quantity'];


Zoiets kan doen:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
$_SESSION['cart'][$prod.$getal]['quantity'] += $thisProduct['quantity'];


En voor het verwijderen dit:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
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);
}
Gewijzigd op 19/04/2018 15:33:07 door Snelle Jaap
 
Ward van der Put
Moderator

Ward van der Put

19/04/2018 15:54:42
Quote Anchor link
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
 
Snelle Jaap

Snelle Jaap

19/04/2018 16:30:01
Quote Anchor link
Ward van der Put op 19/04/2018 15:54:42:
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 :)
 
Willem vp

Willem vp

19/04/2018 17:52:54
Quote Anchor link
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.)
 
Thomas van den Heuvel

Thomas van den Heuvel

19/04/2018 19:29:03
Quote Anchor link
Wat de sessie precies is -en hoe je het vervolgens hierbinnen structureert, dit hoeft niet per se een array te zijn- ligt niet vast, ik doelde alleen op de minimale *relevante* hoeveelheid informatie die je bij hoeft te houden, dit hoeft lang niet al die zooi te zijn die eerder voorbij kwam, dat is allemaal redundant en nergens voor nodig. Maakt de boel ook onnodig complexer.

$_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
 
Snelle Jaap

Snelle Jaap

20/04/2018 12:05:02
Quote Anchor link
Kan inderdaad maar deze website heeft geen login-systeem. Dus misschien wat voor in de toekomst bij een andere site.
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.