Shortcode ile Dinamik İçerik Oluşturma: Parametre Kullanımı

WordPress ile ciddi anlamda vakit geçiren herkes, er ya da geç aynı soruyla yüz yüze gelir: “Bu içeriği her sayfaya tek tek mi kopyalayacağım?” İşte tam bu noktada shortcode’lar hayat kurtarıcı oluyor. Ancak shortcode’ların gerçek gücü, onlara parametre geçirebildiğin zaman ortaya çıkıyor. Statik bir kısayol değil, her kullanımda farklı davranabilen dinamik bir içerik motoru elde ediyorsun.

Shortcode Nedir ve Neden Parametre Kullanmalısın?

Shortcode, WordPress’in size sunduğu PHP fonksiyonlarını editör içinde köşeli parantezlerle çağırma mekanizmasıdır. [iletisim_formu] yazdığında arka planda bir PHP fonksiyonu çalışır ve HTML çıktısı üretir. Ama bu temel kullanım seni yalnızca statik içerikle sınırlar.

Parametreli shortcode’larla şunu yapabilirsin:

  • Renk, boyut, başlık gibi görsel özellikleri her kullanımda özelleştirmek
  • Veritabanı sorgularını dinamik olarak filtrelemek
  • Kullanıcıya özel içerik üretmek
  • Tek bir shortcode ile onlarca farklı senaryoyu karşılamak

[urun_kutusu renk="mavi" adet="3" baslik="Öne Çıkan Ürünler"] gibi bir kullanım, aynı shortcode’un farklı sayfalarda farklı içerik üretmesini sağlar. Bu yazıda bu yapıyı sıfırdan kuruyoruz.

functions.php’ye Dokunmadan Önce

Önce şunu netleştireyim: Tüm bu kodlar functions.php dosyasına gidecek. Ama bu dosyayı doğrudan temanın içindeki functions.php‘ye yazmak riskli. Tema güncellendiğinde her şeyi kaybedersin.

Bunun yerine:

  • Child theme kullan ve kodları child temanın functions.php‘sine yaz
  • Ya da özel eklenti oluştur: wp-content/plugins/ozel-shortcodlar/ozel-shortcodlar.php

Ben örneklerde direkt functions.php diyeceğim ama aklında bu yapıyı tut.

Temel Parametre Yapısı: shortcode_atts()

WordPress’in shortcode parametrelerini yönetmek için sunduğu fonksiyon shortcode_atts()‘dır. Bu fonksiyon üç şey yapar:

  • Varsayılan değerleri tanımlar
  • Kullanıcının geçtiği değerleri alır
  • İkisini birleştirerek güvenli bir dizi döndürür

Basit bir örnek görelim:

function basit_kutucuk_shortcode( $atts ) {
    $atts = shortcode_atts(
        array(
            'baslik'  => 'Varsayılan Başlık',
            'renk'    => 'mavi',
            'boyut'   => 'orta',
        ),
        $atts,
        'kutucuk'
    );

    $baslik = esc_html( $atts['baslik'] );
    $renk   = esc_attr( $atts['renk'] );
    $boyut  = esc_attr( $atts['boyut'] );

    $cikti  = '<div class="kutucuk kutucuk-' . $boyut . '" style="border-color:' . $renk . '">';
    $cikti .= '<h3>' . $baslik . '</h3>';
    $cikti .= '</div>';

    return $cikti;
}
add_shortcode( 'kutucuk', 'basit_kutucuk_shortcode' );

Editörde [kutucuk baslik="Merhaba" renk="kırmızı" boyut="büyük"] yazdığında, her parametre ayrı ayrı işlenir. Herhangi bir parametre yazılmadığında shortcode_atts() varsayılan değeri devreye sokar.

Önemli kural: Shortcode fonksiyonundan echo değil, return kullanarak çıktı ver. Aksi hâlde içerik sayfanın yanlış yerine basılır.

Gerçek Dünya Senaryosu 1: Dinamik Ürün Kartı

Diyelim ki bir WooCommerce mağazan var ve editör içinde belirli ürünleri kolayca sergilemek istiyorsun. Her seferinde Elementor widget’ı sürüklemek ya da shortcode eklentisi kurmak yerine kendi shortcode’unu yaz.

