WordPress Excerpt Uzunluğunu ve Devamını Özelleştirme
WordPress sitenizde blog yazılarını listelerken varsayılan excerpt uzunluğu çoğu zaman ya çok kısa kalır ya da tasarımınıza uymaz. Üstelik “Devamını Oku” linkinin görünümü de genellikle berbat bir [...] işaretiyle biter. Bu rehberde functions.php dosyasına ekleyeceğiniz kod parçalarıyla excerpt sisteminizi tamamen kontrol altına alacaksınız.
WordPress Excerpt Sistemi Nasıl Çalışır?
WordPress, her yazı için otomatik olarak bir özet (excerpt) oluşturur. Bu özet iki farklı şekilde gelir:
- Manuel excerpt: Yazı düzenleme ekranındaki “Özet” kutusuna elle yazdığınız metin
- Otomatik excerpt: Manuel özet yoksa WordPress’in yazının başından itibaren kestiği metin
the_excerpt() fonksiyonunu çağırdığınızda WordPress şu sırayla kontrol eder: Manuel özet varsa onu kullanır, yoksa yazının içeriğinden otomatik olarak wp_trim_excerpt() fonksiyonuyla bir özet üretir. Varsayılan uzunluk 55 kelimedir ve sonuna [...] eklenir.
Bu davranışı değiştirmek için functions.php dosyasındaki hook sistemi devreye girer. excerpt_length ve excerpt_more filtreleri bu işin tam merkezindedir.
Excerpt Uzunluğunu Değiştirme
En temel ihtiyaç: varsayılan 55 kelimeyi değiştirmek. Bunu yapmak için excerpt_length filtresini kullanıyoruz.
// functions.php
function custom_excerpt_length( $length ) {
return 30; // Kelime sayısını istediğiniz değere ayarlayın
}
add_filter( 'excerpt_length', 'custom_excerpt_length', 999 );
Öncelik değeri olarak 999 kullanmamızın nedeni, bazı tema ve eklentilerin de bu filtreyi kullanmasıdır. Yüksek öncelik vermek, bizim kodumuzun en son çalışmasını ve diğerlerini ezmesini sağlar.
Gerçek dünya senaryosu olarak düşünün: Ana sayfanızda 3 kolonlu bir grid yapınız var ve her kutucukta özet metni gösteriyorsunuz. 55 kelimelik özet tasarımı mahvediyor, 20-25 kelime çok daha temiz duruyor.
// Ana sayfa ve arşiv sayfaları için farklı uzunluklar
function custom_excerpt_length( $length ) {
if ( is_home() || is_front_page() ) {
return 20; // Ana sayfa için kısa tut
} elseif ( is_archive() || is_category() ) {
return 35; // Arşiv sayfaları için biraz daha uzun
} elseif ( is_search() ) {
return 25; // Arama sonuçları için orta uzunluk
}
return 55; // Diğer durumlar için varsayılan
}
add_filter( 'excerpt_length', 'custom_excerpt_length', 999 );
Bu yaklaşım özellikle büyük sitelerde işe yarar. Kategori sayfalarında daha detaylı özet isterken ana sayfada kompakt tutabilirsiniz.
“Devamını Oku” Linkini Özelleştirme
Varsayılan [...] son derece çirkin ve kullanıcı deneyimi açısından yetersiz. excerpt_more filtresiyle bunu güzel bir “Devamını Oku” linkine dönüştürebiliriz.
// Temel "Devamını Oku" linki
function custom_excerpt_more( $more ) {
return '... <a class="read-more-link" href="' . get_permalink() . '">Devamını Oku →</a>';
}
add_filter( 'excerpt_more', 'custom_excerpt_more' );
Bu kodu ekledikten sonra her excerpt sonunda tıklanabilir bir “Devamını Oku” linki görünür. → HTML entity’si sağa yönlü ok karakteri üretir, görsel olarak daha çekici bir görünüm sağlar.
Daha gelişmiş bir versiyon için CSS sınıfları ekleyip butona benzer bir tasarım yapabilirsiniz:
// Buton stilinde "Devamını Oku"
function custom_excerpt_more( $more ) {
global $post;
return '<span class="excerpt-ellipsis">...</span>
<p class="read-more-wrapper">
<a class="btn btn-primary read-more-btn"
href="' . get_permalink( $post->ID ) . '"
title="' . get_the_title( $post->ID ) . ' - Devamını Oku">
Tamamını Oku
</a>
</p>';
}
add_filter( 'excerpt_more', 'custom_excerpt_more' );
global $post kullanımına dikkat edin. get_permalink() bu bağlamda doğru post ID’sini her zaman yakalayamayabilir, bu yüzden $post->ID ile açıkça belirtmek daha güvenlidir.
Karakter Bazlı Excerpt Kesme
Bazen kelime sayısı yerine karakter sayısına göre kesme yapmak gerekir. Özellikle Türkçe içeriklerde, uzun kelimeler olduğu için kelime bazlı kesme tutarsız görünümler yaratabilir.
// Karakter bazlı excerpt fonksiyonu
function get_excerpt_by_chars( $char_limit = 150, $post_id = null ) {
if ( ! $post_id ) {
global $post;
$post_id = $post->ID;
}
$post_object = get_post( $post_id );
// Manuel excerpt varsa önce onu kullan
if ( ! empty( $post_object->post_excerpt ) ) {
return $post_object->post_excerpt;
}
$content = $post_object->post_content;
// Shortcode ve HTML taglarını temizle
$content = strip_shortcodes( $content );
$content = wp_strip_all_tags( $content );
$content = trim( $content );
// Karakter limitini uygula
if ( mb_strlen( $content ) > $char_limit ) {
$content = mb_substr( $content, 0, $char_limit );
// Son tam kelimede kes, ortada bırakma
$last_space = mb_strrpos( $content, ' ' );
if ( $last_space !== false ) {
$content = mb_substr( $content, 0, $last_space );
}
$content .= '...';
}
return $content;
}
Bu fonksiyonu tema dosyalarında şöyle kullanabilirsiniz:
// Template dosyasında kullanım
echo get_excerpt_by_chars( 200 ); // 200 karakter
echo get_excerpt_by_chars( 150, 42 ); // Belirli bir post için
mb_strlen ve mb_substr kullanmak Türkçe karakterler için kritik önem taşır. PHP’nin standart strlen fonksiyonu çok baytlı UTF-8 karakterleri doğru saymaz, bu yüzden Türkçe içeriklerde mutlaka multibyte fonksiyonlarını kullanın.
Post Türüne Göre Excerpt Ayarları
Farklı post türleri için farklı excerpt davranışları isteyebilirsiniz. Örneğin normal blog yazılarında 30 kelime, ürün yazılarında 15 kelime, duyurularda 50 kelime gibi.
// Post türüne göre dinamik excerpt uzunluğu
function dynamic_excerpt_length( $length ) {
global $post;
if ( ! $post ) {
return $length;
}
$excerpt_lengths = array(
'post' => 30, // Normal blog yazıları
'page' => 40, // Sayfalar
'duyuru' => 50, // Özel post türü: duyurular
'portfolio' => 20, // Özel post türü: portfolyo
'product' => 15, // WooCommerce ürünleri
);
$post_type = get_post_type( $post );
if ( isset( $excerpt_lengths[ $post_type ] ) ) {
return $excerpt_lengths[ $post_type ];
}
return 30; // Tanımlı olmayan post türleri için varsayılan
}
add_filter( 'excerpt_length', 'dynamic_excerpt_length', 999 );
Bu yaklaşımın güzelliği, yeni bir custom post type eklediğinizde sadece $excerpt_lengths dizisine bir satır eklemeniz yeterli. Fonksiyonu tekrar yazmanıza gerek yok.
HTML Destekli Özel Excerpt Fonksiyonu
Bazen the_excerpt() yerine tamamen özelleştirilmiş bir excerpt fonksiyonu yazmak gerekir. Özellikle içerikte görseller, listeler veya özel HTML yapıları varsa.
// Gelişmiş custom excerpt fonksiyonu
function advanced_custom_excerpt( $args = array() ) {
global $post;
$defaults = array(
'length' => 30, // Kelime sayısı
'more_text' => 'Devamını Oku',
'more_class' => 'read-more',
'ellipsis' => '...',
'strip_html' => true, // HTML taglarını temizle
'allowed_tags' => '<p><strong><em>', // İzin verilen tagler
'post_id' => null,
);
$args = wp_parse_args( $args, $defaults );
$post_id = $args['post_id'] ? $args['post_id'] : $post->ID;
$post_data = get_post( $post_id );
// Manuel excerpt kontrolü
if ( ! empty( $post_data->post_excerpt ) ) {
$excerpt = $post_data->post_excerpt;
} else {
$content = $post_data->post_content;
$content = strip_shortcodes( $content );
if ( $args['strip_html'] ) {
$content = wp_strip_all_tags( $content );
} else {
$content = strip_tags( $content, $args['allowed_tags'] );
}
$words = preg_split( '/s+/', trim( $content ), -1, PREG_SPLIT_NO_EMPTY );
$excerpt = implode( ' ', array_slice( $words, 0, $args['length'] ) );
if ( count( $words ) > $args['length'] ) {
$excerpt .= $args['ellipsis'];
}
}
$read_more_link = sprintf(
' <a href="%s" class="%s">%s</a>',
get_permalink( $post_id ),
esc_attr( $args['more_class'] ),
esc_html( $args['more_text'] )
);
return '<p>' . $excerpt . $read_more_link . '</p>';
}
Bu fonksiyonu template dosyalarında şöyle kullanabilirsiniz:
// Basit kullanım
echo advanced_custom_excerpt();
// Özelleştirilmiş kullanım
echo advanced_custom_excerpt( array(
'length' => 25,
'more_text' => 'Yazının Devamı →',
'more_class' => 'btn btn-outline-primary',
'ellipsis' => ' ...',
) );
// Belirli bir post için
echo advanced_custom_excerpt( array(
'post_id' => 123,
'length' => 20,
) );
wp_parse_args() kullanımı WordPress’e özgü güzel bir pattern’dir. Varsayılan değerler ile kullanıcı tarafından geçilen değerleri birleştirir. Bunu array_merge yerine kullanmak daha semantik bir yaklaşımdır.
Tag’ini Özelleştirme
WordPress editöründe tag’i koyduğunuzda bu, excerpt’in nerede kesileceğini manuel olarak belirler. Bu tag’den önceki içerik excerpt olarak kullanılır. Bunu da özelleştirebilirsiniz.
// <!--more--> tag'ini custom metinle kullanma
// Editörde şöyle yazabilirsiniz:
// <!--more Haberin Devamı İçin Tıklayın-->
function custom_more_tag_text( $more_link, $more_link_element ) {
return str_replace(
'more-link',
'more-link custom-more-link',
$more_link
);
}
add_filter( 'the_content_more_link', 'custom_more_tag_text', 10, 2 );
Daha gelişmiş bir kontrol için:
// the_content_more_link filteriyle tam kontrol
function customize_more_link( $more_link, $more_link_element ) {
// Orijinal linki kaldır, kendi stilini ekle
return '<div class="read-more-container">
<a href="' . get_permalink() . '#more-' . get_the_ID() . '"
class="custom-read-more-btn">
<span>Devamını Oku</span>
<svg width="16" height="16" viewBox="0 0 24 24">
<path d="M5 12h14M12 5l7 7-7 7"/>
</svg>
</a>
</div>';
}
add_filter( 'the_content_more_link', 'customize_more_link', 10, 2 );
WooCommerce Ürün Excerpt Özelleştirme
WooCommerce kullananlar için ürün kısa açıklamaları (short description) ayrı bir excerpt sistemiyle çalışır. Ama ürün arşiv sayfalarında gösterilen excerpt’i de kontrol edebilirsiniz.
// WooCommerce ürün arşivi için excerpt uzunluğu
function woo_product_excerpt_length( $length ) {
if ( is_shop() || is_product_category() || is_product_tag() ) {
return 15; // Ürün listelerinde kısa tut
}
return $length;
}
add_filter( 'excerpt_length', 'woo_product_excerpt_length', 999 );
// Ürün kısa açıklamasına karakter limiti uygula
function limit_woo_short_description( $description ) {
if ( ! is_product() ) {
return $description;
}
$limit = 200; // Karakter limiti
$description = strip_tags( $description );
if ( mb_strlen( $description ) > $limit ) {
$description = mb_substr( $description, 0, $limit ) . '...';
}
return '<p>' . $description . '</p>';
}
add_filter( 'woocommerce_short_description', 'limit_woo_short_description' );
Bu kodu eklerken dikkatli olun: woocommerce_short_description filtresi sadece kısa açıklamayı etkiler, uzun ürün açıklamasını değil. WooCommerce ürün sayfalarında zaten tam açıklama gösterildiği için bu filtre sadece arşiv ve widget’larda görünen yerde işe yarar.
Excerpt Cache ile Performans Optimizasyonu
Büyük sitelerde her sayfa yüklemesinde excerpt hesaplamak performansı etkileyebilir. Transient API ile excerpt’leri önbelleğe alabiliriz.
// Excerpt'leri cache'le
function get_cached_excerpt( $post_id = null, $length = 30 ) {
if ( ! $post_id ) {
global $post;
$post_id = $post->ID;
}
$cache_key = 'excerpt_' . $post_id . '_' . $length;
$cached = get_transient( $cache_key );
if ( false !== $cached ) {
return $cached;
}
$post_data = get_post( $post_id );
if ( ! empty( $post_data->post_excerpt ) ) {
$excerpt = $post_data->post_excerpt;
} else {
$content = strip_shortcodes( $post_data->post_content );
$content = wp_strip_all_tags( $content );
$words = preg_split( '/s+/', trim( $content ), -1, PREG_SPLIT_NO_EMPTY );
$excerpt = implode( ' ', array_slice( $words, 0, $length ) );
if ( count( $words ) > $length ) {
$excerpt .= '...';
}
}
// 12 saat cache'le
set_transient( $cache_key, $excerpt, 12 * HOUR_IN_SECONDS );
return $excerpt;
}
// Post güncellendiğinde cache'i temizle
function clear_excerpt_cache( $post_id ) {
// Farklı uzunluklar için cache'leri temizle
$lengths = array( 15, 20, 25, 30, 35, 40, 50, 55 );
foreach ( $lengths as $length ) {
delete_transient( 'excerpt_' . $post_id . '_' . $length );
}
}
add_action( 'save_post', 'clear_excerpt_cache' );
add_action( 'edit_post', 'clear_excerpt_cache' );
Cache mekanizması yoğun trafikli sitelerde gerçekten fark yaratır. Özellikle ana sayfada 10-20 yazının excerpt’ini aynı anda çektiğinizde, her birinin veritabanı sorgusu olmadan gelmesi sayfa yükleme süresini belirgin şekilde düşürür.
Sık Yapılan Hatalar ve Çözümleri
Hook önceliği çakışmaları: Temanız zaten excerpt_length filtresini kullanıyorsa add_filter( 'excerpt_length', 'custom_excerpt_length' ) dediğinizde hiçbir şey değişmeyebilir. Önceliği yüksek tutun, 999 genellikle güvenlidir.
get_the_excerpt() vs the_excerpt(): get_the_excerpt() string döndürür, the_excerpt() direkt ekrana basar. Template dosyalarında echo get_the_excerpt() ile the_excerpt() aynı sonucu verir ama get_the_excerpt() kullanmak kodu daha okunabilir kılar.
Manuel excerpt HTML içeriyorsa: Manuel olarak girilen excerpt wpautop() filtresinden geçer ve paragraf tagleri eklenir. Bunu istemiyorsanız the_excerpt filtresini kullanarak temizleyebilirsiniz.
// Manuel excerpt'teki otomatik paragraf eklemeyi devre dışı bırak
remove_filter( 'the_excerpt', 'wpautop' );
Post döngüsü dışında excerpt: the_excerpt() veya get_the_excerpt() fonksiyonlarını WordPress loop döngüsü dışında kullandığınızda yanlış post verisi döner. Bunun yerine her zaman get_the_excerpt( $post_id ) şeklinde açıkça post ID geçin.
Sonuç
WordPress excerpt sistemi, functions.php dosyasına ekleyeceğiniz birkaç satır kodla tamamen özelleştirilebilir bir yapıya sahiptir. Özetle yapabilecekleriniz şunlar:
excerpt_lengthfiltresi ile kelime sayısını site geneli veya sayfa türüne göre ayarlayınexcerpt_morefiltresi ile[...]yerine güzel ve tıklanabilir bir “Devamını Oku” linki ekleyin- Karakter bazlı kesme için custom fonksiyon yazın, Türkçe içerikler için
mb_prefix’li fonksiyonları kullanın - Post türüne göre farklı uzunluklar belirleyin
- WooCommerce entegrasyonu için ayrı filtreler kullanın
- Transient cache ile performansı artırın
Tüm bu özelleştirmeleri yaparken en önemli nokta, functions.php dosyasına yazdığınız fonksiyon isimlerinin mevcut WordPress fonksiyonları veya eklenti fonksiyonlarıyla çakışmamasıdır. Fonksiyon isimlerinizi proje veya tema adınıza özgü bir prefix ile başlatmak bu riski ortadan kaldırır. Örneğin mytheme_excerpt_length() gibi bir isimlendirme kullanmak en sağlıklı yaklaşımdır.
