#Assert\Valid() on Entity, remove the validation on form - forms

I been searching online, couldn't find the answer to my problem.
I want to disable #Assert/Valid() on first field, if second field is selected by the user. right now validation is happening on both fields.
Form type
AppBundle/Form/ParcelType.php
class ParcelType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$user = 1;
$builder
//TODO if address is selected from history, then dont validate this field
->add('pickupAddressNew', new AddressType())
->add('pickupAddressHistory', 'entity', [
'class' => 'AppBundle\Entity\Address',
'property' => 'formatAddress',
'query_builder' => function (EntityRepository $er) use ($user) {
return $er->createQueryBuilder('a')
->where('a.user = :user')
->andWhere('a.type = :type')
->setParameter('user', $user)
->setParameter('type', 'pickup')
->orderBy('a.isDefault', 'DESC')
->addOrderBy('a.id', 'DESC');
}
]););
}
public function getName()
{
return 'parcel';
}
}
AppBundle/Entity/Model/Parcel.php
class Parcel
{
protected $name;
/**
* #Assert\Type(type="AppBundle\Entity\Address")
* #Assert\Valid()
*/
protected $pickupAddressNew;
/**
* #Assert\Type(type="AppBundle\Entity\Address")
* #Assert\Valid()
*/
protected $pickupAddressHistory;
...
}
Address
AppBundle/Entity/Address.php
class Address
{
...
private $id;
..
private $firstName;
/**
* #var string
*
* #Assert\NotBlank(message="field.address.blank")
* #Assert\Length(
* min = 3,
* max = 255,
* minMessage = "field.address.min",
* maxMessage = "field.address.max"
* )
* #ORM\Column(name="format_address", type="string", length=255, nullable=false)
*/
private $address;
}

After long search, I couldn't find any answer, but found another solution which will solve it. Sharing with community, so others can solve it quickly.
Remove #Assert/Valid() from the annotation and add following on the form type
public function buildForm(...) {
...
$form->add('pickupAddressNew', new AddressType(), [
'label' => 'form.label.pickupAddressNew',
'constraints' => new Valid()
])
// also add event listener
$builder->addEventListener(FormEvents::SUBMIT, array($this, 'conditionValid'));
}
now create condition valid method on same formType class.
public function conditionValid (FormEvent $event)
{
$parcel = $event->getData();
$form = $event->getForm();
if ($parcel->getPickupAddressHistory() > 0)
{
$form->add('pickupAddressNew', new AddressType(), [
'label' => 'form.label.pickupAddress'
]);
}
}
On this method, we check if second field has value and its selected, then recreate the first field without the validation rule, this will bypass the group validation.

Related

Symfony 4.3 dynamic form for tags solution with Doctrine many to one association

First, I'm sorry for my bad english. I need to create form to adding new tags for Article but when I submit form then Request data is not handled in my form because new added tags are not in entity array collection. Is possible to add custom choices to form field with many to one association?
Here is my code:
public function buildForm(FormBuilderInterface $builder, array $options)
{
dump($builder->getFormConfig()); die;
/** #var Domain $domain */
$domain = $this->currentDomainService->getCurrentDomain();
$builder
->add('articleTitle', TextType::class, [])
->addEventSubscriber(new TagsChoicesSubscriber())
;
}
class TagshoicesSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return array(
FormEvents::PRE_SET_DATA => ['preSetData', -50],
FormEvents::PRE_SUBMIT => ['preSetData', -50],
);
}
public function preSetData(FormEvent $event, $childName)
{
$choices = array();
/** #var Article $article */
$article = $event->getData();
if ($article instanceof Article) {
foreach ($article->getTags() as $tag) {
$tags[] = $tag->getTagName();
}
$event->getForm()->add(
'tags',
ChoiceType::class,
[
'multiple' => true,
'mapped' => false,
'choices' => $choices,
'data' => $tags,
'required' => true,
'constraints' => [
new NotBlank(),
],
]
);
}
}
}
/**
* Article
* #ORM\Entity()
*/
class Article
{
/**
* #ORM\OneToMany(targetEntity="App\Entity\Tags", mappedBy="article")
*/
private $tags;
}
/**
* Tag
*
* #ORM\Entity()
*/
class Tag
{
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Article", inversedBy="tags")
* #ORM\JoinColumn(name="article_id", referencedColumnName="id")
*/
private $article;
}
$form = $this->createForm('App\Form\ArticleType', $article);
$form->handleRequest($request);
The thing you need to implement is either collection type field, or choice type with multiple set to true, here is Symfony collection type and here is Symfony choice type, you will also need a toString function in Tag class.

