Ürün kataloğu

WooCommerce'te kurallara göre kategoriye otomatik ürün ekleme

WooCommerce'te kurala dayalı kategori diye yerleşik bir şey yoktur: üyelik, saklanan bir terim ilişkileri listesidir. Bu boşluğu kapatmayı deneyen dört yaklaşımın nerede kırıldığını ve güvenebileceğiniz bir kural motorunu ayıran beş soruyu ele alıyoruz.

Kurallara göre bir WooCommerce kategorisine otomatik ürün eklemenin yolunu arayanların çoğu aslında şunu istiyor: üyeliği ürün kimliklerinden oluşan bir liste olarak değil, bir kural olarak saklanan bir kategori. WooCommerce’te böyle bir şey yerleşik olarak yoktur. Kategori ataması, wp_term_relationships tablosundaki bir grup satırdan ibarettir: bir ürün Clearance kategorisindeyse, birisi onu oraya koyduğu içindir. Sonrasında o kararı yeniden denetleyen hiçbir şey yoktur.

Bu boşluğu kapatmayı deneyen dört yaklaşım var ve dördü de farklı bir noktada çuvallıyor. Üçü, bir ay kadar işe yarıyormuş gibi görünür.

Kısa cevap#

WooCommerce’te kurala dayalı kategori diye yerleşik bir şey yoktur: üyelik, saklanan bir terim ilişkileri listesidir. Dolayısıyla bunu otomatikleştirmek, koşullar değiştikçe o ilişkileri yazan bir motor eklemek demektir.

  • Çekirdek liste saklar, kural değil. Bir ürün Clearance kategorisindedir çünkü birisi onu oraya koymuştur; wp_term_relationships tablosunda, sonradan kimsenin denetlemediği bir satır.
  • Dört yaklaşım, dört zayıf nokta. Elle toplu düzenleme dürüst bir yöntemdir ve küçük bir katalog için gerçekten doğru cevaptır, ama indirimler bitip stoklar tükendikçe eskir; CSV’deki Categories sütunu birleştirmez, değiştirir; functions.php içindeki bir sorgu filtresi de Product Collection bloğu da yalnızca tek bir sayfanın gösterdiğini değiştirir.
  • Görüntüleme anında filtreleme kategori değildir. Ortada gerçek bir terim yoksa terim sayacı da olmaz, katmanlı gezinmede filtre de; menüler, breadcrumb’lar, REST API ve Store API de orayı bir kategori olarak tanımaz.
  • Yalnızca olaylar yetmez. Kullanılabilir bir motor; ürün, fiyat ve stok değişikliklerinde ve düzenli bir tarama turunda yeniden değerlendirme yapar, çünkü “son 30 günde oluşturuldu” gibi bir koşul sırf zaman geçtiği için bayatlar.
  • Bir motorun bozulmasının iki yolu. Kendi oluşturmadığı üyelikleri de kaldıran bir motor, elle atanmış istisnaları süpürür; boş ya da bozuk bir kuralı eşleşme sayan bir motor ise bütün kataloğu Clearance’a doldurur. Bu yüzden ilk çalıştırmadan önce önizlemenin sıfır yazdığını doğrulayın ve işi arka planda partiler hâlinde Action Scheduler’a yaptırın.

Saklanan liste ile saklanan kural#

  • Saklanan liste, WooCommerce’in size verdiği şeydir. Üyelik veridir: kaydettiğiniz anda doğrudur, o andan sonra bozulmaya başlar; çünkü dünya değişir, liste değişmez.
  • Saklanan kural ise bir tanımdır — indirimde VE stokta VE siparişe özel etiketi yok. Üyelik türetilir ve son değerlendirme anı itibarıyla doğrudur. Soru artık şuna dönüşür: bu ne sıklıkta oluyor?

Daha geç ve daha acı biçimde keşfedilen ikinci soru, türetilen sonucun nereye düştüğüdür. Kural gerçek terim ilişkileri üretiyorsa kategori diğerleri gibi davranır: URL, terim sayacı, breadcrumb, menü öğesi, Ürünler listesindeki filtre, Store API kaydı. Yalnızca görüntüleme anında filtrelenmiş bir sorgu üretiyorsa, doğru ürünleri gösteren bir sayfanız ve WordPress’in geri kalanının boş saydığı bir kategoriniz olur.

Kurallara göre bir WooCommerce kategorisine otomatik ürün eklemenin dört yolu#

1. Elle, belirli aralıklarla yapmak#

