WordPress’te Özel Shortcode Oluşturma: Temel Örnekler
WordPress ile çalışırken er ya da geç şu soruyla karşılaşırsın: “Bu içeriği her sayfaya kopyalayıp yapıştırmak yerine daha akıllıca bir yol yok mu?” İşte tam bu noktada shortcode’lar devreye giriyor. Shortcode’lar, WordPress’in sunduğu en pratik özelliklerden biri ve doğru kullanıldığında hem geliştirici hem de editör hayatını ciddi ölçüde kolaylaştırıyor. Bu yazıda functions.php dosyasına ekleyebileceğin gerçek dünya senaryolarıyla özel shortcode’lar oluşturmayı ele alacağız.
Shortcode Nedir, Neden Kullanmalısın?
Shortcode, köşeli parantez içine yazılan kısa bir etiket sistemi. [iletisim_formu] ya da [son_urunler adet="5"] gibi. WordPress bu etiketleri sayfa veya yazı içinde gördüğünde, arkada tanımladığın PHP fonksiyonunu çalıştırıyor ve çıktısını oraya yerleştiriyor.
Neden kullanmalısın?
- Tekrar eden içerikleri tek yerden yönetirsin, bir düzenleme tüm sayfalara yansır
- Editörlere PHP bilgisi gerektirmeden dinamik içerik ekleme imkanı tanırsın
- Kod karmaşasını azaltırsın, şablon dosyaları temiz kalır
- Bakım kolaylığı sağlarsın, iş mantığı tek bir fonksiyonda toplanır
Shortcode’ların functions.php dosyasında mı yoksa özel bir eklentide mi tutulması gerektiği tartışması var. Eğer tema değiştirdiğinde bu fonksiyonların çalışmaya devam etmesini istiyorsan, küçük bir “site-specific plugin” oluşturmak daha mantıklı. Ama hızlı denemeler ve tema’ya özgü işlevler için functions.php gayet uygun.
Temel Shortcode Yapısı
Önce iskelet kodu görelim. add_shortcode() fonksiyonu iki parametre alır: shortcode adı ve bu shortcode çağrıldığında çalışacak fonksiyon.
// functions.php dosyasına eklenir
function basit_mesaj_shortcode() {
return '<p class="ozel-mesaj">Merhaba, bu bir shortcode çıktısı!</p>';
}
add_shortcode( 'mesaj', 'basit_mesaj_shortcode' );
Sayfana [mesaj] yazınca bu paragraf görünür. Dikkat etmen gereken en önemli nokta: shortcode fonksiyonları echo değil, return kullanır. echo ile yazdığında çıktı sayfanın yanlış yerine gelir.
Parametreli Shortcode: Gerçek Gücün Başladığı Yer
Asıl esnekliği $atts parametresiyle yakalıyorsun. Kullanıcıların shortcode’a özelleştirilmiş değerler geçirmesine izin veriyorsun.
function uyari_kutusu_shortcode( $atts, $content = null ) {
// Varsayılan değerler ve kullanıcı değerlerini birleştir
$atts = shortcode_atts(
array(
'tip' => 'bilgi',
'baslik' => 'Dikkat',
'renk' => '#3498db',
),
$atts,
'uyari_kutusu'
);
$tip = sanitize_text_field( $atts['tip'] );
$baslik = sanitize_text_field( $atts['baslik'] );
$renk = sanitize_hex_color( $atts['renk'] );
$cikti = '<div class="uyari-kutusu uyari-' . esc_attr( $tip ) . '" ';
$cikti .= 'style="border-left: 4px solid ' . esc_attr( $renk ) . ';">';
$cikti .= '<strong>' . esc_html( $baslik ) . '</strong>';
if ( $content ) {
$cikti .= '<p>' . esc_html( $content ) . '</p>';
}
$cikti .= '</div>';
return $cikti;
}
add_shortcode( 'uyari_kutusu', 'uyari_kutusu_shortcode' );
Bu shortcode’u şu şekillerde kullanabilirsin:
[uyari_kutusu]– Tüm varsayılan değerlerle[uyari_kutusu tip="hata" baslik="Dikkat!" renk="#e74c3c"]İçerik buraya[/uyari_kutusu][uyari_kutusu tip="basari" baslik="Tamamlandı" renk="#2ecc71"]
shortcode_atts() kullanmak kritik. Bu fonksiyon hem varsayılan değerleri ayarlıyor hem de kullanıcının geçirdiği bilinmeyen parametreleri filtreliyor, güvenlik açısından önemli.
İçerik Alan (Wrapping) Shortcode’lar
Açılış ve kapanış etiketi kullanan shortcode’lar, $content parametresiyle içeriği işleyebiliyor.
function kart_shortcode( $atts, $content = null ) {
$atts = shortcode_atts(
array(
'baslik' => '',
'resim' => '',
'class' => '',
),
$atts,
'kart'
);
$ekstra_class = sanitize_html_class( $atts['class'] );
$html = '<div class="ozel-kart ' . $ekstra_class . '">';
if ( ! empty( $atts['resim'] ) ) {
$html .= '<div class="kart-resim">';
$html .= '<img src="' . esc_url( $atts['resim'] ) . '" alt="' . esc_attr( $atts['baslik'] ) . '">';
$html .= '</div>';
}
$html .= '<div class="kart-icerik">';
if ( ! empty( $atts['baslik'] ) ) {
$html .= '<h3 class="kart-baslik">' . esc_html( $atts['baslik'] ) . '</h3>';
}
// İçerikteki shortcode'ların da işlenmesi için do_shortcode kullanıyoruz
if ( $content ) {
$html .= '<div class="kart-metin">' . do_shortcode( $content ) . '</div>';
}
$html .= '</div></div>';
return $html;
}
add_shortcode( 'kart', 'kart_shortcode' );
Kullanımı:
[kart baslik="Ürün Adı" resim="https://site.com/resim.jpg" class="ozellik-karti"]
Bu ürün hakkında detaylı açıklama buraya gelir.
[/kart]
do_shortcode( $content ) çağrısına dikkat et. İçeride başka shortcode’lar varsa bunların da işlenmesini sağlıyor. Shortcode içinde shortcode kullanmak istediğinde bu şart.
WooCommerce Entegrasyonu: Son Ürünler Shortcode’u
Gerçek dünya senaryosuna geçelim. Bir e-ticaret sitesinde herhangi bir sayfaya son eklenen ürünleri listelemek istiyorsun.
function son_urunler_shortcode( $atts ) {
// WooCommerce aktif mi kontrol et
if ( ! class_exists( 'WooCommerce' ) ) {
return '<p>WooCommerce aktif değil.</p>';
}
$atts = shortcode_atts(
array(
'adet' => 4,
'kategori' => '',
'sirala' => 'date',
'duzeni' => 'DESC',
),
$atts,
'son_urunler'
);
$args = array(
'post_type' => 'product',
'posts_per_page' => intval( $atts['adet'] ),
'orderby' => sanitize_key( $atts['sirala'] ),
'order' => in_array( strtoupper( $atts['duzeni'] ), array( 'ASC', 'DESC' ) ) ? strtoupper( $atts['duzeni'] ) : 'DESC',
'post_status' => 'publish',
);
if ( ! empty( $atts['kategori'] ) ) {
$args['tax_query'] = array(
array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => sanitize_text_field( $atts['kategori'] ),
),
);
}
$urunler = new WP_Query( $args );
$html = '';
if ( $urunler->have_posts() ) {
$html .= '<div class="ozel-urun-grid">';
while ( $urunler->have_posts() ) {
$urunler->the_post();
global $product;
$product = wc_get_product( get_the_ID() );
if ( ! $product ) continue;
$html .= '<div class="urun-karti">';
$html .= '<a href="' . esc_url( get_permalink() ) . '">';
$html .= get_the_post_thumbnail( get_the_ID(), 'medium', array( 'class' => 'urun-resmi' ) );
$html .= '<h4>' . esc_html( get_the_title() ) . '</h4>';
$html .= '<span class="fiyat">' . $product->get_price_html() . '</span>';
$html .= '</a>';
$html .= '</div>';
}
$html .= '</div>';
wp_reset_postdata();
} else {
$html = '<p>Ürün bulunamadı.</p>';
}
return $html;
}
add_shortcode( 'son_urunler', 'son_urunler_shortcode' );
Kullanımı: [son_urunler adet="6" kategori="elektronik" sirala="date"]
Bu shortcode ile blog yazılarına, özel sayfalara, hatta widget alanlarına ürün listeleri ekleyebilirsin.
Kullanıcıya Özel İçerik Shortcode’u
Bazen belirli içerikleri sadece giriş yapmış kullanıcılara ya da belirli rollere göstermek istersin. Bu senaryo üye sitelerinde çok işe yarıyor.
function giris_icin_shortcode( $atts, $content = null ) {
$atts = shortcode_atts(
array(
'rol' => '',
'mesaj' => 'Bu içeriği görmek için giriş yapmalısınız.',
'yonlendir' => '',
),
$atts,
'giris_icin'
);
// Kullanıcı giriş yapmamışsa
if ( ! is_user_logged_in() ) {
$html = '<div class="giris-gerekli">';
$html .= '<p>' . esc_html( $atts['mesaj'] ) . '</p>';
if ( ! empty( $atts['yonlendir'] ) ) {
$giris_url = wp_login_url( esc_url( $atts['yonlendir'] ) );
} else {
$giris_url = wp_login_url( get_permalink() );
}
$html .= '<a href="' . esc_url( $giris_url ) . '" class="giris-butonu">Giriş Yap</a>';
$html .= '</div>';
return $html;
}
// Rol kontrolü istenmişse
if ( ! empty( $atts['rol'] ) ) {
$current_user = wp_get_current_user();
$izin_verilen_roller = array_map( 'trim', explode( ',', $atts['rol'] ) );
$rol_var = false;
foreach ( $izin_verilen_roller as $rol ) {
if ( in_array( sanitize_text_field( $rol ), (array) $current_user->roles ) ) {
$rol_var = true;
break;
}
}
if ( ! $rol_var ) {
return '<p class="yetki-yok">Bu içeriği görme yetkiniz bulunmuyor.</p>';
}
}
return do_shortcode( $content );
}
add_shortcode( 'giris_icin', 'giris_icin_shortcode' );
Kullanımı:
[giris_icin]Gizli içerik burada[/giris_icin][giris_icin rol="administrator,editor"]Sadece admin ve editörler görür[/giris_icin][giris_icin mesaj="Üye olmanız gerekiyor!" yonlendir="https://site.com/uyelik"]İçerik[/giris_icin]
Dinamik Sayaç Shortcode’u: JavaScript ile Entegrasyon
Shortcode’lar sadece PHP çıktısıyla sınırlı değil. İnline CSS ve JavaScript de ekleyebilirsin. Ama dikkatli ol, her shortcode çağrısında script tekrar yüklenmemesi için wp_enqueue_script tercih et.
function geri_sayim_shortcode( $atts ) {
$atts = shortcode_atts(
array(
'tarih' => '',
'baslik' => 'Etkinliğe Kalan Süre',
'bitti' => 'Etkinlik başladı!',
),
$atts,
'geri_sayim'
);
if ( empty( $atts['tarih'] ) ) {
return '<p>Lütfen bir tarih belirtin.</p>';
}
// Tarih formatını doğrula
$hedef_tarih = sanitize_text_field( $atts['tarih'] );
if ( ! strtotime( $hedef_tarih ) ) {
return '<p>Geçersiz tarih formatı. Örnek: 2024-12-31 23:59:59</p>';
}
// Benzersiz ID oluştur, aynı sayfada birden fazla sayaç olabilir
$sayac_id = 'sayac-' . uniqid();
$html = '<div id="' . esc_attr( $sayac_id ) . '" class="geri-sayim-widget">';
$html .= '<h4>' . esc_html( $atts['baslik'] ) . '</h4>';
$html .= '<div class="sayac-display">';
$html .= '<span class="gun"><strong>0</strong> Gün</span>';
$html .= '<span class="saat"><strong>0</strong> Saat</span>';
$html .= '<span class="dakika"><strong>0</strong> Dakika</span>';
$html .= '<span class="saniye"><strong>0</strong> Saniye</span>';
$html .= '</div>';
$html .= '<p class="bitti-mesaji" style="display:none;">' . esc_html( $atts['bitti'] ) . '</p>';
$html .= '</div>';
$html .= '<script>
(function() {
var hedef = new Date("' . esc_js( $hedef_tarih ) . '").getTime();
var sayacId = "' . esc_js( $sayac_id ) . '";
var interval = setInterval(function() {
var simdi = new Date().getTime();
var fark = hedef - simdi;
if (fark < 0) {
clearInterval(interval);
document.querySelector("#" + sayacId + " .sayac-display").style.display = "none";
document.querySelector("#" + sayacId + " .bitti-mesaji").style.display = "block";
return;
}
var gun = Math.floor(fark / (1000 * 60 * 60 * 24));
var saat = Math.floor((fark % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var dakika = Math.floor((fark % (1000 * 60 * 60)) / (1000 * 60));
var saniye = Math.floor((fark % (1000 * 60)) / 1000);
document.querySelector("#" + sayacId + " .gun strong").innerHTML = gun;
document.querySelector("#" + sayacId + " .saat strong").innerHTML = saat;
document.querySelector("#" + sayacId + " .dakika strong").innerHTML = dakika;
document.querySelector("#" + sayacId + " .saniye strong").innerHTML = saniye;
}, 1000);
})();
</script>';
return $html;
}
add_shortcode( 'geri_sayim', 'geri_sayim_shortcode' );
Kullanımı: [geri_sayim tarih="2025-01-01 00:00:00" baslik="Yeni Yıla Kalan" bitti="Mutlu Yıllar!"]
Shortcode’larda Güvenlik: Atlanmaması Gereken Noktalar
Shortcode yazarken güvenliği es geçmek ciddi sorunlara yol açabilir. Temel kuralları şöyle özetleyebilirim:
- sanitize_text_field(): Genel metin girdilerini temizler
- sanitize_hex_color(): Renk değerlerini doğrular
- sanitize_key(): Anahtar/slug formatındaki değerleri temizler
- sanitize_html_class(): CSS sınıf isimlerini güvenli hale getirir
- esc_html(): HTML çıktısında metin güvenliği
- esc_attr(): HTML özelliklerinde güvenlik
- esc_url(): URL çıktısında güvenlik
- esc_js(): JavaScript string değerlerinde güvenlik
- intval(): Sayısal değerleri zorla integer’a çevirir
- wp_kses_post(): İzin verilen HTML taglarını filtreler, içerik için idealdir
Editörlerin girdiği değerlerin her zaman temizlendiğinden emin ol. $atts içindeki değerler direk kullanıcıdan geliyor.
Shortcode’ları Gutenberg ile Uyumlu Hale Getirme
Gutenberg editöründe shortcode’lar hala çalışıyor, ama kullanıcı deneyimi eskisi kadar iyi değil. Editörler için shortcode’u daha erişilebilir yapmak istiyorsan, bir Gutenberg bloğu yazmak uzun vadede daha iyi. Ancak kısa vadede şu yaklaşım işe yarıyor:
// Shortcode açıklamalarını admin panelinde göster
function shortcode_aciklamalari_ekle() {
if ( ! current_user_can( 'edit_posts' ) ) {
return;
}
?>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function() {
// Klasik editör için TinyMCE'ye shortcode listesi eklenebilir
// Bu alan tema dokümantasyonu için kullanılabilir
console.log('Mevcut shortcode'lar: [mesaj], [uyari_kutusu], [kart], [son_urunler], [giris_icin], [geri_sayim]');
});
</script>
<?php
}
add_action( 'admin_footer', 'shortcode_aciklamalari_ekle' );
Daha kullanışlı bir yaklaşım ise editörler için bir yardım sayfası oluşturmak. Böylece [shortcode_yardim] kısa kodunu bir admin sayfasına yerleştirip tüm mevcut kısa kodları belgeleyebilirsin.
Performans: Shortcode’larda Önbellekleme
Veritabanı sorgusu yapan shortcode’lar her sayfa yüklemesinde çalışır. son_urunler gibi shortcode’larda Transient API kullanmak performansı ciddi artırır.
function son_urunler_onbellekli_shortcode( $atts ) {
if ( ! class_exists( 'WooCommerce' ) ) {
return '';
}
$atts = shortcode_atts(
array(
'adet' => 4,
'kategori' => '',
),
$atts,
'son_urunler_h'
);
// Önbellek anahtarı oluştur (parametrelere göre benzersiz)
$cache_key = 'son_urunler_' . md5( serialize( $atts ) );
$cached = get_transient( $cache_key );
if ( false !== $cached ) {
return $cached;
}
// WP_Query ile ürünleri çek (önceki örnekteki gibi)
$args = array(
'post_type' => 'product',
'posts_per_page' => intval( $atts['adet'] ),
'post_status' => 'publish',
);
$urunler = new WP_Query( $args );
$html = '<div class="urun-liste">';
if ( $urunler->have_posts() ) {
while ( $urunler->have_posts() ) {
$urunler->the_post();
$html .= '<div class="urun-item">';
$html .= '<a href="' . esc_url( get_permalink() ) . '">' . esc_html( get_the_title() ) . '</a>';
$html .= '</div>';
}
wp_reset_postdata();
}
$html .= '</div>';
// 1 saat önbellekle
set_transient( $cache_key, $html, HOUR_IN_SECONDS );
return $html;
}
add_shortcode( 'son_urunler_h', 'son_urunler_onbellekli_shortcode' );
// Ürün güncellendiğinde önbelleği temizle
function urun_onbellek_temizle( $post_id ) {
if ( get_post_type( $post_id ) === 'product' ) {
// Tüm ürün shortcode önbelleklerini temizlemek için
// global $wpdb kullanarak _transient_son_urunler_ ile başlayanları silebilirsin
global $wpdb;
$wpdb->query(
"DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_son_urunler_%'"
);
}
}
add_action( 'save_post', 'urun_onbellek_temizle' );
Yaygın Hatalar ve Çözümleri
Shortcode yazarken sık karşılaşılan sorunları ve çözümlerini sıralayayım:
- Çıktı yanlış yerde görünüyor:
echoyerinereturnkullandığından emin ol - Shortcode işlenmiyor, ham metin görünüyor:
add_shortcode()çağrısının doğru çalıştığını kontrol et, fonksiyon adı yazım hatası olabilir - İç içe shortcode çalışmıyor:
$contentyerinedo_shortcode( $content )kullan - Sayfa önbelleği sorunları: Önbellekleme eklentileri shortcode çıktısını önbelleğe alabilir, dinamik içerikler için shortcode’u Ajax ile çağırmayı düşün
- Otomatik
etiketleri bozuyor:remove_filter( 'the_content', 'wpautop' )yerine shortcode çıktısını tek satırda döndür ya dawpautopönce, shortcode sonra çalışsın diye filtre önceliğini ayarla
Sonuç
WordPress shortcode sistemi, tema veya eklenti geliştirmede çok yönlü ve güçlü bir araç. functions.php dosyasına birkaç satır kod ekleyerek editörlere büyük esneklik kazandırabilirsin. Temel prensipleri özetlemek gerekirse: her zaman return kullan, kullanıcı girdilerini mutlaka sanitize et, çıktıları escape et, ve veritabanı sorgusu yapıyorsan önbelleklemeyi ihmal etme.
Gerçek projelerde bu shortcode’ları bir “site-specific plugin” içinde tutmak daha taşınabilir bir yapı sağlar. Tema değişikliklerinden etkilenmezsin ve içerik veritabanında saklanan shortcode etiketleri geçerliliğini korur. Kod tabanın büyüdükçe her shortcode için ayrı dosya oluşturup require_once ile dahil etmek de okunabilirliği artırır.
Yukarıdaki örnekleri doğrudan kullanabilir ya da kendi ihtiyaçlarına göre uyarlayabilirsin. Önemli olan şemayı kavramak: atts al, temizle, işle, return et.
