...

Brug af WordPress-kortkoder i dit eget tema - teknologi, eksempler og bedste praksis

Jeg vil vise dig specifikt, hvordan jeg registrerer kortkoder direkte i temaet, leverer dem sikkert og gengiver dem på de rigtige steder - sådan bygger jeg en wordpress shortcode-tema med en klar struktur, ren kode og hurtige indlæsningstider. Jeg giver praktiske eksempler, forklarer do_shortcode i skabelonen, diskuterer attributter, escaping og caching og tilføjer bedste praksis for langtidsholdbare temaer.

Centrale punkter

  • Registrering via add_shortcode og clear callback-funktioner
  • Integration i editoren, i widgets og i skabeloner med do_shortcode
  • Sikkerhed gennem escaping, attributter og validering
  • Vedligeholdelse med child theme, dokumentation og versionskontrol
  • Strøm med caching, økonomiske forespørgsler og ugyldiggørelse af cache

Kortkoder i temaet: registrering og struktur

Jeg placerer registreringen i temaet i funktioner.php eller i et lille must-use plugin, hvis jeg vil adskille funktionalitet fra layoutet. Hver tilbagekaldsfunktion returnerer en streng og bruger ikke et ekko, da output ellers ender uventede steder. Jeg vælger unikke præfikser til navngivningen for at undgå konflikter med plugins. På den måde holder jeg koden læsbar og skaber en klar rækkefølge, f.eks. /inc/shortcodes.php med et målrettet require_once i functions.php. Til at begynde med er det tilstrækkeligt med en simpel kortkode til hilsener, som jeg senere udvider trin for trin.

<?php
// /wp-content/themes/my-theme/functions.php
require_once get_template_directory() . '/inc/shortcodes.php';
<?php
// /wp-content/themes/my-theme/inc/shortcodes.php
funktion my_greeting_shortcode() {
    return 'Hej, velkommen til min hjemmeside!
}
add_shortcode('greeting', 'my_greeting_shortcode');

Brug kortkoder i skabelonen: do_shortcode

Jeg kalder kortkoder i skabelonen med do_shortcode når jeg integrerer indhold i overskrifter, sidefødder eller særlige skabeloner. Det holder editoren overskuelig, og jeg holder tilbagevendende moduler på et centralt sted. Jeg dokumenterer skabelonkald i koden med en kort kommentar, så andre straks ved, hvilken shortcode der kører her. For dynamiske parametre opretter jeg shortcode-strengen i PHP og overfører værdier sikkert escaped. Denne metode fungerer i alle skabelonfiler som header.php, footer.php eller page-templates.

<?php
// I en skabelonfil
echo do_shortcode('[hilsen]');
echo do_shortcode('[colourbox color="green"]Flot tekst[/colorbox]');

Attributter, indhold og sikkerhed

Jeg indstiller attributter med shortcode_atts og beskytte værdier med esc_html, esc_attr og esc_url. Det forhindrer XSS og sikrer gyldig HTML i alt output. Jeg behandler eventuelt indhold, der er omsluttet af en shortcode, med wp_kses, hvis jeg kun vil tillade bestemte tags. For farver accepterer jeg kun whitelist-værdier eller tjekker med regex, så ingen scripts slipper igennem. Med disse regler forbliver shortcodes pålidelige og leverer et forudsigeligt output.

<?php
function my_colorbox_shortcode($atts, $content = null) {
    $atts = shortcode_atts([
        'color' => 'blue',
    ], $atts, 'colourbox');

    $color = preg_match('/^#?[0-9a-fA-F]{3,6}$/', $atts['colour']) ? $atts['color'] : 'blue';
    $inner = wp_kses($content, ['strong' =&gt; [], 'em' =&gt; [], 'a' =&gt; ['href' =&gt; []]]);
    $style = 'background:' . esc_attr($color) . ';padding:10px';

    return '<div style="' . $style . '">' . $inner . '</div>';
}
add_shortcode('colourbox', 'my_colorbox_shortcode');

Praktiske eksempler: indeværende år, knap og datoer