symfony: Validating form field, many-to-many-relationship

I have three entities: User, Work and Journal. There is a many-to-many-relationship between User and Work defined as follows:
In the Work entity:
/**
* #ORM\ManyToMany(targetEntity="User", inversedBy="peerReviewedWorks")
* #ORM\JoinTable(name="test_work_user_peer")
*/
private $peerReviewers
In the User entity:
/**
* #ORM\ManyToMany(targetEntity="Work", mappedBy="peerReviewers")
*/
private $peerReviewedWorks;
There is no relationship between my third entity, Journal, and User but a one-to-many-relationship between Journal and Work:
Journal entity:
/**
* #ORM\OneToMany(targetEntity="Work", mappedBy="journal")
*/
private $works;
Work entity:
/**
* #ORM\ManyToOne(targetEntity="Journal", inversedBy="works")
* #ORM\JoinColumn(name="journal_id", referencedColumnName="id")
*/
private $journal;
From the Work controller I am creating a form which lets the editor choose the peer-reviewers from a list and assign them to a work:
<?php
public function manageAction(Request $request, Work $work)
{
// ...
$form = $this->createForm(ManageWorkType::class, $work);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
// ...
}
}
The ManageWorkType class looks as follows:
<?php
class ManageWorkType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
// add some stuff
->add('submit', SubmitType::class)
;
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$work = $event->getData();
$form = $event->getForm();
// form field only added when journal is peer-reviewed
if($work->getJournal()->getIsPeerReviewed() == 1) {
// get a list of all active peer-reviewers
$form->add('peerReviewers', EntityType::class, array(
'class' => 'PlatformBundle:User',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('u')
->where('u.peerReviewStatus = :status')
->setParameter('status', 'active')
;
},
'multiple' => true,
));
}
});
// ...
}
Since not every journal requires the same number of peer-reviews, I have a field number_of_peer_reviewers in the Journal entity which holds the number of required peer-reviewers:
Journal entity:
/**
* #var string
*
* #ORM\Column(name="numberOfPeerReviewers", type="string", length=1, nullable=true)
*/
private $numberOfPeerReviewers;
Before assigning the peer-reviewers from the User entity to the Work entity I have to check if the editor who submitted the form selected the required number of peer-reviewers from the list. If this is not the case the form should not be valid.
In order to achieve this I tried to use a callback validator in the Work entity but failed miserably:
/**
* #ORM\ManyToMany(targetEntity="User", inversedBy="peer_reviewed_works")
* #ORM\JoinTable(name="test_work_user_peer")
* #Assert\Valid
*/
private $peerReviewers;
// ...
/**
* #Assert\Callback
*/
public function validate(ExecutionContextInterface $context, $payload)
{
if(count($this->getPeerReviewers()) < $this->getPeerReviewers()->getNumberOfPeerReviewers()) {
$context->buildViolation('Error message')
->atPath('peerReviewers')
->addViolation();
}
}
As you can see I do not know how to access the number_of_peer_reviewers field from the Journal table.
Any guidance is greatly appreciated.

Symfony2 form collection not calling addxxx and removexxx even if 'by_reference' => false

