Skip to content

Allt om WordPress, webbutveckling — och mer därtill

⚙️ WordPress: hur du anger en standardmall för en anpassad innehållstyp

⚙️ WordPress: hur du anger en standardmall för en anpassad innehållstyp

Du lämnade över en sajt på WordPress med en portfölj till kunden, och de ringer tillbaka nästa dag: "Jag lägger till en ny post, men mallen återgår hela tiden till standardmallen med sidofält. Hur låser jag den?" Situationen är smärtsamt bekant: klicka på "Lägg till ny" i en anpassad posttyp, och istället för den fullbreddslayout du byggt dyker en bloggkolumn med sidofält upp. Att välja mall manuellt för varje post är meningslöst merarbete som frustrerar både dig och kunden. Särskilt när "Full bredd" utan sidofält är vad du behöver nästan varje gång.

Som standard använder WordPress single.php från temat för anpassade posttyper (CPT:er). Och single.php är oftast anpassad för en blogg: titel, innehåll, sidofält med widgetar. För portföljer, case, kundreferenser eller produkter är den layouten en dålig matchning. Den goda nyheten: WordPress erbjuder fyra sätt att tilldela en mall till en CPT, från det enklaste (en fil i temat, ingen kod alls) till helt programmatiskt via hooks och blockteman. Varje metod får jobbet gjort pålitligt; den enda skillnaden är graden av kontroll och hur lätt det är att underhålla.

💡 Snabb översikt:

  • Skapa en fil single-{post_type}.php i temats rot, så plockar WordPress upp den automatiskt via mallhierarkin
  • Haka på filtret template_include i functions.php för att tilldela en mall programmatiskt utan att placera en fysisk fil i temat
  • För blockteman, skapa single-{post_type}.html i mappen templates/; den kan redigeras via webbplatsredigeraren utan kod
  • Efter varje ändring, spola permalänkarna: "Inställningar → Permalänkar → Spara ändringar", annars ser inte WordPress den nya mallen

Metod 1: mallfil via WordPress-hierarkin

Den mest pålitliga och okomplicerade metoden. Sedan version 3.0 har WordPress stöd för anpassade mallar för CPT:er genom den vanliga mallhierarkin. Så här fungerar det: när en besökare öppnar en post av typen portfolio letar WordPress efter en mall i en strikt ordning, uppifrån och ner, och använder den första filen den hittar:

single-portfolio.phpsingle.phpsingular.phpindex.php

Du behöver skapa en fil med namnet single-{post_type}.php, där {post_type} är din anpassade typs slug. Placera den i roten på det aktiva temat:

1/* File: /wp-content/themes/your-theme/single-portfolio.php */
2
3<?php get_header(); ?>
4
5<div class="full-width-content">
6 <?php while ( have_posts() ) : the_post(); ?>
7 <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
8 <h1><?php the_title(); ?></h1>
9 <div class="entry-content">
10 <?php the_content(); ?>
11 </div>
12 </article>
13 <?php endwhile; ?>
14</div>
15
16<?php get_footer(); ?>
17

Det snabbaste sättet att börja: kopiera innehållet från page.php eller template-fullwidth.php från ditt tema och anpassa layouten för den specifika CPT:n. Om ingen single-{post_type}.php-fil finns faller WordPress tyst tillbaka på single.php, och kunden får ett sidofält.

Fördelen med denna metod: ingen kod i functions.php; filen ligger bara i temat och fungerar. Nackdelen: mallen är hårt kopplad till temat. Om du byter tema ligger filen kvar i den gamla mappen och slutar fungera.

Metod 2: programmatiskt via filtret template_include

Den filbaserade metoden fungerar så länge du kontrollerar temat. Men om du utvecklar ett tillägg eller ett barntema som inte ska vara beroende av att en fil finns i roten behöver du hooken template_include.

Filtret körs innan mallen laddas och låter dig peka på en PHP-fil från valfri plats:

1/* File: functions.php (theme) or main plugin file */
2
3add_filter( 'template_include', 'sd_cpt_default_template', 99 );
4
5function sd_cpt_default_template( $template ) {
6 if ( is_singular( 'portfolio' ) ) {
7 $custom_template = plugin_dir_path( __FILE__ ) . 'templates/single-portfolio.php';
8 if ( file_exists( $custom_template ) ) {
9 return $custom_template;
10 }
11 }
12 return $template;
13}

Vad som händer här:

  • is_singular('portfolio') kontrollerar om vi är på en enskild postsida av typen portfolio
  • Om villkoret är sant laddar WordPress mallen från tilläggsmappen och kringgår temats hierarki
  • Prioritet 99 säkerställer att filtret körs sist och inte skrivs över av temat

Denna approach är praktisk när mallen behöver leva inuti ett tillägg och överleva temabyten. Filen templates/single-portfolio.php inuti tillägget kan använda get_header() och get_footer() från det aktiva temat, så visuellt förblir allt konsekvent med sajtens design.

Metod 3: filtret {$type}_template

WordPress tillhandahåller en dynamisk hook {$type}_template, där $type är single, archive eller page. För en CPT tar den formen single-portfolio_template och låter dig åsidosätta mallen precist, utan extra kontroller inuti callbacken:

1add_filter( 'single_template', 'sd_cpt_template_by_type' );
2
3function sd_cpt_template_by_type( $single_template ) {
4 global $post;
5
6 if ( 'portfolio' === $post->post_type ) {
7 $custom_template = get_stylesheet_directory() . '/single-portfolio.php';
8 if ( file_exists( $custom_template ) ) {
9 return $custom_template;
10 }
11 }
12 return $single_template;
13}

