我正在开发一个可定制产品的电子商务系统。每个产品可能有一些选项,就其而言,可能具有消费者选择的一个或多个值。我不能使用变体方法,因为我的用户定制程度很高(某些产品可能有超过1M的变体),所以我需要坚持由costumer选择的选项组合。
每个产品可能有不同的选项,动态组合表单选项。此表单应将用户选择转换为关系数据库的可存储结构。
基本上,这是我的方案(我的尝试):
夹具:
我的目标是:
class OrderItemType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$field = $builder->create('options', new OptionPickerType(), ['options' => $options['product']->getOptions()]);
$field->addModelTransformation(new FixOptionIndexTransformer());
$builder->add($field);
}
}
class OptionPickerType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
foreach ($options['options'] as $productOption) {
$name = $productOption->getId();
$builder->add($name, 'choice', array(
'choice_list' => new ObjectChoiceList($productOption->getValues(), 'label', array(), null, 'id'),
'multiple' => true,
'cascade_validation' => true,
'property_path' => '['.$name.']'
));
}
}
}
$form = $factory->create(new OrderItemType(), ['product' => $product]);
if ($request->isMethod('POST')) {
$form->bind($request);
if ($form->isValid()) {
$item = $form->getItem(); // A collection of ItemOption filled with the OptionValue picked out from Choice field
}
}
此配置将按预期返回OptionValue数组的集合。事实上,这对我的目的来说还不够。我真正需要的是一个展平集合,其中包含所有选择的值以及更多的额外数据:
class ItemOption
{
protected $item;
protected $productOption;
protected $option; // $productOption->getName()
protected $optionValue;
protected $value; // / $optionValue->getLabel()
}
如您所见,Choice字段的值实际上在ItemOption中。
经过几天的尝试,我无法弄清楚如何做到这一点,甚至想到其他方法。
你能帮助我吗?
答案 0 :(得分:1)
首先,通常当我发现很难将表单映射到我的模型时,我后来发现该模型过于复杂。在必要时简化模型以获得清晰的关系和中间对象(在没有必要的情况下没有)这通常有助于此。
话虽如此,在我看来,您的选项选择器上的模型变换器应该可以完成这项任务:
foreach ($options['options'] as $productOption) {
// ...
}
$builder->addModelTransformer(new CallbackTransformer(
// model to normalized
// needed when setting default values, not sure if required in your case
function ($modelData) {
},
// normalized to model
// converts the array of arrays of OptionValues to an array of ItemOptions
function ($normalizedData) {
$itemOptions = array();
foreach ($normalizedData as $optionValues) {
foreach ($optionValues as $optionValue) {
$itemOption = new ItemOption();
$itemOption->setProductOption($optionValue->getProductOption());
$itemOption->setOptionValue($optionValue);
$itemOptions[] = $itemOption;
}
}
return $itemOptions;
}
));