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。希望这有帮助
我在使用 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。希望这有帮助