Skillnaden mot metod 2 är semantisk: du säger uttryckligen "ändra mallen för enskilda poster" istället för "fånga upp alla mallar." Koden är något renare, men funktionellt löser båda hookarna problemet på samma sätt.

Metod 4: mall i ett blocktema (Full Site Editing)

Från och med WordPress 5.9 och övergången till blockteman förändras approach:en. I FSE-teman är mallar HTML-filer i mappen templates/, inte PHP. För en anpassad posttyp, skapa:

1/wp-content/themes/your-fse-theme/templates/single-portfolio.html

Inuti använder du en blockbaserad struktur. Ett minimalt exempel:

1<!-- wp:template-part {"slug":"header","theme":"your-fse-theme"} /-->
2
3<!-- wp:group {"tagName":"main","layout":{"type":"constrained"}} -->
4<main class="wp-block-group">
5 <!-- wp:post-title {"level":1} /-->
6 <!-- wp:post-featured-image /-->
7 <!-- wp:post-content {"layout":{"type":"constrained"}} /-->
8</main>
9<!-- /wp:group -->
10
11<!-- wp:template-part {"slug":"footer","theme":"your-fse-theme"} /-->

Du kan redigera denna mall direkt i webbplatsredigeraren (Utseende → Redigerare) utan att röra någon kod. Om du byter blocktema ligger filen kvar i den gamla mappen, samma sårbarhet som i metod 1.

Vilken metod ska du välja

En snabb beslutsmatris för ditt scenario:

Scenario

Metod

Ett tema, en CPT, inga tillägg

Metod 1: single-{post_type}.php

Tillägg med egen mall

Metod 2: template_include

Barntema, behöver åsidosätta föräldratemats mall

Metod 1 eller 3

FSE / blocktema (Twenty Twenty-Four och nyare)

Metod 4: templates/single-{post_type}.html

Efter att ha implementerat någon av metoderna, se till att gå till "Inställningar → Permalänkar" och klicka på "Spara ändringar." Detta spolar cachen för omskrivningsregler, och WordPress börjar känna igen den nya mallen.

⁉️🤔 Vanliga frågor

Mallen plockas inte upp. Vad ska jag göra?

Först, spola permalänkarna ("Inställningar → Permalänkar → Spara"). Andra, kontrollera att CPT-sluggen i filnamnet matchar sluggen från register_post_type(). Tredje, om ett cachingtillägg är aktivt, rensa cachen. I praktiken handlar problemet oftast om att spola omskrivningsregler efter att CPT:n registrerats, inte om själva mallkoden.

Kan jag tilldela en mall till flera CPT:er samtidigt?

Ja. I metod 2, använd en array i is_singular(): is_singular( array( 'portfolio', 'testimonials', 'team' ) ). Eller kontrollera in_array( $post->post_type, array('portfolio', 'team') ) inuti callbacken. Mallfilen är en, och layouten kommer att delas över alla listade typer.

Mallen fungerar, men layouten är trasig (saknar sidofält/sidhuvudstilar).

Du ärvde mallen från page.php, men temats stilar är beroende av CSS-klasser på body. Lägg till ett body_class-filter i functions.php så att WordPress applicerar en post-type-{slug}-klass på <body>, så kickar stilarna in:

1add_filter( 'body_class', function( $classes ) {
2 if ( is_singular( 'portfolio' ) ) {
3 $classes[] = 'single-portfolio';
4 }
5 return $classes;
6} );

Vad händer när jag byter tema? Mallen försvinner.

Ja, filen single-portfolio.php ligger kvar i det gamla temats mapp. Dina alternativ: flytta filen till det nya temat manuellt, använd ett barntema (filen överlever uppdateringar av föräldratemat), eller flytta mallen till ett tillägg via metod 2, som inte är beroende av det aktiva temat.

Vad gör jag om jag vill att ALLA CPT:er ska öppnas utan sidofält som standard?

Använd ett universellt filter med is_singular() utan att specificera en särskild post_type, men exkludera standardtyperna post och page:

1add_filter( 'template_include', function( $template ) {
2 if ( is_singular() && ! is_singular( array( 'post', 'page' ) ) ) {
3 $fullwidth = get_stylesheet_directory() . '/template-fullwidth.php';
4 if ( file_exists( $fullwidth ) ) {
5 return $fullwidth;
6 }
7 }
8 return $template;
9}, 99 );

Denna lösning applicerar en enda fullbreddsmall på alla anpassade posttyper samtidigt: portföljer, kundreferenser, teammedlemmar, case. Standardinlägg och sidor påverkas inte.

Är det värt att bry sig om template_include när man bara kan skapa en fil?

Om du har en sajt, ett tema och en CPT, skapa single-{post_type}.php och glöm bort det. Detta är en lösning som håller i åratal: den går inte sönder vid WordPress-uppdateringar, är inte beroende av PHP-versionen och är omedelbart begriplig för alla utvecklare som öppnar temamappen. Underhållet handlar om en enda fil du kan fixa på nolltid.

Programmatiska metoder via hooks är motiverade i två fall. För det första: mallen är en del av ett distribuerat tillägg, och du vill inte kräva att användare kopierar filer till temat. För det andra: CPT:er registreras dynamiskt via ACF, Toolset eller ett liknande tillägg, och att sprida ett dussin single-*.php-filer i temat är opraktiskt. För allt annat är WordPress mallhierarki den enklaste och mest pålitliga vägen, beprövad under åratal.