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

Sylius产品变体创建报错:Column 'code' cannot be null

Sylius生成产品变体时的SQL约束错误问题

执行代码设置变体价格时触发SQL约束错误:

SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'code' cannot be null

对应的SQL语句及参数:

'INSERT INTO sylius_product_variant (code, created_at, updated_at, position, enabled, product_id, on_hold, on_hand, tracked, width, height, depth, weight, shipping_required, tax_category_id, shipping_category_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)' with params [null, "2022-09-22 00:24:06", "2022-09-22 00:24:06", 1, 1, 70, 0, 0, 0, null, null, null, null, 1, null, null]

已知产品变体生成器不会自动生成code字段,已手动设置该字段,但仍出现错误。实现代码如下:

$option = $this->productOptionFactory->createNew();
$option->setCode(Uuid::uuid4()->toString());
$option->setName('Test option');

$valuesData = [
    ['locale' => 'en_US', 'value' => 'test1'],
    ['locale' => 'en_US', 'value' => 'test2'],
    ['locale' => 'en_US', 'value' => 'test3'],
];

foreach ($valuesData as $values) {
    $optionValue = $this->productOptionValueFactory->createNew();

    $optionValue->setCode(Uuid::uuid4()->toString());
    $optionValue->setFallbackLocale($values['locale']);
    $optionValue->setCurrentLocale($values['locale']);
    $optionValue->setValue($values['value']);

    $option->addValue($optionValue);
}

$product->addOption($option);

$this->productVariantGenerator->generate($product);
foreach($product->getVariants() as $variant){
    $variant->setCode(Uuid::uuid4()->toString());
    $channelPricing = $this->channelPricingFactory->createNew();
    $channelPricing->setPrice(10);
    $channelPricing->setOriginalPrice(10);
    $channelPricing->setChannelCode('FASHION_WEB');
    $channelPricing->setProductVariant($variant);
    $this->channelPricingRepository->add($channelPricing);
    //dd($variant);  
    $variant->addChannelPricing($channelPricing);
}
$this->productRepository->add($product);

错误原因

问题出在持久化顺序上:

  • 调用$this->channelPricingRepository->add($channelPricing)时,Doctrine会尝试级联持久化关联的$variant对象,但此时虽然设置了$variant->setCode(),但该变更还未被Doctrine的UnitOfWork追踪。
  • 生成器创建的变体初始处于未被Doctrine管理的状态,级联持久化时会使用生成时的null值插入code字段,触发非空约束错误。

解决方案

调整代码执行顺序,确保变体的code字段设置后,先让Doctrine追踪到该变更,再处理渠道定价:

$this->productVariantGenerator->generate($product);
foreach($product->getVariants() as $variant){
    $variant->setCode(Uuid::uuid4()->toString());
    // 先同步变体变更到Doctrine,确保code被正确追踪
    $this->productVariantRepository->add($variant);
    
    $channelPricing = $this->channelPricingFactory->createNew();
    $channelPricing->setPrice(10);
    $channelPricing->setOriginalPrice(10);
    $channelPricing->setChannelCode('FASHION_WEB');
    $channelPricing->setProductVariant($variant);
    $variant->addChannelPricing($channelPricing);
    
    // 此时添加渠道定价,变体的code已被正确标记持久化
    $this->channelPricingRepository->add($channelPricing);
}
$this->productRepository->add($product);

或者拆分步骤,先完成所有变体的code设置与持久化,再统一处理渠道定价:

$this->productVariantGenerator->generate($product);
// 第一步:设置所有变体的code并同步到Doctrine
foreach($product->getVariants() as $variant){
    $variant->setCode(Uuid::uuid4()->toString());
    $this->productVariantRepository->add($variant);
}

// 第二步:处理渠道定价
foreach($product->getVariants() as $variant){
    $channelPricing = $this->channelPricingFactory->createNew();
    $channelPricing->setPrice(10);
    $channelPricing->setOriginalPrice(10);
    $channelPricing->setChannelCode('FASHION_WEB');
    $channelPricing->setProductVariant($variant);
    $variant->addChannelPricing($channelPricing);
    $this->channelPricingRepository->add($channelPricing);
}
$this->productRepository->add($product);

核心逻辑是:必须在关联并持久化渠道定价之前,确保变体的code字段已被Doctrine正确追踪并标记为待持久化状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 11:26:11