Ürünler → bir ölçüte göre filtreleyin → tümünü seçin → Toplu işlemler → Düzenle → kategoriyi ekleyin. Bu otomasyon değildir, ama dürüsttür, kod istemez ve tek bir sezonluk koleksiyonu olan 200 ürünlük bir katalog için gerçekten doğru cevaptır. Kimsenin sizi bundan vazgeçirmesine izin vermeyin.

İki yerde kırılır. Eskime: indirim biter, stok tükenir, fiyat değişir ve kategorinin artık yanlış olduğunu size kimse söylemez. Bir de ifade gücü: yönetim panelinde “%30’dan fazla indirimli” ya da “90 gündür satılmayan” diye bir filtre yoktur; bu yüzden e-tabloya aktarır, seçimi orada çıkarır ve uygulamak için geri dönersiniz. Ürünleri kategorilere toplu atama rehberi bu akışı ve sınırlarını anlatıyor.

2. CSV içinde sürdürmek#

Kataloğunuz zaten bir ERP’den, bir PIM’den ya da tedarikçi beslemesinden geliyorsa akla ilk gelen hamle, kategori sütununu kaynakta hesaplayıp uygulamayı WooCommerce içe aktarıcısına bırakmaktır. Categories, virgülle ayrılmış bir listedir; hiyerarşi Parent > Child biçiminde, okun iki yanında birer boşlukla yazılır, dolayısıyla Sale, Clothing > Dresses iki terim atar.

Tuzak şurada: dolu bir sütun birleştirmez, değiştirir. Bir ürün hem Sale hem Dresses kategorisindeyse ve bir sonraki içe aktarımınız Categories sütununda yalnızca Dresses gönderiyorsa, ürün Sale’den çıkar. Taksonominin sahibi beslemeyse istediğiniz de budur. Ama kategorileri wp-admin içinde atayan biri de varsa bu bir felakettir, çünkü her içe aktarım onun emeğini sessizce geri alır. Yalnızca iki yapılandırma güvenlidir: ya kategorilerin sahibi beslemedir ve insanlar onlara hiç dokunmaz, ya da Categories sütunu eşlenmeden bırakılır; bu durumda mevcut terimler korunur.

Bir de kapsam sorunu var. Besleme tedarikçinin verisini bilir; satış rakamlarınızı, değerlendirme sayılarınızı ya da fotoğrafçınızın hangi ürünleri henüz çekmediğini bilmez. Kaynakta ifade edebileceğiniz kurallar, istediğiniz kuralların bir alt kümesidir.

3. functions.php içinde bir sorgu filtresi#

Stack Overflow’un size verdiği cevap budur. İşe yarar, ama yayımlanmış sürümlerin çoğunun iddia ettiği şekilde değil. woocommerce_product_query kancasına bağlanın, WooCommerce’in uygulamak üzere olduğu terim kısıtını kaldırın ve yerine kendi seçiminizi koyun. Bu, /product-category/clearance/ adresini o an indirimde olan her şeyin canlı listesine dönüştürür:

add_action( 'woocommerce_product_query', function ( $q ) {
	if ( ! $q->is_main_query() || ! is_product_category( 'clearance' ) ) {
		return;
	}

	// Resolve the queried term now, while the taxonomy clause still exists, so
	// the archive title, term description and breadcrumb keep working after it
	// goes. get_queried_object() caches its result on the query object.
	$q->get_queried_object();

	// The term constraint comes from the product_cat query var, which WP_Query
	// re-reads in get_posts(). Clearing that var is what drops the clause.
	// Filtering $q->get( 'tax_query' ) does not, because the clause is not in
	// there yet. Leave tax_query alone: WC_Query has already put its
	// product_visibility exclusions in it, and overwriting it un-hides hidden
	// and out-of-stock products.
	$q->set( 'product_cat', '' );

	// Includes variation IDs and the parents of on-sale variations. Cached in
	// the wc_products_onsale transient.
	$ids = wc_get_product_ids_on_sale();

	// An empty post__in is ignored by WP_Query, which would show the entire
	// catalogue. Fall back to an ID that cannot match.
	$q->set( 'post__in', $ids ? $ids : array( 0 ) );
} );

