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

时间:2017-11-15 16:34:57

标签: forms symfony splobjectstorage

我正在努力学习symfony3表单和CollectionType类:

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

现在假设我有一个名为“ProductService”的请求的实体对象:

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

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

用于呈现表单的类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,或者我错了?)

1 个答案:

答案 0 :(得分:1)

我认为您的错误是由于没有实现表单集合来处理SplObjectStorage所引起的错误。您可以在symfony存储库中为它创建一个问题。

当symfony尝试通过以下方式从ProductService读取您的产品来填充表单集时,会导致错误:

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

因为它期望任何实现ArrayAccess的存储都会以这种方式读取,但是对于SplObjectStorage,情况并非如此。

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

我的解决方案是使用此设置并返回返回数组来填充您的收藏集:

$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。希望这有帮助