Symfony Form Entity - php

I have entity User and field city and country ManyToOne and if user enter for profile I create form - PersonalInformation and dont know how to bring the country to the city and then the user would drop down list.Now I have error and dont now how to solved:
Notice: Object of class Proxies\__CG__\PillsBundle\Entity\Country could not be converted to int
Entity
/**
* #ORM\Entity
* #ORM\Table(name="fos_user")
*/
class User extends BaseUser
{
/**
* #var \PillsBundle\Entity\Cities
*
* #ORM\ManyToOne(targetEntity="\PillsBundle\Entity\Cities")
* #ORM\JoinColumn(name="city_id", referencedColumnName="id", nullable=true)
*/
private $city;
/**
* #var \PillsBundle\Entity\Country
*
* #ORM\ManyToOne(targetEntity="\PillsBundle\Entity\Country")
* #ORM\JoinColumn(name="country_id", referencedColumnName="id", nullable=true)
*/
private $country;
and City&Country
class Cities
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="city", type="string", length=255)
*/
private $city;
class Country
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="country", type="string", length=255)
*/
private $country;
I create form
class CityType extends AbstractType
{
private $em;
public function setEntityManager(EntityManager $em)
{
$this->em = $em;
}
public function getCity()
{
$citiess = $this->em->getRepository('PillsBundle:Cities')->findAll();
$new_cities = array();
foreach($citiess as $citie) {
$new_cities[$citie->getCity()] = $citie->getCity();
}
asort($new_cities);
return $new_cities;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'choices' => $this->getCity(),
'multiple' => false,
'required' => false,
));
}
public function getParent()
{
return 'choice';
}
public function getName()
{
return 'cities';
}
}
and country
class CountryType extends AbstractType
{
private $em;
public function setEntityManager(EntityManager $em)
{
$this->em = $em;
}
public function getCountry()
{
$countrys = $this->em->getRepository('PillsBundle:Country')->findAll();
$new_country = array();
foreach($countrys as $country) {
$new_country[$country->getCountry()] = $country->getCountry();
}
asort($new_country);
return $countrys;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'choices' => $this->getCountry(),
'multiple' => false,
'required' => false,
));
}
public function getParent()
{
return 'choice';
}
public function getName()
{
return 'country';
}
}
and use this type in form
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('firstname', null, array('label' => 'First Name', 'max_length' => 255, 'required' => false))
->add('lastname', null, array('label' => 'Last Name', 'max_length' => 255, 'required' => false))
->add('email', null, array('label' => 'Email', 'max_length' => 255, 'required' => false))
->add('city', 'cities', array('label' => 'Location','required' => false, 'mapped' => true, 'attr' => array('placeholder' => 'Select Location') ))
->add('country', 'country', array('label' => 'Country','required' => false, 'mapped' => true, 'attr' => array('placeholder' => 'Select Country') ))
->add('skype', null, array('label' => 'Skype', 'max_length' => 255, 'required' => false))
->add('telephone', null, array('label' => 'Phone', 'max_length' => 255, 'required' => false, 'attr' => array('data-inputmask' => "'alias': 'date'")))
->add('save', 'submit');
}
and template:
<div class="form-group">
{{ form_label(infoForm.country, label|default(null), {'label_attr': {'class': 'control-label'}}) }}
{{ form_widget(infoForm.country, {'attr': {'class': 'form-control select2 select2_sample4'}}) }}
</div>
<div class="form-group">
{{ form_widget(infoForm.city, {'attr': {'class': 'form-control input-xlarge select2me'}}) }}
</div>
and action:
$formType = new DeveloperPersonalInformationType();
$form = $this->createForm($formType, $developer);
$personalInformationForm = $form->createView();

the second parameter from the add() function must be a formfield-type e.g. text or textarea (see full details). I think you want to use the type 'entity'.
$builder
->add('country', 'entity', , array(
'class' => 'PillsBundle:Country',
'choice_label' => 'Select Country',
));
If the Country entity object does not have a __toString() method the choice_label option is needed.

Related

Symfony Doctrine ArrayCollection error

My current setup is as described below. What i want to achive is. One Distributor can have multiple categories. But One category can have 1 Distributor 1:N <=> N:1. But it fails when i click create category even if the distributor input field is empty.
Category
/**
* #var string
*
* #ORM\Id()
* #ORM\Column(type="string", nullable=false, unique=true)
* #ORM\GeneratedValue(strategy="UUID")
*/
private $id;
/**
* #var string
* #ORM\Column(type="string", nullable=false)
*/
private $title;
/**
* #var Distributor
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Distributor", inversedBy="category")
* #ORM\JoinColumn(referencedColumnName="id")
*/
private $distributor;
Distributor:
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="string", length=100)
*/
private $name;
/**
* #var ArrayCollection
* #ORM\OneToMany(targetEntity="AppBundle\Entity\Category", mappedBy="distributor")
*/
private $category;
public function __construct()
{
$this->category = new ArrayCollection();
}
CategoryForm:
$builder
->add('parent', EntityType::class, [
'class' => Category::class,
'choice_label' => 'title',
'multiple' => true,
'required' => false,
'attr' => [
'class' => 'select2 form-control select2insidemodal js-example-matcher'
]
])
->add('title', TextType::class, [
'label' => 'Title',
'required' => true,
'by_reference' => true
])
->add('distributor', EntityType::class, [
'class' => Distributor::class,
'choice_label' => 'name',
'required' => false,
'attr' => [
'class' => 'select2 form-control select2insidemodal js-example-matcher'
]
]);
Create Category Action
public function createAction(Request $request)
{
$category = new Category();
$categoryForm = $this->createForm(CategoryForm::class, $category);
$categoryForm->handleRequest($request);
if ($categoryForm->isSubmitted() && $categoryForm->isValid()) {
$result = $this->categoryService->create($category);
}
return $this->render(
'#app_bar/Category/categoryNew.twig',
[
'form' => $categoryForm->createView(),
]
);
}
The error message I get :
Expected argument of type "AppBundle\Entity\Category",
"Doctrine\Common\Collections\ArrayCollection" given
As i understood , parent is not a collection, so change the form parent multiple option to false:
->add('parent', EntityType::class, [
'class' => Category::class,
'choice_label' => 'title',
'multiple' => false,
'required' => false,
'attr' => [
'class' => 'select2 form-control select2insidemodal js-example-matcher'
]
])

Symony 3 Dynamic Forms and Doctrine

still strugling with a Symfony3 and Doctrine. Just trying to make simply autofilling form from database. I got 2 tables - countries and states.
countries.php
namespace AppBundle\Entity\Forms;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
/**
* #ORM\Entity
* #ORM\Table(name="countries")
*/
class Countries
{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string")
*/
private $country_code;
/**
* #ORM\Column(type="string")
*/
private $country_name;
public function __toString()
{
return $this->country_name;
}
/**
* #var Collection|States[]
*
* #ORM\OneToMany(targetEntity="AppBundle\Entity\Forms\States", mappedBy="country_code")
*/
protected $states;
public function __constructor()
{
$this->states = new ArrayCollection();
}
/**
* #return mixed
*/
public function getId()
{
return $this->id;
}
/**
* #return mixed
*/
public function getCountryCode()
{
return $this->country_code;
}
/**
* #param mixed $country_code
*/
public function setCountryCode($country_code)
{
$this->country_code = $country_code;
}
/**
* #return mixed
*/
public function getCountryName()
{
return $this->country_name;
}
/**
* #param mixed $country_name
*/
public function setCountryName($country_name)
{
$this->country_name = $country_name;
}
/**
* #return States[]|Collection
*/
public function getStates()
{
return $this->states;
}
/**
* #param States[]|Collection $states
* #return $this
*/
public function setStates($states)
{
$this->states = $states;
}
states.php
/**
* Created by PhpStorm.
* User: Alvydas Budrys
* Website: http://alvy.lt
* Date: 2017-02-07
* Time: 6:13 AM
*/
namespace AppBundle\Entity\Forms;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="states")
*/
class States
{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string")
*/
private $name;
/**
*
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Forms\Countries", inversedBy="states")
* #ORM\JoinColumn(name="country_code", referencedColumnName="id", onDelete="CASCADE")
*/
private $country_code;
public function __toString()
{
return $this->name;
}
/**
* #return mixed
*/
public function getId()
{
return $this->id;
}
/**
* #return mixed
*/
public function getName()
{
return $this->name;
}
/**
* #param mixed $name
*/
public function setName($name)
{
$this->name = $name;
}
/**
* #return mixed
*/
public function getCountryCode()
{
return $this->country_code;
}
/**
* #param mixed $country_code
*/
public function setCountryCode($country_code)
{
$this->country_code = $country_code;
}
Also formfile:
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormInterface;
use AppBundle\Entity\Forms\States;
class UserType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', TextType::class,
array('label' => false,
'mapped'=>false,
'attr' => array(
'placeholder' => 'FirstName'
)))
->add('lastname', TextType::class,
array('label' => false,
'mapped'=>false,
'attr' => array(
'placeholder' => 'Lastname'
)))
->add('email', EmailType::class,
array('label' => false,
'mapped'=>false,
'attr' => array(
'placeholder' => 'Email'
)))
->add('plainPassword', RepeatedType::class, [
'type' => PasswordType::class,
'mapped'=>false,
'first_options' => ['label' => false,'mapped'=>false,'attr' => array(
'placeholder' => 'Password'
) ],
'second_options' => ['label' => false,'mapped'=>false, 'attr' => array(
'placeholder' => 'Confirm Password'
) ],
])
->add('accType',ChoiceType::class,
array(
'choices' => array(
'Personal' => '1',
'Business' => '2',),
'choices_as_values' => true,
'multiple'=>false,
'expanded'=>true,
'required' =>true,
'data' => true,
'mapped'=>false,
))
->add('city', TextType::class,
array('label' => false,
'mapped'=>false,
'attr' => array(
'placeholder' => 'City'
)))
->add('postcode', TextType::class,
array('label' => false,
'mapped'=>false,
'attr' => array(
'placeholder' => 'Postcode'
)))
->add('CountryName', EntityType::class, array(
'class' => 'AppBundle\Entity\Forms\Countries',
'label' => false,
//'mapped'=>false,
'choice_translation_domain' => true,
))
->add('companyName', TextType::class,
array('label' => false,
'mapped'=>false,
'attr' => array(
'placeholder' => 'Company Name'
)))
->add('companyNumber', TextType::class,
array('label' => false,
'mapped'=>false,
'attr' => array(
'placeholder' => 'Company Number'
)))
->add('companyVat', TextType::class,
array('label' => false,
'mapped'=>false,
'attr' => array(
'placeholder' => 'VAT'
)))
;
$formModifier = function (FormInterface $form, States $states = null) {
$positions = null === $states ? array() : $states->getStates();
$form->add('states', EntityType::class, array(
'class' => 'AppBundle\Entity\Forms\States',
'placeholder' => '',
'choices' => $positions,
));
};
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formModifier) {
// this would be your entity, i.e. SportMeetup
$data = $event->getData();
$formModifier($event->getForm(), $data->getCountryName());
}
);
$builder->get('CountryName')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($formModifier) {
// It's important here to fetch $event->getForm()->getData(), as
// $event->getData() will get you the client data (that is, the ID)
$countries = $event->getForm()->getData();
// since we've added the listener to the child, we'll have to pass on
// the parent to the callback functions!
$formModifier($event->getForm()->getParent(), $countries);
}
);
}
}
but stil getting errors:
Type error: Argument 2 passed to AppBundle\Form\UserType::AppBundle\Form\{closure}() must be an instance of AppBundle\Entity\Forms\States, instance of AppBundle\Entity\Forms\Countries given, called in /var/www/hostera.dev/public_html/src/AppBundle/Form/UserType.php on line 139
Uncaught PHP Exception Symfony\Component\Debug\Exception\FatalThrowableError: "Type error: Argument 2 passed to AppBundle\Form\UserType::AppBundle\Form\{closure}() must be an instance of AppBundle\Entity\Forms\States, instance of AppBundle\Entity\Forms\Countries given, called in /var/www/hostera.dev/public_html/src/AppBundle/Form/UserType.php on line 139" at /var/www/hostera.dev/public_html/src/AppBundle/Form/UserType.php line 111
I think something bad with Doctrine Association, but I can't figure out what.

Doctrine OneToOne Bi- and Unidirectional with ZF2 Fieldsets not saving/hydrating

I have 2 Doctrine entities (Environment and EnvironmentConfig). They have a bi-directional OneToOne relationship.
Each entity has their own Fieldset so that re-use is easy.
To create an Environment it can also have an EnvironmentConfig, however not required. To allow them to be made at the same time I have an EnvironmentForm that uses the EnvironmentFieldset and the EnvironmentConfigFieldset.
The Form renders properly. However, it saves the Environment but not the EnvironmentConfig.
Where is it that I've gone wrong in setting this up and how to fix it?
Code below, leaving out getters/setters, would be too much.
Entities
// abstract class AbstractEntity has $id + getters/setters.
class Environment extends AbstractEntity
{
/**
* #var string
* #ORM\Column(name="name", type="string", length=255, nullable=false)
*/
protected $name;
/**
* #var EnvironmentConfig
* #ORM\OneToOne(targetEntity="Environment\Entity\EnvironmentConfig", inversedBy="environment")
*/
protected $config;
/**
* #var EnvironmentScript
* #ORM\OneToOne(targetEntity="EnvironmentScript")
*/
protected $script;
//Getters/setters
}
class EnvironmentConfig extends AbstractEntity
{
/**
* #var string
* #ORM\Column(name="name", type="string", length=255, nullable=false)
*/
protected $name;
/**
* #var Environment
* #ORM\OneToOne(targetEntity="Environment\Entity\Environment", mappedBy="config")
*/
protected $environment;
//Getters/setters
}
Fieldsets
class EnvironmentFieldset extends AbstractFieldset
{
/**
* {#inheritdoc}
*/
public function init()
{
//Loads id element validation
parent::init();
$this->add([
'name' => 'name',
'type' => Text::class,
'options' => [
'label' => _('Name'),
'label_attributes' => [
'class' => 'col-xs-2 col-form-label',
],
],
'attributes' => [
'id' => 'name',
'class' => 'form-control'
],
]);
$this->add([
'name' => 'environment_config',
'type' => EnvironmentConfigFieldset::class,
'options' => [
'use_as_base_fieldset' => false,
],
]);
$this->add([
'type' => ObjectSelect::class,
'name' => 'environment_script',
'options' => [
'object_manager' => $this->getEntityManager(),
'target_class' => EnvironmentScript::class,
'property' => 'id',
'display_empty_item' => true,
'empty_item_label' => '---',
'label_generator' => function ($targetEntity) {
return $targetEntity->getId() . ' - ' . $targetEntity->getName();
},
],
]);
}
}
class EnvironmentConfigFieldset extends AbstractFieldset
{
/**
* {#inheritdoc}
*/
public function init()
{
//Loads id element validation
parent::init();
$this->add([
'name' => 'name',
'type' => Text::class,
'options' => [
'label' => _('Name'),
'label_attributes' => [
'class' => 'col-xs-2 col-form-label',
],
],
'attributes' => [
'id' => 'name',
'class' => 'form-control'
],
]);
}
}
Form
class EnvironmentForm extends AbstractForm
{
/**
* EnvironmentForm constructor.
* #param null $name
* #param array $options
*/
public function __construct($name = null, array $options)
{
//Also adds CSRF
parent::__construct($name, $options);
}
/**
* {#inheritdoc}
*/
public function init()
{
//Call parent initializer. Adds submit button.
parent::init();
$this->add([
'name' => 'environment',
'type' => EnvironmentFieldset::class,
'options' => [
'use_as_base_fieldset' => true,
],
]);
}
}
Edit: added debug data and AddAction()
Above debugging done on the persist() line in the function below.
public function addAction($formName, array $formOptions = null, $route, array $routeParams = [])
{
if (!$this->formElementManager instanceof FormElementManagerV2Polyfill) {
throw new InvalidArgumentException('Dependency FormElementManagerV2Polyfill not set. Please check Factory for this function.');
}
if (!class_exists($formName)) {
throw new ClassNotFoundException('Given class could not be found. Does it exist?');
}
/** #var AbstractForm $form */
$form = $this->getFormElementManager()->get($formName, (is_null($formOptions) ? [] : $formOptions));
/** #var Request $request */
$request = $this->getRequest();
if ($request->isPost()) {
$form->setData($request->getPost());
if ($form->isValid()) {
$entity = $form->getObject();
$this->getEntityService()->getEntityManager()->persist($entity);
$this->getEntityService()->getEntityManager()->flush();
$this->flashMessenger()->addSuccessMessage(
_('Successfully created object.')
);
$this->redirectToRoute($route, $this->getRouteParams($entity, $routeParams));
}
}
return [
'form' => $form,
'validationMessages' => $form->getMessages() ?: '',
];
}
You created a field called 'environment_config' but in class Environment you called protected $config;. Both names must be the same. Same problem for 'environment_script' field and $script attribute.
Another thing, you want to create a EnvironmentConfig dynamically so you must add in $config annotation a cascade option to be able to create a $config from Environment:
/**
* #var EnvironmentConfig
* #ORM\OneToOne(targetEntity="Environment\Entity\EnvironmentConfig", inversedBy="environment", cascade={"persist"})
*/
protected $config;

Symfony3 persisting generated entities

I'm working on a project saving IP Addresses and IP Ranges. Currently, my Range entity has references to two IP Address entities (the network and broadcast entities) and has a OneToMany relationship to the hosts. The IP Address entity has a ManyToOne relationship to the IP Range, that is optional.
Here is my IP Address entity:
class IPAddress {
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
// relations to other tables
/**
* #var IPRange
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\IPRange", inversedBy="hosts", cascade={"persist", "remove"})
* #ORM\JoinColumn(name="ip_range_id", referencedColumnName="id", nullable=true)
*/
private $ipRangeId;
// entity variables
/**
* #var mixed
* #ORM\Column(name="ip_address", type="binary", length=16, nullable=false, unique=true)
* #SIAssert\IpPacked(version="all")
*/
private $ipAddress;
/**
* #var string
* #ORM\Column(name="ip_address_text", type="string", length=50, nullable=false)
*/
private $ipAddressText;
/**
* #var int
* #ORM\Column(name="cidr", type="smallint", nullable=false, options={"unsigned"=true})
*/
private $cidr;
/**
* #var mixed
* #ORM\Column(name="gateway", type="binary", length=16, nullable=false)
*/
private $gateway;
/**
* #var string
* #ORM\Column(name="gateway_text", type="string", length=50, nullable=false)
*/
private $gatewayText;
/**
* #var int
* #ORM\Column(name="type", type="smallint", options={"unsigned"=true})
*/
private $type;
/**
* #var string
* #ORM\Column(name="description", type="string", length=50)
*/
private $description;
// getters and setters not shown
}
And my IP Range entity:
class IPRange {
/**
* #var int
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
// relations to other tables
/**
* #var IPAddress
* #ORM\OneToOne(targetEntity="AppBundle\Entity\IPAddress", cascade={"persist", "remove"}, orphanRemoval=true)
* #ORM\JoinColumn(name="network", referencedColumnName="id", nullable=false)
*/
private $network;
/**
* #var IPAddress
* #ORM\OneToOne(targetEntity="AppBundle\Entity\IPAddress", cascade={"persist", "remove"}, orphanRemoval=true)
* #ORM\JoinColumn(name="broadcast", referencedColumnName="id", nullable=false)
*/
private $broadcast;
/**
* #var array
* #ORM\OneToMany(targetEntity="AppBundle\Entity\IPAddress", mappedBy="ipRangeId")
*/
private $hosts;
// entity variables
/**
* #var string
* #ORM\Column(name="description", type="string", length=50, nullable=false)
*/
private $description;
/**
* #var int
* #ORM\Column(name="cidr", type="smallint", nullable=false, options={"unsigned"=true})
*/
private $cidr;
/**
* #var string
* #ORM\Column(name="notes", type="text", length=65535, nullable=true)
*/
private $notes;
// getters and setters not shown
}
My current flow when I create a new IP Range:
generate new IP Range entity (display form)
get information back from form
generate IP Address entities with a null for the IP Range entity (IP Range not yet persisted, because the network and broadcast IP Address entities are not created)
persist my IP Range entity
get that ID and rewrite all my IP Address entities with the a valid IP Range entity
I must be missing something, because it seems like a lot of steps to programmatically create entities.
Is there a better and more efficient way of doing this?
Edited ... added my form types ...
My IPRangeType:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('description', TextType::class, array(
'required' => true,
'label' => 'Description:',
'label_attr' => array(
'class' => 'text-right middle',
),
))
->add('notes', TextareaType::class, array(
'required' => false,
'label' => 'Notes:',
'label_attr' => array(
'class' => 'text-right middle',
),
))
->add('cidr', ChoiceType::class, array(
'required' => true,
'multiple' => false,
'expanded' => false,
'choices' => array (
'IPv4' => [
'/30 (255.255.255.252)' => 30,
'/29 (255.255.255.248)' => 29,
'/28 (255.255.255.240)' => 28,
'/27 (255.255.255.224)' => 27,
'/26 (255.255.255.192)' => 26,
'/25 (255.255.255.128)' => 25,
'/24 (255.255.255.0)' => 24,
'/23 (255.255.254.0)' => 23,
'/22 (255.255.252.0)' => 22,
'/21 (255.255.248.0)' => 21,
'/20 (255.255.240.0)' => 20,
],
'IPv6' => [
'/64 network' => 64,
]
),
'label' => 'CIDR (subnet):',
'label_attr' => array(
'class' => 'text-right middle',
),
))
->add('network', IPAddressType::class, array(
'required' => true,
))
->add('gateway_select', ChoiceType::class, array(
'mapped' => false,
'required' => true,
'multiple' => false,
'expanded' => false,
'choices' => array (
'- enter in valid IP and CIDR -' => 0,
),
'label' => 'Gateway:',
'label_attr' => array(
'class' => 'text-right middle',
),
))
->add('json_data', HiddenType::class, array(
'mapped' => false,
))
;
}
My IPAddressType:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('ipAddress', TextType::class, array(
'required' => true,
'label' => 'IP Address:',
'label_attr' => array(
'class' => 'text-right middle',
),
))
->add('cidr', ChoiceType::class, array(
'required' => true,
'multiple' => false,
'expanded' => false,
'choices' => array (
'IPv4' => [
'/30 (255.255.255.252)' => 30,
'/29 (255.255.255.248)' => 29,
'/28 (255.255.255.240)' => 28,
'/27 (255.255.255.224)' => 27,
'/26 (255.255.255.192)' => 26,
'/25 (255.255.255.128)' => 25,
'/24 (255.255.255.0)' => 24,
'/23 (255.255.254.0)' => 23,
'/22 (255.255.252.0)' => 22,
'/21 (255.255.248.0)' => 21,
'/20 (255.255.240.0)' => 20,
],
'IPv6' => [
'/64 network' => 64,
]
),
'label' => 'CIDR (subnet):',
'label_attr' => array(
'class' => 'text-right middle',
),
))
->add('gateway', TextType::class, array(
'required' => true,
'label' => 'Gateway:',
'label_attr' => array(
'class' => 'text-right middle',
),
))
->add('type', ChoiceType::class, array(
'required' => true,
'multiple' => false,
'expanded' => false,
'choices' => IPAddress::TYPE,
'label' => 'Address Type:',
'label_attr' => array(
'class' => 'text-right middle',
),
))
->add('description', TextType::class, array(
'required' => true,
'label' => 'Description:',
'label_attr' => array(
'class' => 'text-right middle',
),
))
;
$builder->get('ipAddress')
->addModelTransformer(new IPToStringTransformer());
$builder->get('gateway')
->addModelTransformer(new IPToStringTransformer());
}
Sounds very roundabout. I'll loosely detail for you what I would do as a general approach.
I would create two form types, call one IpAddressType and the other IpRangeType. Because you're sharing purposes in IpAddress you should only need one type, it's all the same data.
So your form type will look something like:
(this is symfony 2.3 syntax - there will be some differences if you have a newer version - but the approach is the same)
class IpRangeType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('description');
$builder->add('cidr'); // and other single fields
$builder->add('network', new IpAddressType());
$builder->add('broadcast', new IpAddressType());
$builder->add('hosts', 'collection', ['type' => new IpAddressType()]);
}
public function getName()
{
return 'ip_range';
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'YourBundle\Entity\IpRange',
));
}
}
Sub form type.
class IpAddressType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('ipAddress');
$builder->add('ipAddressText'); // etc etc
}
public function getName()
{
return 'ip_address';
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'YourBundle\Entity\IpAddress',
));
}
}
Then in your controller:
$ipRange = new IpRange();
$em = $this->getDoctrine()->getManager();
$form = $this->createForm(new IpRangeType(), $ipRange);
$form->handleRequest($request);
if ($form->isValid()) {
$em->persist($ipRange);
$em->flush();
return $this->redirect($this->generateUrl('your_success_route'));
}
It should be that simple.
Note: you will need to set at least cascade=persist on IpRange $hosts property, otherwise it won't persist IpAddress items added to the collection.
Because of cascade persist on IpRange network, broadcast and hosts properties you don't need to persist individual items, the ipAddress entities will automatically be associated with the parent entity.
You will need to follow this approach for adding your host entries:
http://symfony.com/doc/current/form/form_collections.html
Also please have a look at the forms documentation in general, you should never need to 'generate' an entity if a form is done correctly (other than in very special cases).
Correctly implemented the form should return your complete entities with the data added in the form and all you have to do is validate & persist.
Docs for handling form submissions here: http://symfony.com/doc/current/forms.html#handling-form-submissions

Get a non-mapped data from the post's return

I have the segments checkbox in my form and when I submit, these values doesn't appears in post's return. The segment isn't mapped because it's a external value from database.
Users.php (Entity)
/**
* Users
*
* #ORM\Table(name="users", indexes={#ORM\Index(name="fk_users_users_groups1_idx", columns={"users_groups_id"})})
* #ORM\Entity
*/
class Users
{
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=45, nullable=true)
*/
private $name;
/**
* #var string
*
* #ORM\Column(name="email", type="string", length=45, nullable=true)
*/
private $email;
/**
* #var string
*
* #ORM\Column(name="password", type="string", length=32, nullable=true)
*/
private $password;
/**
* #var boolean
*
* #ORM\Column(name="active", type="boolean", nullable=true)
*/
private $active;
/**
* #var \DateTime
*
* #ORM\Column(name="created_at", type="datetime", nullable=true)
*/
private $createdAt;
/**
* #var \DateTime
*
* #ORM\Column(name="updated_at", type="datetime", nullable=true)
*/
private $updatedAt;
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var UsersGroups
*
* #ORM\ManyToOne(targetEntity="UsersGroups", cascade={"all"}, fetch="EAGER")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="users_groups_id", referencedColumnName="id")
* })
*/
private $usersGroups;
public function __construct()
{
$this->usersGroups = new ArrayCollection();
}
UsersType.php (Form)
class UsersType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', 'text', array(
'label' => 'Nome',
'attr' => array(
'class' => 'form-control'
)
))
->add('email', 'text', array(
'label' => 'E-mail',
'attr' => array(
'class' => 'form-control'
)
))
->add('password', 'password', array(
'label' => 'Senha',
'attr' => array(
'class' => 'form-control'
)
))
->add('usersGroups', 'entity', array(
'class' => 'Ad\SisBundle\Entity\UsersGroups',
'label' => 'Grupo do usuário',
'attr' => array(
'class' => 'form-control'
)
))
->add('active', 'checkbox', array(
'label' => 'Ativo',
'attr' => array(
'class' => 'form-control'
)
))
->add('segments', 'entity', array(
'class' => 'Ad\SisBundle\Entity\Segments',
'query_builder' => function( EntityRepository $segments ) {
return $segments->createQueryBuilder("s");
},
'multiple' => true,
'mapped' => false,
'expanded' => true,
))
;
}
And this is the post's result
Users {#2011 ▼
-name: "xxx"
-email: "xxx#hotmail.com"
-password: "312321"
-active: true
-createdAt: null
-updatedAt: null
-id: 1
-usersGroups: UsersGroups {#2013 ▶}
}
I've tried this:
$segments = $editForm->get('segments')->getData();
I believe that if the segment information was the object of users, it would be easier to handle the information.
This is the right way to do this? How can I get the segment data?
If the segments are not mapped it won't passed to the entity.
you can either get it from the request in a preSubmit event subscriber(look at
http://symfony.com/doc/current/components/form/form_events.html#event-subscribers)
or , changing mapped to true, and pass it to the entity but leave the field of the entity without the ORM annotation if you don't want it to be persisted.

Categories