Yirmi küsur satır, eklenti yok ve arşiv gerçekten kurala dayalı çalışıyor. Ona güvenmeden önce üretilen SQL’i Query Monitor ile bir kez okuyun: tax_query‘i filtreleyip sorgu değişkenine dokunmayan saf sürüm, kuralınızı özgün terimle sessizce AND ile birleştirir. Bunun bedeli, arşiv sorgusunu değil taksonomiyi okuyan her şeydir:

  • Sayaçlar sıfır kalır. Bir ürün kategorisindeki count değeri, gerçek terim ilişkilerinden yola çıkarak _wc_term_recount() tarafından hesaplanır; bu da WooCommerce’in product_cat için tanımladığı sayım geri çağrısıdır. Sizin filtreniz hiç ilişki oluşturmadığı için kategori bileşeni, alt kategori kutucukları ve Ürünler listesi kategoriyi boş gösterir.
  • O tek arşiv dışında her şey aksini söyler. wp-admin içinde Ürünler’i Clearance’a göre filtrelemek hiçbir şey döndürmez. Katmanlı gezinme, filtre eklentileri, Store API, REST API ve besleme dışa aktarıcıları, sizin arşiv sorgunuzu değil terim ilişkilerini okur.
  • Blok temalar işi karmaşıklaştırır. Geçerli sorguyla eşitle seçeneği kapalı bir Product Collection bloğu kendi sorgusunu kurar ve filtrenizi tamamen yok sayar; sitenin başka yerlerine elle yerleştirilmiş her koleksiyon da öyle.
  • Ölçeklenmesi kötüdür. Beş bin kimlik içeren bir post__in, her sayfa yüklenişinde beş bin öğelik bir IN() ifadesi demektir; önbelleğe alması da sorgu planı çıkarması da zahmetlidir.
  • Görünmezdir. wp-admin içinde hiçbir şey bu kategorinin özel olduğunu söylemez. Sonraki geliştirici bunu tesadüfen öğrenecek.

Bunu, kural basitken ve yalnızca tek bir arşiv sayfasını etkilemesi gerekiyorken kullanın. Bir düzine koleksiyon için kötü bir temeldir.

4. Product Collection ve Query Loop blokları#

Product Collection bloğu, “indirimde, stokta, Dresses kategorisinde, çok satanlara göre sıralı” listeyi istediğiniz sayfada hiç kod yazmadan seve seve gösterir. Bir açılış sayfası ya da ana sayfadaki bir şerit için doğru araç budur; okumayı burada bırakabilirsiniz.

Yine de bu bir kategori değildir. Ortada terim yoktur; dolayısıyla /product-category/…/ adresi de yoktur, breadcrumb da, kategori menüsünde bir kayıt da, terim sayacı da, katmanlı gezinme filtresi de, SEO eklentinizin başlık iliştirebileceği bir nesne de. Hiçbir şeyin üstü ya da altı olamaz, bu yüzden müşterilerin gezindiği ağaçta hiç görünmez. Amacınız bir sayfaysa bloklar yeter. Amacınız bir kategoriyse yetmez. Aynısı çekirdekteki Query Loop bloğu için de geçerli.

Yan yana#

YöntemGerçek terimYeniden içe aktarmayı atlatırDoğru sayaçlar ve menülerZamanla doğru kalır
Elle atamaEvetYalnızca besleme kategorileri atlarsaEvetHayır
CSV ile yeniden içe aktarmaEvetBesleme kazanır, insan kaybederEvetYalnızca içe aktardığınız sıklıkta
Kod içinde sorgu filtresiHayırEtkilenmezHayırGörüntüleme anında
Product Collection bloğuHayırEtkilenmezHayırGörüntüleme anında
Terim yazan kural motoruEvetİçe aktarmadan sonra yeniden uygulanırEvetTetikleyicilerine bağlı

Bir kural motorunun doğru yapması gerekenler#

Son satırdaki çekince çok iş görüyor. “Kural motoru” bir araç sınıfını tarif eder, bir garantiyi değil. Güvenebileceğiniz bir motoru, taksonominizi sessizce bozan bir motordan beş soru ayırır.

Elinizdeki koşulu ifade edebiliyor mu?#

Çoğu kural oluşturucu, tüm liste için bir kez seçilen AND ya da OR ile birleştirilmiş düz bir koşul listesi sunar. Gerçek ürün yönetimi koşulları düz değildir. “İndirimde olsun; ya %30’dan fazla indirimli olsun ya da Outlet markasında olsun, ama siparişe özel etiketli hiçbir şey olmasın” ifadesi iç içe gruplama ve olumsuzlama ister. Düz bir AND listesi bunu söyleyemez; iki düz kural da söyleyemez, çünkü “ama olmasın” kısmının gidecek bir yeri yoktur.

İkinci yarısı, hangi alanların sunulduğudur. Fiyat, stok durumu ve kategori zaten olmazsa olmazdır. İndirim yüzdesi, görsel sayısı, değerlendirme sayısı, genel bir nitelik, keyfî bir meta anahtarı — işe yarayan kurallar orada yaşar. Yalnızca fiyatı ve kategoriyi okuyan bir oluşturucu sizi elle çalışmaya geri gönderir.

