为什么 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
创建变体。所以 price
、originalPrice
、code
或 name
都不会生成。您需要手动设置它们。关于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'
}
手动添加 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
创建变体。所以 price
、originalPrice
、code
或 name
都不会生成。您需要手动设置它们。关于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'
}