Symfony Forms - 获取多个未映射的集合以合并并提交给单个实体

Symfony Forms - Getting multiple unmapped collections to merge and submit to a single entity

我有一个 WholesaleRuleset 实体 (https://pastebin.com/PYjHmGi1) 与 WholesaleRuleQuantityStep (https://pastebin.com/JLrQfQV7) 的 M2M 关系。

此关系已正确建立。它在 WholesaleRulesetType (https://pastebin.com/VGCdABb9).This is the "Edit" page of the submitted ruleset with its quantity step rule collection.

完美

这是我的要求变得棘手的地方。如您所见,管理员可以使用不同的选项卡.

在分类法、产品和分类法 范围内添加 quantitySteps

我正在尝试将多个单独的集合提交给同一个实体。:

  • 按分类数量步进规则
  • QuantityStepRuleByProduct
  • QuantityStepRuleByProductVariant

WholesaleRulesetType 最终看起来像这样(甚至在此特征中添加了必要的收集方法 https://pastebin.com/F5B97xgW)。 所需的表单类型:

            ->add(
                'quantityStepRulesByTaxon',
                CollectionType::class,
                [
                    'entry_type' => WholesaleRuleQuantityStepByTaxonType::class,
                    'allow_add' => true,
                    'allow_delete' => true,
                    'by_reference' => false,
                ]
            )
            ->add(
                'quantityStepRulesByProduct',
                CollectionType::class,
                [
                    'entry_type' => WholesaleRuleQuantityStepByProductType::class,
                    'allow_add' => true,
                    'allow_delete' => true,
                    'by_reference' => false,
                ]
            )
            ->add(
                'quantityStepRulesByProductVariant',
                CollectionType::class,
                [
                    'entry_type' => WholesaleRuleQuantityStepByProductVariantType::class,
                    'allow_add' => true,
                    'allow_delete' => true,
                    'by_reference' => false,
                ]
            );

并且在请求数据中,它们全部组合起来提交给 WholesaleRuleQuantityStep。它必须是单独的集合,因为您不能同时多次使用同一个表单域。 我已经坚持了一个月。 Sylius 或 Symfony slacks 没有回应。请。帮助。

(好的,我希望我现在就明白了,为了简洁(和懒惰)我已经缩短了所有 class 名称和字段名称,因为你的 MWE 非常广泛并且不必要地冗长。所以,你必须将我的实体 RuleSet 映射到您的 WholesaleRuleset,并将我的规则映射到您的 WholesaleRuleQuantityStep。)

我相信您有两个实体 RuleSet 和 Rule,它们通过 many-to-many 连接。这些规则基本上具有三种类型的产品、变体和分类单元。

现在您想在不同的表单字段中显示这些规则,您试图通过本质上通过您的特征在 object 上创建新属性来缓解这些规则,但据我所知,这些没有关联many-to-many 字段。

为了以后也能够编辑您的实体,我提出以下建议:使您的“字段”完全虚拟。对于 Symfony 表单,“字段”实际上是 属性 访问者可以访问以进行读写的东西(获取和设置,或者在 collections 的情况下获取和添加和删除)。

我已经这样做了几次,我喜欢这个概念,对于您的每种类型的规则都这样做:

// in class RuleSet
protected $rules; // <-- collection containing *all* rules.

public function getTaxonRules(): array {
    // extract the rules of type taxon
    return array_filter(function($rule) {
        return $rule->getType() == 'taxon';
    }, $this->rules->toArray());
}
public function addTaxonRule(Rule $rule) {
    // you might even set the type here ;o)
    if (!in_array($rule, $this->getTaxonRules()) && $rule->getType() == 'taxon') {
        $this->rules->add($rule);
    }
}
public function removeTaxonRule(Rule $rule) {
    if (in_array($rule, $this->getTaxonRules()) && $rule->getType() == 'taxon') {
        $this->rules->removeElement($rule);
    }
}
// add these functions:
// public function getVariantRules() ...
// public function addVariantRule(Rule $rule) ...
// public function removeVariantRule(Rule $rule) ...
// public function getProductRules() ...
// public function addProductRule(Rule $rule) ...
// public function removeProductRule(Rule $rule) ...

这样,实体的行为就好像它有一个字段 taxonRules,因为如果不是它与外界的接口(即 getter 和 setter),那么真正的字段就是字段。外面不关心里面的实现细节

注意:$rule->getType() == ... 的测试确实没有必要。此外,不需要表单事件或其他花哨的东西,您现在可以继续并拥有三个表单字段。

Side-Note:我真的不喜欢将 Collection 暴露在我的实体之外。 collection 的任何更改都应该通过 setters/adders/removers 发生。返回数组也会使 byReference => false 过时。在我看来,collections 在这种情况下不值得麻烦。你也许可以让它工作,但代码量会更大(恕我直言,没有任何收获)。

(Side-Burn:yoda 条件已过时!另外:尝试向您的规则添加一个函数 isTaxonRule(): bool,不要在您的代码中使用“魔术”字符串,它们不支持 auto-completion,至少在你的规则 class 上使用常量,这些字符串存储在那里并像 $rule->getType() === Rule::TAXON 一样,但是,不要直接使用字符串。一个错字会弄乱你的代码,你可能只会在生产中注意到 ;o))