为什么 Sylius 产品变体生成器不生成变体代码字段?

Why does Sylius product variant generator does not generate the variant code field?

手动添加 1000 个产品变体是一个很大的禁忌,所以我去 Lastest version of the Sylius book (Product Page) 看看如何动态添加产品变体。幸运的是,他们已经仔细考虑了这一点,并提供了从产品选项中生成变体 (sylius.generator.product_variant) 的服务。

我决定尝试一下,我写了一个小控制台命令来测试它:

<?php

namespace App\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

use Sylius\Component\Product\Model\ProductOptionInterface;
use Sylius\Component\Product\Model\ProductOptionValueInterface;
use Sylius\Component\Product\Generator\ProductVariantGeneratorInterface;
use Sylius\Component\Product\Factory\ProductFactoryInterface;

use Sylius\Component\Core\Model\ProductInterface;
use Sylius\Component\Resource\Repository\RepositoryInterface;

class TestCommand extends Command
{
    protected static $defaultName = 'app:test';

    /** @var ContainerInterface $_serviceContainer */
    private $_serviceContainer;

    public function __construct(ContainerInterface $fullServiceContainer)
    {
        $this->_serviceContainer = $fullServiceContainer;

        parent::__construct();
    }

    protected function configure()
    {
        $this->setDescription('Just testing');
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        /** @var ProductFactoryInterface $productFactory **/
        $productFactory = $this->_serviceContainer->get('sylius.factory.product');

        /** @var ProductInterface $product */
        $product = $productFactory->createNew();

        $product->setName('T-Shirt');
        $product->setCode('00001');
        $product->setSlug('t-shirt');

        /** @var RepositoryInterface $productRepository */
        $productRepository = $this->_serviceContainer->get('sylius.repository.product');
        $productRepository->add($product);

        /** @var ProductOptionInterface $option */
        $option = $this->_serviceContainer->get('sylius.factory.product_option')->createNew();
        $option->setCode('t_shirt_color');
        $option->setName('T-Shirt Color');

        // Prepare an array with values for your option, with codes, locale code and option values.
        $valuesData = [
            'OV1' => ['locale' => 'en_US', 'value' => 'Red'],
            'OV2' => ['locale' => 'en_US', 'value' => 'Blue'],
            'OV3' => ['locale' => 'en_US', 'value' => 'Green'],
        ];

        foreach ($valuesData as $code => $values)
        {
            /** @var ProductOptionValueInterface $optionValue */
            $optionValue = $this->_serviceContainer->get('sylius.factory.product_option_value')->createNew();

            $optionValue->setCode($code);
            $optionValue->setFallbackLocale($values['locale']);
            $optionValue->setCurrentLocale($values['locale']);
            $optionValue->setValue($values['value']);

            $option->addValue($optionValue);
        }

        // Assuming that you have a basic product let's add the previously created option to it.
        $product->addOption($option);

        // Having option of a product you can generate variants. Sylius has a service for that operation.
        /** @var ProductVariantGeneratorInterface $variantGenerator */
        $variantGenerator = $this->_serviceContainer->get('sylius.generator.product_variant');
        $variantGenerator->generate($product);

        // added code for test purpose
        // foreach ($product->getVariants() as $parsingVariant)
        //    dump($parsingVariant);

        // And finally add the product, with its newly generated variants to the repository.
        /** @var RepositoryInterface $productRepository */
        $productRepository = $this->_serviceContainer->get('sylius.repository.product');
        $productRepository->add($product);

        return 0;
    }
}

但不幸的是,当我 运行 命令时出现以下错误:

In AbstractMySQLDriver.php line 107:
                                                                                                                                                                                        
  An exception occurred while executing 'INSERT INTO sylius_product_variant (code, created_at, updated_at, position, enabled, on_hold, on_hand, tracked, width, height, depth, weight,  
   shipping_required, product_id, tax_category_id, shipping_category_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)' with params [null, "2020-11-18 17:33:49", "2020-11-1  
  8 17:33:49", 0, 1, 0, 0, 0, null, null, null, null, 1, 13, null, null]:                                                                                                               
                                                                                                                                                                                        
  SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'code' cannot be null                                                                                                    
                                                                                                                                                                                        

In PDOStatement.php line 131:
                                                                                      
  SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'code' cannot be null  
                                                                                      

In PDOStatement.php line 129:
                                                                                      
  SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'code' cannot be null  
                                                                                     

code 字段不是应该自动生成的吗?我错过了什么 ? 谢谢。

很遗憾,code 没有生成。事实上,生成器只是用 ProductOptionValue 创建变体。所以 priceoriginalPricecodename 都不会生成。您需要手动设置它们。关于code,我个人是用Ramsey/Uuid生成的

/** @var ProductVariantGeneratorInterface $variantGenerator */
$variantGenerator = $this->_serviceContainer->get('sylius.generator.product_variant');
$variantGenerator->generate($product);

foreach ($product->getVariants() as $variant) {
    // You need to use these methods to have valid variants
    $variant->setCode(Uuid::uuid4()); // Or whatever you want
    $variant->addChannelPricing($channelPricing); // Create $channelPricing with : '@sylius.factory.channel_pricing'
}