
🔧 Hur man skapar en mall för en anpassad posttyp i WordPress
Du har lagt till en anpassad posttyp på din webbplats, till exempel "Erbjudanden", "Portfölj" eller "Referenser". Allt fungerar: inlägg skapas, metafält fylls i. Men när du öppnar ett av dessa inlägg på frontend ser det ut som ett vanligt blogginlägg. Samma layout, samma sidopaneler, ingen skillnad alls. Ändå skapade du en anpassad posttyp just för att innehållet skulle presenteras annorlunda.
Problemet är att WordPress som standard renderar alla anpassade inlägg via single.php, den universella mallen för alla enskilda inlägg. För att få en unik layout för en specifik typ behöver du en egen mallfil. Och det visar sig vara förvånansvärt enkelt.
Nedan följer en steg-för-steg-genomgång: från mallhierarkin till två skapandemetoder (via en temafil och via template_include-filtret), med fungerande kodexempel.
💡 Snabb översikt:
- Förstå hur WordPress letar efter en mall för en anpassad posttyp, och prioriteten för
single-{post_type}.php - Kopiera ditt temas
single.php, döp om den för din CPT och anpassa den - Utforska en alternativ metod via
template_include-filtret (praktiskt om du inte vill röra temat) - Skapa själva den anpassade posttypen med hjälp av tillägget Custom Post Type UI, snabbt och utan kod
1. Hur WordPress väljer en mall för en anpassad posttyp
WordPress mallhierarki är en kedja av filer som kärnan kontrollerar för att hitta rätt mall för att rendera en sida. För standardinlägg är kedjan lång: single-post.php → single.php → singular.php → index.php. För anpassade posttyper är den kortare, men logiken är densamma.
När en besökare öppnar ett anpassat inlägg av typen aktsii kontrollerar WordPress filer i denna ordning:
single-aktsii.php, mallen specifikt för denna anpassade posttypsingle.php, den generiska mallen för enskilda inläggsingular.php, mallen för allt singulärt innehåll (inlägg, sida, CPT)index.php, den slutliga fallbacken
Den första filen som hittas i kedjan är den som används för rendering. Om single-aktsii.php finns, plockar WordPress upp den och stannar. Om den inte hittas går kärnan vidare till single.php. Det är precis därför din anpassade posttyp ser ut som ett vanligt inlägg: det finns ingen single-aktsii.php-fil, så kärnan faller tillbaka på den generiska single.php.
Lösningen följer direkt av detta: skapa single-{post_type}.php, så plockar WordPress upp den automatiskt.
2. Skapa en mallfil: kopiera single.php och döp om den
Detta är den enklaste och mest pålitliga metoden. Den fungerar med alla klassiska teman och kräver inga tillägg eller filter.
Steg 1: hitta ditt temas single.php. Den ligger i temamappens rot: /wp-content/themes/your-theme/single.php. Om temat använder FSE (Full Site Editing) och är byggt på block, kanske denna fil inte finns, och filtermetoden (template_include) blir smidigare (avsnitt 4).
Steg 2: kopiera och döp om. Kopiera single.php och namnge den enligt mönstret single-{slug}.php: ersätt {slug} med sluggen för din anpassade posttyp (den som angavs vid registreringen, med latinska tecken). Till exempel, för en typ med sluggen aktsii:
1 single-aktsii.php
För en typ med sluggen portfolio skulle filen heta single-portfolio.php. För testimonials blir det single-testimonials.php. Viktigt: sluggen måste matcha den som angavs i parametern 'rewrite' => array('slug' => '...') vid registreringen.
Steg 3: placera filen tillbaka i temamappen. WordPress kommer automatiskt att plocka upp den för alla inlägg av denna typ. Ingen ytterligare konfiguration behövs; mallhierarkin hanterar det automatiskt.
Steg 4: verifiera. Öppna ett inlägg av den anpassade typen på frontend. Om du ser samma sida som tidigare, kontrollera filnamnet (skiftlägeskänslighet, bindestreck istället för understreck) och rensa cachen. Om filen skapades i ett barntema och föräldratemat också innehåller single-{post_type}.php, har barntemat prioritet.
3. Anpassa mallinnehållet
Den kopierade single.php är fortfarande identisk med originalet; den renderar helt enkelt samma generiska layout. Nu fyller vi den med innehåll specifikt för den anpassade posttypen.
3.1. Grundstruktur: skriva ut anpassade fält
Anta att den anpassade posttypen aktsii har fälten aktsiya_data_start, aktsiya_data_end och aktsiya_skidka (skapade via ACF, Meta Box eller manuellt). Här är en minimal mall som skriver ut dem:
1 <?php 2 /** 3 * Template for custom type "Promotions" (single-aktsii.php) 4 */ 5 6 get_header(); 7 ?> 8 9 <main id="main" class="site-main" role="main"> 10 11 <?php while ( have_posts() ) : the_post(); ?> 12 13 <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>> 14 15 <header class="entry-header"> 16 <?php the_title( '<h1 class="entry-title">', '</h1>' ); ?> 17 </header> 18 19 <?php if ( has_post_thumbnail() ) : ?> 20 <div class="post-thumbnail"> 21 <?php the_post_thumbnail( 'large' ); ?> 22 </div> 23 <?php endif; ?> 24 25 <div class="entry-content"> 26 <?php the_content(); ?> 27 28 <div class="custom-fields"> 29 <?php 30 $data_start = get_post_meta( get_the_ID(), 'aktsiya_data_start', true ); 31 $data_end = get_post_meta( get_the_ID(), 'aktsiya_data_end', true ); 32 $skidka = get_post_meta( get_the_ID(), 'aktsiya_skidka', true ); 33 34 if ( $data_start ) { 35 echo '<p><strong>Start Date:</strong> ' . esc_html( $data_start ) . '</p>'; 36 } 37 if ( $data_end ) { 38 echo '<p><strong>End Date:</strong> ' . esc_html( $data_end ) . '</p>'; 39 } 40 if ( $skidka ) { 41 echo '<p><strong>Discount:</strong> ' . esc_html( $skidka ) . '%</p>'; 42 } 43 ?> 44 </div> 45 </div> 46 47 </article> 48 49 <?php 50 if ( comments_open() || get_comments_number() ) : 51 comments_template(); 52 endif; 53 ?> 54 55 <?php endwhile; ?> 56 57 </main> 58 59 <?php 60 get_sidebar(); 61 get_footer();
Detta är en fullt fungerande mall som du kan släppa in i ditt tema som den är. Den skriver ut titeln, den utvalda bilden, innehållet och tre anpassade fält i ett separat block.
3.2. Vad mer du kan göra med mallen
Härifrån är möjligheterna till anpassning praktiskt taget obegränsade:
- Ta bort sidopanelen: ta helt enkelt bort anropet
get_sidebar(). - Ändra HTML-omslaget: ersätt
<article>med en<div>som bär den klass du behöver, lägg till ditt eget grid. - Anropa en specifik malldel: till exempel
get_template_part( 'template-parts/content', 'aktsii' )och håll logiken i en separat fil. - Köa anpassade stilar: via
wp_enqueue_style()inutifunctions.phpmed enis_singular( 'aktsii' )-kontroll.
En viktig notering: om temat uppdateras kan en fil i föräldratemat skrivas över. Så arbeta antingen i ett barntema, eller använd filtermetoden från nästa avsnitt.
4. Alternativ metod: filtret template_include
Om du föredrar att inte modifiera temafiler (eller om temat är blockbaserat och saknar en klassisk single.php), kan du tilldela en mall via hooken template_include. Den körs innan WordPress inkluderar mallfilen och låter dig åsidosätta sökvägen.
Nackdel: du måste lagra mallfilen antingen i ett tillägg eller i ett barntema, och koden måste peka på rätt sökväg. Fördel: logiken går inte förlorad när föräldratemat uppdateras.
4.1. Exempel: en CPT, en mall
Lägg till detta i barntemats functions.php (eller i ett MU-plugin):
1 add_filter( 'template_include', 'techblog_cpt_template', 99 ); 2 3 function techblog_cpt_template( $template ) { 4 if ( is_singular( 'aktsii' ) ) { 5 $custom_template = get_stylesheet_directory() . '/single-aktsii.php'; 6 if ( file_exists( $custom_template ) ) { 7 return $custom_template; 8 } 9 } 10 return $template; 11 }
Koden kontrollerar om den aktuella sidan tillhör den anpassade posttypen aktsii. Om så är fallet letar den efter filen single-aktsii.php i barntemats mapp (get_stylesheet_directory()) och returnerar den. Om filen inte hittas returneras den förvalda $template oförändrad.
4.2. Exempel: flera CPT:er med en enda hanterare
Om du har flera anpassade posttyper är det praktiskt att konsolidera logiken i ett filter:
1 add_filter( 'template_include', 'techblog_cpt_templates', 99 ); 2 3 function techblog_cpt_templates( $template ) { 4 $cpt_templates = array( 5 'aktsii' => 'single-aktsii.php', 6 'portfolio' => 'single-portfolio.php', 7 'testimonials' => 'single-testimonials.php', 8 ); 9 10 foreach ( $cpt_templates as $cpt => $template_file ) { 11 if ( is_singular( $cpt ) ) { 12 $custom_template = get_stylesheet_directory() . '/' . $template_file; 13 if ( file_exists( $custom_template ) ) { 14 return $custom_template; 15 } 16 } 17 } 18 19 return $template; 20 }
Nu får varje CPT sin egen mall, och all logik finns i en enda funktion.
4.3. Lagra mallar i ett tillägg
Om du distribuerar den anpassade posttypen som ett tillägg (snarare än som en del av ett tema), är det vettigt att lagra mallen i tilläggets mapp. I så fall anger du sökvägen via plugin_dir_path( __FILE__ ):
1 add_filter( 'template_include', 'myplugin_cpt_template', 99 ); 2 3 function myplugin_cpt_template( $template ) { 4 if ( is_singular( 'aktsii' ) ) { 5 $custom_template = plugin_dir_path( __FILE__ ) . 'templates/single-aktsii.php'; 6 if ( file_exists( $custom_template ) ) { 7 return $custom_template; 8 } 9 } 10 return $template; 11 }
Detta mönster används av många populära tillägg (WooCommerce, Easy Digital Downloads, The Events Calendar): de levererar mallar internt och inkluderar dem via filtret.
5. Skapa den anpassade posttypen
Vi har mallen redo, men för fullständighetens skull, några ord om var själva den anpassade posttypen kommer ifrån.
5.1. Registrering via kod
En minimal CPT-registrering i functions.php eller ett MU-plugin:
1 add_action( 'init', 'techblog_register_cpt_aktsii' ); 2 3 function techblog_register_cpt_aktsii() { 4 $labels = array( 5 'name' => 'Promotions', 6 'singular_name' => 'Promotion', 7 'menu_name' => 'Promotions', 8 ); 9 10 $args = array( 11 'labels' => $labels, 12 'public' => true, 13 'has_archive' => true, 14 'supports' => array( 'title', 'editor', 'thumbnail' ), 15 'rewrite' => array( 'slug' => 'aktsii' ), 16 'show_in_rest' => true, 17 ); 18 19 register_post_type( 'aktsii', $args ); 20 }
Nyckeldetaljen här är att parametern 'rewrite' => array( 'slug' => 'aktsii' ) sätter sluggen som används både i URL:en och i mallfilens namn. Om sluggen är aktsii måste mallfilen heta single-aktsii.php.
5.2. Använda tillägget Custom Post Type UI
Om du hellre inte vill redigera functions.php kan du skapa en CPT visuellt med det kostnadsfria tillägget Custom Post Type UI på WordPress.org. Efter installation:
- Gå i adminpanelen till CPT UI → Add/Edit Post Types
- Fyll i fälten: Post Type Slug (latinska tecken), Plural Label, Singular Label
- På fliken Settings väljer du vilka redigeringsfunktioner du behöver (titel, editor, utvald bild)
- Klicka på Add Post Type
Tillägget genererar PHP-registreringskoden, som du kan exportera och klistra in i functions.php. Detta är praktiskt om du senare vill ta bort beroendet av tillägget. Sluggen du angav i CPT UI är densamma som går in i mallfilens namn.
⁉️🤔 Vanliga frågor
Vad ska jag göra om mallen inte plockas upp efter att filen skapats?
Spola permalänkarna: gå till Inställningar → Permalänkar och klicka på "Spara ändringar" (du behöver inte ändra något). WordPress bygger om sina routingregler. Om det inte hjälper, kontrollera filnamnet: den anpassade posttypens slug och filnamnet måste matcha (skiftläge, bindestreck och understreck). Som ett tredje steg, rensa cachen i ditt cachingtillägg, om ett sådant är installerat. Permalänkar bör spolas efter registrering av varje ny anpassad posttyp, inte bara när du stöter på mallproblem. Detta är standardpraxis: gå till Inställningar → Permalänkar → Spara, så börjar de nya URL:erna fungera omedelbart.
Kan jag använda en mall för flera anpassade posttyper?
Ja, på två sätt. För det första, skapa en fysisk fil
single-aktsii.php, och för den andra typen (sägportfolio) kopiera den somsingle-portfolio.php. För det andra, användtemplate_include-filtret (avsnitt 4): i arrayen$cpt_templates, peka olika typer till samma mallfil. I praktiken har dock olika CPT:er nästan alltid olika layouter; att kopiera och redigera är enklare än att bygga villkorlig logik inuti en enda mall. Om du verkligen har många typer med identisk logik, skapa en deladsingle-cpt.php, kontrolleraget_post_type()inuti den och inkludera motsvarande malldel viaget_template_part( 'template-parts/content', get_post_type() ). Detta är en ren och skalbar metod.
Behöver jag skapa archive-{post_type}.php** för arkivsidan?**
Det rekommenderas men krävs inte. Utan den använder WordPress
archive.phpellerindex.php. Om CPT:n har'has_archive' => trueoch arkivet öppnas på/aktsii/men det inte finns någonarchive-aktsii.php-fil, kommer den generiskaarchive.phpatt användas. Att skapa en separat arkivmall är vettigt när inläggsgriden, kolumnlayouten eller sidopanelen ska skilja sig från bloggarkivet.
Fungerar detta med blockteman (FSE)?
I blockteman är klassiska PHP-mallfiler inte den primära metoden. Men
template_include-filtret (avsnitt 4) fungerar även i FSE: du kan placerasingle-aktsii.phpi ett barntema eller tillägg och inkludera den via filtret. Alternativt kan du i Webbplatsredigeraren skapa en mall för en specifik anpassad posttyp via gränssnittet: Utseende → Redigerare → Mallar → Lägg till ny mall → Enskilt objekt: Aktsii. WordPress sparar den som en HTML-mall i databasen, och den fungerar utan några filer i temat.
Vad ska man välja 2026: fil eller filter?
En snabb beslutsmatris för att välja metod:
Scenario | Vad du ska använda |
|---|---|
Klassiskt tema, en eller två CPT:er |
|
Barntema, du lägger till CPT:n | Fil i barntemat, överlever uppdateringar av föräldratemat |
Blocktema (FSE), CPT via ett tillägg |
|
CPT distribuerad som ett tillägg | Filter + mall inuti tilläggets mapp |
Många CPT:er med liknande struktur | Filter + delad |
I praktiken använder vi på techblog.sdstudio.top oftast en kombination: registrera CPT:n via kod i ett MU-plugin och placera mallarna som filer i ett barntema. Detta ger automatisk upphämtning utan extra filter, och uppdateringar av föräldratemat förstör ingenting.
Om du precis har börjat lära dig om anpassade posttyper, börja med filen single-{post_type}.php. Det tar fem minuter och ger omedelbara resultat. När du känner att den filbaserade metoden inte längre räcker till (du behöver ladda mallar från ett tillägg eller byta dem i farten), byt till template_include. Båda metoderna är fullt legitima och stöds av WordPress kärna.