Jeg bruger små hjælpekortkoder til tilbagevendende indhold som f.eks. den aktuelle Årknapper eller lister fra brugerdefinerede indlægstyper. Et års shortcode sparer mig for vedligeholdelsesarbejde i footeren eller i tekstblokke. Jeg udstyrer knapper med tekst, URL og farve, så redaktører kan arbejde uden at ændre koden. Ved dataoutput fra CPT'er begrænser jeg forespørgslen og cacher resultaterne, så siden forbliver hurtig. Her er tre korte uddrag som grundlag.

<?php
// Jahr
add_shortcode('current-year', function() {
    return date('Y');
});

// Button
add_shortcode('button', function($atts) {
    $atts = shortcode_atts([
        'text'  => 'Klik nu',
        'url' =&gt; '#',
        'color' =&gt; '#2d89ef',
    ], $atts, 'knap');

    $text = esc_html($atts['text']);
    $url = esc_url($atts['url']);
    $color = esc_attr($atts['colour']);

    return '<a href="/da/' . $url . '/" style="background:' . $color . ';padding:8px 18px;color:#fff;border-radius:4px;text-decoration:none">' . $text . '</a>';
});

Tema eller plugin? Beslutningsstøtte og migration

Jeg inkluderer kortkoder i Tema hvis de påvirker layoutet, og i et plugin, hvis jeg vil fortsætte med at bruge dem uafhængigt af temaet. På den måde mister jeg ikke funktioner, når jeg skifter tema, og holder arkitekturen klar. Til dokumentationen laver jeg en oversigt over alle shortcodes med parametre, så redaktører hurtigt kan finde den korrekte syntaks. Når jeg senere flytter, eksporterer jeg kortkodefilerne og udskifter omhyggeligt de nødvendige stier. Følgende tabel hjælper med beslutningen.

Brug Tema Plugin
Binding til layout Høj (f.eks. Hero-Box) Lav
Risiko for migration Højere med temaskift Lav, bevares
Vedligeholdelse/opdateringer Med temaudgivelse Egen udgivelse, mere fleksibel
Målgruppe Funktioner i layoutet Indhold/Funktioner

Brug af kortkoder i editoren og i blokeditoren

Jeg tilføjer kortkoder i den klassiske editor direkte som Tekst og bruge kortkodeblokken i blokeditoren. Denne adskillelse holder indholdet klart og reducerer fejl ved kopiering. For redaktører dokumenterer jeg eksempler direkte i backend, f.eks. som en eksempelblok eller en note i skabelonen. Jeg er opmærksom på forskelle mellem editorer i afstand og inline-stilarter, da blokke nogle gange tilføjer ekstra indpakning. Hvis du overvejer valget af editor, finder du i sammenligningen Block editor vs classic nyttige tips.

Performance: Caching og rene forespørgsler

Jeg holder kortkoder hurtige ved at cachelagre beregningsintensive dele og begrænse dataadgang, hvilket reducerer Opladningstid sænker. Ved tilbagevendende problemer bruger jeg Transients eller WP Object Cache med en meningsfuld nøgle. Jeg begrænser forespørgsler med posts_per_page, indstiller kun nødvendige felter og undgår dyre COUNT-operationer. Jeg tilføjer bredde/højde og lazy loading til billedoutput for at gøre siden synlig hurtigere. For dynamiske komponenter sletter jeg cachen, så snart indholdet ændres.

<?php
add_shortcode('latest-offers', function($atts) {
    $key = 'sc_latest_offers_v1';
    $html = wp_cache_get($key);
    if ($html !== false) {
        return $html;
    }

    $q = new WP_Query([
        'post_type'      => 'angebot',
        'posts_per_page' => 5,
        'no_found_rows'  => true,
        'fields'         => 'all',
    ]);

    ob_start();
    if ($q->have_posts()) {
        echo '<ul class="offers">';
        while ($q->have_posts()) { $q->the_post();
            echo '<li>' . esc_html(get_the_title()) . '</li>';
        }
        echo '</ul>';
        wp_reset_postdata();
    }
    $html = ob_get_clean();
    wp_cache_set($key, $html, '', 600);
    return $html;
});