I have the Customer entity and two one-to-many relations CustomerPhone and CustomerAddress.
The Customer entity has addPhone/removePhone and addAddress/removeAddress "adders".
CustomerType collections options has 'by_reference' => false for both collections.
Entity functions addPhone/removePhone and addAddress/removeAddress not called after form submitted, so CustomerPhone and CustomerAddress have no parent id after persist.
Why could addPhone/removePhone and addAddress/removeAddress not called on form submit?
UPD 1.
After #Baig suggestion now I have addPhone/removePhone "adders" called, but addAddress/removeAddress not. Can't get why because they are identical.
# TestCustomerBundle/Entity/Customer.php
/**
* #var string
*
* #ORM\OneToMany(targetEntity="CustomerPhone", mappedBy="customerId", cascade={"persist"}, orphanRemoval=true)
*/
private $phone;
/**
* #var string
*
* #ORM\OneToMany(targetEntity="CustomerAddress", mappedBy="customerId", cascade={"persist"}, orphanRemoval=true)
*/
private $address;
Same file "adders"
# TestCustomerBundle/Entity/Customer.php
/**
* Add customer phone.
*
* #param Phone $phone
*/
public function addPhone(CustomerPhone $phone) {
$phone->setCustomerId($this);
$this->phone->add($phone);
return $this;
}
/**
* Remove customer phone.
*
* #param Phone $phone customer phone
*/
public function removePhone(CustomerPhone $phone) {
$this->phone->remove($phone);
}
/**
* Add customer address.
*
* #param Address $address
*/
public function addAddress(CustomerAddress $address) {
$address->setCustomerId($this);
$this->address->add($address);
return $this;
}
/**
* Remove customer address.
*
* #param Address $address customer address
*/
public function removeAddress(CustomerAddress $address) {
$this->address->remove($address);
}
Relations:
# TestCustomerBundle/Entity/CustomerPhone.php
/**
* #ORM\ManyToOne(targetEntity="Customer", inversedBy="phone")
* #ORM\JoinColumn(name="customer_id", referencedColumnName="id")
**/
private $customerId;
#TestCustomerBundle/Entity/CustomerAddress.php
/**
* #ORM\ManyToOne(targetEntity="Customer", inversedBy="address")
* #ORM\JoinColumn(name="customer_id", referencedColumnName="id")
**/
private $customerId;
CustomerType form:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('phone', 'collection', array(
'type' => new CustomerPhoneType(),
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
'options' => array('label' => false)
))
->add('address', 'collection', array(
'type' => new CustomerAddressType(),
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
'options' => array('label' => false)
))
->add('submit', 'submit')
;
}
Controller.
# TestCustomerBundle/Controller/DefaultController.php
public function newAction(Request $request)
{
$customer = new Customer();
// Create form.
$form = $this->createForm(new CustomerType(), $customer);
// Handle form to store customer obect with doctrine.
if ($request->getMethod() == 'POST')
{
$form->bind($request);
if ($form->isValid())
{
/*$em = $this->get('doctrine')->getEntityManager();
$em->persist($customer);
$em->flush();*/
$request->getSession()->getFlashBag()->add('success', 'New customer added');
}
}
// Display form.
return $this->render('DeliveryCrmBundle:Default:customer_form.html.twig', array(
'form' => $form->createView()
));
}
UPD 2.
Test if addAddress called.
/**
* Add customer address.
*
* #param Address $address
*/
public function addAddress(Address $address) {
jkkh; // Test for error if method called. Nothing throws.
$address->setCustomerId($this);
$this->address->add($address);
}
UPD 3.
CustomerAddressType.php
<?php
namespace Delivery\CrmBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class CustomerAddressType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('street')
->add('house')
->add('building', 'text', ['required' => false])
->add('flat', 'text', ['required' => false])
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Delivery\CrmBundle\Entity\CustomerAddress'
));
}
/**
* #return string
*/
public function getName()
{
return 'delivery_crmbundle_customeraddress';
}
}
CustomerPhoneType.php
<?php
namespace Delivery\CrmBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class CustomerPhoneType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('number')
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Delivery\CrmBundle\Entity\CustomerPhone'
));
}
/**
* #return string
*/
public function getName()
{
return 'phone';
}
}
For me this was eventually solved by adding getXXX, which returns the collection to the PropertyAccessor. Without that you keep on wondering why addXXX or removeXXX aren't called.
So make sure that:
The option by_reference is set to false at the field,
You have both the adder and remover method on the owning side of the relationship,
The getter is accessible for the PropertyAccessor to check if by_reference can be used,
If you want to use the prototype to handle adding/removing via Javascript, make sure allow_add is set to true.
This answer corresponds to Symfony 3, but I am sure this applies to Symfony 2 as well. Also this answer is more as a reference than addressing OP's issue in particular (which I am not to clear)
On ..Symfony/Component/PropertyAccess/PropertyAccessor.php the method writeProperty is responsible for calling either setXXXXs or addXXX & removeXXXX methods.
So here is order on which it looks for the method:
If the entity is array or instance of Traversable (which ArrayCollection is) then pair of
addEntityNameSingular()
removeEntityNameSingular()
Source for reference:
if (is_array($value) || $value instanceof \Traversable) {
$methods = $this->findAdderAndRemover($reflClass, $singulars);
if (null !== $methods) {
$access[self::ACCESS_TYPE] = self::ACCESS_TYPE_ADDER_AND_REMOVER;
$access[self::ACCESS_ADDER] = $methods[0];
$access[self::ACCESS_REMOVER] = $methods[1];
}
}
If not then:
setEntityName()
entityName()
__set()
$entity_name (Should be public)
__call()
Source for reference:
if (!isset($access[self::ACCESS_TYPE])) {
$setter = 'set'.$camelized;
$getsetter = lcfirst($camelized); // jQuery style, e.g. read: last(), write: last($item)
if ($this->isMethodAccessible($reflClass, $setter, 1)) {
$access[self::ACCESS_TYPE] = self::ACCESS_TYPE_METHOD;
$access[self::ACCESS_NAME] = $setter;
} elseif ($this->isMethodAccessible($reflClass, $getsetter, 1)) {
$access[self::ACCESS_TYPE] = self::ACCESS_TYPE_METHOD;
$access[self::ACCESS_NAME] = $getsetter;
} elseif ($this->isMethodAccessible($reflClass, '__set', 2)) {
$access[self::ACCESS_TYPE] = self::ACCESS_TYPE_PROPERTY;
$access[self::ACCESS_NAME] = $property;
} elseif ($access[self::ACCESS_HAS_PROPERTY] && $reflClass->getProperty($property)->isPublic()) {
$access[self::ACCESS_TYPE] = self::ACCESS_TYPE_PROPERTY;
$access[self::ACCESS_NAME] = $property;
} elseif ($this->magicCall && $this->isMethodAccessible($reflClass, '__call', 2)) {
// we call the getter and hope the __call do the job
$access[self::ACCESS_TYPE] = self::ACCESS_TYPE_MAGIC;
$access[self::ACCESS_NAME] = $setter;
} else {
$access[self::ACCESS_TYPE] = self::ACCESS_TYPE_NOT_FOUND;
$access[self::ACCESS_NAME] = sprintf(
'Neither the property "%s" nor one of the methods %s"%s()", "%s()", '.
'"__set()" or "__call()" exist and have public access in class "%s".',
$property,
implode('', array_map(function ($singular) {
return '"add'.$singular.'()"/"remove'.$singular.'()", ';
}, $singulars)),
$setter,
$getsetter,
$reflClass->name
);
}
}
To answer OP's issue, based on the above mentioned information, the PropertyAccessor class of symfony is not able to read your addXX and removeXX method properly. The potential reason might be that is not identified as array or ArrayCollection which has to be done from the constructor of the entity
public function __construct() {
$this->address = new ArrayCollection();
// ....
}
I had the same problem, but I'm not sure that it's the same cause.
I your entity's attribute that has OneToMany relation ship must have an 's' at the end. So that in "handleRequest" (leave it a black box, I didn't look up inside), symfony would find your "addxxx" without "s".
In the exemple 'Task - Tag', he declared "tags" but getTag.
In your case I would think you change your $phone to $phones and the method follow:
public function setPhones($phones){}
public function addPhone(Phone $phone){}
To the name of method your form searching for, just delete temporarily setter in your entity and submit your form, symfony will told you.
Just hope this would help you out :)

Symfony Form render with Self Referenced Entity

I have an Entity containing Self-Referenced mapping.
class Category
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=100)
*/
private $name;
/**
* #ORM\OneToMany(targetEntity="Category", mappedBy="parent")
*/
private $children;
/**
* #ORM\ManyToOne(targetEntity="Category", inversedBy="children")
* #ORM\JoinColumn(name="parent_id", referencedColumnName="id")
*/
private $parent;
}
In my CategoryType I have this :
public function buildForm(FormBuilderInterface $builder, array $options)
{
$plan = $this->plan;
$builder->add('name');
$builder->add('parent', 'entity', array(
'class' => 'xxxBundle:Category',
'property' => 'name',
'empty_value' => 'Choose a parent category',
'required' => false,
'query_builder' => function(EntityRepository $er) use ($plan) {
return $er->createQueryBuilder('u')
->where('u.plan = :plan')
->setParameter('plan', $plan)
->orderBy('u.id', 'ASC');
},
));
}
Actually, when I render the form field Category this is something like
Cat1
Cat2
Cat3
Subcat1
Subcat2
Cat4
I would like to know if it's possible and how to display something more like, a kind of a simple tree representation :
Cat1
Cat2
Cat3
-- Subcat1
-- Subcat2
Cat4
Regards.
I came up with something which seems correct from what you and jperovic wrote. You will need two new attributes for your Category class :
$level will contain ID's of its parents like "idA-idB", etc. this attribute will be use to sort your results when querying your database so you can be certain SubCatOf3 won't come before Cat3 !
$treeName will contain what jperovic already wrote and will be printed in the form.
I also used Doctrine Events [doc] so when you update/persist them, you don't have to worry about the value of these attributes.
This is your brand new Category.php file :
/**
* #ORM\HasLifeCycleCallbacks()
*/
class Category
{
private $level;
private $treeName;
/**
* Renders something like : "---- Subcategory A"
* #ORM\PreUpdate()
* #ORM\PrePersist()
**/
public function updateTreeName()
{
$itemDepth = 0;
$parent = $this->parent;
while ($parent != null) {
$itemDepth++;
$parent = $parent->getParent();
}
$this->treeName = str_repeat('--', $itemDepth) . ' ' . $this->name
}
/** renders something like : "idParent-idChild1-idChild2"
* #ORM\PreUpdate()
* #ORM\PrePersist()
**/
public function updateLevelName()
{
$this->level = '';
$parent = $this->parent;
while ($parent != null) {
$parent = $parent->getParent();
$this->level .= '-' . $p->getId();
}
}
public function getTreeName()
{
return $this->treeName;
}
public function getLevel()
{
return $this->level;
}
// ...
}
Then, put your query_builder in your CategoryRepository.php like this :
namespace Foo\BarBundle\Entity;
use Doctrine\ORM\EntityRepository;
class CategoryRepository extends EntityRepository
{
public function getHierarchicalCategoryList($plan)
{
$qb = $this->createQueryBuilder('u')
->where('u.plan = :plan')
->setParameter('plan', $plan)
->orderBy('u.level', 'ASC');
$return $qb;
}
}
And in your CategoryType.php :
public function buildForm(FormBuilderInterface $builder, array $options)
{
$plan = $this->plan;
$builder->add('name');
$builder->add('parent', 'entity', array(
'class' => 'xxxBundle:Category',
'property' => 'treeName',
'empty_value' => 'Choose a parent category',
'required' => false,
'query_builder' => function(EntityRepository $er) use ($plan) {
return $er->getHierarchicalCategoryList($plan)
},
));
}
Note : this is quick&dirty work so you might need to correct typos, annotations, etc. Yet, you have the idea ! Hope it helps.
This is a really long shot at best, but I think it could be achieved pretty easily.
Within your query_builder you specified the 'property' => 'name'. You would need to change it to 'treeName'. Doctrine will try to find and invoke property's getter method - that's where all the printing logic comes in:
class Category
{
....
Everything else
....
public function getTreeName(){
$itemDepth = 0;
$p = $this->parent;
while ( $p != null ){
$itemDepth++;
$p = $p->getParent();
}
return str_repeat('--', $itemDepth) . ' ' . $this->name
}
}
This could pose a serious performance hit due to need to iterate for each item the depth times.
What do you think? What is the average depth of items?
Just to be clear, name property and its getter and setter are to remain intact.

