WordPress ist ein altes CMS, aber auch das meistgenutzte. Da es in der Vergangenheit veraltete PHP-Versionen und Legacy-Code unterstützt hat, mangelt es immer noch an der Umsetzung moderner Programmierpraktiken – WordPress-Abstraktion ist ein Beispiel dafür.

Es wäre zum Beispiel viel besser, die WordPress-Kern-Codebasis in Pakete aufzuteilen, die von Composer verwaltet werden. Oder vielleicht, um WordPress-Klassen automatisch aus Dateipfaden zu laden.

In diesem Artikel erfährst du, wie du WordPress-Code manuell abstrahieren und abstrakte WordPress-Plugin-Funktionen nutzen kannst.

Probleme bei der Integration von WordPress und PHP-Tools

Aufgrund seiner alten Architektur stoßen wir gelegentlich auf Probleme, wenn wir WordPress mit Werkzeugen für PHP-Codebasen integrieren, z. B. mit dem statischen Analysator PHPStan, der Unit-Test-Bibliothek PHPUnit und der Namespace-Scoping-Bibliothek PHP-Scoper. Betrachte zum Beispiel die folgenden Fälle:

Der WordPress-Code in unseren Projekten macht nur einen Bruchteil des Gesamtumfangs aus; das Projekt enthält auch Geschäftscode, der unabhängig vom zugrunde liegenden CMS ist. Dennoch kann es sein, dass das Projekt allein aufgrund des WordPress-Codes nicht richtig in das Tooling integriert werden kann.

Aus diesem Grund könnte es sinnvoll sein, das Projekt in Pakete aufzuteilen, von denen einige WordPress-Code enthalten und andere nur Business-Code mit „Vanilla“-PHP und keinen WordPress-Code enthalten. Auf diese Weise sind die letztgenannten Pakete nicht von den oben beschriebenen Problemen betroffen, sondern können perfekt in das Tooling integriert werden.

Was ist Code-Abstraktion?

Die Code-Abstraktion entfernt feste Abhängigkeiten aus dem Code und erzeugt Pakete, die über Verträge miteinander interagieren. Diese Pakete können dann zu verschiedenen Anwendungen mit unterschiedlichen Stacks hinzugefügt werden, um ihre Nutzbarkeit zu maximieren. Das Ergebnis der Codeabstraktion ist eine sauber entkoppelte Codebasis, die auf den folgenden Säulen beruht:

  1. Programmiere gegen Schnittstellen, nicht gegen Implementierungen.
  2. Erstelle Pakete und verteile sie über den Composer.
  3. Verbinde alle Teile über Dependency Injection miteinander.
Möchtest du mehr über die Codeabstraktion in WordPress erfahren? 👩‍💻 Von Best Practices bis zu empfohlenen Plugins - alles, was du wissen musst, ist nur einen Klick entfernt ⬇️Click to Tweet

Gegen Schnittstellen programmieren, nicht gegen Implementierungen

Beim Programmieren gegen Schnittstellen werden Verträge verwendet, um Code-Teile miteinander interagieren zu lassen. Ein Vertrag ist einfach eine PHP-Schnittstelle (oder eine andere Sprache), die festlegt, welche Funktionen verfügbar sind und welche Signaturen sie haben, d.h. welche Eingaben sie erhalten und welche Ausgaben sie haben.

Eine Schnittstelle deklariert die Absicht der Funktionalität, ohne zu erklären, wie die Funktionalität implementiert wird. Indem wir über Schnittstellen auf Funktionen zugreifen, kann sich unsere Anwendung auf autonome Codeteile verlassen, die ein bestimmtes Ziel erreichen, ohne zu wissen oder sich darum zu kümmern, wie sie es erreichen. Auf diese Weise muss die Anwendung nicht angepasst werden, um zu einem anderen Teil des Codes zu wechseln, der dasselbe Ziel erreicht – zum Beispiel von einem anderen Anbieter.

Beispiel für Verträge

Der folgende Code verwendet den Vertrag CacheInterface von Symfony und den Vertrag CacheItemInterface der PHP Standard Recommendation (PSR), um die Caching-Funktionalität zu implementieren:

use Psr\Cache\CacheItemInterface;
use Symfony\Contracts\Cache\CacheInterface;

$value = $cache->get('my_cache_key', function (CacheItemInterface $item) {
    $item->expiresAfter(3600);
    return 'foobar';
});