Yeniden değerlendirmeyi ne tetikliyor?#

Bütün işin güvenilir olup olmadığına bu karar verir. Cevabın iki yarısı olmalı.

Olaylar. Ürün oluşturuldu, ürün güncellendi, fiyat değişti, stok değişti. Kancalanması kolaydır ve olağan düzenleme işleri için yeterlidir.

Düzenli bir tarama turu. Yalnızca olaylar yetmez, çünkü bazı koşullar hiçbir olay olmadan yanlışa döner. “Son 30 günde oluşturuldu” koşulu sırf zaman geçtiği için bayatlar: üründe hiçbir şey değişmez, hiçbir kanca tetiklenmez ve dünkü yeni ürün sonsuza dek New Arrivals kategorisinde kalır. Gerçekten süresi dolan bir yeni ürünler kategorisinin arkasındaki mekanizma budur ve bu, “şu kadar gün önce” kalıbıyla kurulan her koşul için geçerlidir.

Zamanlanmış indirimler diğer klasik durumdur. Güncel WooCommerce sürümleri, indirimleri başlatmak ve bitirmek için ürün başına Action Scheduler olayları kuyruğa alır; eski günlük woocommerce_scheduled_sales cron görevi de emniyet ağı olarak duruyor. Bu yüzden olay güdümlü bir motor çoğu zaman fark eder. Çoğu zaman, her zaman demek değildir: _price meta alanını doğrudan veritabanına yazan ERP eşitlemeleri, toplu SQL güncellemeleri ve CRUD katmanını atlayan fiyatlandırma eklentileri, bir motorun duyabileceği hiçbir şeyi tetiklemeden cevabı değiştirir. Tarama turu, “çoğu zaman doğru”yu “yarın sabaha kadar doğru”ya çevirir; kendini boşaltan bir indirim kategorisini çalıştıran şey de budur.

Elle atadığınız ürünlere ne olur?#

İçinde 400 ürün olan mevcut bir kategoriyi alın, 380 ürünle eşleşen bir kural iliştirin ve kaydete basın. Saf bir motor kategoriyi kurala göre hizalar ve ürün sorumlunuzun bilerek eklediği 20 istisnayı siler. Geri alma diye bir şey yoktur.

Doğru tasarım, motorun hangi üyelikleri kendisinin oluşturduğunu kaydetmesi ve yalnızca onları kaldırmasıdır. Mevcut bir kategoriyi bir araca emanet etmeden önce bunu sınayın: kuralın eşleşmediği bir ürünü elle atayın, motoru çalıştırın, ürünün hâlâ orada olduğunu kontrol edin.

Hiçbir şeyle eşleşmeyen bir kural ne yapar?#

Boş, bozuk ya da silinmiş bir niteliğe atıf yapan bir koşul grubunun iki okuması vardır: hiçbir şeyle eşleşmek ya da her şeyle eşleşmek. Birincisi boş bir kategori ve otuz saniyelik bir hata ayıklama demektir. İkincisi bütün kataloğunuzu Clearance’a atar. tax_query ya da meta_query‘yi birleştirerek kuran motorlar ikincisine yatkındır, çünkü boş bir koşul dizisi kısıtsız bir sorgudur.

Canlı bir önizleme bunu bir dakikada kontrol etmenizi sağlar. Bilerek imkânsız bir kural kurun — SKU, var olmadığını bildiğiniz bir metne eşit olsun — ve önizlemenin yirmi bin değil sıfır yazdığını doğrulayın. Kaydetmeden önce gösterilen bir sayı kolaylık değildir; güvenlik mekanizmasının ta kendisidir.

Partiler hâlinde çalışıyor mu?#

500 üründe bunu fark bile etmezsiniz. 20,000 üründe ise özelliğin kullanılabilir olup olmadığına bu karar verir. Bir kural kümesini katalog genelinde değerlendirmek, binlerce veritabanı yazması artı bir terim yeniden sayımı demektir; sayfa isteği içindeki PHP’nin ise bir zaman aşımı, bir bellek sınırı ve dönen çarkı izleyen bir kullanıcısı vardır.

Doğru cevap, WooCommerce ile birlikte gelen ve sitenizde hâlihazırda çalışan Action Scheduler’dır: partilere bölünmüş, arka planda işlenen ve WooCommerce → Durum → Zamanlanmış Eylemler altında görülebilen eylemler. Yanlış cevap, değerlendirmeyi init üzerinde ya da sayfa yüklenirken yapmaktır. Bir araç işini nerede kuyruğa aldığını size söyleyemiyorsa, kuyruğa almadığını varsayın.