How to set a default value in a Symfony 2 form field?

I've been trying to set up a form with Symfony 2.
So I followed the tutorial and I've created a special class for creating the form and handling the validation process outside the controller (as shown in the documentation)
But now I need to fill in a field automatically, I've heard that I have to do it in the ProductType.php, where the form (for my product) is created.
But I don't know how to do, here is my buildForm function in ProductType.php :
class QuotesType extends AbstractType
{
private $id;
public function __construct($id){
$this->product_id = $id;
}
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('user_name', 'text')
->add('user_lastname', 'text')
->add('user_email', 'email')
->add('user_comments', 'textarea')
->add('user_product_id', 'hidden', array(
'data' => $this->product_id,
));
;
}
and it obviously doesnt work since I got a SQL error saying that my field is null.
How can I put a default value to the user_product_id ? should I do it directly to the object ?
EDIT:
Here is a part of the code of my entity :
namespace QN\MainBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* QN\MainBundle\Entity\Quotes
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="QN\MainBundle\Entity\QuotesRepository")
*/
class Quotes
{
public function __construct($p_id)
{
$this->date = new \Datetime('today');
}
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var integer $user_product_id
*
* #ORM\Column(name="user_product_id", type="integer")
*/
private $user_product_id = "1";
/**
* #var datetime $date
*
* #ORM\Column(name="date", type="datetime")
*/
private $date;
And my controller :
public function requestAction($id)
{
$repository = $this->getDoctrine()
->getEntityManager()
->getRepository('QNMainBundle:Categories');
$categories = $repository->findAll();
$quote = new Quotes($id);
$form = $this->createForm(new QuotesType(), $quote);
$formHandler = new QuotesHandler($form, $this->get('request'), $this->getDoctrine()->getEntityManager());
if( $formHandler->process() )
{
return $this->redirect( $this->generateUrl('QNMain_Product', array('id' => $id)) );
}
return $this->render('QNMainBundle:Main:requestaform.html.twig', array(
'categories' => $categories,
'id' => $id,
'form' => $form->createView(),
));
}
My Handler :
namespace QN\MainBundle\Form;
use Symfony\Component\Form\Form;
use Symfony\Component\HttpFoundation\Request;
use Doctrine\ORM\EntityManager;
use QN\MainBundle\Entity\Quotes;
class QuotesHandler
{
protected $form;
protected $request;
protected $em;
public function __construct(Form $form, Request $request, EntityManager $em)
{
$this->form = $form;
$this->request = $request;
$this->em = $em;
}
public function process()
{
if( $this->request->getMethod() == 'POST' )
{
$this->form->bindRequest($this->request);
if( $this->form->isValid() )
{
$this->onSuccess($this->form->getData());
return true;
}
}
return false;
}
public function onSuccess(Quotes $quote)
{
$this->em->persist($quote);
$this->em->flush();
}
}
I've also put here the Date I try to set up in the entity, I might do something wrong in both case since I can't make it work neither ..Date is not in the buildForm function, I don't know if I should ..
Another way is creating a Form Type Extension:
namespace App\Form\Extension;
// ...
class DefaultValueTypeExtension extends AbstractTypeExtension
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
if (null !== $default = $options['default']) {
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
static function (FormEvent $event) use ($default) {
if (null === $event->getData()) {
$event->setData($default);
}
}
);
}
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefault('default', null);
}
public static function getExtendedTypes(): iterable
{
yield FormType::class;
}
}
Now any possible value can be passed as default to any form field:
$form->add('user', null, ['default' => $this->getUser()]);
$form->add('user_product_id', null, ['default' => 1]);
This method is specially useful when you don't have a chance to hook into the initialization process of the bound object.
What you're trying to do here is creating a security hole: anyone would be able to inject any ID in the user_product_id field and dupe you application. Not mentioning that it's useless to render a field and to not show it.
You can set a default value to user_product_id in your entity:
/**
* #ORM\Annotations...
*/
private $user_product_id = 9000;