Blog

Benutzerdefinierte Blöcke nur mit PHP erstellen. Tschüss alte Shortcodes 🥳

David Wang
Von David Wang ·

Gutenberg-Blöcke zu erstellen hat seit WordPress 5.0 React, Node.js und eine Build-Pipeline bedeutet. Wenn deine Stärken in PHP liegen – wie bei mir und der Mehrheit der WordPress-Entwickler –, hat diese Hürde dich fast ein Jahrzehnt lang ausgebremst. WordPress 7.0 ändert das. PHP-only Blocks ermöglichen es dir, einen vollständig funktionsfähigen Gutenberg-Block mit einer einzigen PHP-Datei und dem Flag autoRegister zu registrieren.

Du schreibst PHP. Du bekommst einen Block. Kein Tooling. Kein Build. 🥳 In diesem Artikel siehst du, wie PHP-only Blocks funktionieren, und gehst ein praxisnahes Beispiel durch, das einen klassischen Shortcode durch sein Block-Äquivalent ersetzt.

Was sind PHP-only Blocks?

Bisher bedeutete das Erstellen eines benutzerdefinierten Gutenberg-Blocks das Einrichten einer JavaScript-Toolchain: npm install, eine block.json-Datei, einen Build-Schritt mit webpack.config.js oder @wordpress/scripts und eine edit.js-Komponente in JSX. Jede Änderung erforderte einen Compile-Schritt, bevor du sie im Editor sehen konntest. Für einen PHP-Entwickler, der einfach nur einen simplen Anzeigeblock registrieren möchte, fühlte sich dieser Aufwand immer unverhältnismäßig zur eigentlichen Aufgabe an.

PHP-only Blocks schneiden durch all das durch. Jetzt musst du in register_block_type() nur 'autoRegister' => true übergeben, und WordPress kümmert sich mit ServerSideRender automatisch um alles auf der JavaScript-Seite. Der Block erscheint im Inserter, zeigt eine Live-Vorschau auf der Canvas und generiert Inspector Controls in der Seitenleiste – alles ohne eine einzige Zeile JavaScript von dir.

Die Controls werden automatisch basierend auf dem Attributtyp generiert:

AttributtypGeneriertes Inspector Control
stringTexteingabe
integer / numberZahleneingabe
booleanToggle
string + enumDropdown-Auswahl

Automatisch generierte Controls decken vorerst nur die vier oben genannten Typen ab. Alles Komplexere wie Bild-Picker, Medien-Uploads oder verschachtelte Daten wird noch nicht unterstützt und würde einen per JavaScript registrierten Block erfordern. Entwickler können einzelne Attribute auch mit einer local-Rolle markieren, um sie als internen Zustand zu kennzeichnen; WordPress überspringt diese beim Aufbau der Seitenleisten-Controls.

PHP-only Blocks sind heute in WordPress 7.0 ohne zusätzliche Abhängigkeiten verfügbar. Lies mehr in der offiziellen Dev-Note auf Make WordPress Core.

Für wen ist das gedacht?

Kleinere Agenturen und Freelancer ohne tiefgreifende JavaScript-Kenntnisse können jetzt Block-Editor-Lösungen entwickeln, die die nativen WordPress-Funktionen vollständig nutzen, ohne eine Build-Pipeline anzufassen. Wenn du themenspezifische benutzerdefinierte Gutenberg-Blöcke wie Autoren-Boxen, Pull-Quotes, Testimonials, CTA-Banner, Hinweise und ähnliche Elemente liefern möchtest, anstatt auf Shortcodes zurückzugreifen, helfen PHP-only Blocks dabei, diese Hürde deutlich zu senken.

Sie sind kein Ersatz für per JavaScript registrierte Blöcke, wenn du In-Canvas-Rich-Text-Bearbeitung, eine reaktive Echtzeit-UI oder verschachtelte Inner Blocks benötigst – aber für eine große Klasse strukturierter Anzeigeblöcke treffen sie genau den richtigen Punkt.

Die alte Methode: Shortcodes