Find og ret hurtigt op på fejlkilder

Jeg aktiverer Fejlfinding-mode og tjekke, om shortcoden er registreret korrekt. Ofte viser en hvid skærm eller rå tekst, at funktionen ikke indlæses eller bruger echo i stedet for return. Logposter afslører uventede datatyper, forkerte attributter eller manglende escapes. I skabeloner tester jeg trin for trin: først statisk tekst, så kortkoden, så parametre. Hvis du vil gå systematisk til værks, kan du bruge guiden til WordPress fejlsøgningstilstand.

Arbejd opdateringssikkert med child theme

Jeg opretter mine egne kortkoder i Barnets tema hvis jeg ikke kan eller vil ændre noget i det overordnede tema. På denne måde bevares tilpasninger under temaopdateringer, og jeg kan kontrollere indlæsningssekvensen. Vigtigt: Registrer child theme korrekt, hold functions.php slank, og inkluder kun specifikke filer. Til strukturerede projekter adskiller jeg kortkoder i /inc og dokumenterer dem med inline-kommentarer. En kompakt vejledning findes i Instruktioner til child theme.

Styling, semantik og tilgængelighed

Jeg sørger for at gøre rent HTML og semantiske tags, så skærmlæsere genkender indholdet korrekt. Jeg viser kun knapper som et tag med role="button", hvis de virkelig er links, ellers vælger jeg rigtige knapper. Jeg holder høje farvekontraster og indstiller fokusstile, så tastaturbrugere tydeligt kan se, hvor de er. Jeg reducerer inline-stilarter og flytter design til en CSS-fil med klare klasser. På den måde forbliver shortcodes fleksible og tilgængelige på samme tid.

API-integration og sikker integration af eksterne data

Jeg henter eksterne data via wp_remote_get og cacher dem, så siden ikke hænger under API-timeouts. Jeg tjekker svar for statuskoder, analyserer JSON på en kontrolleret måde og tillader kun de felter, der virkelig er nødvendige. I tilfælde af fejl viser jeg et magert fallback-output eller skjuler blokken. For brugerindhold fjerner jeg farlige tags og validerer links grundigt. Det sikrer, at shortcodes forbliver stabile, selv om eksterne tjenester svinger.

Indlæs kun aktiver, når de er i brug

Jeg indlæser kun CSS/JS for kortkoder, hvis de rent faktisk vises på siden. Det sparer forespørgsler og holder den kritiske vej til CSS lille. Jeg registrerer stilarter og scripts centralt og indlæser dem i callback eller specifikt, så snart jeg genkender shortcoden i indholdet. Vigtigt: Skriv aldrig hård kode i headeren uden at tænke over det, men arbejd via enqueue-API'erne.