function ozel_urun_karti_shortcode( $atts ) {
    $atts = shortcode_atts(
        array(
            'urun_id'     => 0,
            'buton_metin' => 'Sepete Ekle',
            'gorsel'      => 'true',
        ),
        $atts,
        'urun_karti'
    );

    $urun_id = intval( $atts['urun_id'] );

    if ( ! $urun_id ) {
        return '<p>Lütfen geçerli bir ürün ID girin.</p>';
    }

    $urun = wc_get_product( $urun_id );

    if ( ! $urun || ! $urun->is_visible() ) {
        return '<p>Ürün bulunamadı veya yayında değil.</p>';
    }

    $gorsel_goster = ( $atts['gorsel'] === 'true' );
    $buton_metin   = esc_html( $atts['buton_metin'] );
    $fiyat         = $urun->get_price_html();
    $urun_adi      = esc_html( $urun->get_name() );
    $urun_url      = get_permalink( $urun_id );

    $cikti = '<div class="ozel-urun-karti">';

    if ( $gorsel_goster ) {
        $cikti .= '<a href="' . esc_url( $urun_url ) . '">';
        $cikti .= get_the_post_thumbnail( $urun_id, 'medium' );
        $cikti .= '</a>';
    }

    $cikti .= '<h4><a href="' . esc_url( $urun_url ) . '">' . $urun_adi . '</a></h4>';
    $cikti .= '<span class="fiyat">' . $fiyat . '</span>';
    $cikti .= '<a href="' . esc_url( $urun_url ) . '" class="buton">' . $buton_metin . '</a>';
    $cikti .= '</div>';

    return $cikti;
}
add_shortcode( 'urun_karti', 'ozel_urun_karti_shortcode' );

Kullanımı: [urun_karti urun_id="42" buton_metin="Hemen Al" gorsel="true"]

Bu sayede blog yazısının ortasına, sidebar’a ya da herhangi bir sayfa içeriğine tek satırla dinamik ürün kartı yerleştirebilirsin.

Gerçek Dünya Senaryosu 2: İçerik Sarmalayan (Enclosing) Shortcode

Şimdiye kadar self-closing shortcode’lar gördük. Ama [basla]...[/basla] şeklinde içeriği sarmalayan shortcode’lar da kullanabilirsin. Bu durumda fonksiyona üçüncü bir parametre eklenir: $content.

function vurgulu_kutu_shortcode( $atts, $content = null ) {
    $atts = shortcode_atts(
        array(
            'tur'   => 'bilgi',
            'ikon'  => 'true',
            'renk'  => '',
        ),
        $atts,
        'vurgulu_kutu'
    );

    $tur_sinifi = sanitize_html_class( $atts['tur'] );
    $ikon_goster = ( $atts['ikon'] === 'true' );

    $ikon_haritasi = array(
        'bilgi'   => 'ℹ️',
        'uyari'   => '⚠️',
        'hata'    => '❌',
        'basari'  => '✅',
    );

    $ikon = $ikon_goster && isset( $ikon_haritasi[ $atts['tur'] ] )
        ? '<span class="kutu-ikon">' . $ikon_haritasi[ $atts['tur'] ] . '</span>'
        : '';

    $stil = $atts['renk'] ? ' style="background-color:' . esc_attr( $atts['renk'] ) . '"' : '';

    $cikti  = '<div class="vurgulu-kutu vurgulu-kutu--' . $tur_sinifi . '"' . $stil . '>';
    $cikti .= $ikon;
    $cikti .= '<div class="kutu-icerik">' . do_shortcode( $content ) . '</div>';
    $cikti .= '</div>';

    return $cikti;
}
add_shortcode( 'vurgulu_kutu', 'vurgulu_kutu_shortcode' );

Editörde şöyle kullanırsın:

[vurgulu_kutu tur="uyari" ikon="true"]
Bu alana dikkat edin! Ayarları değiştirmeden önce yedek alın.
[/vurgulu_kutu]

do_shortcode( $content ) çağrısı sayesinde iç içe shortcode’lar da düzgün işlenir.

Gerçek Dünya Senaryosu 3: Özel Sorgu ile Son Yazıları Listeleme

Belki siteye “şu kategoriden son 3 yazıyı getir” diyen dinamik bir bileşen istiyorsun. Widget kullanmak zorunda değilsin:

