WooCommerce CLI ile CSV’den Toplu Ürün İçe Aktarma
E-ticaret sitelerinde yüzlerce hatta binlerce ürünü tek tek WooCommerce arayüzünden girmek, her sysadmin’in ve site yöneticisinin kabusu haline gelebilir. Özellikle büyük katalog aktarımlarında ya da düzenli stok güncellemelerinde manuel yöntem hem zaman hem de hata riski açısından ciddi bir sorun oluşturur. İşte bu noktada WP-CLI’nin WooCommerce eklentisiyle sunduğu komut satırı araçları devreye giriyor. Bu yazıda gerçek dünya senaryoları üzerinden CSV dosyalarından toplu ürün içe aktarma işlemini baştan sona ele alacağız.
Neden WP-CLI ile Toplu İçe Aktarma?
WooCommerce’in kendi admin panelinde de bir CSV import aracı bulunuyor, bunu biliyoruz. Ancak bu araç birkaç kritik noktada yetersiz kalıyor. Binlerce satırlık CSV dosyalarında tarayıcı zaman aşımına uğruyor, büyük dosyaları kesmek ve parça parça yüklemek zorunda kalıyorsunuz. Ayrıca bu işlemi otomatikleştirmek, cron job’a bağlamak ya da başka script’lerle entegre etmek neredeyse imkansız.
WP-CLI ile bu işlemi yaparken şunları elde ediyorsunuz:
- Zaman aşımı sorunu yok: PHP execution time limitleri CLI modunda farklı çalışır
- Otomasyon imkanı: Cron job veya CI/CD pipeline’a entegre edebilirsiniz
- Detaylı loglama: Her adımı kayıt altına alabilirsiniz
- Hata yönetimi: Script seviyesinde hataları yakalayıp yönetebilirsiniz
- Sunucu kaynaklarını verimli kullanma: Batch işlemler ile memory yönetimi yapabilirsiniz
Ortam Hazırlığı
WP-CLI ve WooCommerce CLI Kurulumu
WP-CLI’nin sisteminizde kurulu olduğunu varsayıyorum. Eğer kurulu değilse önce onu halledelim:
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
chmod +x wp-cli.phar
sudo mv wp-cli.phar /usr/local/bin/wp
wp --info
WooCommerce CLI komutları, WooCommerce eklentisi aktif olduğunda otomatik olarak WP-CLI’ye eklenir. Bunu doğrulamak için:
cd /var/www/html/wordpress
wp plugin list --status=active | grep woocommerce
wp wc --help
wp wc product list gibi komutları görebiliyorsanız hazırız demektir. Bir de REST API kimlik doğrulaması için kullanıcı bilgilerine ihtiyacınız var. WooCommerce CLI komutları --user parametresi ister:
# Mevcut admin kullanıcısını kontrol et
wp user list --role=administrator
# Komutları çalıştıracak kullanıcının ID'sini not edin
wp wc product list --user=1 --format=table
CSV Dosyasının Yapısı
WooCommerce’in beklediği CSV formatını doğru anlamak çok önemli. WooCommerce’in native import formatı ile WP-CLI üzerinden import için kullanacağımız JSON tabanlı yaklaşım arasında fark var.
Standart WooCommerce CSV Formatı
WooCommerce’in admin panelindeki import aracının beklediği CSV yapısında şu sütunlar bulunur:
- ID: Güncelleme işlemleri için mevcut ürün ID’si
- Type: simple, variable, grouped, external
- SKU: Stok takip kodu
- Name: Ürün adı
- Published: 1 veya 0
- Short description: Kısa açıklama
- Description: Uzun açıklama
- Regular price: Normal fiyat
- Sale price: İndirimli fiyat
- Stock: Stok miktarı
- Weight: Ağırlık
- Categories: Kategori, virgülle ayrılmış
- Tags: Etiketler
- Images: Resim URL’leri
Örnek bir CSV satırı şu şekilde görünür:
# CSV dosyasının ilk birkaç satırına bakalım
head -5 /tmp/products.csv
# Sütun sayısını kontrol edelim
awk -F',' 'NR==1{print NF}' /tmp/products.csv
WP-CLI ile Import Yöntemleri
Yöntem 1: WooCommerce Native Import Komutu
WooCommerce 3.1 ve sonrasında gelen wc_csv_import fonksiyonu WP-CLI üzerinden çağrılabilir. Ancak bu doğrudan bir WP-CLI komutu değil, PHP kodu aracılığıyla tetiklemeniz gerekiyor:
wp eval-file /tmp/import_products.php --user=1
import_products.php dosyasının içeriği:
# PHP dosyasını oluşturalım
cat > /tmp/import_products.php << 'EOF'
<?php
if ( ! defined( 'WP_CLI' ) || ! WP_CLI ) {
die( 'Bu script sadece WP-CLI ile calistirilabilir.' );
}
$file = '/tmp/products.csv';
if ( ! file_exists( $file ) ) {
WP_CLI::error( 'CSV dosyasi bulunamadi: ' . $file );
}
// WooCommerce importer sinifini yukle
require_once WC()->plugin_path() . '/includes/import/class-wc-product-csv-importer.php';
$params = array(
'delimiter' => ',',
'start_pos' => 0,
'mapping' => array(),
'update_existing' => true,
'lines' => 0,
'parse' => true,
);
$importer = new WC_Product_CSV_Importer( $file, $params );
$results = $importer->import();
WP_CLI::success( 'Import tamamlandi.' );
WP_CLI::line( 'Basarili: ' . count( $results['imported'] ) );
WP_CLI::line( 'Guncellenen: ' . count( $results['updated'] ) );
WP_CLI::line( 'Hata: ' . count( $results['failed'] ) );
if ( ! empty( $results['failed'] ) ) {
foreach ( $results['failed'] as $failed ) {
WP_CLI::warning( 'Basarisiz: ' . $failed['id'] . ' - ' . $failed['error']->get_error_message() );
}
}
EOF
Yöntem 2: WC REST API Komutu ile Satır Satır Import
wp wc product create komutu her seferinde tek bir ürün oluşturur. Büyük CSV’ler için bunu bir bash script’i ile döngüye almanız gerekiyor:
#!/bin/bash
# /usr/local/bin/wc-import.sh
CSV_FILE="/tmp/products.csv"
WP_PATH="/var/www/html/wordpress"
USER_ID=1
LOG_FILE="/var/log/wc-import-$(date +%Y%m%d-%H%M%S).log"
BATCH_SIZE=50
SLEEP_BETWEEN_BATCHES=2
echo "WooCommerce CSV Import Basladi: $(date)" | tee -a "$LOG_FILE"
echo "Dosya: $CSV_FILE" | tee -a "$LOG_FILE"
echo "---" | tee -a "$LOG_FILE"
# Baslik satirini atla, CSV'yi isle
tail -n +2 "$CSV_FILE" | while IFS=',' read -r sku name price stock category description; do
# Bos satirlari atla
[ -z "$sku" ] && continue
# Ozel karakterleri temizle
name=$(echo "$name" | sed 's/^"//;s/"$//')
description=$(echo "$description" | sed 's/^"//;s/"$//')
echo "Isleniyor: SKU=$sku, Urun=$name" | tee -a "$LOG_FILE"
result=$(cd "$WP_PATH" && wp wc product create
--sku="$sku"
--name="$name"
--regular_price="$price"
--stock_quantity="$stock"
--manage_stock=true
--status=publish
--user="$USER_ID"
--format=json 2>&1)
if echo "$result" | grep -q '"id"'; then
product_id=$(echo "$result" | grep -o '"id":[0-9]*' | head -1 | cut -d: -f2)
echo " BASARILI: Urun olusturuldu, ID=$product_id" | tee -a "$LOG_FILE"
else
echo " HATA: $sku - $result" | tee -a "$LOG_FILE"
fi
done
echo "---" | tee -a "$LOG_FILE"
echo "Import Tamamlandi: $(date)" | tee -a "$LOG_FILE"
Bu script’i çalıştırmadan önce:
chmod +x /usr/local/bin/wc-import.sh
# Test icin once kuru calistirma yapın (echo modunda)
bash -x /usr/local/bin/wc-import.sh 2>&1 | head -50
Gelişmiş Senaryo: Varyasyonlu Ürünler
Gerçek hayatta en zorlu import senaryosu değişken ürünler (variable products). Bir tişörtün farklı renk ve beden kombinasyonlarını yönetmek için önce ana ürünü, sonra attribute’ları, sonra varyasyonları oluşturmanız gerekiyor.
#!/bin/bash
# Variable product import ornegi
# CSV formati: parent_sku,variation_sku,name,color,size,price,stock
WP_PATH="/var/www/html/wordpress"
USER_ID=1
VARIABLE_CSV="/tmp/variable_products.csv"
create_variable_product() {
local sku=$1
local name=$2
# Once parent urunu olustur
parent_result=$(cd "$WP_PATH" && wp wc product create
--sku="$sku"
--name="$name"
--type=variable
--status=publish
--user="$USER_ID"
--format=json 2>/dev/null)
parent_id=$(echo "$parent_result" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])" 2>/dev/null)
echo "$parent_id"
}
create_variation() {
local parent_id=$1
local var_sku=$2
local color=$3
local size=$4
local price=$5
local stock=$6
cd "$WP_PATH" && wp wc product_variation create "$parent_id"
--sku="$var_sku"
--regular_price="$price"
--stock_quantity="$stock"
--manage_stock=true
--status=publish
--attributes='[{"id":0,"name":"Renk","option":"'"$color"'"},{"id":0,"name":"Beden","option":"'"$size"'"}]'
--user="$USER_ID"
--format=json 2>/dev/null
}
# CSV'yi isle
declare -A parent_ids
while IFS=';' read -r parent_sku var_sku name color size price stock; do
[ "$parent_sku" = "parent_sku" ] && continue
# Parent urun daha once olusturulmadiysa olustur
if [ -z "${parent_ids[$parent_sku]}" ]; then
echo "Parent urun olusturuluyor: $name ($parent_sku)"
pid=$(create_variable_product "$parent_sku" "$name")
parent_ids[$parent_sku]=$pid
echo " Parent ID: $pid"
fi
# Varyasyon olustur
parent_id=${parent_ids[$parent_sku]}
echo " Varyasyon olusturuluyor: $var_sku ($color / $size)"
create_variation "$parent_id" "$var_sku" "$color" "$size" "$price" "$stock"
done < "$VARIABLE_CSV"
echo "Varyasyonlu urun import tamamlandi."
Mevcut Ürünleri Güncelleme
Import senaryolarının önemli bir kısmı yeni ürün oluşturmak değil, mevcut ürünlerin fiyat ve stok bilgilerini güncellemektir. Günlük ya da haftalık stok senkronizasyonu için şu yaklaşımı kullanabilirsiniz:
#!/bin/bash
# Stok ve fiyat guncelleme script'i
# CSV: sku,stock,regular_price,sale_price
UPDATE_CSV="/tmp/stock_update.csv"
WP_PATH="/var/www/html/wordpress"
USER_ID=1
LOG_FILE="/var/log/wc-stock-update-$(date +%Y%m%d).log"
update_counter=0
error_counter=0
notfound_counter=0
while IFS=',' read -r sku stock regular_price sale_price; do
# Baslik satirini atla
[ "$sku" = "sku" ] && continue
[ -z "$sku" ] && continue
# SKU'ya gore urun ID'sini bul
product_id=$(cd "$WP_PATH" && wp wc product list
--sku="$sku"
--field=id
--user="$USER_ID"
--format=csv 2>/dev/null | tail -1)
if [ -z "$product_id" ] || [ "$product_id" = "id" ]; then
echo "BULUNAMADI: SKU=$sku" | tee -a "$LOG_FILE"
((notfound_counter++))
continue
fi
# Urunu guncelle
update_args="--stock_quantity=$stock --manage_stock=true"
[ -n "$regular_price" ] && update_args="$update_args --regular_price=$regular_price"
[ -n "$sale_price" ] && update_args="$update_args --sale_price=$sale_price"
result=$(cd "$WP_PATH" && wp wc product update "$product_id"
$update_args
--user="$USER_ID"
--format=json 2>&1)
if echo "$result" | grep -q '"id"'; then
echo "GUNCELLENDI: SKU=$sku, ID=$product_id, Stok=$stock" | tee -a "$LOG_FILE"
((update_counter++))
else
echo "HATA: SKU=$sku - $result" | tee -a "$LOG_FILE"
((error_counter++))
fi
done < "$UPDATE_CSV"
echo "---" | tee -a "$LOG_FILE"
echo "Guncellenen: $update_counter | Bulunamayan: $notfound_counter | Hata: $error_counter" | tee -a "$LOG_FILE"
Ürün Resimlerini Import’a Dahil Etme
Ürün resimlerini import sırasında eklemek çoğu zaman gözden kaçan bir detay. WooCommerce CLI ile resim URL’si veya local dosya yolu kullanabilirsiniz:
# Oncelikle resmi WordPress media kutuphanesine yukle
image_id=$(cd /var/www/html/wordpress && wp media import "/tmp/images/urun-001.jpg"
--title="Urun 001 Gorseli"
--porcelain 2>/dev/null)
echo "Medya ID: $image_id"
# Ardindan urunu olusturirken image ID'sini ver
cd /var/www/html/wordpress && wp wc product create
--sku="URN-001"
--name="Test Ürünü"
--regular_price="99.90"
--images='[{"id":'"$image_id"'}]'
--user=1
--format=json
Birden fazla resim için:
# Birden fazla resim yukle ve ID'leri topla
IMAGE_DIR="/tmp/product_images"
PRODUCT_SKU="URN-MULTI-001"
WP_PATH="/var/www/html/wordpress"
image_ids=()
for img_file in "$IMAGE_DIR"/${PRODUCT_SKU}*.jpg; do
[ -f "$img_file" ] || continue
img_id=$(cd "$WP_PATH" && wp media import "$img_file" --porcelain 2>/dev/null)
image_ids+=("$img_id")
echo "Yuklendi: $img_file -> ID: $img_id"
done
# JSON array olustur
images_json="["
for i in "${!image_ids[@]}"; do
[ $i -gt 0 ] && images_json+=","
images_json+='{"id":'"${image_ids[$i]}"'}'
done
images_json+="]"
# Urunu guncelle
cd "$WP_PATH" && wp wc product update
$(wp wc product list --sku="$PRODUCT_SKU" --field=id --user=1 --format=csv 2>/dev/null | tail -1)
--images="$images_json"
--user=1
Cron Job ile Otomatik Senkronizasyon
Tüm bu script’leri bir cron job’a bağlayarak otomatik çalışmasını sağlayabilirsiniz:
# /etc/cron.d/woocommerce-sync dosyasini olustur
cat > /etc/cron.d/woocommerce-sync << 'EOF'
# WooCommerce Urun Senkronizasyonu
# Her gece 02:00'de stok guncelleme
0 2 * * * www-data /usr/local/bin/wc-stock-update.sh >> /var/log/wc-cron.log 2>&1
# Her Pazartesi 03:00'de tam katalog import
0 3 * * 1 www-data /usr/local/bin/wc-full-import.sh >> /var/log/wc-full-import.log 2>&1
EOF
# Cron dosyasina dogru izinleri ver
chmod 644 /etc/cron.d/woocommerce-sync
Script’lerin başına şunu eklemeyi unutmayın:
#!/bin/bash
# Script'in cron ortaminda da calisabilmesi icin PATH'i tanimla
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
# PHP ve WP-CLI'nin tam yollarini kullan
WP_CLI=$(which wp)
PHP=$(which php)
# WordPress kurulum dizini
WP_PATH="/var/www/html/wordpress"
# Lock dosyasi kontrolu - iki script ayni anda calismasm
LOCK_FILE="/tmp/wc-import.lock"
if [ -f "$LOCK_FILE" ]; then
echo "Import zaten calisuyor, cikiliyor."
exit 1
fi
touch "$LOCK_FILE"
trap "rm -f $LOCK_FILE" EXIT
Yaygın Hatalar ve Çözümleri
Import sürecinde karşılaştığım en yaygın sorunları ve çözümlerini paylaşayım:
Memory limit hatası: PHP memory limit düşükse büyük CSV’lerde crash yaşarsınız. wp-cli.yml dosyasına şunu ekleyin:
# WordPress dizininde wp-cli.yml olustur
cat > /var/www/html/wordpress/wp-cli.yml << 'EOF'
path: /var/www/html/wordpress
url: https://siteniz.com
user: 1
skip-plugins:
- some-heavy-plugin
require:
- /tmp/custom-commands.php
EOF
# PHP memory limitini gecici olarak artir
php -d memory_limit=512M /usr/local/bin/wp wc product list --user=1
Karakter kodlama sorunları: Türkçe karakterler içeren CSV dosyalarında UTF-8 encoding’e dikkat edin:
# Dosyanin encoding'ini kontrol et
file -i /tmp/products.csv
# Gerekirse UTF-8'e donustur
iconv -f ISO-8859-9 -t UTF-8 /tmp/products.csv > /tmp/products_utf8.csv
# BOM karakterini kaldir (Excel'den gelen CSV'lerde olabilir)
sed -i '1s/^xEFxBBxBF//' /tmp/products_utf8.csv
Duplicate SKU hataları: Import tekrarlandığında aynı SKU’nun tekrar oluşturulmaması için kontrol ekleyin:
# SKU var mi kontrolu
check_sku_exists() {
local sku=$1
local count=$(cd /var/www/html/wordpress && wp wc product list
--sku="$sku"
--field=id
--user=1
--format=csv 2>/dev/null | grep -v "^id$" | wc -l)
echo "$count"
}
# Kullanim
if [ "$(check_sku_exists 'TEST-001')" -gt 0 ]; then
echo "SKU zaten mevcut, guncelleniyor..."
# wp wc product update ...
else
echo "Yeni urun olusturuluyor..."
# wp wc product create ...
fi
Performance İpuçları
Binlerce ürünlük import’larda performansı artırmak için şu önlemleri alın:
- Search indexer’ı geçici olarak devre dışı bırakın: WooCommerce lookup tablolarının rebuild edilmesini ertelemek için import sırasında
WC_Install::create_lookup_table()çağrısını engelleyin - Cache’i import sonrası temizleyin:
wp cache flushkomutuyla object cache’i temizleyin - Batch boyutunu ayarlayın: Tek seferde çok fazla ürün işlemeyin, 100-200’lük batch’ler genellikle ideal
- WooCommerce webhook’larını geçici olarak kapatın: Her ürün oluşturma olayında webhook tetikleniyorsa ciddi yavaşlama yaşarsınız
- MySQL slow query log’u açık tutun: Import sırasında yavaş sorguları tespit edip index ekleyebilirsiniz
Sonuç
WP-CLI ile WooCommerce ürün import’u, doğru kurgulandığında hem çok daha hızlı hem de çok daha güvenilir bir süreç haline geliyor. Admin panelindeki import aracının zaman aşımı korkusu olmadan, scriptlerinizi cron job’a bağlayarak tamamen otomatize bir katalog yönetimi altyapısı kurabilirsiniz.
Yazıda ele aldığımız başlıca konuları özetleyecek olursak: basit ürün import’undan başlayarak varyasyonlu ürünlere, stok güncelleme scriptlerinden resim yönetimine kadar kapsamlı bir yol haritası çıkardık. Pratik bir tavsiye olarak her import işlemi öncesinde mutlaka bir veritabanı yedeği alın ve ilk denemeyi birkaç satırlık test CSV’siyle yapın. Production’da bin ürünlük bir import’u test etmeden çalıştırmak sizi zor durumda bırakabilir.
Özellikle düzenli ERP veya stok sistemi entegrasyonlarında bu yaklaşım çok işinize yarayacak. Sisteminizden CSV alıp WP-CLI ile WooCommerce’e otomatik import yapan bir pipeline kurduğunuzda, ürün yönetimi artık tamamen ellerin dışında bir sürece dönüşüyor. Bu da sizin asıl işinize, yani sistemlerin stabil çalışmasına odaklanmanız için zaman açıyor.
