formBuilder - How to add an entity? - symfony

I have two classes : Class and Students. Each class contain one or many student.
In my form (create student), I want a scroll selector with all the available class to put my student in a class.
I have do that :
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('classe', 'entity', array(
'required' => true,
'class' => 'MyCoolBundle:Classe',
'query_builder' => function(ClasseRepository $cr) {
return $cr->createQueryBuilder('c')
->orderBy('c.name', 'ASC');
}))
;
}
But the result is :
Could not load type "entity"
500 Internal Server Error - InvalidArgumentException

After the doc you've to rewrite the field type:
Extract from doc
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
// ...
$builder->add('users', EntityType::class, array(
'class' => 'AppBundle:User',
'choice_label' => 'username',
));
So I think you should try something like :
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
...
...
$builder
->add('name')
->add('classe', EntityType::class, array(
'required' => true,
'class' => 'MyCoolBundle:Classe',
'query_builder' => function(ClasseRepository $cr) {
return $cr->createQueryBuilder('c')
->orderBy('c.name', 'ASC');
}))
;

Related

Creating multiple entities with one form using collection type

so I tried creating a form that can create multiple entities in one form.
The goal is simply by using collection type I can create multiple entities with similar attributes.
The view works where I can add new positions to create more "artikels".
Unfortunately I do not receive any Data if I use $form['artikelList']->getData(). I only receive an empty array(0) but when using $form->getData() I do see the informations on the "artikels".
Can you help me how I can access that data? Googling around did not really help in this regard.
My MultipleFormType file:
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('artikelList', CollectionType::class, [
'entry_type' => ArtikelEmbeddedFormType::class,
'entry_options' => [
'label' => false
],
'allow_delete' => true,
'allow_add' => true,
'by_reference' => false,
'label' => false,
])
->add('Speichern', SubmitType::class, [
'attr' => ['class' => 'btn--red']
]);
}
My embeddedFormType file:
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
...some entries
->add('artikelName', null,
['label' => 'Name', 'attr' => ['pattern' => '[A-Za-z0-9-_ öÖäÄüÜß]+', 'maxlength' => 255]])
->add('artikelActive', null,
['label' => 'Aktiv']);
}
And here my controller:
public function createMultipleArtikel(Request $request)
{
//creating multiple articles at once
$form = $this->createForm(MultipleArtikelFormType::class, null);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
var_dump($form->getData());
var_dump($form->get('artikelList')->getData());
foreach($form->get('artikelList')->getData() as $artikel) {
$this->artikelRepository->update($artikel);
$this->get('session')->getFlashBag()->add(
'notice',
'done!'
);
}
}

Pass array of data to form

I'm using symfony and I need to pass two arrays so I can make a selectable list.
For now in form builder I have this:
->add('city', EntityType::class, [
'label' => 'Select city',
'class' => Cities::class,
'choice_label' => 'title',
'choice_value' => 'title'
])
It throws me all cities in the list. I want to filtrate them. I've done filtration on my controller like this:
$capitals = $cityRepository->findBy(['cityType' => CityType::capital()->id()]);
$villages = $cityRepository->findBy(['villageType' => CityType::village()->id()]);
this returns me two arrays: capitals and villages.
How can I pass them to the form ?
In your controller :
$form=$this->createForm(YourFormType::class, $yourEntity, array(
'capitals'=>$capitals,
'villages'=>$villages
));
In your form :
public function buildForm(FormBuilderInterface $builder, array $options) {
/** #var array $capitals */
$capitals=$options['capitals'];
/** #var array $villages */
$villages=$options['villages'];
$builder->add('city', EntityType::class, array(...)
->add('vallacap', ChoiceType::class, array(
'mapped'=>false, //Make sure it's not mapped to any entity
'choices'=>array(
'Capitals'=>$capitals,
'Villages'=>$villages
),
'required'=>false,
));
}
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults(array(
'data_class'=>Personnalisation::class,
'capitals'=>null, // Set default to null in case argument is not passed
'villages'=>null,
));
}
You need to pass the arrays to choices option.
https://symfony.com/doc/current/reference/forms/types/entity.html#using-choices
->add('city', EntityType::class, [
'label' => 'Select city',
'class' => Cities::class,
'choice_label' => 'title',
'choice_value' => 'title',
'choices' => $choices // ------------> This line
])
$choices = array_merge($capitals, $villages);

