Använda registermönstret i WordPress
Jag har haft några samtal med olika vänner och andra på Twitter om begreppet globala variabler i programmeringsspråk. För dig som är ny på programmering eller som är osäker på varför de är dåliga:
Användningen av globala variabler gör programvara svårare att läsa och förstå. Eftersom vilken kod som helst i programmet kan ändra värdet på variabeln när som helst, kan förståelsen av användningen av variabeln innebära att man förstår en stor del av programmet.
Detta betyder inte att de inte har sin användning, men om du är intresserad av objektorienterad programmering (särskilt i en WordPress-miljö där du ska använda PHP), så är det viktigt att förstå några bättre alternativ än globala variabler.
Det vill säga, det finns sätt att arbeta med att skicka data runt din applikation utan behov av globala variabler. Och ett sådant sätt är registermönstret.
Registermönstret i WordPress
Först, notera att designmönster överskrider ett givet speciellt mönster. Så länge som ett språk erbjuder begreppen objekt (eller till och med abstraktioner), så är det möjligt att implementera mönstret.
Men varför bry sig om att använda detta?
Foto av Samuel Zeller på Unsplash
Kort sagt, det ger ett objektorienterat sätt att skicka information runt din applikation utan behov av globala variabler. Saker som injektionsbehållare för beroende är också bra för detta, men de ligger utanför ramen för detta inlägg. Jag skulle också hävda att det finns tillfällen då de kan vara överdrivna i samband med små plugins.
Implementering av mönstret
Med det sagt, hur kan vi implementera registermönstret i WordPress och sedan utnyttja det genom hela vårt arbete? Låt oss först ta en titt på mönstrets grundläggande struktur :
<?php
/**
* Serves as a registry for all objects that need to be accessed globally throughout the
* plugin.
*/
class Registry
{
/**
* @var array The array used to the the various objects that will be used in the plugin.
*/
private $storage;
/**
* Initializes the plugin by creating an instance of an empty array.
*/
public function __construct()
{
$this->storage = [];
}
/**
* Adds an instance of a class to the registry's storage array using the given key
*
* @param string $id The ID of the object to be used to retrieve it later in the plugin.
* @param mixed $class An instance of the class that will be associated with the specified key.
*/
public function add($id, $class)
{
$this->storage[$id] = $class;
}
/**
* @param string $id The ID of the object to retrieve from the repository.
* @return mixed $class An instance of the class associated with the specified key (or null if it doesn't exist).
*/
public function get($id)
{
return array_key_exists($id, $this->storage)? $this->storage[$id]: null;
}
}
Observera att implementeringen är ganska enkel:
- Klassen innehåller en enda array som en privat egendom.
- Data läggs till i arrayen med ett specifikt ID.
- Data kan hämtas från mönstret med ID.
Du kan till och med ta det här specifika mönstret till nästa nivå om det bara accepterar en klass av en viss typ (som en AbstractEvent, till exempel) och sedan automatiskt anropa en funktion på klassen när den skickas in (eller hämtas) från registret.
Men det blir en mer komplex implementering som jag skulle vilja ha för det här inlägget.
Konfigurera registret
På grund av naturen hos WordPress hook-system finns det ett speciellt sätt på vilket registret måste ställas in och sedan registreras med WordPress.
Låt oss säga att du arbetar med ett plugin. Gör något så här i pluginens bootstrap-fil :
<?php
/**
* Creates a Registry using the Registry Design Pattern to store objects
* that can be used throughout the plugin.
*
*/
$registry = new Registry();
add_filter('acmeRegistry', function() use ($registry) {
return $registry;
});
Detta skapar registret och skapar sedan ett motsvarande filter som vi kan använda senare i pluginet för att hämta registret och därmed andra objekt som det underhåller.
Använda registret
För att lägga till ett objekt i registret, anropa add-funktionen och skicka ett unikt ID och en instans av objektet. Observera att vår nuvarande implementering kommer att kassera alla tidigare instanser av ett objekt som har samma nyckel och ersätta det med vad vi än skickar till det.
<?php
/**
* Get an reference to the repository and add an instance of a
* PostManager to it. The PostManager is a class that allows us
* to manipulate posts.
*/
$this->registry = apply_filters('acmeRegistry', null);
$this->registry->add('postManager', new PostManager());
Därifrån kan du sedan hämta objekten som du hade lagrat i registret:
<?php
/**
* Get an reference to the repository, get a reference to the PostManager
* then you can begin working with it.
*/
$this->registry = apply_filters('acmeRegistry', null);
$this->registry->add('postManager', new PostManager());
// An example call that you can make to set the title of the post.
$postManager->updateTitle('This Is the New Title');
Och du kan använda dem precis som du skulle göra på något annat sätt. Men detta undviker användningsbehovet för singlar, globala variabler eller andra farliga saker.
Ett ord om testbarhet
En annan fördel som jag finner med implementeringen av det här mönstret är att det inte bara gör att du lättare kan skriva enhetstester mot det, utan det ger dig också möjligheten att skriva tester mot de objekt som det kan hålla.
Med det menar jag att du kan skriva dina klasser mer oberoende av WordPress och på så sätt separera domänlogiken från kärnapplikationen och göra dem mer representativa för den data de ska underhålla.