Kurala dayalı kategorilerin çözmediği şeyler#

Üyeliği otomatikleştirmek üyeliği çözer. Yanı başındaki birkaç sorun ise tam olduğu yerde kalır.

  • Dizine ekleme ve meta veriler. Kuralla kurulmuş bir kategorinin de bir başlığa, bir açıklamaya ve Google’ın onu dizine ekleyip eklemeyeceğine dair bir karara ihtiyacı vardır. Bu, SEO eklentinizin işidir; zayıf içerikli kategori sayfalarının neden zorlandığı kategori sayfalarının neden dizine eklenmediği yazısında duruyor.
  • Yönlendirmeler. Bu iş sizi ağacı yeniden kurgulamaya götürürse eski URL’lerin yine de ele alınması gerekir: bir yönlendirme eklentisi ve bir plan. Bakınız sıralama kaybetmeden kategori yapısını değiştirmek.
  • WooCommerce’in kendi arşiv davranışı. Üst kategorilerin ürün yerine alt kategori kutucukları göstermesi ve stokta olmayan ürünleri katalogdan gizlediğinizde sayaçların onları düşürmesi, çekirdeğin davranışıdır.
  • Çok fazla kategori. Elinizdekileri hiçbir şey birleştirmez ya da tekilleştirmez; daha fazlasını üretmek de kendiliğinden bir iyileşme değildir.

Bir uygulama örneği: Smart Categories for WooCommerce#

Bu alanda bir eklenti geliştiriyoruz; dolayısıyla bunu, beş soruyu atlamanız için bir tavsiye değil, o soruların çözümlü bir örneği olarak okuyun. Elle ya da CSV yolu işinizi görüyorsa onu kullanın.

Smart Categories for WooCommerce, bir kural kümesini gerçek bir product_cat terimine ya da bir ürün etiketine iliştirir — paralel bir taksonomiye değil — böylece eşleşen ürünlere terimin kendisi atanır ve alt taraftaki her şey normal davranır. Beş soru karşısında durumu şöyle: gruplar sınır olmadan iç içe geçer ve her biri TÜMÜ, HERHANGİ BİRİ ya da olumsuzlanmış olur; ücretsiz sürümde 35 eşleşme alanı vardır, aralarında indirim yüzdesi, görsel sayısı, kâr marjı, herhangi bir genel nitelik ve meta anahtarına göre bir özel alan bulunur; yeniden değerlendirme ürün oluşturma, güncelleme, fiyat değişikliği ve stok değişikliğinde, ayrıca günlük bir tarama turunda çalışır; eklentinin oluşturduğu üyelikler kaydedilir ve yalnızca onlar kaldırılır, böylece elle atadığınız her şey yerinde kalır; eşleştirme de Action Scheduler üzerinden partiler hâlinde kuyruğa alınır.

İç içe AND, OR ve NOT grupları ile eşleşen WooCommerce ürünlerinin anlık sayısını içeren kural oluşturucu.
Gruplar istediğiniz derinlikte iç içe geçer; önizleme siz kurarken eşleşen ürünleri sayar.

Canlı önizleme, siz kuralı kurarken ve daha kaydetmeden eşleşen ürünleri ve sayılarını gösterir; imkânsız kural testini orada çalıştırın. Ücretsiz sürüm wordpress.org üzerinde ve kategori, kural ya da ürün sınırı yok. Pro katmanı, nitelik değeri başına ya da iki niteliğin her bileşimi için üretilen alt kategoriler ekler; ayrıca son 30 günde satılan adet gibi altı satış zekâsı alanı getirir.

Canlı ürün sayıları ve tek tıkla yenileme seçeneğiyle listelenen tüm akıllı kategoriler
Kurala dayalı her kategori, güncel ürün sayısıyla birlikte.

Nereden başlamalı#

Önce kuralı düz cümlelerle yazın. Tek bir cümleye sığıyorsa, içinde “bir de şu” türü ekler yoksa ve alttaki veri neredeyse hiç kıpırdamıyorsa, toplu düzenleyici ve aylık bir hatırlatıcı işinizi görür. Cümlenin bir “ama şunlar hariç”e ihtiyacı varsa, ya da veri her gün değişiyorsa, ya da elle üç civarında koleksiyondan fazlasını yönetiyorsanız, kendi kendine yeniden değerlendirme yapan bir şeye ihtiyacınız var. O noktada da yalnızca yukarıdaki beş soru önemlidir; hangi aracı seçerseniz seçin, bu soruları ona sorun.

Okumaya devam

İlgili yazılar