Vor PHP-only Blocks war der praktische PHP-Entwickler-Ansatz ein Shortcode. Hier ist ein einfacher Testimonial-Shortcode mit drei Attributen: Autorname, Unternehmen, Sternebewertung, plus Innerem Inhalt für den Rezensionstext:

function testimonial_shortcode( $atts, $content = '' ) {
    $atts = shortcode_atts( [
        'name'    => '',
        'company' => '',
        'stars'   => 5,
    ], $atts );
 
    $stars_count = max( 1, min( 5, intval( $atts['stars'] ) ) );
    $stars_html  = str_repeat( '★', $stars_count )
                 . str_repeat( '☆', 5 - $stars_count );
 
    return sprintf(
        '<blockquote class="testimonial">
            <p class="testimonial__stars">%s</p>
            <p class="testimonial__body">%s</p>
            <footer class="testimonial__attribution">
                <strong>%s</strong>%s
            </footer>
        </blockquote>',
        esc_html( $stars_html ),
        wp_kses_post( $content ),
        esc_html( $atts['name'] ),
        $atts['company'] ? ', ' . esc_html( $atts['company'] ) : ''
    );
}
add_shortcode( 'testimonial', 'testimonial_shortcode' );

Verwendung:

[testimonial name="Sarah K." company="Acme Corp" stars="4"]
	Saved us hours every week.
[/testimonial]

Es funktioniert ... aber es ist nur ein Shortcode 🤷🏻‍♂️

Hier sind nur einige der Probleme mit Shortcodes:

  • Im Editor unsichtbar. Der Autor sieht [testimonial name="Sarah K." ...] im Editor, nicht die gerenderte Karte. Es gibt keine Vorschau.
  • Nicht auffindbar. Du musst wissen, dass der Shortcode existiert, und dir seine Parameternamen merken. Nichts zeigt ihn in der UI an.
  • Keine nativen Stil-Controls. Das Anpassen von Farbe, Abstand oder Typografie erfordert benutzerdefiniertes CSS oder manuell verdrahtete zusätzliche Attribute.
  • Der innere Inhalt ist kein Rich Text. Der Rezensionstext wird als einfacher String in $content übergeben – kein bearbeitbarer Rich-Text-Bereich.

Shortcodes waren das richtige Werkzeug für ihre Zeit. Der Block-Editor bietet etwas Besseres, war aber schwer zu nutzen. WordPress 7.0 bietet mit PHP-only Blocks eine Abkürzung.

Um es klar zu sagen: Der richtige neue Weg, einen Gutenberg-Block zu erstellen, ist nach wie vor ein per JavaScript registrierter Block mit einer vollständigen edit-Komponente. PHP-only Blocks sind ein vereinfachter Weg – bewusst auf serverseitig gerenderte Blöcke beschränkt, die keine Rich-In-Canvas-Bearbeitung benötigen. Sie sind kein Ersatz für JavaScript-Blöcke, sondern eine neue Option für einfachere Anwendungsfälle, bei denen der Aufwand einer Build-Pipeline und React-Komponenten nicht gerechtfertigt ist.

Eine einfachere Option: PHP-only Blocks

Lass uns dasselbe Testimonial als benutzerdefinierten WordPress-Block nur mit PHP bauen. Das Rezept: register_block_type() mit 'autoRegister' => true in supports, plus einem render_callback.

Hier ist der vollständige Code für den Block:

function my_plugin_register_testimonial_block() {
    register_block_type(
        'my-plugin/testimonial', // Block name: namespace/slug
        array(
            'title'      => 'Testimonial', // Shown in the block inserter
            'attributes' => array(
                // string attributes generate a text input in the sidebar
                'name'    => array(
                    'type'    => 'string',
                    'default' => '',
                ),
                'company' => array(
                    'type'    => 'string',
                    'default' => '',
                ),
                // integer attributes generate a number input
                'stars'   => array(
                    'type'    => 'integer',
                    'default' => 5,
                ),
                'body'    => array(
                    'type'    => 'string',
                    'default' => '',
                ),
            ),
            // render_callback is the PHP function that outputs the block's HTML
            'render_callback' => function ( $attributes ) {
                $stars_count = max( 1, min( 5, intval( $attributes['stars'] ) ) );
                $stars_html  = str_repeat( '★', $stars_count )
                             . str_repeat( '☆', 5 - $stars_count );
 
                // Translatable string for screen readers — standard WordPress i18n, nothing extra needed
                /* translators: %d: star rating out of 5 */
                $stars_label = sprintf( __( '%d out of 5 stars', 'my-plugin' ), $stars_count );
 
                return sprintf(
                    '<blockquote %s>
                        <p class="testimonial__stars" aria-label="%s">%s</p>
                        <p class="testimonial__body">%s</p>
                        <cite class="testimonial__attribution">
                            <strong>%s</strong>%s
                        </cite>
                    </blockquote>',
                    // Merges your class with editor-added colour, spacing, and typography styles
                    get_block_wrapper_attributes( array( 'class' => 'testimonial wp-block-quote' ) ),
                    esc_attr( $stars_label ),
                    esc_html( $stars_html ),
                    wp_kses_post( $attributes['body'] ),
                    esc_html( $attributes['name'] ),
                    $attributes['company'] ? ', ' . esc_html( $attributes['company'] ) : ''
                );
            },
            'supports' => array(
                // The key flag — tells WordPress to handle JS registration automatically
                'autoRegister' => true, 
                // The rest unlock native colour, typography, and spacing panels in the sidebar
                'color'      => array(
                    'background' => true,
                    'text'       => true,
                ),
                'typography' => array(
                    'fontSize' => true,
                ),
                'spacing'    => array(
                    'padding' => true,
                    'margin'  => true,
                ),
            ),
        )
    );
}
add_action( 'init', 'my_plugin_register_testimonial_block' );

Das Ergebnis:

Beispiel eines benutzerdefinierten WordPress-Blocks, der nur mit PHP erstellt wurde
Der PHP-only Testimonial-Block mit automatisch generierten Controls und Live-Vorschau auf der Editor-Canvas im Vergleich zur Shortcode-Version.

Ein paar Dinge sind hier zu beachten. Erstens hat der innere Inhalt eines Shortcodes kein direktes Äquivalent in PHP-only Blocks. Der Rezensionstext wird zu einem string-Attribut, das über die Inspector Controls in der Seitenleiste bearbeitet wird – ein einzeiliges Textfeld, kein In-Canvas-Rich-Text-Bereich. Für ein kurzes Testimonial-Zitat ist das in Ordnung. Für längere Texte würdest du einen per JavaScript registrierten Block mit einer RichText-Komponente bevorzugen.

Zweitens kombiniert get_block_wrapper_attributes() deine Klasse mit allem, was der Editor für Farbe, Typografie und Abstand hinzufügt – so funktionieren die nativen Stil-Panels ohne zusätzliche CSS-Verdrahtung. Der render_callback erhält ein $attributes-Array, das nur die vom Benutzer gesetzten Werte enthält; kein $content-Parameter, da innerer Inhalt nicht unterstützt wird.

Was du gegenüber der Shortcode-Version gewinnst:

  • Live-Vorschau auf der Editor-Canvas. Keine rohe Shortcode-Syntax mehr – der Autor sieht die gerenderte Testimonial-Karte während er bearbeitet.
  • Automatisch generierte Controls. Name, Unternehmen, Text (Texteingaben) und Sterne (Zahleneingabe) erscheinen automatisch in den Inspector Controls der Seitenleiste.
  • Native Farb-, Schrift- und Abstand-Panels. Kommt von supports – kein benutzerdefiniertes CSS nötig.
  • Auffindbar. Der Block erscheint im Inserter unter seinem Namen, mit einem Icon.

Von Anfang an übersetzungsbereit

Es gibt zwei unterschiedliche Übersetzungsaspekte bei der Arbeit mit PHP-only Blocks, und es lohnt sich, beide klar zu unterscheiden.