&lt;?php // functions.php – Registrer aktiver add_action(&#039;wp_enqueue_scripts&#039;, function() { wp_register_style(&#039;my-shortcodes&#039;, get_template_directory_uri() . &#039;/assets/shortcodes.css&#039;, [], &#039;1.0&#039;);
    wp_register_script(&#039;my-shortcodes&#039;, get_template_directory_uri() . &#039;/assets/shortcodes.js&#039;, [], &#039;1.0&#039;, true); });

// Indlæs kun, hvis det findes i indholdet add_action(&#039;wp&#039;, function() { if (is_singular() &amp;&amp; has_shortcode(get_post_field(&#039;post_content&#039;, get_queried_object_id()), &#039;button&#039;)) { wp_enqueue_style(&#039;my-shortcodes&#039;);
        wp_enqueue_script(&#039;my-shortcodes&#039;); } }); // Alternativt kaldes direkte i shortcode-callback: function my_assets_example_shortcode($atts, $content = null) { wp_enqueue_style(&#039;my-shortcodes&#039;); return &#039;<div class="my-box">' . wp_kses_post($content) . '</div>';
}
add_shortcode('my-box', 'my_assets_example_shortcode');

Kortkoder vs. direkte funktionskald i skabelonen

Jeg skelner bevidst: For faste skabelonmoduler foretrækker jeg at kalde funktionen direkte i stedet for at parse en shortcode. Det sparer overhead, øger læsbarheden og undgår overraskende filtereffekter. Kortkoder er beregnet til redaktionelt indhold; skabeloner har gavn af klare funktionskald med klare parametre.

<?php
// I stedet for:
echo do_shortcode('[hilsen]');

// Bedre i skabelonen:
echo my_greeting_shortcode();

Indlejrede kortkoder og formatering

Jeg tager højde for indlejrede kortkoder og den automatiske indsættelse af p- og br-tags. Hvis kortkoder omslutter andet indhold, fortsætter jeg med at gengive det indre indhold med do_shortcode, men tillader kun tilladte tags. Jeg fjerner grimme p-tags omkring shortcodes med shortcode_unautop, hvis markup'en ellers ville blive revet op.

&lt;?php function my_wrap_shortcode($atts, $content = null) { $inner = do_shortcode($content); // tillad indlejrede shortcodes return &#039;<div class="wrap">' . wp_kses_post($inner) . '</div>';
}
add_shortcode('wrap', 'my_wrap_shortcode');

// Valgfri hjælp til formatering
add_filter('the_content', 'shortcode_unautop');

Internationalisering og lokalisering

Jeg holder kortkoder sprogkompatible: Jeg oversætter tekststrenge med temaets tekstdomæne og bruger date_i18n til datoer. På den måde fungerer modulerne i flersprogede miljøer og forbliver konsistente, når man skifter sprog. Jeg lokaliserer standardtekster direkte i shortcode callbacks og escaper dem i henhold til konteksten.

<?php
// Tema forberedt til oversættelser
add_action('after_setup_theme', function() {
    load_theme_textdomain('my-theme', get_template_directory() . '/languages');
});

// Lokaliseret hilsen
function my_greeting_shortcode() {
    return esc_html__('Hej, velkommen til min hjemmeside!', 'my-theme');
}

// Lokaliseret årstal
add_shortcode('current-year', function() {
    return esc_html(date_i18n('Y'));
});

Ugyldiggørelse af cache, varianter og nøgler

Jeg planlægger cacher på en sådan måde, at varianter er rent adskilt, og indhold bliver forældet med det samme, når der foretages ændringer. Attributter som limit eller taxonomi er inkluderet i nøglen. Når jeg gemmer relevante indlægstyper, sletter jeg specifikt de berørte nøgler. I opsætninger med høj trafik bruger jeg en vedvarende objektcache-backend og grupperer nøgler efter funktion, så jeg kan tømme dem samlet.

<?php
add_shortcode('latest-offers', function($atts) {
    $atts  = shortcode_atts(['limit' => 5], $atts, 'latest-offers');
    $limit = max(1, (int) $atts['limit']);
    $key   = 'sc_latest_offers_v1_' . $limit;

    if (($html = wp_cache_get($key, 'mytheme')) !== false) {
        return $html;
    }

    $q = new WP_Query([
        'post_type'      => 'angebot',
        'posts_per_page' => $limit,
        'no_found_rows'  => true,
    ]);

    ob_start();
    if ($q->have_posts()) {
        echo '<ul class="offers">';
        while ($q->have_posts()) { $q->the_post();
            echo '<li>' . esc_html(get_the_title()) . '</li>';
        }
        echo '</ul>';
        wp_reset_postdata();
    }
    $html = ob_get_clean();
    wp_cache_set($key, $html, 'mytheme', 600);
    return $html;
});

// Cache invalidieren, wenn Angebote geändert werden
add_action('save_post_angebot', function() {
    foreach ([1,5,10] as $limit) {
        wp_cache_delete('sc_latest_offers_v1_' . $limit, 'mytheme');
    }
});

Uddyb sikkerheden: sanitiser, tilladte attributter og rel/target

Jeg udvider kortkoder med fornuftige, men sikre indstillinger. For links begrænser jeg target til _self/_blank og sætter rel="noopener noreferrer" for nye faner. Jeg kontrollerer farver med sanitize_hex_color. Jeg behandler indhold kontekstafhængigt, og for lukket indhold vælger jeg wp_kses_post eller en mere restriktiv tilladelsesliste.

<?php
add_shortcode('button', function($atts, $content = null) {
    $atts = shortcode_atts([
        'text'   => '',
        'url' =&gt; '#',
        'farve' =&gt; '#2d89ef',
        'target' =&gt; '_self',
    ], $atts, 'knap');

    $text = $atts['text'] !'== '' ? $atts['text'] : ($content ?: esc_html__('Click now', 'my-theme'));
    $text = esc_html($text);
    $url = esc_url($atts['url']);
    $color = sanitise_hex_color($atts['colour']) ?: '#2d89ef';
    $target = in_array($atts['target'], ['_self','_blank'], true) ? $atts['target'] : '_self';
    $rel = $target === '_blank' ? 'noopener noreferrer' : '';

    $style = 'baggrund:' . $colour . ';padding:8px 18px;color:#fff;border-radius:4px;text-decoration:none';

    return '<a class="sc-button" href="/da/' . $url . '/" style="' . esc_attr($style) . '" target="' . esc_attr($target) . '" rel="' . esc_attr($rel) . '">' . $text . '</a>';
});

Editor-, widget- og feed-kontekster

Jeg tager højde for den kontekst, som kortkoden kører i. Jeg tillader eksplicit shortcodes i klassiske tekstwidgets og bruger shortcode-blokken i blockwidget-editoren. I feeds eller i søgningen deaktiverer jeg særligt komplekse shortcodes og returnerer dem tomme. Derudover indlæser jeg kun aktiver på enkelte sider, hvis kortkoden vises i indholdet.

<?php
// Klassiske widgets: aktiver kortkoder
add_filter('widget_text', 'do_shortcode');

// Undgå dyrt output i feeds
add_shortcode('latest-offers-feed-safe', function($atts) {
    if (is_feed()) {
        return '';
    }
    // ... almindeligt output
});

Udfasning, migration til blokke og kompatibilitet

Jeg planlægger fremtiden for mine kortkoder: Når et tag udskiftes, omdirigerer jeg det til det nye i et stykke tid og annoncerer ændringen i changeloggen. Hvis du er afhængig af blokeditoren, kan du registrere blokke på serversiden med render_callback og bruge den samme PHP-funktion internt som kortkoden. På den måde sameksisterer begge stier rent, indtil kortkoden udløber.

'', 'url' => '#'], $atts, 'old-button');
    $text = $map['text'] ?: $content;
    return do_shortcode('[button text="' . esc_attr($text) . '" url="' . esc_url($map['url']) . '"]');
});

