Symfony 3 - 表单 - 实体中的 CollectionType 没有 Doctrine

Symfony 3 - Form - CollectionType in Entity without Doctrine

我在使用 symfony3 表单和 CollectionType class:

我有一个包含多个复杂表单的页面。我不使用任何数据库(经过验证的表单被发送到外部 REST 服务)

现在假设我的请求有一个名为 "ProductService":

的实体对象
class ProductService
{
    /** @var string */
    private $msg;

    /** @var array*/
    private $products
}

还有一个 class ProductServiceType 来呈现表单:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('products', CollectionType::class, [
            'entry_type'   => ProductType::class,
        ])
        ->add('msg' [...]);
}

public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults([
        'data_class' => ProductService::class,
    ]);
}

有了这个设置,一切都很顺利,所有产品都将添加到我实体的产品数组中。 问题是,我希望 $products 成为 SplObjectStorage 对象:

class ProductService
{
    /** @var string */
    private $msg;

    /** @var SplObjectStorage */
    private $products
}

如果我将它设置为此并将一个空对象附加到其中,symfony 将无法再呈现该表单。它抛出以下错误: 警告:SplObjectStorage::offsetExists() 要求参数 1 为对象,给出的字符串

所以,有人能告诉我,在不使用 doctrine 和 orm 的情况下如何处理实体中的 collectionType 吗? 是使用数组的唯一可能性,还是我没有找到关于这种情况的任何文档? (我仍然想知道 symfony 是如何调用 offsetExists 的,必须有一些实现来处理 SplObjectStorage,或者我错了吗?)

我认为您的错误是因为没有实现表单集合来处理 SplObjectStorage,正如您所期望的那样。您可以在 symfony 存储库中为它创建一个问题。

错误是在 symfony 试图通过以这种方式从 ProductService 读取您的产品来填充表单集合时引起的:

$products = $productService->getProducts();
$products->offsetExists(0); //here is the error.

因为它希望以这种方式读取任何实现 ArrayAccess 的存储,但对于 SplObjectStorage 而言并非如此。

表单元素有一个设置 property_path link,您可以利用它来解决您的问题。

我的解决方案是使用此设置和 return return 一个数组 来填充您的集合:

$builder
        ->add('products', CollectionType::class, [
            'entry_type'   => ProductType::class,
            'property_path' => 'productsArray'
        ])

class ProductService
{

... 
public function getProductsArray() {
    $prArray= [];
    foreach ($this->products as $value) {
        $prArray[] = $value;
    }
    return $prArray;
}

这样您就可以使用生成的数组填充您的表单集合。

我认为另一种解决方案是使用 data transformer。希望这有帮助