$cache implementiert das CacheInterface, das die Methode get definiert, um ein Objekt aus dem Cache zu holen. Durch den Zugriff auf diese Funktion über den Vertrag kann die Anwendung nicht wissen, wo sich der Cache befindet. Ob er sich im Speicher, auf der Festplatte, in der Datenbank, im Netzwerk oder sonst wo befindet. Trotzdem muss sie die Funktion ausführen. CacheItemInterface definiert die Methode expiresAfter, um festzulegen, wie lange das Objekt im Cache gehalten werden muss. Die Anwendung kann diese Methode aufrufen, ohne sich darum zu kümmern, was das gecachte Objekt ist; es ist nur wichtig, wie lange es im Cache bleiben muss.

Gegen Schnittstellen in WordPress programmieren

Da wir den WordPress-Code abstrahieren, hat das zur Folge, dass die Anwendung nicht direkt auf WordPress-Code verweist, sondern immer über eine Schnittstelle. Die WordPress-Funktion get_posts hat zum Beispiel diese Signatur:

/**
 * @param array $args
 * @return WP_Post[]|int[] Array of post objects or post IDs.
 */
function get_posts( $args = null )

Anstatt diese Methode direkt aufzurufen, können wir sie über den Vertrag Owner\MyApp\Contracts\PostsAPIInterface:

namespace Owner\MyApp\Contracts;

interface PostAPIInterface
{
  public function get_posts(array $args = null): PostInterface[]|int[];
}

Beachte, dass die WordPress-Funktion get_posts Objekte der Klasse WP_Post zurückgeben kann, die spezifisch für WordPress ist. Wenn wir den Code abstrahieren, müssen wir diese Art der festen Abhängigkeit aufheben. Die Methode get_posts im Vertrag gibt Objekte des Typs PostInterface zurück, so dass du die Klasse WP_Post referenzieren kannst, ohne es explizit zu erwähnen. Die Klasse PostInterface muss Zugriff auf alle Methoden und Attribute von WP_Post bieten:

namespace Owner\MyApp\Contracts;

interface PostInterface
{
  public function get_ID(): int;
  public function get_post_author(): string;
  public function get_post_date(): string;
  // ...
}

Executing this strategy can change our understanding of where WordPress fits in our stack. Instead of thinking of WordPress as the application itself (over which we install themes and plugins), we can think of it simply as another dependency within the application, replaceable as any other component. (Even though we won’t replace WordPress in practice, it is replaceable from a conceptual point of view.)

Erstellen und Verteilen von Paketen

Composer ist ein Paketmanager für PHP. Er ermöglicht es PHP-Anwendungen, Pakete (d. h. Codeteile) aus einem Repository abzurufen und als Abhängigkeiten zu installieren. Um die Anwendung von WordPress zu entkoppeln, müssen wir ihren Code in zwei verschiedene Pakete aufteilen: die Pakete mit WordPress-Code und die anderen mit Geschäftslogik (also ohne WordPress-Code).

Schließlich fügen wir alle Pakete als Abhängigkeiten in die Anwendung ein und installieren sie über den Composer. Da das Tooling auf die Pakete mit dem Geschäftscode angewendet wird, müssen diese den größten Teil des Codes der Anwendung enthalten; je höher der Prozentsatz, desto besser. Ein gutes Ziel ist es, dass sie etwa 90% des gesamten Codes verwalten.

WordPress-Code in Pakete extrahieren

In Anlehnung an das Beispiel von vorhin werden die Verträge PostAPIInterface und PostInterface zu dem Paket hinzugefügt, das den Geschäftscode enthält, und ein weiteres Paket wird die WordPress-Implementierung dieser Verträge enthalten. Um PostInterface zu erfüllen, erstellen wir eine PostWrapper-Klasse, die alle Attribute von einem WP_Post-Objekt abruft:

namespace Owner\MyAppForWP\ContractImplementations;

use Owner\MyApp\Contracts\PostInterface;
use WP_Post;

class PostWrapper implements PostInterface
{
  private WP_Post $post;
  
  public function __construct(WP_Post $post)
  {
    $this->post = $post;
  }

  public function get_ID(): int
  {
    return $this->post->ID;
  }

  public function get_post_author(): string
  {
    return $this->post->post_author;
  }

  public function get_post_date(): string
  {
    return $this->post->post_date;
  }

  // ...
}

Bei der Implementierung der PostAPI müssen wir, da die Methode get_posts PostInterface[] zurückgibt, Objekte von WP_Post in PostWrapper umwandeln:

namespace Owner\MyAppForWP\ContractImplementations;

use Owner\MyApp\Contracts\PostAPIInterface;
use WP_Post;

class PostAPI implements PostAPIInterface
{
  public function get_posts(array $args = null): PostInterface[]|int[]
  {
    // This var will contain WP_Post[] or int[]
    $wpPosts = \get_posts($args);

    // Convert WP_Post[] to PostWrapper[]
    return array_map(
      function (WP_Post|int $post) {
        if ($post instanceof WP_Post) {
          return new PostWrapper($post);
        }
        return $post
      },
      $wpPosts
    );
  }
}

Dependency Injection verwenden

Dependency Injection ist ein Entwurfsmuster, mit dem du alle Teile der Anwendung lose miteinander koppeln kannst. Bei Dependency Injection greift die Anwendung über ihre Verträge auf Dienste zu, und die Vertragsimplementierungen werden über die Konfiguration in die Anwendung „injiziert“.

Wenn du die Konfiguration änderst, kannst du ganz einfach von einem Vertragsanbieter zu einem anderen wechseln. Es gibt mehrere Bibliotheken für die Injektion von Abhängigkeiten, aus denen wir wählen können. Wir empfehlen, eine auszuwählen, die sich an die PHP Standard Recommendations (oft als „PSR“ bezeichnet) hält, damit wir die Bibliothek bei Bedarf leicht durch eine andere ersetzen können. Was die Dependency Injection angeht, muss die Bibliothek PSR-11 erfüllen, die die Spezifikation für eine „Container-Schnittstelle“ bietet. Unter anderem erfüllen die folgenden Bibliotheken die PSR-11:

Zugriff auf Dienste über den Service Container

Die Dependency-Injection-Bibliothek stellt einen „Service-Container“ zur Verfügung, der einen Vertrag in die entsprechende implementierende Klasse auflöst. Die Anwendung muss sich auf den Service-Container verlassen, um auf alle Funktionen zuzugreifen. Normalerweise würden wir zum Beispiel WordPress-Funktionen direkt aufrufen:

$posts = get_posts();

…mit dem Service-Container müssen wir zunächst den Dienst erhalten, der PostAPIInterface erfüllt, und die Funktionalität über ihn ausführen:

use Owner\MyApp\Contracts\PostAPIInterface;

// Obtain the service container, as specified by the library we use
$serviceContainer = ContainerBuilderFactory::getInstance();

// The obtained service will be of class Owner\MyAppForWP\ContractImplementations\PostAPI
$postAPI = $serviceContainer->get(PostAPIInterface::class);

// Now we can invoke the WordPress functionality
$posts = $postAPI->get_posts();

DependencyInjection von Symfony verwenden

Die DependencyInjection-Komponente von Symfony ist derzeit die beliebteste Dependency-Injection-Bibliothek. Sie ermöglicht es dir, den Service-Container über PHP-, YAML- oder XML-Code zu konfigurieren. Um zum Beispiel festzulegen, dass der Vertrag PostAPIInterface über die Klasse PostAPI erfüllt wird, wird dieser in YAML wie folgt konfiguriert:

services:
  Owner\MyApp\Contracts\PostAPIInterface:
    class: \Owner\MyAppForWP\ContractImplementations\PostAPI

Mit DependencyInjection von Symfony können Instanzen eines Dienstes auch automatisch in jeden anderen Dienst injiziert (oder „autowired“) werden, der von ihm abhängt. Außerdem ist es einfach zu definieren, dass eine Klasse eine Implementierung ihres eigenen Dienstes ist. Betrachte zum Beispiel die folgende YAML-Konfiguration:

services:
  _defaults:
    public: true
    autowire: true

  GraphQLAPI\GraphQLAPI\Registries\UserAuthorizationSchemeRegistryInterface:
    class: '\GraphQLAPI\GraphQLAPI\Registries\UserAuthorizationSchemeRegistry'

  GraphQLAPI\GraphQLAPI\Security\UserAuthorizationInterface:
    class: '\GraphQLAPI\GraphQLAPI\Security\UserAuthorization'
    
  GraphQLAPI\GraphQLAPI\Security\UserAuthorizationSchemes\:
    resource: '../src/Security/UserAuthorizationSchemes/*'

Diese Konfiguration definiert Folgendes:

Schauen wir uns an, wie das Autowiring funktioniert. Die Klasse UserAuthorization hängt vom Dienst mit dem Vertrag UserAuthorizationSchemeRegistryInterface ab:

class UserAuthorization implements UserAuthorizationInterface
{
  public function __construct(
      protected UserAuthorizationSchemeRegistryInterface $userAuthorizationSchemeRegistry
  ) {
  }

  // ...
}

Dank autowire: true erhält die DependencyInjection-Komponente für den Dienst UserAuthorization automatisch die erforderliche Abhängigkeit, nämlich eine Instanz von UserAuthorizationSchemeRegistry.

Wann man abstrahieren sollte

Das Abstrahieren von Code kann viel Zeit und Mühe kosten, deshalb sollten wir es nur dann tun, wenn die Vorteile die Kosten überwiegen. Im Folgenden findest du Vorschläge, wann es sich lohnen kann, den Code zu abstrahieren. Du kannst dazu die Codeschnipsel in diesem Artikel oder die unten vorgeschlagenen abstrakten WordPress-Plugins verwenden.

Zugang zu Werkzeugen

Wie bereits erwähnt, ist es schwierig, PHP-Scoper auf WordPress laufen zu lassen. Durch die Entkopplung des WordPress-Codes in verschiedene Pakete wird es möglich, ein WordPress-Plugin direkt zu scopen.

Zeit- und Kostenersparnis beim Tooling

Die Ausführung einer PHPUnit-Testsuite dauert länger, wenn sie WordPress initialisieren und ausführen muss, als wenn sie das nicht muss. Ein geringerer Zeitaufwand kann sich auch in geringeren Kosten für die Durchführung der Tests niederschlagen – GitHub Actions zum Beispiel berechnet die Kosten für auf GitHub gehostete Runner nach dem Zeitaufwand für die Nutzung.

Schweres Refactoring muss nicht sein

Ein bestehendes Projekt erfordert möglicherweise ein umfangreiches Refactoring, um die erforderliche Architektur einzuführen (Dependency Injection, Aufteilung des Codes in Pakete usw.), so dass es nur schwer herausgezogen werden kann. Wenn du den Code bei der Erstellung eines Projekts von Grund auf abstrahierst, ist es viel überschaubarer.

Code für mehrere Plattformen programmieren

Indem wir 90% des Codes in ein CMS-agnostisches Paket extrahieren, können wir eine Bibliotheksversion erstellen, die für ein anderes CMS oder Framework funktioniert, indem wir nur 10% der gesamten Codebasis ersetzen.

Migrieren auf eine andere Plattform

Wenn wir ein Projekt von Drupal zu WordPress, WordPress zu Laravel oder einer anderen Kombination migrieren müssen, müssen nur 10% des Codes neu geschrieben werden – eine erhebliche Einsparung.

Bewährte Praktiken

Während wir die Verträge so gestalten, dass sie unseren Code abstrahieren, gibt es mehrere Verbesserungen, die wir an der Codebasis vornehmen können.

PSR-12 einhalten

Bei der Definition der Schnittstelle für den Zugriff auf die WordPress-Methoden sollten wir uns an die PSR-12 halten. Diese neue Spezifikation zielt darauf ab, die kognitive Reibung beim Scannen von Code verschiedener Autoren zu verringern. Wenn wir uns an PSR-12 halten, müssen wir die WordPress-Funktionen umbenennen.

WordPress benennt Funktionen mit snake_case, während PSR-12 camelCase verwendet. Daher wird die Funktion get_posts zu getPosts:

interface PostAPIInterface
{
  public function getPosts(array $args = null): PostInterface[]|int[];
}

…und:

class PostAPI implements PostAPIInterface
{
  public function getPosts(array $args = null): PostInterface[]|int[]
  {
    // This var will contain WP_Post[] or int[]
    $wpPosts = \get_posts($args);

    // Rest of the code
    // ...
  }
}

Aufgeteilte Methoden

Die Methoden in der Schnittstelle müssen nicht eine Kopie der Methoden aus WordPress sein. Wir können sie umwandeln, wann immer es sinnvoll ist. Die WordPress-Funktion get_user_by($field, $value) weiß zum Beispiel, wie man den Benutzer aus der Datenbank über den Parameter $field abruft, der die Werte "id", "ID", "slug", "email" oder "login" akzeptiert. Dieses Design hat ein paar Probleme:

Wir können diese Situation verbessern, indem wir die Funktion in mehrere Funktionen aufteilen:

namespace Owner\MyApp\Contracts;

