Elementor is natuurlijk een prachtige page- en theme builder, maar is toch een aantal kleine uitdagingen waar je af en toe tegenaan kan lopen.
Zelf liep ik zo een tijdje geleden dus tegen een aardige uitdaging aan. Ik moest een numeriek custom field uit een post type gebruiken om het aantal sterren in de Elementor ‘Aantal Sterren’ widget in te stellen.
Een meer uitgebreide omschrijving van de daadwerkelijke uitdaging vind je in het blogartikel hierover.
Hier vind je ook de uiteindelijke code, zoals ik deze in de cursus gebruik.
Maar laat ik eens stap voor stap beschrijven, wat ik nu eigenlijk doe in deze code.
<?php
add_shortcode('star_rating', 'wxp_get_star_rating');
function wxp_get_star_rating($args) {
$atts = shortcode_atts(
array(
'default' => 1,
'posttype' => false
), $args);
}
De code hierboven is eigenlijk de ‘boilerplate’ code voor het definiëren van een shortcode. We vertellen dat de shortcode ‘star_rating’ de functie ‘wxp_get_star_rating’ aan moet roepen en we vertellen alvast, dat de parameters ‘default’ en ‘posttype’ alvast bepaalde waarden hebben.
Verder doet de code nog helemaal niets.
Om deze shortcode te laten werken, hebben we informatie nodig over de post die op dat moment ‘actief’ is.
WordPress heeft hiervoor een globale variabele, $post. Een globale variabele is een variabele die overal binnen WordPress (of eigenlijk binnen PHP) toegankelijk is. Om verwarring te voorkomen is het echter nodig duidelijk te maken over welke variabele we het hebben.
Kijk eens naar onderstaand voorbeeld
<?php
$hallo = 'Hallo';
function say_hello() {
echo $hallo; //geen output
}
Hierboven zie je een heel simpel voorbeeld. Omdat $hallo gedefinieerd is buiten functies om, is $hallo een globale variabele.
Wanneer ik binnen een functie echter $hallo wil tonen (door ‘echo’ aan te roepen) gaat het fout. Binnen de functie is ‘$hallo’ namelijk onbekend. Variabelen binnen een functie hebben een lokale ‘scope’.
Willen we toch de waarde van een globale variabele gebruiken, moeten we PHP expliciet vertellen, dat we dit willen, door het sleutelwoord ‘global’.
Dus
<?php
$hallo = 'Hallo';
function say_hello() {
global $hallo;
echo $hallo; // Output is 'Hallo'
}
We vertellen hier dus, dat we de globale variabele $hallo willen gebruiken.
Dat doen we dus ook met de ‘$post’ variabele.
Dat maakt de code nu dus
<?php
add_shortcode('star_rating', 'wxp_get_star_rating');
function wxp_get_star_rating($args) {
global $post;
$atts = shortcode_atts(
array(
'default' => 1,
'posttype' => false
), $args);
}
Je ziet, dat in regel 5 het statement ‘global $post;’ is toegevoegd. De code doet nog steeds niet veel anders.
Hoewel je het ‘global $var;‘ statement in principe overal binnen de functie kan schrijven, zolang je het maar doet ,voor je de variabele ook daadwerkelijk gebruikt, is het een goede gewoonte dit helemaal aan het begin van een functie te doen. Op deze manier hoeft iemand anders die jouw functie moet onderhouden niet op zoek te gaan, naar welke variabelen nu lokaal en welke globaal zijn.
Het volgende wat we willen doen is controleren of we wel met het juiste post type te maken hebben. Deze controle is geheel optioneel, maar het is toch altijd wel handig om deze mogelijkheid te hebben. Bijvoorbeeld wanneer je twee custom post types hebt (bijvoorbeeld door twee verschillende plugins geïmplementeerd) die allebei een custom field hebben met eenzelfde naam, maar verschillende betekenis.
En dan komt nu de complete code, hieronder leg ik uit wat er precies gebeurt.
<?php
add_shortcode('star_rating', 'wxp_get_star_rating');
function wxp_get_star_rating($args) {
global $post;
$atts = shortcode_atts(
array(
'default' => 1,
'posttype' => false
), $args);
if ($atts['posttype']) {
if ($post->post_type <> $atts['posttype']) return $atts['default'];
}
if (!isset($post) || !$post) return $atts['default'];
$result = get_post_meta( $post->ID, 'star_rating', true);
if ($result === false) return $atts['default'];
return $result;
}
Op regels 11-13 kijk ik of de shortcode parameter ‘posttype’ is gezet. En als dat het geval is, of het veld ‘post_type’ van de post ook gelijk is aan deze meegegeven waarde. Is dat het geval, dan wordt de waarde van de parameter ‘default’ teruggegeven.
Ook als de globale variabele ‘post’ leeg is, of niet bestaat, geven we diezelfde waarde terug. Kortom, in alle situaties waarin we niet met het juiste post type te maken hebben krijgen we een vooraf ingestelde waarde terug.
De functie op regel 15 doet het eigenlijke ‘zware’ werk. get_post_meta haalt een specifieke waarde van een post op, op basis van de ID van deze post. De controles die we hiervoor deden waren allemaal om er zeker van de zijn, dat er ook wel een post ID beschikbaar zou zijn.
Deze functie krijgt drie parameters mee, de post ID, de sleutelwaarde van het custom field en een mysterieuze waarde ’true’.
Die ’true’ geeft aan, dat de teruggegeven waarde een enkelvoudige waarde moet zijn. Standaard geeft deze functie namelijk een array van waarden terug. En hoewel ons array slechts één waarde zou hebben, kan de ontvanger (Elementor Dynamic Tags) niet goed overweg met arrays. Vandaar dat we door middel van de ’true’ parameter aangeven, dat we een enkelvoudige waarde verwachten.
Minder specifiek
Deze functie is natuurlijk heel specifiek. Je kan de functie ook minder specifiek maken, door ook de naam van het custom field wat je terug wilt krijgen als parameter mee te geven.
Dan noemen we de functie natuurlijk ook anders. Dergelijke code zou er als volgt uit kunnen zien:
<?php
add_shortcode('customfield', 'wxp_get_custom_field');
function wxp_get_custom_field($args) {
global $post;
$atts = shortcode_atts(
array(
'default' => 1,
'posttype' => false,
'customfield' => false
), $args);
if (!$atts[customfield]) {
return "Parameter 'customfields' is verplicht";
}
if ($atts['posttype']) {
if ($post->post_type <> $atts['posttype']) return $atts['default'];
}
if (!isset($post) || !$post) return $atts['default'];
$result = get_post_meta( $post->ID, $atts['customfield'], true);
if ($result === false) return $atts['default'];
return $result;
}