function son_yazilar_shortcode( $atts ) {
    $atts = shortcode_atts(
        array(
            'kategori'  => '',
            'adet'      => 5,
            'siralama'  => 'date',
            'gorsel'    => 'false',
            'ozet'      => 'true',
        ),
        $atts,
        'son_yazilar'
    );

    $sorgu_argumanlari = array(
        'post_type'      => 'post',
        'post_status'    => 'publish',
        'posts_per_page' => intval( $atts['adet'] ),
        'orderby'        => sanitize_key( $atts['siralama'] ),
        'order'          => 'DESC',
    );

    if ( ! empty( $atts['kategori'] ) ) {
        $sorgu_argumanlari['category_name'] = sanitize_text_field( $atts['kategori'] );
    }

    $sorgu = new WP_Query( $sorgu_argumanlari );

    if ( ! $sorgu->have_posts() ) {
        return '<p>Bu kriterlere uygun yazı bulunamadı.</p>';
    }

    $cikti = '<ul class="ozel-son-yazilar">';

    while ( $sorgu->have_posts() ) {
        $sorgu->the_post();

        $cikti .= '<li class="yazi-item">';

        if ( $atts['gorsel'] === 'true' && has_post_thumbnail() ) {
            $cikti .= '<a href="' . esc_url( get_permalink() ) . '">';
            $cikti .= get_the_post_thumbnail( get_the_ID(), 'thumbnail' );
            $cikti .= '</a>';
        }

        $cikti .= '<a class="yazi-baslik" href="' . esc_url( get_permalink() ) . '">';
        $cikti .= esc_html( get_the_title() );
        $cikti .= '</a>';

        if ( $atts['ozet'] === 'true' ) {
            $cikti .= '<p class="yazi-ozet">' . esc_html( get_the_excerpt() ) . '</p>';
        }

        $cikti .= '</li>';
    }

    wp_reset_postdata();

    $cikti .= '</ul>';

    return $cikti;
}
add_shortcode( 'son_yazilar', 'son_yazilar_shortcode' );

Kullanım: [son_yazilar kategori="wordpress" adet="3" gorsel="true" ozet="false"]

wp_reset_postdata() çağrısını unutursan global $post değişkeni bozulur ve sayfanın geri kalanında beklenmedik davranışlar görürsün. Bu satırı her WP_Query kullanımının ardından eklemek alışkanlık hâline getir.

Güvenlik: Parametre Sanitizasyonu

Bu konuyu ayrı bir bölümde ele almam gerekiyor çünkü çoğu shortcode örneği internette bu adımı atlıyor. Shortcode parametreleri kullanıcı girdisidir ve güvenilmez olarak kabul edilmelidir.

Kullanman gereken fonksiyonlar:

  • intval(): Sayısal değerler için, adet="5" gibi parametreler
  • esc_html(): HTML içinde gösterilecek metin için
  • esc_attr(): HTML attribute değerleri için, class="" veya style="" içine yazacakların
  • esc_url(): URL değerleri için
  • sanitize_text_field(): Genel metin temizleme için
  • sanitize_html_class(): CSS sınıf adları için
  • sanitize_key(): Dizi anahtarları, slug değerleri için
function guvenli_kart_shortcode( $atts ) {
    $atts = shortcode_atts(
        array(
            'baslik'   => '',
            'url'      => '#',
            'sinif'    => 'varsayilan',
            'yukseklik'=> 200,
        ),
        $atts,
        'guvenli_kart'
    );

    // Her parametreyi uygun fonksiyonla temizle
    $baslik    = esc_html( $atts['baslik'] );
    $url       = esc_url( $atts['url'] );
    $sinif     = sanitize_html_class( $atts['sinif'] );
    $yukseklik = intval( $atts['yukseklik'] );

    // Yükseklik için mantıklı bir sınır belirle
    if ( $yukseklik < 50 || $yukseklik > 800 ) {
        $yukseklik = 200;
    }

    $cikti  = '<div class="kart ' . $sinif . '" style="height:' . $yukseklik . 'px">';
    $cikti .= '<a href="' . $url . '">' . $baslik . '</a>';
    $cikti .= '</div>';

    return $cikti;
}
add_shortcode( 'guvenli_kart', 'guvenli_kart_shortcode' );

Performans: Çıktı Önbellekleme (Output Caching)

Shortcode’un her çalıştığında veritabanı sorgusu yapıyorsa, aynı parametrelerle gelen isteklerde gereksiz yük oluşturur. Transient API ile bunu önleyebilirsin:

