微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Symfony Forms - 将多个未映射的集合合并并提交到单个实体

如何解决Symfony Forms - 将多个未映射的集合合并并提交到单个实体

我有一个 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.

这就是我的要求变得棘手的地方。如您所见,管理员可以在分类法、产品和分类使用不同的标签的范围内添加数量步骤。

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

  • QuantityStepRuleByTaxonomy
  • 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',[
                    'entry_type' => WholesaleRuleQuantityStepByProductType::class,]
            )
            ->add(
                'quantityStepRulesByProductvariant',[
                    'entry_type' => WholesaleRuleQuantityStepByProductvariantType::class,]
            );

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

解决方法

(好吧,我希望我现在能明白这个,为了简洁(和懒惰)我缩短了所有类名和字段名,因为你的 MWE 非常广泛而且不必要地冗长。所以,你必须映射我的实体规则集到您的 WholesaleRuleset 和我的规则到您的 WholesaleRuleQuantityStep。)

我相信您有两个实体 RuleSet 和 Rule,通过多对多连接。规则基本上包含三种类型的产品、变体和分类单元。

现在你想在不同的表单字段中显示这些规则,你试图通过本质上通过你的特征在你的对象上创建新属性来缓解这些规则,但据我所知,这些与许多 -对多字段。

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

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

// 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() == ... 的测试真的没有必要。此外,不需要表单事件或其他花哨的东西,您现在可以继续使用三个表单字段。

旁注:我真的不喜欢将 Collection 暴露在我的实体外部。对集合的任何更改都应该通过 setter/adders/removers 发生。返回数组也会使 byReference => false 过时。在我看来,在这种情况下不值得麻烦。您也许可以让它工作,但代码量会更大(恕我直言,一无所获)。

(Side-Burn:yoda 条件出来了!另外:尝试向您的规则 isTaxonRule(): bool 添加一个函数,不要在您的代码中使用“魔法”字符串,它们不支持自动完成,在至少在您的 Rule 类中使用常量,这些字符串存储在其中并且类似于 $rule->getType() === Rule::TAXON,但是,不要直接使用字符串。拼写错误可能会搞砸您的代码,您可能只会在生产中注意到 ;o))

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。