Turning a string into a valid php code in object context? - php

I'm using Silex FormBuilder in my application. The structure of a builder is like this:
$form = $app['form.factory']->createBuilder('form')
->add('name', 'text', array(
'constraints' => array(new Assert\NotBlank(), new Assert\Length(array('min' => 5)))
))
->add('email', 'text', array(
'constraints' => new Assert\Email()
))
->add('gender', 'choice', array(
'choices' => array(1 => 'male', 2 => 'female'),
'expanded' => true,
'constraints' => new Assert\Choice(array(1, 2)),
))
->getForm();
Let's say I would build such builder from blocks, which would be stored in a database as a whole. Always, in any form I would create I know, that e-mail field will always be defined the same. So I would get definitions from database and foreach them to create form.
->add('email', 'text', array(
'constraints' => new Assert\Email()))
When i get this from a database (posgresql in my case) this would be a string (because the database field is text type).My question: is there any possibility to convert this to a valid code?
I thought of something like this:
$form = $app['form.factory']->createBuilder('form')
foreach ($definitions as $definition) {
something to do with the $definition;
}
->getForm();
But instead of foreach createBuilder expects ->add... method, and this is where im stuck.
Best Regards,Kamil

/*Concidering $definitions = array("$form->add('email', 'text', array(
'constraints' => new Assert\Email()
));");
*/
$form = $app['form.factory']->createBuilder('form');
foreach($definitions as $definition){
eval($definition);
}
$form->getForm();
I would not recommend you use eval like so... You'd better store the parameters to pass to the function to make it work... You could also create a function or class to handle typical elements such as your email, so you would only need to reference the kind of input in the database, a bit like so:
function addFormElement(&$form,$type){
switch($type){
case 'email':$form->add('email', 'text', array(
'constraints' => new Assert\Email()
));
break;
}
}
/*Concidering $definitions = array("email");
*/
$form = $app['form.factory']->createBuilder('form');
foreach($definitions as $definition){
addFormElement($form,$definition);
}
$form->getForm();

Related

Doctrine tries to insert a null object Symfony 5.4

when i submit my form, I have two values ​​to choose from:
WorkPlanningDay and workPlanningHour.
if workplanninghour is specified, we insert a row in the workplanninghour table and vice versa
When I submit a workPlanningHour, I want to prevent doctrine from inserting a workPlanningDay object with null data. I tried to use a $form->remove but without success.
here is my request datas :
{"statuses":[6],"work_planning":1,"work_planning_hour":{"count_jrtt":1,"end_at":"31-12","jrtt":true,"lower_hour_jrtt":35,"nbr_jrtt":24,"start_at":"01-01","upper_hour_jrtt":39},"work_planning_period":0,"working_time_aspect":{"days":["MON","TUE","WED","THU","FRI"],"time":0,"weekly_hours":35}}
here is my form with my EventListener :
class WorkingTimeParametersRESTType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('work_planning', Field\ChoiceType::class, array(
'property_path' => 'workPlanning',
'required' => true,
'choices' => WorkingTimeParameters::getAllowedWorkPlannings(),
))
->add('work_planning_period', Field\ChoiceType::class, array(
'property_path' => 'workPlanningPeriod',
'required' => false,
'choices' => WorkingTimeParameters::getAllowedWorkPlanningPeriods(),
))
->add('working_time_aspect', WorkingTimeAspectType::class, array(
'property_path' => 'workingTimeAspect',
'required' => true,
'constraints' => array(new Valid())
))
->add('work_planning_hour', WorkPlanningHourType::class, array(
'property_path' => 'workPlanningHour',
'required' => true,
'constraints' => array(new Valid())
))
->add('work_planning_day', WorkPlanningDayType::class, array(
'property_path' => 'workPlanningDay',
'required' => true,
'constraints' => array(new Valid())
))
->add('statuses', Field\CollectionType::class, array(
'entry_type' => CategoryIntegerType::class,
'entry_options' => array(
'category_type' => Category::TYPE_STATUS,
),
'allow_add' => true,
'allow_delete' => true,
'required' => true,
'error_bubbling' => false,
))
->addEventListener(FormEvents::PRE_SET_DATA, array($this, 'onPreSetData'))
->addEventListener(FormEvents::SUBMIT, function (FormEvent $event) {
/** #var WorkingTimeParameters $contract */
$parameters = $event->getData();
$form = $event->getForm();
// dd($form->has('work_planning_day'));
// Remove useless work planning
if ($parameters->getWorkPlanning() == Contract::WORK_PLANNING_HOUR) {
$parameters->setWorkPlanningDay(null);
$form->remove('work_planning_day');
}
else if ($parameters->getWorkPlanning() == Contract::WORK_PLANNING_DAY) {
$parameters->setWorkPlanningHour(null);
$form->remove('work_planning_hour');
}
else {
dd('rerer');
$form->remove('work_planning_day');
$form->remove('work_planning_hour');
$parameters->setWorkPlanningDay(null);
$parameters->setWorkPlanningHour(null);
$parameters->setWorkPlanningPeriod(null);
}
})
;
}
/**
* #param FormEvent $event
*/
public function onPreSetData(FormEvent $event)
{
$rttParameters = $event->getData();
$form = $event->getForm();
// The company can be set only on creation
if (!$rttParameters || !$rttParameters->getId()) {
$form->add('company', CompanyIntegerType::class, array(
'required' => true,
));
}
}
and here are the requests that doctrine is trying to launch :
INSERT INTO w2d_tm_work_planning_hour (startAt, endAt, jrtt, countJrtt, lowerHourJrtt, upperHourJrtt, nbrJrtt) VALUES ('1970-01-01 00:00:00', '1970-12-31 00:00:00', 1, 1, 35, 39, 24);
UPDATE w2d_tm_work_planning_day SET startAt = NULL, endAt = NULL, nbrDays = NULL, nbrJrtt = NULL WHERE id = 1;
how to do so that doctrine does not launch the second request with the null values ?
Symfony form type are not made to handle different entities depending on a option you selected inside.
This not how Symfony FormType are supposed to be used. This is why the data_class attribute is made for one entity.
You best option is to create two distinct FormType and submit only the one needed depending on what the user selected on frontend. (easy with a little of javascript)
The second advantage of this is you will have much more understandable and maintable code.

Symfony Selection of Entity using Doctrine

i need some help.
I have a Form where i would like to either choose an existing Entity or submit a new one. So i have a Class Dolmetscher (Interpreter for languages) with title, name, surname and language. To create the Form i have a Class InterpreterType with the function
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('anrede', ChoiceType::class, array(
'choices' => array(
'Herr' => 'Herr',
'Frau' => 'Frau'
)
))
->add('vorname')
->add('nachname')
->add('sprache')
->add('dolmetscher', EntityType::class, array(
'class' => 'AppBundle:Dolmetscher',
'placeholder' => 'Dolmetscher wählen',
'label' => 'Dolmetscher',
'choice_value' => 'id',
'choice_label' => function ($dolmetscher) {
return $dolmetscher->getAnrede() . ' ' .
$dolmetscher->getVorname() . ' ' .
$dolmetscher->getNachname();
},
'mapped' => false,
))
->add('select', SubmitType::class, array(
'label' => 'Übernehmen',
'attr' => array(
'class' => 'btn btn-default',
'formnovalidate' => 'formnovalidate'
)
))
->add('save', SubmitType::class, array(
'label' => 'OK',
'attr' => array(
'style' => 'float: right',
'class' => 'btn btn-default'
)
))
->add('reset', SubmitType::class, array(
'label' => 'Zurücksetzen',
'attr' => array(
'style' => 'float: right; margin-right: 10px',
'class' => 'btn btn-warning',
'formnovalidate' => 'formnovalidate'
)
));
}
So i have a selection with Entities, which is working, with a 'select' Button and Form fields for a new Dolmetscher with a 'save' Button. Also a 'reset' Button
My Controller Class looks like
/**
* #Route("/u01/5", name="u1_5")
*/
public function dolmetscherAction(Request $request) {
$session = $this->get("session");
var_dump($session->get("foo"));
if (!$session->get("dolmetscher")) {
$dolmetscher = new Dolmetscher();
} else {
$dolmetscher = $session->get("dolmetscher");
}
$dolmetscherForm = $this->createForm(DolmetscherType::class, $dolmetscher);
$dolmetscherForm->handleRequest($request);
if ($dolmetscherForm->get('select')->isClicked()) {
$dolmetscher = $dolmetscherForm->get('dolmetscher');
$session->set("dolmetscher", $dolmetscher);
return $this->redirectToRoute('u1_5');
}
if ($dolmetscherForm->get('reset')->isClicked()) {
$dolmetscher = new Dolmetscher();
$session->set("dolmetscher", $dolmetscher);
return $this->redirectToRoute('u1_5');
}
if ($dolmetscherForm->get('save')->isClicked() && $dolmetscherForm->isSubmitted() && $dolmetscherForm->isValid()) {
$dolmetscher = $dolmetscherForm->getData();
$session->set("dolmetscher", $dolmetscher);
return $this->redirectToRoute('homepage');
}
return $this->render('urkunden/u01/5.html.twig', [
'form' => $dolmetscherForm->createView(),
'page_title' => 'U01'
]);
}
I want to put the Dolmetscher from the selection into $_SET for later use ,e.g. persist in DB, which works fine for a new Dolmetscher but not for my selection. I get an Exception
Serialization of 'Closure' is not allowed
I'm not sure if I'm doing this right at all (I have some OneToMany Relations and wanted to have a view for each Entity/Form and persist everything at once at the end so that i don't have only a Dolmetscher in my DB when the user quits in mid process)
I also thought it might be possible to populate the Form fields from the selection which I couldn't get to work. Can someone please help me, i would appreciate it.
This part of code is probably the origin of your problems :
if ($dolmetscherForm->get('select')->isClicked()) {
$dolmetscher = $dolmetscherForm->get('dolmetscher'); <------ this one
$session->set("dolmetscher", $dolmetscher);
return $this->redirectToRoute('u1_5');
}
you are trying to serialize a form object which contains a closure. Closure can not be serialized ( visit this link for more insights Exception: Serialization of 'Closure' is not allowed )
If you dump $dolmetscher variable you will probably get a form object not the entity you want. try to replace the line :
$dolmetscher = $dolmetscherForm->get('dolmetscher');
with :
$dolmetscher = $dolmetscherForm->get('dolmetscher')->getData();

How get field value in form builder in Symfony

How to get field value in form builder in Symfony.
I have 2 Dropdowns in the form
I want to should the related option in Dropdown2 based on Dropdown1 in when the Page is Opening.
Here is My Form
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\Event\DataEvent;
use C2Educate\ToolsBundle\Entity\Students;
public function buildForm(FormBuilder $builder, array $options) {
Field 1:
$builder->add('leadSource', 'entity', array(
'label' => 'How did you hear about C2? Source ',
'class' => 'C2EducateToolsBundle:LeadSources',
'query_builder' => function($repo) {
return $repo->createQueryBuilder('p')->orderBy('p.sort_order', 'ASC');
},
'property' => 'name',
'empty_value' => 'Select'
));
$leadSource = 1;
$leadSource = 1; - it works when I assign value statically, but I want to get the value of "leadSource" and assign it to $leadSource
I want to get the leadSource and pass it to leadSourceSub query
Field 2:
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (DataEvent $event) {
$form = $event->getForm();
$entity = $event->getData();
$leadSource = $entity->getLeadSourceID();
$form->add('leadSourceSub', 'C2Educate\ToolsBundle\Entity\Students', array(
'label' => ' Source Detail ',
'required' => true,
'class' => 'C2EducateToolsBundle:LeadSourceSubs',
'query_builder' => function($repo) use ($leadSource) {
return $repo->createQueryBuilder('p')
->where('p.lead_source_id =:leadSource')
->setParameter('leadSource', $leadSource)
->orderBy('p.sort_order', 'ASC');
},
'property' => 'name',
'empty_value' => 'Select'
));
});
You cannot get form data from $builder, because... it's a form builder, not a form. It doesn't contain any data yet.
To make this work you need to make use of FormEvents. In this case, you probably will need FormEvents::PRE_SET_DATA event listener.
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$form = $event->getForm();
// in your case it's C2EducateToolsBundle:LeadSourceSubs
$entity = $event->getData();
$leadSource = $entity->getLeadSource();
// adding this field again will override it.
$form->add('leadSourceSub', 'entity', array(
'label' => ' Source Detail ',
'required' => true,
'class' => 'C2EducateToolsBundle:LeadSourceSubs',
'query_builder' => function($repo) use ($leadSource) {
return $repo->createQueryBuilder('p')
->where('p.lead_source_id =:leadSource')
->setParameter('leadSource', $leadSource)
->orderBy('p.sort_order', 'ASC');
},
'property' => 'name',
'empty_value' => 'Select'
));
}
});
Please note that this code is not tested and may need some validation like to check if $entity is what you expect it to be in any case.

