Wanneer ik wil weten of iets een goed idee is voor een webshop, dan heb ik de gewoonte om naar een aantal ‘grote jongens’ te kijken, zoals Bol.com, CoolBlue en nog een paar. Die steken namelijk heel wat geld en tijd in de vraag, wat mensen het prettigst vinden bij het winkelen.
Wat ik daar vooral opmerk, is dat er maar weinig grote webwinkels gebruik maken van tab bladen. Bij WooCommerce is het echter de standaard manier om productinformatie te organiseren. Helaas.
Toen ik besloot, dat ik dit toch eigenlijk heel anders zou willen, viel dat eigenlijk niet eens mee. Want hoewel de WooCommerce interface goed gedocumenteerd is, was de informatie over dit onderdeel wel heel karig.
Toen ik nog dieper ging graven ontdekte ik ook waarom. Eén van de mooie dingen aan WordPress en WooCommerce is de prachtig open interface, waardoor iedereen zijn eigen functionaliteiten kan aan- en in-haken door middel van ‘action’ en ‘filter’ hooks. Maar ooit in een grijs verleden hebben zowel WordPress als WooCommerce zich schuldig gemaakt aan een wel heel luie manier van programmeren. Een ‘pluggable’ interface.
Ik wil er niet al te diep op in gaan -jij komt her waarschijnlijk om oplossingen en niet om rants hoe fout WooCommerce het heeft gedaan- maar in het kort komt het erop neer, dat de huidige API met ‘hooks’ ervoor zorgt, dat iedereen makkelijk kan integreren met onderdelen van WordPress en WooCommerce. Een ‘pluggable’ interface komt er op neer, dat je een functionaliteit kan vervangen door exact één andere functionaliteit. En dat is dus het geval met de tabbladen.
De oplossing die ik hier geef om tabbladen anders te tonen zal absoluut niet met ieder thema werken. Want zodra jouw thema zelf al de manier waarop WooCommerce de tabbladen toont heeft vervangen, dan zal het helemaal fout gaan. En hoewel het geldt voor iedere code snippet, geldt het voor deze snippet nog meer: Probeer het eerst uit op een kopie van je website!
Laten we eerst eens kijken naar de originele code voor tabbladen in WooCommerce. Het kan dat het door de versies heen enigszins is aangepast maar in grote lijnen ziet die code er als volgt uit.
if ( ! function_exists( 'woocommerce_output_product_data_tabs' ) ) {
/**
* Output the product tabs.
*/
function woocommerce_output_product_data_tabs() {
wc_get_template( 'single-product/tabs/tabs.php' );
}
}
Wat staat hierboven? Is de functie ‘woocommerce_output_product_data_tabs’ niet gedefinieerd, dan moet er een functie gedefinieerd worden, zoals gedefinieerd op regels 6-8 gedefinieerd worden.
Dus het enige wat we hoeven te doen is een vervangende functie voor het tonen van onze tabbladen – maar dan niet als tabbladen- te definiëren.
Als oplettende lezer zal jij natuurlijk zeggen -en daar heb je gelijk in- ‘maar hoe weet ik dat mijn functie eerder geladen wordt, dan de WooCommerce eigen functie? Heb ik daar invloed op?
En ja, daar heb jij invloed op, omdat WooCommerce deze functie als ‘pluggable’ heeft aangemerkt. En een functie die als ‘pluggable’ is gedefinieerd, wordt helemaal aan het einde van de laad-sequentie van de WordPress en WooCommerce functies geladen. Dus wat je ook definieert als functie, hij zal altijd eerder geladen worden dan een ‘pluggable’ functie. Tenzij natuurlijk jouw themabouwer ook probeert deze pluggable functie te overrulen. Op dat moment knalt gewoon je webshop. En daarom probeer je het eerst uit op een kopie van je site.
Het gevaar van pluggable functies
Laat me je nog wat verder waarschuwen. Want ‘pluggable functies’ zijn echt niet leuk. Want zelfs wanneer alles goed gaat, heb je natuurlijk in de toekomst altijd het risico dat een willekeurige plugin of een willekeurig thema toch besluit deze pluggable functie te overrulen. En dan knalt je site alsnog.
Gelukkig zitten (hopelijk) de meeste plugin- en themabouwers niet op klachten regens richting helpdesk te wachten, en blijven daarom meestal met hun vingers van pluggable functies af. Maar wees je bewust van het gevaar, voordat je besluit je toch aan deze snippet te wagen.
<?php
function woocommerce_output_product_data_tabs() {
$product_tabs = apply_filters( 'woocommerce_product_tabs', array() );
if ( empty( $product_tabs ) ) return;
echo '<div class="woocommerce-tabs wc-tabs-wrapper">';
foreach ( $product_tabs as $key => $product_tab ) {
?>
<h2><?php echo $product_tab['title']; ?></h2>
<div id="tab-<?php echo esc_attr( $key ); ?>">
<?php
if ( isset( $product_tab['callback'] ) ) {
call_user_func( $product_tab['callback'], $key, $product_tab );
}
?>
</div>
<?php
}
echo '</div>';
}
Wanneer je deze code plaatst in je snippet bestand, dan zal de oorspronkelijke code niet uitgevoerd worden, maar in plaats daarvan wordt jouw code hier uitgevoerd. Let erop, dat ik hier geen gebruik heb gemaakt van prefixes voor functienamen en CSS classes. Dat is geen vergissing, dat is opzet. Als ik hier een prefix voor de functie zou hebben geplaats, zou de naam niet identiek zijn aan die van de pluggable functie, en zou mijn functie niet eens worden uitgevoerd.
Succes ermee!