Symfony Form How to do it cleaner - symfony

I'm trying to create new order in eshop, now I have it like this, but is it possible to somehow do this data inserting cleaner or automatic?
$order = new Orders();
$customers = new Customers();
foreach ($form['cart']->getData() as $product) {
if ($product['product']->getQuantity() >= $product['quantity']) {
$cart = new Cart();
$cart->setUserId($sessionID);
$cart->setProductId($product['product']);
$cart->setQuantity($product['quantity']);
$cart->setPrice($product['product']->getPrice());
$cart->setBoughtPrice($product['product']->getBoughtPrice());
$em->persist($cart);
$em->flush();
} else {
$this->addFlash('error', 'Není skladem tolik kusu!');
return $this->redirectToRoute('web_admin_cash_register');
}
}
$customers->setBillingFullName($form['customer']['billingFullName']->getData());
$customers->setBillingAddress($form['customer']['billingAddress']->getData());
$customers->setBillingCity($form['customer']['billingCity']->getData());
$customers->setBillingCountry($form['customer']['billingCountry']->getData());
$customers->setBillingPhoneNumber($form['customer']['billingPhoneNumber']->getData());
$customers->setBillingPostalCode($form['customer']['billingPostalCode']->getData());
$customers->setIco($form['customer']['ico']->getData());
$customers->setDic($form['customer']['dic']->getData());
$customers->setEmail($form['customer']['email']->getData());
$em->persist($order);
$em->flush();
Orders Entity:
/**
* #ORM\OneToMany(targetEntity="OrderItems", mappedBy="order", cascade={"persist", "remove"})
*/
private $cart;
OrderItems Entity:
/**
* #ORM\ManyToOne(targetEntity="Orders", inversedBy="cart")
* #ORM\JoinColumn(name="order_id", referencedColumnName="id")
*/
private $order;
NewOrderType:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('cart', CollectionType::class, [
'entry_type' => CartType::class,
'label' => false,
'allow_add' => true,
'allow_delete' => true,
'prototype' => true,
'required' => false,
'attr' => array(
'class' => 'collection',
),
])
->add('customer', BillingInfoType::class);
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
));
}
CartType(OrderItems):
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('product', EntityType::class, [
'class' => 'Web\ShopBundle\Entity\Product',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('p')
->where('p.enabled = true')
->orWhere('p.quantity >= 1');
},
'constraints' => [
new NotBlank(['message' => 'Povinné pole'])
],
'choice_label' => 'productCode'
])
->add('quantity', IntegerType::class);
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(
[]
);
}
Thank you

Related

Symfony : embeded subform and createdAt / updatedAt : validation conflict

I have an entity form that embed a collectionType and subforms.
In order to make the required option work, I had to enable Auto_mapping
class ClassePriceType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('priceform', PriceformType::class, [
'data_class' => ClassePrice::class,
'block_prefix' => 'mainprice_block'
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => ClassePrice::class,
'attr' => array(
'class' => 'fullwidth'
)
]);
}
}
class PriceformType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('pricecover', ChoiceType::class, [
'label' => 'Price type',
'placeholder' => 'Select a price option',
'choices' => [ 'Global' => '1' ,'Step' => '2'],
'required' => true
])
->add('rangesubform', RangesubformType::class, [
'data_class' => ClassePrice::class,
'block_prefix' => 'range_block'
])
->add('pricesubform', PricesubformType::class, [
'data_class' => ClassePrice::class,
'block_prefix' => 'price_block'
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'inherit_data' => true
]);
}
}
class RangesubformType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('rangetype', EntityType::class, [
'class' => Ptur::class,
'label' => 'Step type',
'choice_translation_domain'=> true,
'required' => true
])
->add('rangeformat', EntityType::class, [
'class' => Format::class,
'label' => 'Format',
'required' => true
])
->add('rangemin', IntegerType::class, [
'label' => 'Range min',
'required' => true
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'inherit_data' => true,
'attr' => array(
'class' => 'form-horizontal'
)
]);
}
}
framework:
validation:
email_validation_mode: html5
# Enables validator auto-mapping support.
# For instance, basic validation constraints will be inferred from Doctrine's metadata.
auto_mapping:
App\Entity\: []
enabled:
true
In my entites I also use the createdAt / updatedAt auto generation made by
use Gedmo\Timestampable\Traits\TimestampableEntity;
use Gedmo\SoftDeleteable\Traits\SoftDeleteableEntity;
use Gedmo\Mapping\Annotation as Gedmo;
The problem is that with auto_mapping activation, I got a validator error when creating a new entity input : createdAt and updatedAt can not be null...
Any idea how to solve that please?
Make sure your object is valid, inside the class:
public function __construct()
{
$this->createdAt = new DateTime();
$this->updatedAt = new DateTime();
}
Set the time like this in your entity:
/**
* #var datetime $created_at
*
* #Orm\Column(type="datetime")
*/
protected $created_at;
/**
* #var datetime $updated_at
*
* #Orm\Column(type="datetime", nullable = true)
*/
protected $updated_at;
/**
* #orm\PrePersist
*/
public function onPrePersist()
{
$this->created_at = new \DateTime("now");
}
/**
* #Orm\PreUpdate
*/
public function onPreUpdate()
{
$this->updated_at = new \DateTime("now");
}

