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 flush komutuyla 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.

Bir yanıt yazın

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