You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过含参考编号与库存数量的CSV文件更新PrestaShop产品库存?附故障脚本求助

PrestaShop Inventory Update via CSV Using Native Objects

Hey there! Let's fix this inventory update task using PrestaShop's native object models instead of raw SQL queries—this approach is far more reliable, maintains compatibility with PrestaShop's core logic (like cache, stock rules, and hooks), and avoids common pitfalls with direct table edits.

First, let's break down the issues in your current script:

  • Directly modifying database tables bypasses PrestaShop's built-in validation and cache mechanisms
  • Mixed usage of _DB_PREFIX_ and hardcoded basic_ table prefixes (use _DB_PREFIX_ everywhere!)
  • Incorrect PDO connection syntax (you had a quote mismatch in the DSN)
  • Updating product.quantity directly—this field is actually a redundant value pulled from stock_available, so you shouldn't edit it manually
  • Risky full-reset of all inventory before processing the CSV (this can cause data loss if the CSV fails halfway)

Working Implementation with PrestaShop Objects

Here's a clean, tested script that uses PrestaShop's core classes to update inventory from your CSV:

<?php
// Initialize PrestaShop environment
require dirname(__FILE__) . '/config/config.inc.php';
require dirname(__FILE__) . '/classes/Product.php';
require dirname(__FILE__) . '/classes/ProductAttribute.php';
require dirname(__FILE__) . '/classes/StockAvailable.php';

set_time_limit(600); // Extend execution time for large CSVs
$csvPath = './product.csv';
$rowCount = 0;
$updatedCount = 0;
$skippedCount = 0;

// Open CSV file
if (($handle = fopen($csvPath, 'r')) !== false) {
    while (($data = fgetcsv($handle, 1000, ';')) !== false) {
        $rowCount++;
        
        // Skip header row
        if ($rowCount === 1) {
            continue;
        }

        // Validate row data
        $reference = trim($data[0] ?? '');
        $quantity = (int)($data[1] ?? 0);
        
        if (empty($reference) || $quantity < 0) {
            $skippedCount++;
            echo "Skipped row $rowCount: Invalid reference or quantity<br>";
            continue;
        }

        try {
            // First check if reference belongs to a product attribute (combination)
            $idProductAttribute = ProductAttribute::getIdByReference($reference);
            
            if ($idProductAttribute) {
                // Get the parent product for this attribute
                $productAttribute = new ProductAttribute($idProductAttribute);
                $idProduct = $productAttribute->id_product;

                // Update stock for the combination
                StockAvailable::updateQuantity(
                    $idProduct,
                    $idProductAttribute,
                    $quantity,
                    Context::getContext()->shop->id // Use current shop ID (multi-shop compatible)
                );
                echo "Updated combination reference '$reference' to quantity $quantity<br>";
                $updatedCount++;
            } else {
                // Check if reference belongs to a simple product
                $idProduct = Product::getIdByReference($reference);
                
                if ($idProduct) {
                    // Update stock for the simple product (id_product_attribute = 0)
                    StockAvailable::updateQuantity(
                        $idProduct,
                        0,
                        $quantity,
                        Context::getContext()->shop->id
                    );
                    echo "Updated product reference '$reference' to quantity $quantity<br>";
                    $updatedCount++;
                } else {
                    $skippedCount++;
                    echo "Skipped row $rowCount: No product/combination found for reference '$reference'<br>";
                }
            }
        } catch (Exception $e) {
            $skippedCount++;
            echo "Error on row $rowCount: " . $e->getMessage() . "<br>";
        }
    }
    fclose($handle);

    echo "<br>=== Summary ===";
    echo "<br>Total rows processed: " . ($rowCount - 1); // Subtract header row
    echo "<br>Successfully updated: $updatedCount";
    echo "<br>Skipped: $skippedCount";
} else {
    die("Failed to open CSV file at $csvPath");
}
?>

Key Details Explained

  1. PrestaShop Core Classes:

    • Product::getIdByReference($reference): Native method to get a simple product ID from its reference
    • ProductAttribute::getIdByReference($reference): Gets a product combination ID from its reference
    • StockAvailable::updateQuantity(): The recommended way to update inventory in PrestaShop—this method handles:
      • Updating the stock_available table (the single source of truth for inventory)
      • Syncing redundant quantity fields in product and product_attribute
      • Triggering core hooks (like actionUpdateQuantity)
      • Multi-shop compatibility
  2. Data Validation:

    • Skips empty references or negative quantities
    • Handles missing CSV columns safely with ?? operator
    • Tracks processed/updated/skipped rows for debugging
  3. Error Handling:

    • Wraps operations in try/catch blocks to catch PrestaShop exceptions
    • Provides clear feedback for each row's status

Important Notes

  • Backup First: Always back up your database before running inventory updates
  • CSV Format: Ensure your CSV uses ; as the delimiter, with columns reference (first) and quantity (second)
  • Multi-Shop: If you're using a multi-shop setup, the script uses the current shop ID—adjust if you need to update stock across all shops
  • Cache: After running the script, clear PrestaShop's cache (Advanced Parameters > Performance) to ensure frontend changes reflect immediately

内容的提问来源于stack exchange,提问作者GKS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 20:53:14