How to set a value for entity field in a form? Symfony2

I have 3 tables realated, inProducto, inProveedor and InProveedorProducto, here my relashionship:
inProveedorProducto:
class InProveedorProducto
{
/**
* #ORM\ManyToOne(targetEntity="InProducto", inversedBy="InProveedorProducto")
* #ORM\JoinColumn(name="id_producto", referencedColumnName="id_producto")
*/
protected $producto;
/**
* #ORM\ManyToOne(targetEntity="InProveedor", inversedBy="InProveedorProducto")
* #ORM\JoinColumn(name="id_proveedor", referencedColumnName="id")
*/
protected $proveedor;
InProveedor:
class InProveedor
{
/**
* #ORM\OneToMany(targetEntity="InProveedorProducto", mappedBy="InProveedor", cascade={"persist"})
*/
protected $proveedorProducto;
public function __construct()
{
$this->proveedorProducto = new ArrayCollection();
}
And InProducto:
class InProducto
{
/**
* #ORM\OneToMany(targetEntity="InProveedorProducto", mappedBy="InProducto", cascade={"persist"})
*/
protected $producto;
public function __construct()
{
$this->producto = new ArrayCollection();
}
My problem is that I have to open a new Form for inProveedorProducto, but idProveedor field should be automatic from prior selection of user.
My controller:
public function newAction()
{
$entity = new InProveedorProducto();
$form = $this->createCreateForm($entity);
$form->get('idProveedor')->setData(1);
return $this->render('NivalInventarioBundle:InProveedorProducto:new.html.twig', array(
'entity' => $entity,
'form' => $form->createView(),
));
}
When I open de form, the first field which is idProveedor appears filled out with the number 1.
THen we select the idProducto and put the price, but when try to create:
Error:
An exception occurred while executing 'INSERT INTO in_proveedor_producto (id_proveedor, id_producto, precio_compra) VALUES (?, ?, ?)' with params [null, 21, 1]:
It seems like idProveedor is comming NULL.
My inProveedorProducto type:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('idProveedor')
->add('producto', 'entity', array(
'class' => 'NivalInventarioBundle:InProducto',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('u')
->orderBy('u.nombre', 'ASC');
},
'choice_label' => 'nombre',
'by_reference' => true,
'expanded' => false,
'placeholder' => 'Seleccione una opción',
'mapped' => true,
'multiple' => false
))
->add('precioCompra')
;
Please help me.
Regards,
Operate with a model, not with a form data.
public function newAction()
{
$entity = new InProveedorProducto();
$entity->setProveedor($this->get('doctrine')->getRepository('NivalInventarioBundle:InProveedor')->find(1));
$form = $this->createCreateForm($entity);
return $this->render('NivalInventarioBundle:InProveedorProducto:new.html.twig', array(
'entity' => $entity,
'form' => $form->createView(),
));
}
And then just
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('proveedor')
->add('producto')
->add('precioCompra')
;

FormType - ManyToMany on himself

I try to do a Parents, Children relation on an Entity, but I've a problem when I submit the form. (It's a ManyToMany on himself)
To do it, I've a ManyToMany relation on my entity like it:
class Strain
{
/**
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\Strain", inversedBy="children")
*/
private $parents;
/**
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\Strain", mappedBy="parents")
*/
private $children;
public function __construct()
{
$this->parents = new ArrayCollection();
$this->children = new ArrayCollection();
}
public function addParent(Strain $strain)
{
$this->parents->add($strain);
}
public function removeParent(Strain $strain)
{
$this->parents->removeElement($strain);
}
public function getParents()
{
return $this->parents;
}
public function getChildren()
{
return $this->children;
}
I think it's okay, I've the foreign keys, an intermediate table strain_strain, with 2 columns: strain_source and strain_target.
My FormTypes:
class StrainType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('parents', CollectionType::class, array(
'entry_type' => StrainParentType::class,
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
'required' => false,
))
;
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Strain'
));
}
And the second:
class StrainParentType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('gmoStrain', EntityType::class, array(
'class' => 'AppBundle\Entity\Strain',
'choice_label' => 'systematicName',
'placeholder' => '-- select a parent --',
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('strain')
->orderBy('strain.systematicName', 'ASC');
}
))
;
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Strain'
));
}
When I send the form, symfony return this error:
Neither the property "strain" nor one of the methods "getStrain()", "strain()", "isStrain()", "hasStrain()", "__get()" exist and have public access in class "AppBundle\Entity\Strain".
If someone have an idea :/ Because I don't know how to do it.
EDIT:
The problem is in the FormType, because I need a Collection of EntityType, I've do 2 FormType, but I can do it in on FormType and use entry_options to define config of EntityType, like this:
class StrainType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('parents', CollectionType::class, array(
'entry_type' => EntityType::class,
'entry_options' => array(
'class' => 'AppBundle\Entity\Strain',
'choice_label' => 'systematicName',
'placeholder' => '-- select a parent --',
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('strain')
->orderBy('strain.systematicName', 'ASC');
}
),
'by_reference' => false,
'allow_add' => true,
'allow_delete' => true,
'required' => false,
))
;
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Strain'
));
}