OneToMany relationship with checkboxes as choices in a form using custom FormType

I have a model CostTypeConnection which has an one to many relation to DepartmentConnection.
I want, that the DepartmentConnection is displayed as checkboxes.
My CostTypeConnection Class has a variable $costType, which is an Entity CostType, that has a $name varaible in it.
My DepartmentConnection Class has a variable $department, which is an Entity Department, that has also a $name variable.
My CostTypeFormType:
....
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('costType', 'text', array(
'label' => 'costType'
))
->add('departmentConnections', 'collection', array(
'type' => new DepartmentConnectionType(),
'allow_add' => false,
'label' => false,
'by_reference' => false,
'options' => array('label' => false),
))
;
} ...
My DepartmentConnection:
...
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('department', 'text', array(
'label' => false
))
;
}...
So it is not possible to define a checkbox-Type in my Formbuilder for department, because it is an entity and not a variable. Has someone an idea what I can do? This doesnt work in my DepartmentConnectionType Class:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('department', 'choice', array(
'label' => false
))
;
}
It finishs with the error:
The value of type "object" cannot be converted to a valid array key
THANKS FOR ANY HELP!!!
Note : recommended minimum version symfony 2.7
You should use \Symfony\Bridge\Doctrine\Form\Type\EntityType in your form.
see http://symfony.com/doc/2.7/reference/forms/types/choice.html
and http://symfony.com/doc/2.7/reference/forms/types/entity.html
Here's an example :
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('costType', 'text', array(
'label' => 'Cost type :' // -> <label class="required">Cost type :</label><input value="<?php echo $costTypeConnection->getCostType(); ?> required>
))
->add('departmentConnections', 'entity', array(
'class' => 'Acme\Bundle\Entity\DepartmentConnection',
// before 2.7 use 'property' instead of 'choice_label'
'choice_label' => 'type', // equals $costTypeConnections->getDepartmentConnexion()->getType();
'label' => 'Department connexion :',
'expanded' => true, // will output a set of inputs instead of a select tag
'multiple' => true, // will output checkboxes instead of radio buttons
'required' => true, // unused as multiple is true
))
;
} ...
would output :
<div id="form_cost_type_connexion_department_connections">
Department connexion :
<input type="checkbox" value="on" ... <label>$costTypeConnections->getDepartmentConnections()->getType()
...

Symfony2: formbuilder : dynamically modify querybuilder