// Senere: fjern helt
// remove_shortcode('old-button');

Test og kvalitetssikring

Jeg validerer kritiske kortkoder med enhedstests, så refaktoriseringer ikke giver nogen overraskelser. I testene kontrollerer jeg, at obligatoriske attributter er valideret, at standardværdier er indstillet, og at output er korrekt escaped. Til HTML-output vælger jeg robuste assertions (contains i stedet for exact match), så små formateringsændringer ikke ødelægger alle tests. Jeg tester også edge cases som tomt indhold, ugyldige farver og meget lange tekster.

assertStringContainsString('Hi', $out);
        $this->assertStringContainsString('href="#"', $out);
    }

    public function test_button_blocked_invalid_color() {
        $out = do_shortcode('[button color="javascript:alert(1)"]');
        $this->assertStringNotContainsString('javascript:', $out);
    }
}

Til sidst: Min kompakte praktiske oversigt

Jeg registrerer kortkoder tydeligt, leverer dem sikkert og opbevarer dem med Caching hurtigt. Til redaktionel brug dokumenterer jeg eksempler og sikrer ensartede parametre, så alle kan bruge dem med tillid. Layout-relaterede moduler ender i temaet, indholdsrelaterede funktioner i et plugin, så sitet forbliver fleksibelt på lang sigt. Med et child theme, debug logs og ren semantik forbliver udvikling og vedligeholdelse afslappet. Resultatet er et wordpress shortcode-tema, der er pålideligt, nemt at vedligeholde og giver indholdsteams reel frihed.

Aktuelle artikler