Categorieën
PHP WordPress

PHP namespaces `use` of `\` prefix?

Het lijkt er op dat er steeds meer PHP-ontwikkelaars binnen namespaces gebruik gaan maken van zogenaamde ‘fully qualified name’ definities. Aan het gebruik van bijvoorbeeld globale PHP-functies zonder use function of \-prefix kleven namelijk een aantal nadelen. In het artikel “Optimizing PHP performance by using fully-qualified function calls” van Toon Verwerft is hier meer over te lezen. En ook op de website van DEV Community staat meer informatie:

Normally your code is namespaced (right?). So what happens when you call a function from the standard PHP library? The “compiler” (opcode producer) will look into the current namespace, then go up, and eventually use the global namespace. This means that if you add a “\” in front of standard functions (so effectively namespacing it in the global namespace explicitely), it will result in less opcode instructions, and that means faster code execution. Think it’s one of those useless micro-optimization like the use of single vs. double quotes? Think again.

DEV Community – https://dev.to/elabftw/optimizing-your-php-app-speed-3hd4

Ook op de website van PHP zelf is meer informatie te vinden over hoe PHP-namespaces werken qua naamgeving van classes, functies, constanten, etc. In de FAQ staan een groot aantal voorbeelden van hoe PHP omgaat met de naamgeving binnen namespaces.

Inmiddels zijn er ook enkele tools beschikbaar die kunnen helpen bij het gebruik van ‘fully qualified name’ definities. Zo kun je bijvoorbeeld met “PHP Coding Standards Fixer” het volgende doen:

➜  ~ php-cs-fixer fix test.php --rules=native_function_invocation,native_constant_invocation

Bron: https://stackoverflow.com/questions/55419673/php7-adding-a-slash-to-all-standard-php-functions-php-cs-fixer-rule

Naast php-cs-fixer kwam ik ook de volgende tools geven:

Waar ik echter geen goed antwoord op kon vinden was of je nou beter kunt prefixen met een \ of use statements kunt gebruiken. In de TYPO3 decision topic “Should we use fully qualified function (FQN) calls like \is_array in the core?” kwam ik uiteindelijk de volgende vraag tegen:

do I read you correctly that you prefer having slashes over “use…” imports?

why?

Tymoteusz Motylewski

Deze vraag werd als volgt beantwoord:

Because we use the same PHP function within a file mostly not more than one or two times. Hence, it’s a waste of space up there to have 10 lines for 10 different functions.

(and I do not consider PHP core functions as “dependencies” like other classes, which should be easily readable at the top of a file)

Markus Klein

Op basis van deze argumenten en de momenteel beschikbare tools lijkt het prefixen met \ de voorkeur te hebben. Het was me ook zelf opgevallen dat je al snel veel use function definities kunt krijgen:

use function apply_filters;
use function implode;
use function is_object;
use function json_decode;
use function sprintf;
use function wp_json_encode;
use function wp_remote_request;
use function wp_remote_retrieve_body;
use function wp_remote_retrieve_response_code;
use function wp_remote_retrieve_response_message;

Het toevoegen van een prefix \ is in veel gevallen korter.

Bekijk ook eens de presentatie “For the love of code: Modernizing WordPress, plugins, and themes” van Juliette Reinders Folmer. Ze geeft in de presentatie aan op welke manier je PHP-code nog verder kunt moderniseren. Ze geeft ook nog een aantal goede ‘best practices’:

  • Focus on function, not syntax
  • Don’t attempt to do everything at once

Categorieën
PHP WooCommerce WordPress

WordPress en PHP Exception

Binnen WordPress core wordt nog niet heel veel gebruik gemaakt van PHP Exceptions. In plaats daarvan wordt er veel gebruik gemaakt van de WP_Error class. Binnen de populaire webwinkel plugin WooCommerce is de overstap naar PHP Exceptions echter al wel gemaakt. Afgelopen maanden zijn we ook binnen de Pronamic Pay plugin de overstap naar PHP Exceptions aan het maken. In het artikel “Modern WordPress Development: You should throw an exception when you encounter a WP_Error” zijn enkele argumenten te vinden voor PHP Exceptions. Ook vond ik de Stack Overflow vraag “Best practices: Use of @throws in php-doc, and how it could be handle” en antwoorden interessant om te lezen. Ik denk dat het voor veel WordPress ontwikkelaars interessant is om (meer) gebruik te maken van PHP Exceptions.

Categorieën
PHP WordPress

WP-CLI – PHP Fatal error: Uncaught Error: Maximum function nesting level of ‘256’ reached

~/.wp-cli/config.yml

require:
  - config.php

~/.wp-cli/config.php

<?php

ini_set( 'xdebug.var_display_max_depth', -1 );
ini_set( 'xdebug.var_display_max_children', -1 );
ini_set( 'xdebug.var_display_max_data', -1 );

ini_set( 'xdebug.max_nesting_level', -1 );

Categorieën
PHP WordPress

WordPress Coding Standards en Squiz.Commenting

Iedereen die met de WordPress Coding Standards weet waarschijnlijk ook dat deze kan controleren op hoe goed de code is gedocumenteerd. Hiervoor wordt gebruik gemaakt van de Squiz.Commenting sniffs. Bij Pronamic schakelen we deze sniffs vaak uit, omdat het voor maatwerk trajecten vaak niet uit kan om ook de documentatie tip top in orde te hebben. Voor de Pronamic Pay plugin willen we echter toewerken naar beter gedocumenteerde code. Daarom hebben we binnen deze plugin de Squiz.Commenting sniffs weer ingeschakeld. Dit resulteert momenteel nog in veel PHP_CodeSniffer fouten, zoals bijvoorbeeld:

   1 | ERROR | [ ] Missing file doc comment
     |       |     (Squiz.Commenting.FileComment.Missing)

Het is niet altijd even duidelijk wat PHP_CodeSnifer precies verwacht bij dergelijke fouten. De foutmelding geeft wel aan dat er een FileComment ontbreekt. Hoe deze FileComment er uit moet komen te zien wordt er echter niet bij vermeld. Na een kleine zoektocht kwam ik gelukkig wat resources tegen met meer informatie hierover:

Categorieën
Linux Mac WordPress

Sublime Text 3 en SourceTree openen via command line (CLI)

Als WordPress ontwikkelaar maak ik veel gebruik van de command line. Tijdens het ontwikkelen van WordPress oplossingen werk ik namelijk veel met command line tools zoals git, npm, grunt, gulp, composer, etc. Andere zaken regel ik weer liever via een app. Gelukkig kunnen deze vaak ook eenvoudig via de command line opgestart worden. Voor Sublime en SourceTree gebruik ik daarvoor de volgende commando's:

Sublime Text 3

➜ wp-pronamic-ideal git:(develop) subl .

SourceTree

➜ wp-pronamic-ideal git:(develop) stree .

Deze commando's openen automatisch Sublime Text 3 of SourceTree met de huidige project map. Hoe je deze commando's beschikbaar kunt maken is te lezen in de volgende artikelen:

Categorieën
WordPress

Verwijderen van WordPress berichten in bulk traag door Sucuri

Onlangs liepen we bij Pronamic tegen “504 Gateway Timeout” fouten aan bij het verwijderen van (veel) WordPress berichten de WordPress admin omgeving. In eerste instantie dachten we aan een hosting issue, maar al snel bleek dat een plugin de boosdoener was. Het kan echter soms lastig zijn om te achterhalen welke plugin de veroorzaker is. Plugins kunnen op allerlei filter/actie hooks inhaken en zaken vertragen. In dit geval trad het probleem op bij het verwijderen van berichten. Door de WordPress code te bekijken kwamen we er snel achter dat WordPres bij het verwijderen van berichten o.a. de wp_trash_post en deleted_post actie uitvoert:

Met 20+ actieve plugins en duizenden bestanden blijft het echter zoeken naar een speld in een hooiberg. Gelukkig hebben we vaak SSH-toegang tot onze hosting omgevingen en kunnen we met een eenvoudig commando snel zoeken:

  • grep --recursive --include="*.php" "deleted_post" .
  • grep --recursive --include="*.php" "trash_post" .

Hieruit bleek al snel dat de “Sucuri Security” plugin de boosdoener was. Deze plugin communiceert elke bericht verwijdering door naar de Sucuri API. Doordat voor elk bericht een HTTP-request werd uitgevoerd ontstond er een enorme vertraging bij het verwijderen van berichten.

Deze API-communicatie kan gelukkig eenvoudig uitgeschakeld worden via de Sucuri plugin instellingen pagina:

SSH-toegang en tools zoals grep kunnen goed helpen bij het opspeuren van dergelijke problemen.

Categorieën
Hosting Linux WordPress

WordPress network/multisite cron vervangen met Linux cron SiteGround

Veel WordPress ontwikkelaars zijn geen fan van de standaard WordPress cron functionaliteit. Vaak wordt daarom geadviseerd om de WordPress cron te vervangen met een Linux cron. De meeste artikelen adviseren om in wp-config.php de WordPress uit te schakelen via define( 'DISABLE_WP_CRON', 'true' ); en via cPanel of DirectAdmin een Linux cron in te stellen:

/usr/local/bin/php /home/user/public_html/wp-cron.php

Voor een eenvoudige WordPress installatie werkt dit vaak goed, maar binnen een WordPress network/multisite installatie wordt het vaak al lastiger. Als je je website host bij SiteGround is dit echter ook een fluitje van een cent. De volgende WP-CLI commando komt hier namelijk goed bij van pas:

wp site list --path=/home/user/public_html --deleted=0 --field=url | xargs -I {} wp cron event run --due-now --path=/home/user/public_html --quiet --url={}

Bovenstaand commando bestaat eigenlijk uit 2 commando’s, één voor het opvragen alle sites en één voor het uitvoeren van de verlopen cron events:

  1. wp site list --path=/home/user/public_html --deleted=0
  2. wp cron event run --due-now --path=/home/user/public_html --quiet --url={}

Met behulp van het xargs command geven we de output van het eerste commando door aan het tweede commando. Op die manier worden de verlopen cron events van alle (niet verwijderde) websites uitgevoerd.

Resources

Categorieën
Linux Mac PHP WordPress

Homebrew, PHP 7.1 en cURL error 56: SSLRead() return error -9806

Na het installeren van PHP 7.1 via Brew kreeg ik via de WordPress HTTP API soms de volgende foutmelding te zien:

cURL error 56: SSLRead() return error -9806

Ik was deze fout wel vaker tegen gekomen, maar het is altijd weer even zoeken naar de oplossing. Het belangrijkste is dat er gewerkt wordt Homebrew curl en openssl:

brew uninstall git
brew uninstall curl

brew install openssl
brew install libressl

brew install curl --with-openssl

brew install php71 --with-homebrew-curl --with-homebrew-libressl --build-from-source
brew install php71-xdebug
brew install php71-mcrypt

Verder zijn ook de volgende Homebrew packages handig om te installeren:

brew install svn

brew install git --with-brewed-curl --with-brewed-openssl --with-brewed-svn --without-completions
brew install git-ftp
brew install git-flow

brew install composer
brew install php-code-sniffer
brew install phpmd
brew install phpunit
brew install phpmyadmin

Update 29 augustus 2017

Bovenstaande commando’s lijken het probleem niet altijd op te lossen. Eventueel kan onderstaande dan geprobeerd worden:

brew reinstall curl --with-openssl

De Homebrew curl formule is ‘keg-only’, maar om er zeker van te zijn dat Homebrew curl formule gebruikt wordt linken we deze wel:

brew link curl --force

Ook zorgen we er voor dat de Homebrew curl formule gebruikt wordt in de shell:

echo 'export PATH="/usr/local/opt/curl/bin:$PATH"' >> ~/.zshrc

Als het goed is geeft het volgende commando nu het volgende resultaat:

curl --version
curl 7.55.1 (x86_64-apple-darwin16.7.0) libcurl/7.55.1 OpenSSL/1.0.2l zlib/1.2.8 libssh2/1.8.0
Release-Date: 2017-08-14
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp
Features: AsynchDNS IPv6 Largefile NTLM NTLM_WB SSL libz TLS-SRP UnixSockets HTTPS-proxy

Met name de OpenSSL/1.0.2l is hierbij belangrijk. Daarna gaan we PHP 7.1 opnieuw installeren met Homebrew curl:

brew reinstall php71 --with-homebrew-curl

Als het goed is geeft het volgende commando nu het volgende resultaat:

php -i | grep "SSL Version"
SSL Version => OpenSSL/1.0.2l

Bronnen

Categorieën
PHP WordPress

WordPress plugin testen met PHPUnit – mysqli_query(): Couldn’t fetch mysqli

Verschillende WordPress plugins die we ontwikkelen bij Pronamic testen we automatisch. Hiervoor maken we gebruik van de WordPress test repository https://develop.svn.wordpress.org/ en PHPUnit. Voor onder andere de Pronamic iDEAL plugin maken we hier al een aantal jaren gebruik maken. Echter na het bijwerken naar de laatste versie van de WordPress test repository https://develop.svn.wordpress.org/ liep ik tegen de volgende foutmelding aan:

mysqli_query(): Couldn't fetch mysqli

In eerste instantie kon ik niet achterhalen waar wat fout ging, maar na lang zoeken en overleg met mijn collega Reüel heb ik hier wat meer informatie over kunnen vinden. In een WordPress.org support topic van 1½ maand geleden werd dezelfde foutmelding genoemd: https://wordpress.org/support/topic/wp_unittestcaseteardown-causes-mysqli_query-couldnt-fetch-mysqli/. Ryan McCue verwijst daar weer naar WordPress Trac ticket 39327. Hij beschrijft hier ook direct een oplossing:

Tracked this down a bit with @pento; it turns out to be a problem with PHPUnit’s global backups, and can be fixed by setting protected $backupGlobals = true in the test class. The key is that PHPUnit serialises the data and unserialises it to restore it.

Vervolgens geeft @pento later in een reactie ook aan hoe dit probleem het beste opgelost kan worden:

For an immediate plugin fix, the best option is to add backupGlobals=”false” to your phpunit.xms.dist.

Plugins zoals bijvoorbeeld Easy Digital Downloads hebben dit ook opgenomen in hun phpunit.xml  bestand: https://github.com/easydigitaldownloads/easy-digital-downloads/blob/master/phpunit.xml. Na het toevoegen van backupGlobals="false" is het probleem ook daadwerkelijk opgelost.

Categorieën
WordPress

Test de WordPress XML-RPC interface

Bij problemen met de WordPress XML-RPC interface zijn er verschillende manieren om de werking te testen:

Jetpack

https://jetpack.wordpress.com/jetpack.testsite/1/?url=https://www.pronamic.nl/xmlrpc.php

cURL

curl -d "<?xml version="1.0" encoding="iso-8859-1"?> <methodCall><methodName>demo.sayHello</methodName></methodCall>" https://www.pronamic.nl/xmlrpc.php