问题
In a Sonata admin form, I'd like to display all images related to the current object. Don't need to edit them. I managed to get this working with an entity field type and its property option to select the image URL as label so I can call all pictures in the template :
->add('image', 'entity', array(
'class' => 'Hop\HopBundle\Entity\Image',
'property' => 'image_url',
'query_builder' => function($er) use ($object) {
return $er->createQueryBuilder('i')
->where('i.object = :object')
->setParameter('object', $object)
;
},
'expanded' => true,
))
.
{% for child in form %}
<img src="{{ child.vars.label }}" alt="{{ child.vars.label }}" />
{% endfor %}
It's because it seems that the entity type only give label and one value to the template.
But I'd like to get also image width, descriptions, date, ... In other word : how can we get each entire related image object in the Twig template ?
Thanks.
回答1:
So I googled it a lot and here's what worked for me (Symfony 2.2)
Updated as @flu suggested in a comment
{% for key, child in form %}
<div>
{% set entity = form.vars.choices[key].data %}
{{ form_widget(child) }}
{{ form_label(child) }}
</div>
{% endfor %}
and entity
is the child object.
As of Symfony 2.3 there will be just form.vars.data
, if I understand correctly: https://github.com/symfony/symfony/pull/5023
回答2:
I´ve spend the whole day to get a solution for this problem.
First I created a new FormType which extends the ChoiceType:
class NomineesType extends AbstractType
{
protected $em;
public function __construct(EntityManager $em) {
$this->em = $em;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$submissionRepository = $this->em->getRepository('BundleName:Submission');
$choices = $submissionRepository->findBy(array(
'nominee' => true
));
$resolver->setDefaults(array(
'choices' => $choices
));
}
public function getName()
{
return 'nominees';
}
public function getParent()
{
return 'choice';
}
}
Than I had to register the service:
services:
form.type.nominees:
class: Bundle\Form\Type\NomineesType
arguments:
entityManager: "@doctrine.orm.entity_manager"
tags:
- { name: form.type, alias: nominees }
After that I added the new type to my form:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$game = $this->game;
$builder->add('submission', 'nominees', array(
'expanded' => true,
'multiple' => false
));
$builder->add('email');
}
Now I am able to get all properties in my twig-template:
{% block nominees_widget %}
{% spaceless %}
{% if expanded %}
<ul {{ block('widget_container_attributes') }}>
{% for child in form %}
<li>
{{ child.get('form').get('label').firstname }}
{{ child.get('form').get('label').lastname }}
{{ form_widget(child) }}
{{ form_label(child) }}
</li>
{% endfor %}
</ul>
{% else %}
{# just let the choice widget render the select tag #}
{{ block('choice_widget') }}
{% endif %}
{% endspaceless %}
{% endblock %}
Because the choice list is returning only integer values I´ve created a new data transformer to transform the id of the choice into an entity:
class IntToEntityTransformer implements DataTransformerInterface
{
/**
* @var ObjectManager
*/
private $om;
/**
* @param ObjectManager $om
*/
public function __construct(ObjectManager $om)
{
$this->om = $om;
}
/**
* Transforms an object (issue) to a string (number).
*
* @param Issue|null $issue
* @return string
*/
public function transform($issue)
{
if (null === $issue) {
return "";
}
return $issue->getNumber();
}
/**
* Transforms a string (number) to an object (issue).
*
* @param string $number
* @return Issue|null
* @throws TransformationFailedException if object (issue) is not found.
*/
public function reverseTransform($number)
{
if (!$number) {
return null;
}
$issue = $this->om
->getRepository('BundleName:Submission')
->findOneBy(array('id' => $number))
;
if (null === $issue) {
throw new TransformationFailedException(sprintf(
'An Submission with number "%s" does not exist!',
$number
));
}
return $issue;
}
}
This data transformer is initialized in the build form method:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$transformer = new IntToEntityTransformer($this->em);
$builder->add($builder->create('submission', 'nominees', array(
'expanded' => true,
'multiple' => false
))->addModelTransformer($transformer));
$builder->add('email');
}
回答3:
I've been fighting this problem with Symfony 2.3. Don't know how it works in 2.1.
In my case I had a entity choice (expanded and multiple) for which I needed to add the entitie's 'descripcion' field, next to the label of each choice.
I solved as follows:
1- created a custom type, whose parent is EntityType, and name 'xxxxxxx_form_reparacionnormalizada'
class ReparacionNormalizadaType extends AbstractType
{
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'class' => 'xxxxxxxxx\Entity\TipoReparacion',
));
}
public function getName()
{
return 'xxxxxxx_form_reparacionnormalizada';
}
public function getParent()
{
return 'entity';
}
}
2- register the form type as service as usual
3- created a custom template as follows:
{% block xxxxxxx_form_reparacionnormalizada_widget %}
<ul {{ block('widget_container_attributes_choice_widget') }}>
{% for id, child in form.children %}
<li>
{{ form_label(child, child.vars.label|default(null), { 'in_list_checkbox' : true, 'widget' : form_widget(child) } ) }}
<span>{{ choices[id].data.descripcion }}</span>
</li>
{% endfor %}
</ul>
{% endblock %}
4- in your sonata admin you use your custom type instead of 'entity'
hope it helps
regards
javier
来源:https://stackoverflow.com/questions/12029684/symfony2-entire-child-entity-in-form-and-twig-template