Der erste betrifft statische Strings, die in dein PHP-Template eingebaut sind – Labels, Button-Texte, UI-Copy. Diese werden von __() und _e() behandelt, genau wie in jeder anderen WordPress-PHP-Datei. Im obigen Block ist das Stars-Label ein Beispiel dafür:

/* translators: %d: star rating out of 5 */
$stars_label = sprintf( __( '%d out of 5 stars', 'my-plugin' ), $stars_count );

Standard-WordPress-Werkzeuge erkennen diese automatisch. Nichts Zusätzliches nötig.

Der zweite Aspekt betrifft vom Benutzer eingegebene Inhalte, die als Block-Attribute gespeichert sind – der Testimonial-Text, der Name des Rezensenten, das Unternehmen. Das ist der Inhalt, den deine Redakteure tatsächlich in den Block eintippen, und __() berührt ihn nicht. Auf einer mehrsprachigen Website müssen diese Attributwerte separat in jede Sprache übersetzt werden, und das ist nichts, was WordPress von sich aus erledigt.

Gato AI Translations for Polylang unterstützt PHP-only Blocks von Anfang an, genauso wie es Gutenberg, Bricks, Elementor und andere Page Builder unterstützt. Es ist keine zusätzliche Einrichtung erforderlich.

Alle String-Attribute werden automatisch für die Übersetzung registriert. Wenn ein bestimmtes Feld nicht übersetzt werden soll – eine interne Referenz, eine URL, ein numerischer Code, der als String gespeichert ist –, kannst du es mit einem Filter ausschließen.

Für den Testimonial-Block in diesem Artikel werden Rezensenten-Name, Unternehmen und Textkörper alle automatisch übersetzt – keine Konfiguration außer der Plugin-Installation.

Was PHP-only Blocks (noch) nicht können

Die aktuellen Einschränkungen von PHP-only Blocks:

  • Keine Inner Blocks oder Verschachtelung. Du kannst keine anderen Blöcke in einen PHP-only Block einfügen.
  • Keine In-Canvas-Rich-Text-Bearbeitung. Die RichText-Komponente erfordert JavaScript. Text-Controls werden nur als Seitenleisten-Textfeld gerendert.
  • Seitenleisten-String-Felder sind einzeilig. Ein string-Attribut wird zu einem TextControl, nicht zu einem TextareaControl – nicht ideal für längere Texte.
  • Keine Bild- oder Medien-Picker-Attribute. Unterstützung für Bild-/Datei-Uploads ist für eine spätere Version über die Block Fields API geplant.
  • Die Editor-Vorschau hat eine Round-Trip-Verzögerung. Attributänderungen lösen eine REST-API-Anfrage aus, um serverseitig neu zu rendern, daher aktualisiert sich die Vorschau nicht sofort.

Für einfache strukturierte Blöcke – Testimonials, CTAs, Hinweise, Autoren-Biografien, Unternehmenslistings – treffen PHP-only Blocks genau den richtigen Punkt. Für alles, was Rich-In-Canvas-Bearbeitung erfordert, bleibt die JavaScript-Registrierung das richtige Werkzeug.

Was kommt als Nächstes

WordPress 7.0s PHP-only Blocks bringen die Block-Entwicklung in Reichweite jedes PHP-Entwicklers. Eine PHP-Datei, ein register_block_type()-Aufruf, und du hast einen vollständig funktionsfähigen Gutenberg-Block mit Seitenleisten-Controls, einer Live-Canvas-Vorschau und nativem Stil-Support. Du schreibst PHP. Du bekommst einen Block. Kein Tooling. Kein Build. Kein JavaScript.

Wenn du mehrsprachige Websites erstellst, funktioniert Gato AI Translations nahtlos mit PHP-only Blocks – dein Inhalt ist von Tag eins an übersetzbar.

Bereit für mehr?


Erfahre, was als Nächstes kommt

Abonniere unseren Newsletter: Erfahre, wenn wir eine neue Version veröffentlichen, ein neues Plugin starten oder Neuigkeiten mit dir teilen.