私は私にとって有効な解決策を見つけました。それほどエレガントではないと思いますが、この問題を解決する良い方法がない場合は、私や他の人にとってうまくいく可能性があります.
まず、オブジェクトを配列に保持するのではなく、配列を保持することにしました。ただし、MyEntityParameter
Symfony のフォーム ビルダーでクラスを使用したいと考えています。この場合、アイデアはフィールドのマッピングを無効にすることです:
フォーム ビルダーでは、次のことを行います。
// Acme/Bundle/DemoBundle/Form/Type/MyEntityType.php
// ...
class MyEntityType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('parameters', 'collection', array(
'mapped' => false, // do not map this field
'type' => new MyEntityParameterType(),
// ... other options ...
));
}
}
子型 ( MyEntityParameterType
) では、「data_class」をMyEntityParameter
(問題とは関係がないため、コードは表示しません) に設定します。
ここで必要なのは、このマップされていないフィールドのデータを手動で入力して処理することだけです。
コントローラーで:
public function editAction($id, Request $request)
{
// ...
// $object is an instance of MyEntity
$form = $this->createForm(new MyEntityType(), $object);
$parameters = $object->getParameters();
if ($parameters) {
foreach ($parameters as $key => $parameter)
{
$form->get('parameters')->add($key, new MyEntityParameterType(),
array(
// here I assume that the constructor of MyEntityParameter
// accepts the field data in an array format
'data' => new MyEntityParameter($parameter),
)
);
}
}
if ($request->isMethod('POST')) {
$form->submit($request);
$parameters = array();
foreach ($form->get('parameters')->all() as $parameter) {
// here first getData() gives MyEntityParameter instance
// and the second getData() is just a method of MyEntityParameter
// that returns all the fields in an array format
$parameters[] = $parameter->getData()->getData();
}
$object->setParameters($parameters);
// if the parameters were changed in the form,
// this change will be detected by UnitOfWork
}
// ...
}