Ik heb een aantal blogartikelen geschreven over het zelf maken van een abandoned cart pop-up. Eén gebaseerd op Elementor, de ander gebaseerd op If-So. Wat ik in deze ‘zelf maak pop-ups’ echter niet deed was het tonen van de inhoud van die abandoned cart. Een klant van mij, die het artikel had gelezen, vroeg mij of het mogelijk was om ook de producten in zo’n pop-up te tonen.
En dat is best een uitdaging. Tenminste, wanneer je dat wilt doen zonder te hoeven coderen. Op het moment dat ik dit schrijf heeft WooCommerce een enorme hoeveelheid shortcodes om allerlei informatie uit WooCommerce in pagina’s en posts te kunnen tonen, maar een code om de producten in de winkelwagen te tonen ontbreekt.
De shortcode [ woocommerce_cart] kan hier niet voor gebruikt worden: Die toont de inhoud van de complete checkout pagina, niet van alleen de producten.
Dus besloot ik er één zelf in elkaar te knutselen.
Wat wil ik bereiken
Voor mijn doel, moet het mogelijk zijn het aantal resultaten te beperken. Want wanneer ik een ‘Abandoned Cart pop-up’ wil tonen, dan schieten we er niet veel mee op om honderden producten te tonen, wanneer tenminste de winkelwagen zo vol zou zijn. Daarom wil ik de mogelijkheid hebben om slechts een aantal producten uit de winkelwagen te tonen.
Die producten wil ik in een tabel laten zien, waarbij een afbeelding van het product, en de titel van het product worden getoond.
Bovendien wil ik de titel en de afbeelding gelinkt hebben naar het product zelf.
Deze producten wil ik tonen in een matrix, waarvan ik zelf het aantal kolommen en rijen kan bepalen.
Bovendien wil ik mee kunnen geven, of de links wel of niet in een nieuwe tab moeten worden geopend.
En omdat ik bij een lege winkelwagen ook iets wil kunnen zien, wordt in dat geval een tekst getoond.
Het resultaat zou een shortcode kunnen worden, die er ongeveer als volgt uit zou zien.
[cartgrid newtab="true" max_items="6" rows="2" cols="3" empty="Winkelwagen is leeg"]
Code
Hieronder zie je de code, die we straks per onderdeel gaan bespreken. In de code is een aantal constructies opgenomen, die voor wat betreft de voorbeelden die je in eerdere snippets hebt aangetroffen nieuw zijn. Vandaar dat de code wat uitvoeriger besproken wordt.
Deze constructies richten zich op code compacter en efficienter te maken.
function cart_products_grid_shortcode($atts) {
// Set up shortcode attributes with defaults
$atts = shortcode_atts(
array(
'new_tab' => 'false', // Open link in the same tab by default
'max_items' => 4, // Default max items shown
'rows' => 2, // Default 2 rows
'cols' => 2, // Default 2 columns
'empty' => 'No products in the cart', // Default empty cart message
),
$atts,
'cartgrid'
);
// Check if WooCommerce is active and the cart is not empty
if (!class_exists('WooCommerce') || WC()->cart->is_empty()) {
return "<p>{$atts['empty']}</p>";
}
// Parse attributes
$max_items = intval($atts['max_items']);
$new_tab = filter_var($atts['new_tab'], FILTER_VALIDATE_BOOLEAN) ? ' target="_blank"' : '';
$rows = intval($atts['rows']);
$cols = intval($atts['cols']);
$max_count = min($max_items, $rows * $cols, WC()->cart->get_cart_contents_count()); // Limit items based on max_items or grid size
// Get cart items
$cart_items = WC()->cart->get_cart();
$count = 0;
// Start building the grid table HTML
$output = '<table class="cart-products-grid" style="width: 100%; text-align: center;">';
for ($r = 0; $r < $rows; $r++) {
$output .= '<tr>';
for ($c = 0; $c < $cols; $c++) {
if ($count >= $max_count) {
// If max items reached, fill empty cells and break
$output .= '<td></td>';
continue;
}
// Get product information for each cart item
$cart_item = array_shift($cart_items); // Get and remove the first item
$product = $cart_item['data'];
$product_id = $product->get_id();
$product_name = $product->get_name();
$product_link = get_permalink($product_id);
$product_image = $product->get_image('thumbnail');
// Cell content: product image and title link
$output .= '<td style="padding: 10px; vertical-align: top;">';
$output .= '<a href="' . esc_url($product_link) . '"' . $new_tab . '>' . $product_image . '</a><br>';
$output .= '<a href="' . esc_url($product_link) . '"' . $new_tab . '>' . esc_html($product_name) . '</a>';
$output .= '</td>';
$count++;
}
$output .= '</tr>';
}
$output .= '</table>';
return $output;
}
// Register the shortcode
add_shortcode('cartgrid', 'cart_products_grid_shortcode');
Initialisatie
Wanneer je al meer code voor shortcodes gezien hebt, dan zal regel 3-13 je bekend voorkomen, zo niet, lees dan de toelichting op mijn ‘coupon code’ shortcode.
Het volgende wat we moeten controleren is natuurlijk of WooCommerce is geïnstalleerd. Dat doen we in de regels 15-18, bovendien controleren we hier gelijk of de winkelwagen gevuld is. Is dat niet het geval, dan geven we de boodschap terug, dat de winkelwagen inderdaad niet gevuld is.
Om de code wat makkelijker te maken in het gebruik, kennen we de attributen in $attr toe aan afzonderlijke variabelen. De meeste zaken spreken voor zich, behalve misschien de variabele $new_tab in regel 22.
$new_tab = filter_var($atts['new_tab'], FILTER_VALIDATE_BOOLEAN) ? ' target="_blank"' : '';
De tertiare operator ? :
In PHP zijn er vele mogelijkheden om een logische (boolean) waarde weer te geven . Voor ‘waar’ kan je de volgende waarden gebruiken:
- true
- ’true’
- 1
- ‘1’
- Elke willekeurige string, die niet één van waarden voor ‘onwaar’ is.
- Elke bewerking die één van bovenstaande waarden als resultaat heeft.
Voor ‘onwaar’
- false
- ‘false’
- 0
- ‘0’
- “” (een ‘lege string’)
- Elke bewerking die één van de bovenstaande waarden als resultaat heeft.
De constructie zoals hierboven in de code is weergegeven zal ongeacht de waarde van het $atts[‘new_tab’] een boolean (logische) true of false teruggeven.
Wat je hier ziet is een zogenaamde ’tertiare operator’. De algemene vorm is
$variabele = $logische_voorwaarde ? $indien_waar : $indien_niet_waar
Dus een korte manier om de volgende code te schrijven :
if ($logische_voorwaarde) {
$variabele = $indien_waar;
} else {
$variabele = $indien_niet_waar;
}
Dus in mensentaal, wordt er hier gezegd, wanneer het attribuut ‘new_tab’ waar is, dan moet de variabele ‘new_tab’ de waarde ‘ target=”_blank”‘ krijgen, anders de waarde van een lege string (”).
Ook regel 25 verdient wat speciale aandacht:
$max_count = min($max_items, $rows * $cols, WC()->cart->get_cart_contents_count());
We willen een beperkt aantal producten in de matrix tonen. Maar de beperking wordt bepaald door een drietal factoren:
- Het aantal producten daadwerkelijk in de winkelwagen
- Het resultaat van de rijen maal de kolommen, dus het aantal cellen in de tabel.
- Het maximaal aantal items zoals meegegeven aan de shortcode
Aangezien we niet meer producten kunnen tonen, dan we daadwerkelijk hebben, willen eerst weten welke van deze aantallen het kleinst is.
De function ‘min()’ kan een onbeperkt aantal parameters meekrijgen, en geeft de laagste waarde terug.
En… Action!
Nu we alle variabelen netjes waarden hebben gegeven halen we de daadwerkelijke cart op. in regel 29.
De variabele $count gaan we gebruiken om ervoor te zorgen, dat we niet meer dan het maximum aantal producten (zie boven de bespreking van $max_count) in de winkelwagen tonen.
Het eindresultaat is een HTML string, die we stukje bij beetje construeren in de variabele $output.
Laten we eens naar de openings HTML in de variabele output kijken:
<table class="cart-products-grid" style="width: 100%; text-align: center;">
We geven de tabel een class om via CSS de tabel verder vorm te kunnen geven. Wanneer je in je thema al specifieke tabellen opmaak gebruikt, zou je er ook voor kunnen kiezen om de class als parameter mee te geven. Dat is één van de optimalisaties die je eventueel aan deze code toe zou kunnen voegen.
In regel 34 beginnen we met een geneste loop. In de buitenste loop, die in de variabele $r wordt bijgehouden.
Omdat iedere regel in een tabel met ‘<tr>’ moet beginnen, is het goed om bij iedere iteratie van de buitenste loop deze code aan de output variabele toe te voegen.
De volgende stap die we nemen is de afzonderlijke cellen aan te maken. Hier lopen we echter tegen één situatie aan. Omdat de cellen in een matrix staan, is het altijd mogelijk dat we meer tabel cellen hebben, dan producten in de winkelwagen. Bij een matrix van 2 rijen van 3 kolommen, en vijf producten, hebben we meer cellen, dan producten.
Daarom bouwen we een kleine test in. Op het moment dat we geen producten meer hebben, maar er nog wel ‘cellen over zijn’ willen we alleen de opening- en sluit tag van die cel toevoegen. Dat gebeurt in regels 37-41.
Speciale aandacht verdient regel 40.
continue;
Wanneer in PHP het continue commando wordt gebruikt, verlaat de pointer het codeblock waarin ‘continue’ voorkomt, en begint aan het begin van het omliggende codeblock.
Dus in ons geval, gaat hij van regel 40 terug naar regel 34, en slaat de overige code in het block over.
Door arrays wandelen
Er zijn twee manieren om door een array heen te lopen. In eerdere codevoorbeelden heb ik gebruik gemaakt van de ‘foreach’ loop. Die loop zou er ongeveer als volgt uit zien
foreach ($cart_items as $cart_item) {
//doe iets met $cart_item
}
De code in regel 44 heeft hetzelfde resultaat, maar toch gebeurt er iets heel anders
$cart_item = array_shift($cart_items);
In het eerste voorbeeld wordt het $cart_items array stap voor stap doorlopen. En aan het einde van al die stappen, heb je nog steeds het array om er nog iets anders mee te doen.
In het tweede voorbeeld wordt het eerste element van de array in de variabele $cart_item geplaatst, en wordt deze waarde verwijderd van het array. Of met andere woorden, het array is een elementje kleiner geworden, en aan het einde van de omliggende for-loop, is het array leeg.
Omdat we het array niet meer nodig hebben (bedenk het is een kopie van de cart, niet de cart zelf) is dit de betere manier om dit te doen.
De rest van de code spreekt eigenlijk voor zich.
Uitbreiden en optimaliseren
Deze snippet is een voorbeeld hoe je de producten in je winkelwagen makkelijk via een shortcode kan tonen. En als zodanig is het al een behoorlijk lang verhaal geworden.
Je kunt deze code nog op een aantal manieren optimaliseren. Maar dan zou bij de bespreking van deze plugin ook een halve HTML en CSS handleiding geschreven moeten worden.
Enkele zaken waar je aan kunt denken:
- Maak de code meer responsive. Wanneer je CSS Flexbox zou gebruiken in plaats van een HTML tabel, is je code beter toepasbaar op mobiele devices. Aangezien in de praktijk -je toont waarschijnlijk het resultaat in een pop-up- je waarschijnlijk niet meer dan 3 kolommen naast elkaar zal willen tonen, zal dit geen punt zijn.
- Maak het getoonde product meer configureerbaar. In ons voorbeeld laat ik de titel en de afbeelding zien, maar je zal nog meer willen laten zien. Zoals bijvoorbeeld de prijs, het aantal, de totaalprijs. En misschien wil je onder aan de producten de totale prijs voor de producten laten zien.
- Voeg meer parameters toe voor de opmaak. In het voorbeeld ga ik ervan uit, dat je de opmaak in CSS doet voor de ‘cart-product-grid’ class. Maar je zou de opmaak ook via meegegeven parameters kunnen doen.
Maar al met al is deze plugin een nuttige aanvulling op jouw persoonlijke WooCommerce conversie toolkit.