put data form database into checkbox symfony 3

I started learn symfony 3. For the first project i chose a simple totodlist.
So now i have possibility to create and save the user in my database. Next I can create a task for them.
I want to create a checkbox where can i choose a users to perform a task.
So i need put data from my user database to checkbox form ($temp_users varbiable). I don't know how to do it.
Can anybody show me how to do it.
below is my code:
public function createAction(Request $request)
{
$todo = new Todo;
$users = $this->getDoctrine()
->getRepository('AppBundle:User')
->findAll();
$temp_users = array();
foreach($users as $user) {
$temp_users[$user->getUsername()] = $user->getId();
}
$form = $this->createFormBuilder($todo)
->add('name', TextType::class, array('attr' => array('class' => 'form- control', 'style' => 'margin-bottom:15px')))
->add('wykona', CheckboxType::class, array('label' => $temp_users, 'required' => false,))
I'm not sure what you mean by checkbox - are you wanting to select one, or many users? I'm going to assume you want to select just one for simplicity's sake (you can adapt this to your liking)
You don't need to get all the users like you're trying to do, something like this should work (untested)
$form = $this->createFormBuilder($todo)
->add('user', EntityType::class, array(
'label' => 'Name',
'class' => AppBundle\Entity\User::class,
'choice_label' => 'name', //if you have a variable 'name' in your User entity, otherwise you will need a __toString method in the User entity
));
Try this code inside your createAction.
ADD this into your code
$form = $this->createFormBuilder($todo)
->add('users', EntityType::class, array(
'class' => 'AppBundle:User',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('u')
->orderBy('u.name', 'ASC')
},
'choice_label' => 'name',
'multiple' => true,
'expanded' => true,
));
Also you don't need the following code anymore inside createAction.
REMOVE Below code from your code
$users = $this->getDoctrine()
->getRepository('AppBundle:User')
->findAll();
$temp_users = array();
foreach($users as $user) {
$temp_users[$user->getUsername()] = $user->getId();

Fields in a form behave like "required", although they are not

I am trying to set up an edit form for an entity (Place) in my app. For this purpose I have written the form (PlaceForm), fieldset (PlaceFieldset), .phtml pages and functions in the controller. Since I am new in zf2, I have concentrated on the tutorlias on their homepage. I have seen that from validation is provided by the framework but in my case it is not necessary. None of the fields added in the fieldset have not the required attribute, however when I submit the form under all empty fields I get the message "Value is required and can't be empty" although it is actually not required. I do not want to create a wall of code in this question, so I will start with the function from the controller. If there is someone who would like to help me with this issue, just let me know and I will update any other part of the code (form, fieldset etc.) Thx in advance.
...
public function editPlaceAction() {
$id = $this->params()->fromRoute('id');
$uiServiceProvider = $this->getServiceLocator()->get('FamilyTree\Service\UiServiceProvider');
$placeArray = $uiServiceProvider->fetchSinglePlaceById($id);
$place = new Places($placeArray);
$form = new PlaceForm();
$form->bind($place);
$request = $this->getRequest();
if ($request->isPost()) {
$form->setData($request->getPost());
if ($form->isValid()) {
var_dump($place);
}
}
$view = new ViewModel(array(
'form' => $form,
'title'=>"Edit place"
));
$view->setTemplate("family-tree/family-tree-maintenance/editPlace");
return $view;
}
...
and here you can see how my Fieldset looks like
<?php
namespace Places\Form;
use Zend\Form\Fieldset;
class PlaceFieldset extends Fieldset {
public function __construct() {
parent::__construct('place');
$this->add(array(
'name' => 'id',
'type' => 'Hidden',
));
$this->add(array(
'name' => 'name',
'type' => 'Text',
'options' => array(
'label' => 'Name',
),
));
$this->add(array(
'name' => 'admUnit1',
'type' => 'Text',
'options' => array(
'label' => 'AdmUnit1',
),
));
}
}

Categories