interface UserAPIInterface
{
  public function getUserById(int $id): ?UserInterface;
  public function getUserByEmail(string $email): ?UserInterface;
  public function getUserBySlug(string $slug): ?UserInterface;
  public function getUserByLogin(string $login): ?UserInterface;
}

Der Vertrag wird für WordPress wie folgt aufgelöst (vorausgesetzt, wir haben UserWrapper und UserInterface erstellt, wie weiter oben erklärt):

namespace Owner\MyAppForWP\ContractImplementations;

use Owner\MyApp\Contracts\UserAPIInterface;

class UserAPI implements UserAPIInterface
{
  public function getUserById(int $id): ?UserInterface
  {
    return $this->getUserByProp('id', $id);
  }

  public function getUserByEmail(string $email): ?UserInterface
  {
    return $this->getUserByProp('email', $email);
  }

  public function getUserBySlug(string $slug): ?UserInterface
  {
    return $this->getUserByProp('slug', $slug);
  }

  public function getUserByLogin(string $login): ?UserInterface
  {
    return $this->getUserByProp('login', $login);
  }

  private function getUserByProp(string $prop, int|string $value): ?UserInterface
  {
    if ($user = \get_user_by($prop, $value)) {
      return new UserWrapper($user);
    }
    return null;
  }
}

Implementierungsdetails aus der Funktionssignatur entfernen

Funktionen in WordPress können in ihrer eigenen Signatur Informationen darüber bieten, wie sie implementiert sind. Diese Informationen können entfernt werden, wenn die Funktion aus einer abstrakten Perspektive bewertet wird. Zum Beispiel wird der Nachname des Benutzers in WordPress durch den Aufruf von get_the_author_meta ermittelt, wodurch klar wird, dass der Nachname eines Benutzers als „Meta“-Wert gespeichert wird (in der Tabelle wp_usermeta):

$userLastname = get_the_author_meta("user_lastname", $user_id);

Du musst diese Informationen nicht an den Vertrag weitergeben. Interfaces interessieren sich nur für das Was, nicht für das Wie. Daher kann der Vertrag stattdessen eine Methode getUserLastname enthalten, die keine Informationen darüber liefert, wie sie implementiert wird:

Alle Kinsta Hosting Pläne beinhalten 24/7 Support durch unsere erfahrenen WordPress Entwickler und Techniker. Chatte mit demselben Team, das auch unsere Fortune 500 Kunden betreut. Schau dir unsere Pläne an!

interface UserAPIInterface
{
  public function getUserLastname(UserWrapper $userWrapper): string;
  ...
}

Strengere Typen hinzufügen

Einige WordPress-Funktionen können Parameter auf unterschiedliche Weise entgegennehmen, was zu Mehrdeutigkeit führt. Zum Beispiel kann die Funktion add_query_arg entweder einen einzelnen Schlüssel und einen Wert erhalten:

$url = add_query_arg('id', 5, $url);

… oder ein Array aus  key => value:

$url = add_query_arg(['id' => 5], $url);

Unsere Schnittstelle kann eine verständlichere Absicht definieren, indem sie solche Funktionen in mehrere separate Funktionen aufteilt, von denen jede eine einzigartige Kombination von Eingaben akzeptiert:

public function addQueryArg(string $key, string $value, string $url);
public function addQueryArgs(array $keyValues, string $url);

Technische Schuld beseitigen

Die WordPress-Funktion get_posts gibt nicht nur „posts“, sondern auch „pages“ oder jede Entität vom Typ „custom posts“ zurück, und diese Entitäten sind nicht austauschbar. Sowohl Beiträge als auch Seiten sind benutzerdefinierte Beiträge, aber eine Seite ist weder ein Beitrag noch eine Seite. Daher kann die Ausführung von get_posts Seiten zurückgeben. Dieses Verhalten ist eine konzeptionelle Diskrepanz.

Um es richtig zu machen, sollte get_posts stattdessen get_customposts heißen, aber es wurde im WordPress-Kern nie umbenannt. Das ist ein häufiges Problem bei langlebiger Software und wird als „technische Schuld“ bezeichnet – Code, der Probleme hat, aber nie behoben wird, weil er brechende Änderungen mit sich bringt.

Wenn wir unsere Verträge erstellen, haben wir jedoch die Möglichkeit, diese Art von technischer Schuld zu vermeiden. In diesem Fall können wir eine neue Schnittstelle ModelAPIInterface erstellen, die mit Entitäten verschiedener Typen umgehen kann, und wir erstellen mehrere Methoden, die jeweils einen anderen Typ behandeln:

interface ModelAPIInterface
{
  public function getPosts(array $args): array;
  public function getPages(array $args): array;
  public function getCustomPosts(array $args): array;
}

Auf diese Weise wird die Diskrepanz nicht mehr auftreten und du wirst diese Ergebnisse sehen:

Vorteile des Abstrahierens von Code

Die wichtigsten Vorteile der Abstraktion des Anwendungscodes sind:

Probleme beim Abstrahieren von Code

Die Nachteile der Abstraktion des Codes einer Anwendung sind:

WordPress abstrahieren Plugin-Optionen

Obwohl es in der Regel am klügsten ist, deinen Code in eine lokale Umgebung zu extrahieren, bevor du daran arbeitest, können dir einige WordPress-Plugins helfen, deine Abstraktionsziele zu erreichen. Dies sind unsere Top-Tipps.

1. WPide

Das beliebte Plugin WPide von WebFactory Ltd. erweitert die Funktionen des standardmäßigen Code Editors von WordPress erheblich. Es dient als abstraktes WordPress-Plugin, indem es dir ermöglicht, deinen Code an Ort und Stelle zu betrachten, um besser zu erkennen, worauf du achten musst.

Das WPide Plugin

Das WPide Plugin

WPide verfügt außerdem über eine Such- und Ersetzungsfunktion, mit der du veralteten oder abgelaufenen Code schnell aufspüren und durch eine überarbeitete Version ersetzen kannst.

Darüber hinaus bietet WPide eine Menge zusätzlicher Funktionen, darunter:

2. Ultimate DB Manager

Das Plugin Ultimate WP DB Manager von WPHobby bietet dir eine schnelle Möglichkeit, deine Datenbanken vollständig herunterzuladen, um sie zu extrahieren und zu überarbeiten.

Das ultimative DB Manager Plugin

Das ultimative DB Manager Plugin

Natürlich sind Plugins dieser Art für Kinsta-Nutzer nicht notwendig, da Kinsta allen Kunden direkten Datenbankzugang bietet. Wenn du jedoch keinen ausreichenden Datenbankzugriff über deinen Hosting-Provider hast, kann Ultimate DB Manager als WordPress-Plugin zum abstrahieren sehr nützlich sein.

3. Dein eigenes WordPress-Plugin zum abstrahieren

Am Ende ist es immer die beste Wahl, ein eigenes Plugin zu erstellen. Das mag wie ein großes Unterfangen erscheinen, aber wenn du nur begrenzte Möglichkeiten hast, deine WordPress-Kerndateien direkt zu verwalten, ist das eine abstraktionsfreundliche Lösung.

Diese Vorgehensweise hat klare Vorteile:

Wie du dein abstraktes WordPress-Plugin erstellst, erfährst du im Plugin-Entwicklerhandbuch von WordPress.

In diesem ausführlichen Leitfaden erfährst du, wie du deinen Code manuell abstrahieren & abstrakte WordPress-Plugin-Funktionen nutzen kannst 🚀⬇️Click to Tweet

Zusammenfassung

Sollten wir den Code in unseren Anwendungen abstrahieren? Wie bei allem gibt es auch hier keine vordefinierte „richtige Antwort“, da es von Projekt zu Projekt abhängt. Diejenigen Projekte, die einen enormen Zeitaufwand für die Analyse mit PHPUnit oder PHPStan erfordern, können am meisten davon profitieren, aber der Aufwand, der dafür betrieben werden muss, ist es nicht immer wert.

Du hast alles gelernt, was du wissen musst, um mit der Abstraktion von WordPress-Code zu beginnen.

Hast du vor, diese Strategie in deinem Projekt umzusetzen? Wenn ja, wirst du ein WordPress-Plugin verwenden? Lass es uns in den Kommentaren wissen!


Spare Zeit, Kosten und maximiere die Leistung deiner Seite mit:

  • Schnelle Hilfe von WordPress Hosting Experten, 24/7.
  • Cloudflare Enterprise Integration.
  • Globale Reichweite mit 28 Rechenzentren weltweit.
  • Optimierung mit unserem integrierten Application Performance Monitoring.

All das und noch viel mehr, in einem Plan ohne langfristige Verträge, betreute Migrationen und eine 30-Tage-Geld-zurück-Garantie. Schau Dir hier unsere Pakete an oder sprich mit dem Vertrieb, um den richtigen Tarif für dich zu finden.