我正在努力学习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,或者我错了?)
答案 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。希望这有帮助