Get parent object within child formType event

I've created two form types as below
EmailOptInType.php
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->addEventListener(FormEvents::SUBMIT, function (FormEvent $event) {
$_1 = $event->getData();
$_2 = $event->getForm()->getData();
$_3 = $event->getForm()->getParent()->getData();
$form = $event->getForm();
});
}
/**
* #return string
*/
public function getParent()
{
return 'checkbox';
}
And SubscribeType.php
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('email', 'text', array(
'label' => 'Sign up to news',
'required' => true,
'attr' => array(
'placeholder' => 'Enter your email to subscribe',
),
))
->add('email_opt_in', 'newsletter_opt_in', array(
'data' => true
));
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
parent::configureOptions($resolver);
$resolver->setDefaults(array(
'data_class' => 'Bundle\Entity\Customer',
));
}
As you can see the subscribeType form includes the opt in form. Is it possible to fetch the parent forms data within the event listener of the child form EmailOptInType?
In the snippet above $_1 returns a boolean value of true which represents the checked checkbox, $_2 returns the same and $_3 returns an empty customer object.
Is it possible to get the customer object that has just been created / submitted?
You can pass the customer object an a form option when building the form (eg. in the controller):
$customer = $myRepository->find($customerID);
$form = $this->createForm(SubscribeType::class, $customer, ['customer' => $customer]);
The new SubscribeType.php:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('email', 'text', array(
'label' => 'Sign up to news',
'required' => true,
'attr' => array(
'placeholder' => 'Enter your email to subscribe',
),
'customer' => $options['customer']
))
->add('email_opt_in', 'newsletter_opt_in', array(
'data' => true
));
}
public function configureOptions(OptionsResolver $resolver)
{
parent::configureOptions($resolver);
$resolver->setDefaults(array(
'data_class' => 'Bundle\Entity\Customer',
'customer' => null
));
}
And the new EmailOptInType.php:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$customer = $options['customer'];
$builder
->addEventListener(FormEvents::SUBMIT, function (FormEvent $event) use ($customer) {
//do thing with $customer
$_1 = $event->getData();
$_2 = $event->getForm()->getData();
$_3 = $event->getForm()->getParent()->getData();
$form = $event->getForm();
});
}
public function configureOptions(OptionsResolver $resolver)
{
parent::configureOptions($resolver);
$resolver->setDefaults(array(
//[...]
'customer' => null
));
}

$event->getData() returns null for an embedded form

