I have two entities 'status' and 'doctor'. Every doctor can add a status in his profile. When the doctor wants to add a status, he can add status for another doctor because of the choice field .
It's not logic, I want that every doctor add only his status, not for other doctor.
How can I fix it ?
This is the status form:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('medecin','entity',array('class'=>'DoctorBundle:medecin','property'=>'prenom','multiple'=>false))
->add('text')
->add('description')
->add('image',new ImageType())
;
}`
Remove the field Doctor (medecin for you) from the Form and then in the controller when you are handling the form response just do this
if ('POST' === $request->getMethod()) {
$statusForm->handleRequest($request);
if ($statusForm->isValid()) {
$status = $statusForm->getData();
$status->setDoctor($this->getUser());
$statusManager->flush($status);
}
}
$this->getUser() if you're logged in with the doctor, if you're not, get him however you are doing it.
Ok, based on your comments I think you have several ways to tackle this:
Remove medecin form field altogether and assign it later. For example:
$status = ....; // Your entity
$currentDoctor = ... // logic for getting myself :)
$status->setMedecin($currentDoctor);
$form = $this->createForm(StatusType(), $status);
$form->handleRequest($request);
if ( $form->isValid() ){
// The rest is the same
}
Bind data attribute of medecin form field. This further complicates things as you need to pass yourself (currentDoctor) into the form type. I would definitely go for #1 above.
Hope this helps...
I have this code in my status controller of create form:
/**
* Creates a form to create a statut entity.
*
* #param statut $entity The entity
*
* #return \Symfony\Component\Form\Form The form
*/
private function createCreateForm(statut $entity)
{
$form = $this->createForm(new statutType(), $entity, array(
'action' => $this->generateUrl('statut_create'),
'method' => 'POST',
));
$form->add('submit', 'submit', array('label' => 'Create'));
return $form;
}
`
i try this code its OK with the choice field but the Doctor-id take the value null, this is the code create form:$id= $entity->setMedecin();
$form = $this->createForm(new statutType(), $entity, array(
'action' => $this->generateUrl('statut_create'),
'method' => 'POST',
));
Related
I would like to know if it is possible to automatically assign values to added fields of type:
datetime
entity
Thanks for your help
public function buildForm(FormBuilderInterface $builder, array $options)
{
$user = $options['user']; // entity User
$player = $options['player']; // entity Player
$today = new DateTime('now');
$builder
->add('fieldA')
->add('fieldB')
->add('fieldC');
$builder
->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) use ($user, $player, $today) {
$form = $event->getForm();
$datas = $event->getData();
$form->add('today');
$form->add('user');
$form->add('player');
//dd($form); ok = 3 fields added
$datas['dateDuJour'] = $today;
$datas['user'] = $user;
$datas['player'] = $player;
//dd($datas); ok = 3 assigned values
$form->setData($datas);
question 1 : how to insert the data in the form
question 2 : pb from entity (object) to string
//dd($form, $datas);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Evaluation::class,
'user' => null,
'player' => null
]);
}
}
I thought about inserting the 3 fields with the type = hidden and using Data Transformer
I do not know what is the best practice?
if you have a concrete example
From what i can see, you have some form and you want to plug 3 data to the form on submit.
Depending on your database configuration, you can do 3 different way:
The best one is to use the mapping
Your evaluation have those 3 fields:
date
user
player
Then just add them to the original builder as hidden field whith default value what you have:
$builder->add('token', HiddenType::class, [
'data' => $today,
])->add('user', HiddenType::class, [
'data' => $user,
])->add('player', HiddenType::class, [
'data' => $player,
]);
As they are hidden, the security check will not autorise users to change those value plus thoise fields will be hiddent
It require those three fields exist in your entity
Second one is to use unmapped hidden field. Same a previous, but add 'mapped'` => false . Then you in your controller, you will have the value and use them as needed.
The third one is to not use them in your form (my favorite) but in your controller
public function addEvaluation(Request $request, EvaluationManager $evaluationManager): Response
{
$evaluation = new Evaluation();
$form = $this->createForm(EvaluationType::class, $evaluation);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$evaluation->setTime(new DateTime('now'))
->setUser($user)
->setPlayer($player);
$evaluationManager->save($evaluation);
return $this->redirectToRoute('evaluation_add');
}
return $this->render('/evaluation_add.twig', [
'form' => $form,
]);
}
I was looking for a answer, but i never found something. .
My starting Position:
This classes / files are included
Controller, DataDFu1Controller.php
Form DataAPatientType.php ,DataDFu1Type.php
Entity DataAPatient, DataDFu1
views/DataDfu1/ form.html.twig
The DataDFu1Controller contains (to the overview) the indexAction, newAction and
editAction and so on.
Both Formtypes (DataAPatientType.php ,DataDFu1Type.php) comes in one Form (look Method) this form goes to be rendered later in the form.html.twig file for the newAction and the editAction
For the newAction i did it so:
private function createNewForm(DataAPatient $entity)
{
$form = $this->createForm($this->get('data_livebundle.form.dataapatienttype'), $entity, array(
'action' => $this->generateUrl('dataapatient_new'),
'method' => 'POST',
));
return $form->add('dFu1', new DataDFu1Type());
}
later the form comes rendered. . .
So first i create "DataAPatientType.php" Form and then i add the "DataDFu1Type.php" to the form.
In the view -> form.html.twig it looks like that.
for DataDFu1Type:
{{ form_widget(form.dFu1.fu1Examiner1)}}
for DataAPatientType:
{{ form_label(form.pSnnid, 'SNN-ID (if known)', {'label_attr':{'style':'margin-top:3px'}})}}
So i can get a variable or a function with the suffix 'dfu1' after the form.
Everything works so fine. I hope the condition are understandible till now..
Now my Problem:
I have to create also an editAction which opend of course the same view-> form.html.twig with the filled values from a dataset (entity). In this process i don't understand how i can create the Form Object based also (DataAPatientType, DataDFu1Type) with the corresponding data. -> I'm trying to be more specific
private function createEditForm(DataDFu1 $entity)
{ /*
* This function shoud create the editform which insists
* DataAPatientType.php ,DataDFu1Type.php included the data from
* $entity. I have the opportunity to get the entity for DataDFu1Type
* easy directly with the Primary Key and the data for DataAPatientType
* over a Foreign Key which is safed in the $entity
*
*/
}
So i only dont understand how i can create a Form based on two types (DataAPatientType.php ,DataDFu1Type.php) with the corresponding Data inside, that i can render it like in the newAction.
For one Form i did it everytime like so and it works.. but for two types i tried a lot things which didnt worked. Have somebody a experiance? or a Solution for this Problem?
the syntax of the form.html.twig isnt changeable so the form has to be rendered equivalent like in the newAction
Example for creating a form based only on one Type and not two
private function createEditForm(Event $entity)
{
$form = $this->createForm($this->get('qcycle_eventbundle.form.eventtype'), $entity, array(
'action' => $this->generateUrl('event_edit', array('id' => $entity->getId())),
'method' => 'POST'
));
$form->add('preview', 'button', array('label' => 'Preview', 'attr' => array('data-preview' => 'preview')))
->add('submit', 'submit', array('label' => 'Save Changes'))
->add('sendAndSave', 'submit', array('label' => 'Send Mail & Save'));
return $form;
}
i really hope, that my problem and Question understandable
thanks
mjh
If i understand you have this form:
class DataAPatientType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('dFu1', new DataDFu1Type());
$builder->add('pSnnid', 'text');
[...]
}
}
Then in create
$form = $this->createForm(DataAPatientType(), new DataAPatient());
And in edit you can simply do something like
private function createEditForm(DataDFu1 $entity)
{
$form = $this->createForm(DataAPatientType(), entity); //here the form will be "populated" by the entity data
So if you want to set some default value or overwrite an existing value for example, you would use
private function createEditForm(DataDFu1 $entity)
{
entity->setPSnnid('whatever')
$form = $this->createForm(DataAPatientType(), entity); //here the form will be "populated" by the entity data
I'm new with Symfony2 (2.4.4).
I want to create a HTML layout which shows always a form on top (searchbar). I send the form via post and would like to redirect to another controller, which should pass the user input and generate an output. I created a new function like this:
public function searchFormAction(Request $request)
{
//$defaultData = array('sstring' => 'Suche');
$form = $this->createFormBuilder()
->add('fnr', 'hidden')
->add('sstring', 'search', array('label' => false))
->add('submit', 'submit', array('label' => 'suchen'))
->getForm();
$form->handleRequest($request);
if($request->isMethod('POST'))
{
return $this->redirect('SchmanEmployeeBundle:Employee:search', array(
'sstring' => $form->get('sstring')->getData();
));
}
return $this->render('SchmanEmployeeBundle:Employee:searchForm.html.twig', array(
'form' => $form->createView()
));
}
I extended my base layout (base.html.twig) and include the form with the render function
{% render(controller('SchmanEmployeeBundle:Employee:searchForm')) %}
This works fine and the form is always present in my layout. The given HTML looks like this:
<form name="form" method="post" action="/app_dev.php/">
<div><input type="search" id="form_sstring" name="form[sstring]" required="required"></div>
<div><button type="submit" id="form_submit" name="form[submit]">suchen</button></div>
Now I have 3 questions:
If I submit the form, I don't want to be redirected to the searchAction Controller. This is because the $request->isMethod is always GET. Why? The form actions is post?
In the Symfony Webtool the form section is also empty. I see all form fields (sstring) and the data is always null. Where's the user input?
First off, your form is set to be POST by default, so you should be good. Second, you don't pass any data to be filled by your form, and I think you should. Third, you don't check if the form is valid, which includes the test if it's submitted. You should do this:
$defaultData = array(); // No need for a class object, array is enough
$form = $this->createFormBuilder($defaultData)
->add('fnr', 'hidden')
->add('sstring', 'search', array('label' => false))
->add('submit', 'submit', array('label' => 'suchen'))
->getForm();
$form->handleRequest($request);
if($form->isValid())
{
// Happens if the form is submitted
return $this->redirect('SchmanEmployeeBundle:Employee:search', array(
'sstring' => $form->get('sstring')->getData(); // TODO: This will probably produce an error, fix it
));
}
return $this->render('SchmanEmployeeBundle:Employee:searchForm.html.twig', array(
'form' => $form->createView()
));
Also, I think you shouldn't worry about the form method because you don't have different implementations for other methods. This is the usual way the forms are handled in Symfony. You should read on forms in detail before proceeding, the article is quite informative.
I guess its because you didnt specified, in your routing configuration, that the method of this function is POST.
Because the form never submitted to your function (your function want GET, but send POST)
Where is the last question?
There is a great code to make your search function, it should work (sorry if you dont use annotation).
One good point, you can now use your searchType everywhere in your project, you should make your form like that instead of formbuilder into your controller. Easier to read and to use.
Controller:
/**
* To search something
*
* #Route("/search", name="search")
* #Template()
*/
public function searchAction()
{
$form = $this->createForm(new searchType());
$request = $this->get('request');
if ($request->getMethod() == 'POST')
{
$form->bind($request);
if ($form->isValid())
{
$informations = $form->get('search')->getData();
//make things here
}
}
}
And here is the searchType class:
class searchType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('fnr', 'hidden')
->add('sstring', 'search', array('label' => false))
->add('submit', 'submit', array('label' => 'suchen'));
}
/**
* #return string
*/
public function getName()
{
return 'yournamespace_searchType';
}
}
I have a form with one default value:
class GearType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('options')
->add('model', 'choice', array('choices' => $this->getModelChoices(), 'data' => 2));
}
one of the requirements is form can be pre-populated by re-sellers by passing parameters in URL. It is also nice feature for potential customers to copy and paste link to email, communicators, etc.
I did it this way:
/**
* #Route("/car/gear")
* #Template()
*/
public function gearAction(Request $request)
{
$form = $this->createForm(new GearType());
if ($request->isMethod('POST')) {
$form->bind($request);
if ($form->isValid()) {
return 'is valid';
}
} else {
$get = $this->getRequest()->query->all();
if (!empty($get)) {
$normalizer = new GetSetMethodNormalizer();
$form->setData($normalizer->denormalize($get, new Gear())); # look here
}
}
return array('form' => $form->createView());
}
unfortunately field 'options' has always default value, instead value passed as a parameter.
I have tried to change line # look here into
$gear = $normalizer->denormalize($get, new Gear());
$form = $this->createForm(new GearType(), $gear);
but no result.
It seems that solution is passing additional parameter to GearType object. I do not like this solution. Does anyone know better way?
Add this snippet, and modifiy between the [ ] as appropriate
$form->bind($request);
if ( [ passed parameters from querystring ] ){ //// New Code
$form->getData()->setOptions( [ processed parameter ]); //// New Code
} //// New Code
if ($form->isValid()) {
return 'is valid';
}
The reason for the field options always having default value may be the actual query. Instead of denormalizing and setting the data directly, modify else fragment to:
} else {
$form = $this->createForm(new GearType(), new Gear(), array(
'validation_groups' => array('not-validating')
));
$form->bind($request);
}
The form will validate only against validations associated with the not-validating group, which will avoid showing the common required alerts if the form is built form GET.
Docs about 'validations-groups': http://symfony.com/doc/current/book/forms.html#validation-groups
The question is similar to: Entity form field and validation in Symfony2?
I have a form for my entity called Book and I have a type to display a form in my view. In this type I have some fields that are mapped to properties in my entity.
Now I want to add another field which is not mapped in my entity and supply some initial data for that field during form creation.
My Type looks like this
// BookBundle\Type\Book
public function buildForm(FormBuilderInterface $builder, array $options = null)
{
$builder->add('title');
$builder->add('another_field', null, array(
'mapped' => false
));
}
The form is created like this
$book = $repository->find(1);
$form = $this->createForm(new BookType(), $book);
How can I supply some initial data now during form creation? Or how do I have to change that creation of the form to add initial data to the another_field field?
I also have a form that has fields that mostly match a previously defined entity, but one of the form fields has mapped set to false.
To get around this in the controller, you can give it some initial data pretty easily like this:
$product = new Product(); // or load with Doctrine/Propel
$initialData = "John Doe, this field is not actually mapped to Product";
$form = $this->createForm(new ProductType(), $product);
$form->get('nonMappedField')->setData($initialData);
simple as that. Then when you're processing the form data to get ready to save it, you can access the non-mapped data with:
$form->get('nonMappedField')->getData();
One suggestion might be to add a constructor argument (or setter) on your BookType that includes the "another_field" data, and in the add arguments, set the 'data' parameter:
class BookType
{
private $anotherFieldValue;
public function __construct($anotherFieldValue)
{
$this->anotherFieldValue = $anotherFieldValue;
}
public function buildForm(FormBuilderInterface $builder, array $options = null)
{
$builder->add('another_field', 'hidden', array(
'property_path' => false,
'data' => $this->anotherFieldValue
));
}
}
Then construct:
$this->createForm(new BookType('blahblah'), $book);
You can change the request parameters like this to support the form with additional data:
$type = new BookType();
$data = $this->getRequest()->request->get($type->getName());
$data = array_merge($data, array(
'additional_field' => 'value'
));
$this->getRequest()->request->set($type->getName(), $data);
This way your form will fill in the correct values for your field at rendering. If you want to supply many fields this may be an option.