function onbellekli_yazilar_shortcode( $atts ) {
    $atts = shortcode_atts(
        array(
            'kategori' => 'genel',
            'adet'     => 5,
        ),
        $atts,
        'onbellekli_yazilar'
    );

    // Benzersiz önbellek anahtarı oluştur
    $onbellek_anahtari = 'oysc_' . md5( serialize( $atts ) );

    // Önbellekte varsa direkt döndür
    $onbellekli_cikti = get_transient( $onbellek_anahtari );
    if ( false !== $onbellekli_cikti ) {
        return $onbellekli_cikti;
    }

    // Yoksa sorguyu çalıştır
    $sorgu = new WP_Query( array(
        'post_type'      => 'post',
        'posts_per_page' => intval( $atts['adet'] ),
        'category_name'  => sanitize_text_field( $atts['kategori'] ),
        'post_status'    => 'publish',
    ) );

    $cikti = '<ul class="onbellekli-yazilar">';

    while ( $sorgu->have_posts() ) {
        $sorgu->the_post();
        $cikti .= '<li><a href="' . esc_url( get_permalink() ) . '">';
        $cikti .= esc_html( get_the_title() ) . '</a></li>';
    }

    wp_reset_postdata();
    $cikti .= '</ul>';

    // 1 saatliğine önbelleğe al (3600 saniye)
    set_transient( $onbellek_anahtari, $cikti, 3600 );

    return $cikti;
}
add_shortcode( 'onbellekli_yazilar', 'onbellekli_yazilar_shortcode' );

Önbellek anahtarını oluştururken md5( serialize( $atts ) ) kullanmak, farklı parametre kombinasyonlarının farklı önbellek kayıtlarına gitmesini sağlar. kategori="wordpress" adet="3" ile kategori="linux" adet="5" farklı anahtarlar üretir.

Shortcode’ları Güzelce Organize Etmek

Onlarca shortcode yazmaya başladığında functions.php kaotik hâle gelir. Bunu önlemek için shortcode’ları ayrı dosyalara taşı ve functions.php‘den include et:

// functions.php içinde
$shortcode_dosyalari = array(
    'urun-shortcodlari',
    'icerik-shortcodlari',
    'form-shortcodlari',
);

foreach ( $shortcode_dosyalari as $dosya ) {
    $tam_yol = get_stylesheet_directory() . '/includes/shortcodes/' . $dosya . '.php';
    if ( file_exists( $tam_yol ) ) {
        require_once $tam_yol;
    }
}

Bu yapıyla includes/shortcodes/urun-shortcodlari.php, includes/shortcodes/icerik-shortcodlari.php gibi dosyalara shortcode’ları gruplandırarak organize tutarsın.

Sık Yapılan Hatalar

  • echo kullanmak: Shortcode fonksiyonundan her zaman return kullan. echo kullanırsan içerik sayfanın en üstüne fırlar.
  • wp_reset_postdata() unutmak: Her WP_Query sonrasında çağrılmalı.
  • Güvenlik sanitizasyonunu atlamak: Kullanıcı girdisi her zaman temizlenmeli.
  • Önbellek anahtarı çakışması: Farklı parametre setleri için farklı anahtarlar kullan.
  • Boolean parametreleri yanlış kontrol etmek: Shortcode’da true/false string olarak gelir. $atts['gorsel'] === true değil, $atts['gorsel'] === 'true' şeklinde kontrol et.
  • İç içe shortcode’larda do_shortcode() çağırmamak: Sarmalayan shortcode’larda $content üzerinde do_shortcode() kullanmazsan iç shortcode’lar ham metin olarak görünür.

Sonuç

Parametreli shortcode’lar, WordPress’te içerik üretimini standart hâle getirmenin en pratik yollarından biri. Bir kez doğru kurduğunda, içerik editörlerin teknik bilgiye ihtiyaç duymadan dinamik ve tutarlı içerik oluşturmasını sağlarsın.

Dikkat etmen gereken üç temel prensip var: her zaman return kullan, her parametreyi sanitize et, veritabanı sorgularını önbellekle. Bu üçünü alışkanlık hâline getirirsen hem güvenli hem de performanslı shortcode’lar yazarsın.

Başlangıç için kendi sitendeki tekrar eden içerik bloklarına bak. Her yerde copy-paste yaptığın bir yapı görürsen, o yapıyı shortcode’a dönüştürmek için mükemmel bir aday olduğunu biliyorsun demektir.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir