Maar eerst wat is een snippet?
Ik merk dat ik af en toe de term ‘snippet’ gebruik alsof iedereen zomaar zou moeten begrijpen, wat ik bedoel wanneer ik het over snippets heb. En dat is natuurlijk helemaal niet het geval.
Een ‘snippet’, of compleet ‘een code snippet’ is een ‘code knipsel’, een klein stukje code wat eigenlijk bedoeld is om te knippen, te plakken en daarna eventueel aan te passen aan een eigen situatie. Het zijn kleine oplossingen voor veel voorkomende uitdagingen.
Wanneer je aanpassingen aan WordPress wilt maken, dan zal je af en toe met dit soort ‘snippets’ te maken krijgen. En in het verleden heb ik in bepaalde blogartikelen meer dan eens laten zien, hoe je zelf een stukje PHP code aan je ‘functions.php’ kan toevoegen, of hoe je een eigen ‘mini plugin’ kan maken.
Nu lijkt het misschien alsof het niet uitmaakt of je gebruik maakt van ‘functions.php’ of je eigen plugin maakt. Maar dat is niet helemaal juist. En die indruk die ik mogelijk gewekt heb in eerdere posts wil ik bij deze graag direct uit de weg helpen.
Drie manieren om zelf code toe te voegen
Er zijn ruwweg drie manieren om je eigen site specifieke snippet toe te voegen aan WordPress.
De eerste manier is de al genoemde ‘functions.php’. De tweede manier is gebruik te maken van één van de vele plugins om code snippets aan WordPress toe te kunnen voegen. En de derde manier is gebruik te maken van een site specifieke snippet plugin.
Maar wanneer maak je nu eigenlijk gebruik van wat? Laten we met het makkelijkste antwoord beginnen. Wanneer gebruik je een plugin om zelf PHP code aan de WordPress installatie toe te voegen? Het enig juiste antwoord is hier ‘bij voorkeur nooit’.
Laat me over één ding duidelijk zijn. Er is niets mis met deze plugins. Maar het is eigenlijk teveel overhead op je systeem. De beide andere oplossingen zijn altijd sneller. Daarnaast komt er bij kijken, dat de ‘plugins voor snippets’ ook een zeker theoretisch gevaar inhoudt. SQL-injection!
SQL injection
SQL injection wil eigenlijk zeggen, dat door een onveilige plugin (dat hoeft niet de code snippet plugin zelf te zijn!) ik in staat ben directe opdrachten aan de database te geven. De kans is klein, omdat wanneer je de door WordPress aanbevolen methoden gebruikt om met de database te communiceren, dit vrijwel onmogelijk is, maar hier en daar kom ik nog wel eens een plugin tegen die dat niet doet.
Eén van de mogelijkheden die je dan hebt is direct de door jou gewenste inhoud in de database te schrijven. En stel nu, dat ik heb ontdekt, dat jij een bepaalde snippet plugin gebruikt… en ik de door mij gewenste code opsla in de database… en daarna uit laat voeren.
Ik kan dan met je site doen wat ik wil. Dat risico sluit je eigenlijk uit, door geen gebruik te maken van snippet plugins.
Overigens, als jouw site open staat voor SQL injection, heb je sowieso een gigantisch probleem, of je nu wel of geen snippet plugin geïnstalleerd hebt.
De functions.php
Eén van de geëigende plaatsen voor een code snippet is in de functions.php van je thema. Hier moet ik direct een aantal waarschuwingen bij plaatsen (die je waarschijnlijk bekend in de oren klinken, omdat ik die waarschuwingen al in meerdere blogposts heb geplaatst).
Allereerst: Je doet dit altijd alléén op de functions.php van een child theme. Heb je geen child theme, dan maak je er één.
Een tweede regel, net zo belangrijk, je doet het altijd eerst op een staging omgeving, en pas als het blijkt te werken zet je het over naar je live omgeving.
Het nadeel van zo’n functions.php is echter, dat je bij het veranderen van thema, al die functies opnieuw over moet zetten naar je nieuwe functions.php.
Er is nog een tweede nadeel, maar daar heb ik het later in dit artikel over.
De ‘site specifieke snippet plugin’
De ‘site specifieke snippet plugin’ is niet een plugin die je in de WordPress repository zal vinden. Het is een plugin die je namelijk zelf maakt om code snippets in op te slaan. Het is dus net zoiets als de functions.php. Maar waar de functions.php vaak ‘standaard aanwezig’ is, zal jouw site specifieke snippet plugin van scratch of aan door jou gemaakt moeten worden.
Wanneer gebruik ik wat?
functions.php
Zoals al gezegd, de functions.php hoort bij je thema. En daarmee is het ook de beste plaats voor functies die ook horen bij het thema. Wanneer je bijvoorbeeld programmatisch bepaalde elementen weg wil werken, in volgorde wilt veranderen of extra sidebars of menu’s aan je thema toe wilt voegen.
Je kan ook vele andere functies hier plaatsen, maar bij het wisselen van je thema’s zal je deze functies moeten verhuizen.
De pluggable interface
Waar je met functions.php gigantisch mee de mist in gaat is met zogenaamde ‘pluggable’ functies. WordPress kent een aantal functies die jij als beheerder / programmeur kan overschrijven. Denk hierbij bijvoorbeeld aan de mailberichten die WordPress automatisch verzend, de manier waarop je inlogt en nog wat andere zaken. Dit zijn de zogenaamde ‘pluggable’ functies. WordPress heeft deze voor jou al gedefinieerd, maar het staat je vrij deze te overschrijven.
Je kan alleen geen functie overschrijven, die al is gedefinieerd. Dat staat de programmeertaal achter WordPress -PHP- niet toe.
Vandaar dat deze pluggable functies allemaal het volgende formaat hebben:
if (!function_exists('random_pluggable_function_name')) {
function random_pluggable_function_name() {
// Do something useful
}
}
Nu is hier ‘random_pluggable_function_name’ natuurlijk de werkelijke naam van deze zogenaamde ‘pluggable’ functie. Wil jij echter deze functie vervangen met jouw eigen functie, dan zal je eenzelfde functie met dezelfde naam moeten definiëren. En dit moet je doen voor WordPress dit zelf heeft gedaan.
Gelukkig is dat ook mogelijk. Alleen niet via de functions.php, omdat het thema pas helemaal aan het einde van het laadproces wordt geladen. De ‘pluggable’ functies zijn dan al gedefinieerd. Het kan echter wel, door het laden van een plugin. En dat doen we dus in onze ‘site specifieke snippet plugin’.
De site specifieke snippet plugin
De site specifieke snippet plugin is dus eigenlijk niet veel meer, dan een plugin waarin je jouw specifieke snippets plaatst die in ieder geval niet in de functions.php kunnen. En liefst ook die snippets die niet in de functions.php horen.
Wat kan er niet in de functions.php?
Zoals hierboven aangegeven: Alle ‘pluggable’ functies van WordPress kunnen niet in de functions.php. Er zal niets gebeuren, of je zal een foutmelding krijgen, als je dat wel doet. Verder kunnen eigenlijk vrijwel alle codefragmenten wel in de functions.php
Wat hoort er niet in de functions.php?
Wat er niet in de functions.php hoort is eigenlijk alles wat niet te maken heeft met de presentatie. Wanneer je een functie over moet zetten, wanneer je een nieuwe thema kiest, is de ‘site specifieke snippet plugin’ eigenlijk een betere plaats hiervoor.
Een eerste opzet met een concreet voorbeeld
Stel. Ik heb een webshop of een online leeromgeving. En ik heb hier enige duizenden of tienduizenden klanten. Nu heeft WordPress de gewoonte om bij iedere keer dat iemand een wachtwoord opvraagt of wijzigt een email naar de beheerder te sturen.
Dat is leuk als ‘bewaking’ op het moment dat je vier of vijf gebruikers hebt, maar heb je een platform met duizenden klanten dan wordt je stapelgek van de tientallen tot honderden wachtwoord wijzigingen per dag. Dit wil je dus beslist niet.
Nu verwacht je natuurlijk, dat hiervoor een plugin voor te vinden is. Maar toen ik hier enkele jaren geleden naar zocht, was die er nog niet. En deze hoeft er ook helemaal niet te zijn, omdat je hier maar drie regels code voor nodig hebt.
Plaats je deze code echter in je functions.php zal er helemaal niets gebeuren, of je krijgt een foutmelding. Simpelweg, omdat de functie te laat wordt geladen.
We beginnen met het maken van de plugin zelf. En hoewel ik je in het verleden -in de context van WooCommerce- al eens heb uitgelegd, hoe je zelf een plugin kan maken, doen we het gewoon nog een keer.
Header comments
WordPress laat in het plugin overzicht zien, wat een plugin doet. En dat kan omdat die informatie is opgeslagen in de zogenaamde ‘plugin header’.
In de meest eenvoudige vorm ziet zo’n header er als volgt uit
<?php
/*
* Plugin Name: Site specific snippet plugin voor wordxpression.nl
*/
Ik geef hier dus aan dat het de snippet plugin is, en voor welke site deze is. De naam van de site is belangrijk, wanneer je meerdere sites hebt.
Wat ook handig kan zijn is een versienummer. Op deze manier kan ik ook iets aan versiebeheer doen. Dus bijvoorbeeld:
<?php
/*
* Plugin Name: Site specific snippet plugin voor wordxpression.nl
* Version: 1.0
*/
Ben je een WordPress professional en heb je deze plugin voor een klant gemaakt, dan laat je natuurlijk ook nog even je eigen gegevens achter, plus een kleine omschrijving voor de klant.
<?php
/*
* Plugin Name: Site specific snippet plugin voor wordxpression.nl
* Version: 1.0
* Author: Wilko van der Ploeg - WordXPression
* Author URI: https://wordxpression.nl/
*/
Een compleet overzicht van de verschillende velden die je in zo’n header kan zetten vind je in de WordPress developers guide.
Nu de inhoud nog
Met deze code heb je alleen nog maar gezorgd, dat WordPress dit kan tonen in het plugin overzicht, de plugin doet nog niets.
Laten we nu de daadwerkelijke code gaan toevoegen. In de volgende voorbeelden laat ik de header even weg, die mag je er zelf boven bedenken.
De pluggable functie die ik wil overrulen heet wp_password_change_notification. Het enige wat ik dus hoef te doen is in mijn snippet plugin te vertellen dat deze functie helemaal niets moet doen.
function wp_password_change_notification() {}
Tussen de { en } vertel ik immers, wat die functie moet doen. En aangezien hier niets staat, doet de functie ook niets.
Zo simpel is het. Maar dit is toch eigenlijk iets te simpel. Want stel nu, dat ik nog een andere plugin geïnstalleerd heb staan, die ook probeert deze pluggable functie een nieuwe naam te geven. Wat dan?
Dat ligt een beetje aan de volgorde waarin plugins geladen worden. En daar heb je weinig controle over. Maar wordt die andere plugin eerst geladen en daarna mijn plugin dan zal ik hier proberen een al gedefinieerde functie opnieuw te definiëren, en dat mag niet.
Het script zal ‘breken’.
Om dat te voorkomen, moet ik in ieder geval de code als volgt aanpassen.
if (!function_exists('wp_password_change_notification')) {
function wp_password_change_notification() {}
}
Nu ‘breekt’ de code niet, maar de verkeerde ‘pluggable’ functie zal worden uitgevoerd… namelijk die van die andere plugin. Dit is oplosbaar, maar daar heb je een extra plugin voor nodig.
Voorkeur heeft dus te bekijken of je plugin die niet meewerkt wel echt nodig hebt.
Een compleet overzicht van alle pluggable functies vind je hier. Er zullen geen nieuwe pluggable functies meer aan WordPress worden toegevoegd, omdat het idee van pluggable functies best achterhaald is en je tegen een aantal vervelende potentiële problemen aan kan lopen.
Een tweede code snippet
Laten we voor de grap eens een tweede snippet bij plaatsen. Stel, ik wil ook niet, dat mijn ingelogde klanten de zwarte balk bovenaan het scherm te zien krijgen, de ‘admin bar’.
WordPress toont deze balk namelijk standaard aan de meeste rollen voor ingelogde gebruikers. Het enige wat ik wil, is dat ik als admin dit te zien krijg. Verder niemand.
Dat is ook heel makkelijk te implementeren door middel van onderstaande code snippet.
add_action('after_setup_theme', 'wxp_remove_admin_bar');
function wxp_remove_admin_bar() {
if (!current_user_can('administrator') && !is_admin()) {
show_admin_bar(false);
}
}
De ‘wxp’ die je aan het begin van de functie ziet staan is om te voorkomen dat er dubbele functienamen gebruikt zullen worden. ‘wxp’ is de prefix die ik gebruik voor mijn functies. Het is verstandig dit te vervangen door een eigen prefix, die je zelf consequent blijft gebruiken.
Wanneer ik mijn ‘site specifieke snippet plugin’ gemaakt heb, kan ik deze code gewoon onder aan het bestand toevoegen.
Als eindresultaat zou ik dus het volgende krijgen :
<?php
/*
* Plugin Name: Site specific snippet plugin voor wordxpression.nl
* Version: 1.0
* Author: Wilko van der Ploeg - WordXPression
* Author URI: https://wordxpression.nl/
*/
//Verwijderen van de 'wachtwoord gewijzigd' email.
if (!function_exists('wp_password_change_notification')) {
function wp_password_change_notification() {}
}
//Verwijderen van het admin menu voor niet-admin rollen
add_action('after_setup_theme', 'wxp_remove_admin_bar');
function wxp_remove_admin_bar() {
if (!current_user_can('administrator') && !is_admin()) {
show_admin_bar(false);
}
}
Je ziet, dat ik hier iedere snippet van een regel commentaar heb voorzien, om duidelijk te maken wat het doet. Commentaar ziet er zo uit voor één regel :
// dit is commentaar op één regel
Dit is dus geen commentaar meer en zal een foutmelding opleveren
Heb ik een groter commentaar dan plaats ik /* aan het begin en */ aan het einde van het commentaar.
/*
Dit commentaar kan
op meerdere regels
worden geplaatst
zonder foutmeldingen
*/
Nu moet ik het bestand opslaan onder een zinvolle naam (bijvoorbeeld ‘specific-snippets.php’) en uploaden naar de server.
Op de server maak ik in wp-content/plugins/ een nieuwe map aan (ook specific-snippets, bijvoorbeeld). Dat is de plaats waarheen ik mijn ‘specific-snippets.php’ bestand heen zal verplaatsen.
Het is belangrijk dat het bestand op .php eindigt, anders weet WordPress niet, dat het een programma file is.
Must use plugins
Stel je voor. Jij bent een WordPress professional en je hebt voor een klant allerlei essentiële code snippets in jouw site specifieke snippet plugin geplaatst. De klant herkent de plugin echter niet, vraagt zich af waar hij voor is en deactiveert hem.
Prompt werkt de site totaal anders.
Dat wil je voorkomen.
WordPress kent ook het idee van ‘Must use’ plugins. En die ‘must use’ plugins hebben een aantal voordelen. Het belangrijkste voordeel is wel, dat ze automatisch worden geactiveerd. Je hoeft er niets voor te doen. Je kan hem ook niet deactiveren.
Een tweede belangrijk punt is dat je controle hebt over de volgorde van het uitvoeren. De plugins worden namelijk op alfabetische volgorde geladen. Bovendien worden alle Must use plugins geladen, voordat er enig andere plugin wordt geladen.
Het eerder beschreven probleem van twee plugins die allebei een pluggable functie willen hernoemen is dus ook op te lossen, door van onze plugin -die prioriteit heeft- een must use plugin te maken.
Must use plugins zijn plugins die niet in de map wp-content/plugins/ worden geplaatst, maar in plaats daarvan in wp-content/mu-plugins/. Je kan must use plugins alleen uploaden via (s)FTP, niet vanuit WordPress zelf.
Ten slotte
Ik hoop dat in dit artikel een beetje duidelijk is geworden hoe je zelf code snippets op de beste manier kan toevoegen aan je WordPress website. Vind je het zelf toch allemaal wat eng klinken om zelf te doen, dan kan je dit ook laten doen. Via de WordXPression support strippenkaart is dit allemaal mogelijk.
Ben je een WordPress professional, maar voel je je wat minder thuis met het codeerwerk van WordPress, dan is het ook mogelijk om WordXPression support strippenkaart werkzaamheden ‘white label’ op de achtergrond uit te laten voeren. Voor meer informatie, neem contact op.