I am using the formbuilder to create a form as followed:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('content', 'textarea')
->add('rosters', 'entity', array(
'class' => 'PlatformBundle:team',
'property' => 'display',
'multiple' => true,
'expanded' => true,
'required' => true
))
->add('send', 'submit')
;
}
At the moment I get all "teams". I need to adapt the form to display certain teams depending of the request.
I can use the query-builder inside the form builder
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('content', 'textarea')
->add('rosters', 'entity', array(
'class' => 'PlatformBundle:team',
'property' => 'display',
'query_builder' => function(TeamRepository $t) use ($userId) {
return $r->createQueryBuilder('t')
->where('(t.user = :user')
},
'multiple' => true,
'expanded' => true,
'required' => true
))
->add('send', 'submit')
;
}
But the query changes for different questionnaire. In brief: always the same questionnaire but different teams to be listed (Am I making sense?).
Does someone has an idea how dynamically modify the querybuilder inside a formbuilder?
I suggest two possible alternatives.
If the request comes from the form itself (i.e. you already submitted the form with some data and want to refine the fields) you can access the submitted data like this:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$data = $builder->getData();
// now you can access form data
If the request comes from another source, you should use the "options" parameter. First, build a new $option for the requested user:
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'user' => null,
));
}
Note: I set the default to null but you can set it to whatever you want.
After that you can pass the $option where you build the form, i.e.
// some controller
$option = array('user' => $request->get('user');
$teamForm = $this->createForm(new TeamType(), null, $options);
// ...
For those looking for an answer...
The best solution I found is create a variable in the formtype and to import it form the controller. My formType will look like that:
class formType extends AbstractType
{
// declare and construct the query in the class to use it in the function
private $qb;
public function __construct ($qb)
{
$this->qb = $qb;
}
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
// declare the variable within the function
$qb = $this->qb;
$builder
->add('content', 'textarea', array('required' => false))
->add('rosters', 'entity', array(
'class' => 'PlatformBundle:Team',
// use ($qb) -> $qb is query built in the controller (or repository)
'query_builder' => function(TeamRepository $r) use ($qb) {
return $qb;
},
'property' => 'display',
'multiple' => true,
'expanded' => true,
'required' => true
))
->add('send', 'submit');
}
In my controller I just pass $qb as an argument of the formtype
$qb = $this->getDoctrine()->getManager()->getRepository('PlatformBundle:Team')->qbteam($Id);
$form = $this->createForm(new formType($qb), $form);
with qbteam a function in the team repository which return the query (not a result).
public function qbteam($Id){
$qb = $this->createQueryBuilder('r')
->leftJoin('r.team', 'm')
->addSelect('m')
->where('m.user = :user')
->setParameter('user', $Id);
return $qb;
}
I hope it will help others.
cheers

Symfony2 form queryBuilder find distinct object

I have an Organization entity.
Acme\BaseBundle\Entity\Organization:
type: entity
...
oneToMany:
childOrganizations:
targetEntity: Organization
mappedBy: parentOrganization
manyToOne:
parentOrganization:
targetEntity: Organization
inversedBy: childOrganizations
nullable: true
I have this form:
->add('parentOrganization', 'entity', array(
'class' => "AcmeBaseBundle:Organization",
'property' => 'name',
'required' => false,
'query_builder' => function(EntityRepository $er)
{
return $er
->createQueryBuilder('o')
->select('o')
->add('groupBy', 'o.name');
},
))
Then I would like to show only different organizations. I mean if I have first, second and third organization. Then I have a form for the first organization and I would like to have just two choices in parentOrganization entity field (second and third), but in this case I have three choices (first can be parent of first).
Is there some way to leave out possibility to connect with own org?
EDIT: The problem is that I am working in form class and I don't know how to handle Organization object here. This is my code:
class OrganizationType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', null, array('max_length' => 100))
->add('type')
->add('parentOrganization', 'entity', array(
'class' => "AcmeBaseBundle:Organization",
'property' => 'name',
'required' => false,
'query_builder' => function(EntityRepository $er)
{
return $er->createQueryBuilder('o')
->select('o')
->add('groupBy', 'o.name');
}
))
->add('addresses', 'bootstrap_collection', array(
'type' => new AddressType(),
'allow_add' => true,
'allow_delete' => true,
'add_button_text' => '+',
'delete_button_text' => '-',
'by_reference' => false,
'sub_widget_col' => 9,
'button_col' => 3
))
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Acme\BaseBundle\Entity\Organization'
));
}
public function getName()
{
return 'acme_basebundle_organization';
}
}
If you create form as written in doc (through method createForm of controller), then your current entity available in $options['data']. And your code will look like:
$entity = $options['data'];
...
'query_builder' => function(EntityRepository $er) use ($entity)
{
return $er->createQueryBuilder('o')
->select('o')
->add('groupBy', 'o.name')
->add('where', 'o.id != ?1')
->setParameter(1, $entity->getId());
}

Resources