Standart WooCommerce bileşenleri (Son Eklenenler, Çok Satanlar vb.) çoğu zaman işimizi görse de, e-ticaret projelerinde sıklıkla daha spesifik alanlara ihtiyaç duyarız. “Editörün Seçimi“, “Haftanın Yıldızları” veya “Fırsat Köşesi” gibi özel vitrin alanları oluşturmak, genellikle ya hantal eklentilerle ya da karmaşık kod yığınlarıyla çözülmeye çalışılır.
Bu yazımda, kendi geliştirdiğim ve projelerimde aktif olarak kullandığım hafif, performanslı ve tamamen yönetilebilir bir “Özel Ürün Listeleri” modülünü paylaşıyorum.
Bu çözümün en büyük farkı, geliştiricilerin sıklıkla başını ağrıtan “Hızlı Düzenle (Quick Edit)” alanındaki veri kaydetme ve okuma sorununu, özel bir teknikle (Hidden Data Store) aşmış olmasıdır.
Bu Eklenti/Kod Ne İşe Yarıyor?
Bu yapıyı sitenize kurduğunuzda şunlara sahip olacaksınız:
- 4 Farklı Özel Etiket: Vitrin, Editörün Seçimi, Haftanın Yıldızları ve Fırsat Köşesi.
- Yönetim Paneli Kolaylığı: Ürün listesinde renkli rozetlerle hangi ürünün hangi listede olduğunu anında görürsünüz.
- Hızlı Düzenle (Quick Edit) Desteği: Ürün detayına girmeden, doğrudan listeden tik atıp kaydedebilirsiniz (AJAX uyumlu).
- Gelişmiş Kısa Kod:
[ozel_liste] kısa kodu ile bu ürünleri sitenin istediğiniz yerinde, kategori filtresi uygulayarak listeyebilirsiniz.
- Tema Uyumluluğu: BeTheme, Woodmart gibi temaların karmaşık varyasyon gösterimlerini tek komutla gizleyebilme özelliği.
Teknik Detay: Hızlı Düzenle Sorunu Nasıl Çözüldü?
Bilenler bilir; WooCommerce ürün listesine özel bir sütun eklediğinizde, “Hızlı Düzenle“yi açtığınızda o verinin (örneğin bir checkbox’ın) seçili gelmesi ve AJAX ile kaydedilmesi zordur. Genellikle sayfa yenilenmeden veri güncellenmez veya eski veri görünür.
Bu kodda, verileri sütun içerisine gizli bir div (String formatında) olarak gömüp, JavaScript ile bu ham veriyi okuyarak formu doldurma yöntemini kullandım. Böylece veritabanı sorgusu yapmadan, anlık ve performanslı bir yönetim sağladık.
Kurulum Yöntemleri
Bu özelliği sitenize eklemenin iki yolu var. İster eklenti olarak yükleyin, ister temanızın fonksiyon dosyasına ekleyin.
Yöntem 1: Eklenti Olarak Yükle (Önerilen)
Aşağıdaki kod bloğunu ozel-vitrin.php olarak kaydedip, zip halinde sunucuna yükleyebilir ve kullanabilirsin.
<?php
/**
* Plugin Name: Özel Ürün Vitrini ve Listeleri
* Plugin URI: https://vedataydar.com
* Description: WooCommerce ürünlerine Vitrin, Fırsat vb. etiketler ekler, Hızlı Düzenle (Quick Edit) alanından yönetilmesini sağlar ve [ozel_liste] kısa kodu ile listeler.
* Version: 2.0
* Author: Vedat Aydar
* License: GPL2
*/
defined( 'ABSPATH' ) || exit;
// 1. ÜRÜN DÜZENLEME SAYFASINA KUTUCUKLARI EKLE
add_action( 'woocommerce_product_options_general_product_data', 'vo_add_custom_flags' );
function vo_add_custom_flags() {
echo '<div class="options_group">';
woocommerce_wp_checkbox([ 'id' => '_vo_flag_vitrin', 'label' => 'Vitrin', 'description' => 'Vitrin listesinde göster.' ]);
woocommerce_wp_checkbox([ 'id' => '_vo_flag_editor', 'label' => 'Editörün Seçimi', 'description' => 'Editör listesinde göster.' ]);
woocommerce_wp_checkbox([ 'id' => '_vo_flag_yildiz', 'label' => 'Haftanın Yıldızları', 'description' => 'Yıldız listesinde göster.' ]);
woocommerce_wp_checkbox([ 'id' => '_vo_flag_firsat', 'label' => 'Fırsat Köşesi', 'description' => 'Fırsat listesinde göster.' ]);
echo '</div>';
}
// 2. KAYDETME İŞLEMİ (Save Post - Yüksek Öncelik)
add_action( 'save_post', 'vo_save_custom_flags', 99, 2 );
function vo_save_custom_flags( $post_id, $post ) {
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
if ( ! $post || 'product' !== $post->post_type ) return;
if ( ! current_user_can( 'edit_product', $post_id ) ) return;
if ( isset( $_POST['action'] ) ) {
$flags = ['_vo_flag_vitrin', '_vo_flag_editor', '_vo_flag_yildiz', '_vo_flag_firsat'];
foreach($flags as $flag) {
$val = isset( $_POST[$flag] ) ? 'yes' : 'no';
update_post_meta( $post_id, $flag, $val );
}
}
}
// 3. ADMİN PANELİ ÜRÜN LİSTESİNE SÜTUN EKLEME
add_filter( 'manage_edit-product_columns', 'vo_add_admin_column' );
function vo_add_admin_column( $columns ) {
$new_columns = [];
foreach($columns as $key => $val) {
if($key == 'date') { $new_columns['vo_flags'] = 'Vitrin Durumu'; }
$new_columns[$key] = $val;
}
return $new_columns;
}
// 4. SÜTUN İÇERİĞİ VE ROZETLER
add_action( 'manage_product_posts_custom_column', 'vo_render_admin_column', 10, 2 );
function vo_render_admin_column( $column, $post_id ) {
if ( 'vo_flags' === $column ) {
$flags = [
'_vo_flag_vitrin' => ['label' => 'VİTRİN', 'color' => '#2271b1'],
'_vo_flag_editor' => ['label' => 'EDİTÖR', 'color' => '#d63638'],
'_vo_flag_yildiz' => ['label' => 'YILDIZ', 'color' => '#f0b849'],
'_vo_flag_firsat' => ['label' => 'FIRSAT', 'color' => '#00a32a'],
];
$data_string = "";
foreach ($flags as $key => $data) {
$val = get_post_meta( $post_id, $key, true );
if ( 'yes' === $val ) {
echo '<span style="display:inline-block;padding:2px 5px;margin:1px;border-radius:3px;font-size:10px;color:#fff;background:'.esc_attr($data['color']).';">'.esc_html($data['label']).'</span> ';
}
$data_string .= $key . "=" . ($val === 'yes' ? 'yes' : 'no') . "|";
}
// Hızlı düzenleme için veriyi gizli bir div içine saklıyoruz
echo '<div class="vo_flag_data_store" style="display:none;">' . esc_attr($data_string) . '</div>';
}
}
// 5. HIZLI DÜZENLEME (QUICK EDIT) HTML ALANI
add_action( 'woocommerce_product_quick_edit_end', 'vo_quick_edit_html' );
function vo_quick_edit_html() {
?>
<div style="clear:both;"></div>
<fieldset class="inline-edit-col-left" style="margin-top:10px; padding-top:10px; border-top:1px solid #ddd; width:100%;">
<div class="inline-edit-col">
<span class="title">Özel Vitrin Ayarları</span>
<label class="alignleft" style="margin-right:15px;"><input type="checkbox" name="_vo_flag_vitrin"> Vitrin</label>
<label class="alignleft" style="margin-right:15px;"><input type="checkbox" name="_vo_flag_editor"> Editör</label>
<label class="alignleft" style="margin-right:15px;"><input type="checkbox" name="_vo_flag_yildiz"> Yıldız</label>
<label class="alignleft"><input type="checkbox" name="_vo_flag_firsat"> Fırsat</label>
</div>
</fieldset>
<?php
}
// 6. HIZLI DÜZENLEME JS (Veri Doldurma)
add_action( 'admin_enqueue_scripts', 'vo_enqueue_quick_edit_js' );
function vo_enqueue_quick_edit_js( $hook ) {
if ( 'edit.php' != $hook ) return;
global $post_type;
if ( 'product' != $post_type ) return;
wp_enqueue_script( 'vo-quick-edit', '', ['jquery', 'inline-edit-post'], '', true );
wp_add_inline_script( 'vo-quick-edit', "
jQuery(function($){
if( typeof inlineEditPost === 'undefined' ) return;
var _wp_inline_edit = inlineEditPost.edit;
inlineEditPost.edit = function( id ) {
_wp_inline_edit.apply( this, arguments );
if ( typeof( id ) == 'object' ) { id = parseInt( this.getId( id ) ); }
if ( id > 0 ) {
var edit_row = $('#edit-' + id);
var post_row = $('#post-' + id);
var data_str = post_row.find('.vo_flag_data_store').text();
if( data_str ) {
var pairs = data_str.split('|');
for (var i = 0; i < pairs.length; i++) {
var pair = pairs[i].split('=');
if( pair.length == 2 ) {
edit_row.find('input[name=\"' + pair[0] + '\"]').prop('checked', pair[1] === 'yes');
}
}
}
}
};
});
" );
}
// 7. KISA KOD: [ozel_liste]
add_shortcode( 'ozel_liste', 'vo_shortcode_output' );
function vo_shortcode_output( $atts ) {
$atts = shortcode_atts( array(
'tur' => 'vitrin', // vitrin, editor, yildiz, firsat
'limit' => '-1',
'columns' => '4',
'kategori' => '',
'varyasyon_gizle' => 'hayir'
), $atts );
$map = [ 'vitrin' => '_vo_flag_vitrin', 'editor' => '_vo_flag_editor', 'yildiz' => '_vo_flag_yildiz', 'firsat' => '_vo_flag_firsat' ];
$meta_key = isset($map[$atts['tur']]) ? $map[$atts['tur']] : '_vo_flag_vitrin';
$args = array(
'post_type' => 'product',
'posts_per_page' => $atts['limit'],
'ignore_sticky_posts' => 1,
'meta_query' => array( array( 'key' => $meta_key, 'value' => 'yes', 'compare' => '=' ) ),
);
if ( ! empty( $atts['kategori'] ) ) {
$cats = array_filter( array_map( 'trim', explode( ',', $atts['kategori'] ) ) );
if ( ! empty( $cats ) ) {
$args['tax_query'] = array( array( 'taxonomy' => 'product_cat', 'field' => 'slug', 'terms' => $cats, 'operator' => 'IN' ) );
}
}
// CSS: Varyasyon Gizleme (BeTheme Destekli)
$class = 'woocommerce columns-' . esc_attr($atts['columns']);
$style = '';
if ( $atts['varyasyon_gizle'] === 'evet' ) {
$class .= ' vo-hide-vars';
$style = '<style>.vo-hide-vars .swatch, .vo-hide-vars .swatches-select, .vo-hide-vars .variations_form, .vo-hide-vars .mfn-variations-wrapper-loop { display: none !important; }</style>';
}
$query = new WP_Query( $args ); ob_start();
if ( $query->have_posts() ) {
echo $style;
echo '<div class="' . $class . '">';
woocommerce_product_loop_start();
while ( $query->have_posts() ) { $query->the_post(); wc_get_template_part( 'content', 'product' ); }
woocommerce_product_loop_end();
echo '</div>';
}
wp_reset_postdata(); return ob_get_clean();
}
Yöntem 2: Functions.php ile Manuel Kurulum
Eklenti kullanmak istemiyorsanız, aşağıdaki kod bloğunun tamamını kopyalayıp temanızın functions.php dosyasına yapıştırabilirsiniz.
/* --- ÖZEL VİTRİN VE LİSTELEME BAŞLANGIÇ (Vedat Aydar) --- */
// 1. Panelde Seçenekleri Oluştur
add_action( 'woocommerce_product_options_general_product_data', 'vo_func_add_custom_flags' );
function vo_func_add_custom_flags() {
echo '<div class="options_group">';
woocommerce_wp_checkbox([ 'id' => '_vo_flag_vitrin', 'label' => 'Vitrin', 'description' => 'Vitrin listesinde göster.' ]);
woocommerce_wp_checkbox([ 'id' => '_vo_flag_editor', 'label' => 'Editörün Seçimi', 'description' => 'Editör listesinde göster.' ]);
woocommerce_wp_checkbox([ 'id' => '_vo_flag_yildiz', 'label' => 'Haftanın Yıldızları', 'description' => 'Yıldız listesinde göster.' ]);
woocommerce_wp_checkbox([ 'id' => '_vo_flag_firsat', 'label' => 'Fırsat Köşesi', 'description' => 'Fırsat listesinde göster.' ]);
echo '</div>';
}
// 2. Verileri Kaydet
add_action( 'save_post', 'vo_func_save_custom_flags', 99, 2 );
function vo_func_save_custom_flags( $post_id, $post ) {
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
if ( ! $post || 'product' !== $post->post_type ) return;
if ( ! current_user_can( 'edit_product', $post_id ) ) return;
if ( isset( $_POST['action'] ) ) {
$flags = ['_vo_flag_vitrin', '_vo_flag_editor', '_vo_flag_yildiz', '_vo_flag_firsat'];
foreach($flags as $flag) {
$val = isset( $_POST[$flag] ) ? 'yes' : 'no';
update_post_meta( $post_id, $flag, $val );
}
}
}
// 3. Admin Listesine Sütun Ekle
add_filter( 'manage_edit-product_columns', 'vo_func_add_admin_column' );
function vo_func_add_admin_column( $columns ) {
$new_columns = [];
foreach($columns as $key => $val) {
if($key == 'date') { $new_columns['vo_flags'] = 'Vitrin Durumu'; }
$new_columns[$key] = $val;
}
return $new_columns;
}
// 4. Sütun İçeriğini Doldur
add_action( 'manage_product_posts_custom_column', 'vo_func_render_admin_column', 10, 2 );
function vo_func_render_admin_column( $column, $post_id ) {
if ( 'vo_flags' === $column ) {
$flags = [
'_vo_flag_vitrin' => ['label' => 'VİTRİN', 'color' => '#2271b1'],
'_vo_flag_editor' => ['label' => 'EDİTÖR', 'color' => '#d63638'],
'_vo_flag_yildiz' => ['label' => 'YILDIZ', 'color' => '#f0b849'],
'_vo_flag_firsat' => ['label' => 'FIRSAT', 'color' => '#00a32a'],
];
$data_string = "";
foreach ($flags as $key => $data) {
$val = get_post_meta( $post_id, $key, true );
if ( 'yes' === $val ) {
echo '<span style="display:inline-block;padding:2px 5px;margin:1px;border-radius:3px;font-size:10px;color:#fff;background:'.esc_attr($data['color']).';">'.esc_html($data['label']).'</span> ';
}
$data_string .= $key . "=" . ($val === 'yes' ? 'yes' : 'no') . "|";
}
echo '<div class="vo_flag_data_store" style="display:none;">' . esc_attr($data_string) . '</div>';
}
}
// 5. Hızlı Düzenle HTML
add_action( 'woocommerce_product_quick_edit_end', 'vo_func_quick_edit_html' );
function vo_func_quick_edit_html() {
?>
<div style="clear:both;"></div>
<fieldset class="inline-edit-col-left" style="margin-top:10px; padding-top:10px; border-top:1px solid #ddd; width:100%;">
<div class="inline-edit-col">
<span class="title">Özel Vitrin Ayarları</span>
<label class="alignleft" style="margin-right:15px;"><input type="checkbox" name="_vo_flag_vitrin"> Vitrin</label>
<label class="alignleft" style="margin-right:15px;"><input type="checkbox" name="_vo_flag_editor"> Editör</label>
<label class="alignleft" style="margin-right:15px;"><input type="checkbox" name="_vo_flag_yildiz"> Yıldız</label>
<label class="alignleft"><input type="checkbox" name="_vo_flag_firsat"> Fırsat</label>
</div>
</fieldset>
<?php
}
// 6. Hızlı Düzenle JS (Footer'a Basılır)
add_action( 'admin_footer', 'vo_func_quick_edit_js' );
function vo_func_quick_edit_js() {
global $current_screen;
if ( isset($current_screen->post_type) && 'product' !== $current_screen->post_type ) return;
?>
<script>
jQuery(function($){
if( typeof inlineEditPost === 'undefined' ) return;
var _wp_inline_edit = inlineEditPost.edit;
inlineEditPost.edit = function( id ) {
_wp_inline_edit.apply( this, arguments );
if ( typeof( id ) == 'object' ) { id = parseInt( this.getId( id ) ); }
if ( id > 0 ) {
var edit_row = $('#edit-' + id);
var post_row = $('#post-' + id);
var data_str = post_row.find('.vo_flag_data_store').text();
if( data_str ) {
var pairs = data_str.split('|');
for (var i = 0; i < pairs.length; i++) {
var pair = pairs[i].split('=');
if( pair.length == 2 ) {
edit_row.find('input[name=\"' + pair[0] + '\"]').prop('checked', pair[1] === 'yes');
}
}
}
}
};
});
</script>
<?php
}
// 7. Kısa Kod [ozel_liste]
add_shortcode( 'ozel_liste', 'vo_func_shortcode_output' );
function vo_func_shortcode_output( $atts ) {
$atts = shortcode_atts( array(
'tur' => 'vitrin',
'limit' => '-1',
'columns' => '4',
'kategori' => '',
'varyasyon_gizle' => 'hayir'
), $atts );
$map = [ 'vitrin' => '_vo_flag_vitrin', 'editor' => '_vo_flag_editor', 'yildiz' => '_vo_flag_yildiz', 'firsat' => '_vo_flag_firsat' ];
$meta_key = isset($map[$atts['tur']]) ? $map[$atts['tur']] : '_vo_flag_vitrin';
$args = array(
'post_type' => 'product',
'posts_per_page' => $atts['limit'],
'ignore_sticky_posts' => 1,
'meta_query' => array( array( 'key' => $meta_key, 'value' => 'yes', 'compare' => '=' ) ),
);
if ( ! empty( $atts['kategori'] ) ) {
$cats = array_filter( array_map( 'trim', explode( ',', $atts['kategori'] ) ) );
if ( ! empty( $cats ) ) {
$args['tax_query'] = array( array( 'taxonomy' => 'product_cat', 'field' => 'slug', 'terms' => $cats, 'operator' => 'IN' ) );
}
}
$class = 'woocommerce columns-' . esc_attr($atts['columns']);
$style = '';
if ( $atts['varyasyon_gizle'] === 'evet' ) {
$class .= ' vo-hide-vars';
$style = '<style>.vo-hide-vars .swatch, .vo-hide-vars .swatches-select, .vo-hide-vars .variations_form, .vo-hide-vars .mfn-variations-wrapper-loop { display: none !important; }</style>';
}
$query = new WP_Query( $args ); ob_start();
if ( $query->have_posts() ) {
echo $style;
echo '<div class="' . $class . '">';
woocommerce_product_loop_start();
while ( $query->have_posts() ) { $query->the_post(); wc_get_template_part( 'content', 'product' ); }
woocommerce_product_loop_end();
echo '</div>';
}
wp_reset_postdata(); return ob_get_clean();
}
/* --- ÖZEL VİTRİN VE LİSTELEME SONU --- */
Nasıl Kullanılır?
Kurulumu yaptıktan sonra ürünler sayfasına gidin. Yeni sütunu ve Hızlı Düzenle alanındaki kutucukları göreceksiniz. İstediğiniz ürünleri işaretledikten sonra sitenizin herhangi bir sayfasına şu kısa kodları ekleyebilirsiniz:
1. Sadece Vitrin Ürünlerini Göster: [ozel_liste tur="vitrin" limit="8"]
2. Tişört Kategorisindeki Fırsat Ürünlerini Göster: [ozel_liste tur="firsat" kategori="tisort" limit="4"]
3. Varyasyonları Gizleyerek Listele (Temiz Görünüm): Eğer temanız ürün kartlarında renk topları vb. gösteriyorsa ve bunları bu listede gizlemek istiyorsanız: [ozel_liste tur="yildiz" varyasyon_gizle="evet"]
Güle güle kullanın! Sorularınız olursa yorumlarda belirtebilirsiniz.
Kodlar Kodlayana, Kahveler Bana! ☕
Burada paylaştığım içerikler projelerinde işine yaradıysa veya sana zaman kazandırdıysa, bir kahve ısmarlayarak desteğini gösterebilirsin. Bu destek, daha fazla içerik üretmem için motive edici olacaktır.
☕ Bana Bir Kahve Ismarla