I'm using symfony 2.3. I have a form "AddressType" with an event listener that works as expected when instantiated alone. But when I embeded AddressType into BusinessType, the address form is not displaying. I don't understand what is happening exacltly and how can I fix it.
BusinessType
class BusinessType extends AbstractType {
private $em;
public function __construct($em) {
$this->em = $em;
}
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options) {
// cela suppose que le gestionnaire d'entité a été passé en option
$entityManager = $options['em'];
$transformer = new EmailToUserTransformer($entityManager);
$ActivityTransformer = new ActivityToStringTransformer($entityManager);
$builder
->add('name')
->add('description')
->add('file')
->add('file2')
->add('email')
->add('fb')
->add('twitter')
->add('googlePlus')
->add('linkedin')
->add('tel')
->add('mobile')
->add('fax')
->add('web')
->add('address', new AddressType($this->em))
->add(
$builder->create('user', 'text')
->addModelTransformer($transformer)
)
->add('activity', null, array(
'empty_value' => 'Sélectionner une activité',
))
->add(
$builder->create('secondary', 'entity', array(
'empty_value' => 'Sélectionner une activité secondaire',
'class' => 'BiginfoAdminBundle:Activity',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('a');
},
))
->addModelTransformer($ActivityTransformer)
)
->add('enabled')
->add('medias', 'collection', array(
'type' => new $options['media_form'],
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false))
->add('opens', 'collection', array(
'type' => new $options['open_form'],
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false))
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver) {
$resolver->setDefaults(array(
'data_class' => 'Biginfo\AdminBundle\Entity\Business',
));
$resolver->setDefaults(array(
'data_class' => 'Biginfo\AdminBundle\Entity\Business',
'open_form' => 'Biginfo\AdminBundle\Form\OpenType',
'media_form' => 'Biginfo\AdminBundle\Form\MediaType',
'cascade_validation' => true
));
$resolver->setRequired(array(
'em',
));
$resolver->setAllowedTypes(array(
'em' => 'Doctrine\Common\Persistence\ObjectManager',
));
}
/**
* #return string
*/
public function getName() {
return 'biginfo_adminbundle_business';
}
}
AddressType
class AddressType extends AbstractType {
private $em;
public function __construct($em) {
$this->em = $em;
}
public function buildForm(FormBuilderInterface $builder, array $options) {
$propertyPathToPostalCode = 'postalCode';
$builder
->add('street', 'text', array(
'label' => 'Adresse'
))
;
$builder
->addEventSubscriber(new AddGouvernauratFieldSubscriber($propertyPathToPostalCode, $this->em))
->addEventSubscriber(new AddDelegationFieldSubscriber($propertyPathToPostalCode, $this->em))
->addEventSubscriber(new AddSectorFieldSubscriber($propertyPathToPostalCode, $this->em))
->addEventSubscriber(new AddPostalCodeFieldSubscriber($propertyPathToPostalCode, $this->em))
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver) {
$resolver->setDefaults(array(
'data_class' => 'Biginfo\AdminBundle\Entity\Address',
));
}
public function getName() {
return 'address';
}
}
AddDelegationFieldSubscriber
class AddDelegationFieldSubscriber implements EventSubscriberInterface {
private $propertyPathToCity;
private $em;
public function __construct($propertyPathToCity, $em) {
$this->propertyPathToCity = $propertyPathToCity;
$this->em = $em;
}
public static function getSubscribedEvents() {
return array(
FormEvents::PRE_SET_DATA => 'preSetData',
FormEvents::PRE_SUBMIT => 'preSubmit'
);
}
private function addDelegationForm($form, $gouvernaurat_id, $delegation = null) {
$formOptions = array(
'class' => 'BiginfoAdminBundle:Delegation',
'empty_value' => 'Sélectionner une délégation',
'label' => 'Délégation',
'mapped' => false,
'attr' => array(
'class' => 'delegation_selector',
),
'query_builder' => function (EntityRepository $repository) use ($gouvernaurat_id) {
$qb = $repository->createQueryBuilder('delegation')
->innerJoin('delegation.gouvernaurat', 'gouvernaurat')
->where('gouvernaurat.id = :gouvernaurat')
->setParameter('gouvernaurat', $gouvernaurat_id)
;
return $qb;
}
);
if ($delegation) {
$formOptions['data'] = $delegation;
}
$form->add('delegation', 'entity', $formOptions);
}
public function preSetData(FormEvent $event) {
$data = $event->getData();
$form = $event->getForm();
if (null === $data) {
return;
}
/**
* Le composant PropertyAccess fournit des fonctions pour lire
* et écrire depuis/dans un objet ou un tableau en une simple chaîne de caractères.
*/
$accessor = PropertyAccess::getPropertyAccessor();
$sector1 = $accessor->getValue($data, 'sector');
$sector = $this->em->getRepository('BiginfoAdminBundle:Sector')
->findOneBy(array('name' => $sector1));
$delegation = ($sector) ? $sector->getDelegation() : null;
$gouvernaurat_id = ($delegation) ? $delegation->getGouvernaurat()->getId() : null;
$this->addDelegationForm($form, $gouvernaurat_id, $delegation);
}
public function preSubmit(FormEvent $event) {
$data = $event->getData();
$form = $event->getForm();
$gouvernaurat_id = array_key_exists('gouvernaurat', $data) ? $data['gouvernaurat'] : null;
$this->addDelegationForm($form, $gouvernaurat_id);
}
}
I had the same problem but referring to this issue #5694 you have to set 'prototype' => false in parent form.

Resources