There are questions with the same title but they aren't related to POSTing.
If I submit my form using Symfony I can submit with no problem. Problem is when I submit my form using Angular using via POST method I created. It gives me the exception "Notice: Array to string conversion".
I know it has to do with my ManyToMany Relation (owners). If I don't add any owners it works fine. Problem is when I add owners.
Here is my Stack Trace:
Stack Trace:
1. in vendor/symfony/symfony/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php at line 106
2. at ErrorHandler ->handleError ('8', 'Array to string conversion', '/Applications/MAMP/htdocs/uploader/vendor/symfony/symfony/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php', '106', array('v' => array('id' => '2', 'firstName' => 'Albert', 'lastName' => 'Jankowski', 'username' => 'ajankowski', 'password' => '$2y$13$7lXTaq3w45j3P0HEln71T.ItLxxf8ZX28UkNFpYFPULyR2a7pLW1C', 'email' => 'ajankowski#myemail.com', 'enabled' => true, 'salt' => null, 'usernameCanonical' => 'ajankowski', 'availableRoles' => array('ROLE_USER', 'ROLE_ADMIN'), 'emailCanonical' => 'ajankowski#myemail.com', 'plainPassword' => null, 'lastLogin' => null, 'confirmationToken' => null, 'roles' => array('ROLE_USER'), 'accountNonExpired' => true, 'accountNonLocked' => true, 'credentialsNonExpired' => true, 'credentialsExpired' => false, 'expired' => false, 'locked' => false, 'superAdmin' => false, 'user' => false, 'passwordRequestedAt' => null, 'groups' => array(), 'groupNames' => array())))
in vendor/symfony/symfony/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php at line 106
3. at ORMQueryBuilderLoader ->Symfony\Bridge\Doctrine\Form\ChoiceList\{closure} (array('id' => '2', 'firstName' => 'Albert', 'lastName' => 'Jankowski', 'username' => 'ajankowski', 'password' => '$2y$13$7lXTaq3w45j3P0HEln71T.ItLxxf8ZX28UkNFpYFPULyR2a7pLW1C', 'email' => 'ajankowski#myemail.com', 'enabled' => true, 'salt' => null, 'usernameCanonical' => 'ajankowski', 'availableRoles' => array('ROLE_USER', 'ROLE_ADMIN'), 'emailCanonical' => 'ajankowski#myemail.com', 'plainPassword' => null, 'lastLogin' => null, 'confirmationToken' => null, 'roles' => array('ROLE_USER'), 'accountNonExpired' => true, 'accountNonLocked' => true, 'credentialsNonExpired' => true, 'credentialsExpired' => false, 'expired' => false, 'locked' => false, 'superAdmin' => false, 'user' => false, 'passwordRequestedAt' => null, 'groups' => array(), 'groupNames' => array()))
4. at array_filter (array(array('id' => '2', 'firstName' => 'Albert', 'lastName' => 'Jankowski', 'username' => 'ajankowski', 'password' => '$2y$13$7lXTaq3w45j3P0HEln71T.ItLxxf8ZX28UkNFpYFPULyR2a7pLW1C', 'email' => 'ajankowski#myemail.com', 'enabled' => true, 'salt' => null, 'usernameCanonical' => 'ajankowski', 'availableRoles' => array('ROLE_USER', 'ROLE_ADMIN'), 'emailCanonical' => 'ajankowski#myemail.com', 'plainPassword' => null, 'lastLogin' => null, 'confirmationToken' => null, 'roles' => array('ROLE_USER'), 'accountNonExpired' => true, 'accountNonLocked' => true, 'credentialsNonExpired' => true, 'credentialsExpired' => false, 'expired' => false, 'locked' => false, 'superAdmin' => false, 'user' => false, 'passwordRequestedAt' => null, 'groups' => array(), 'groupNames' => array())), object(Closure))
in vendor/symfony/symfony/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php at line 107
My Entity:
/**
* Company
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="AppBundle\Repository\CompanyRepository")
*/
class Company
{
......
......
/**
* #var User
*
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\User")
*/
private $owners;
......
......
}
My Controller:
/**
* #Route("", name="api_company_create")
* #Method("POST")
*
* #param \Symfony\Component\HttpFoundation\Request $request
*
* #return Response $response
*/
public function createAction(Request $request)
{
// Process the form.
$company = new Company();
$form = $this->createForm(new CompanyType(), $company);
$this->processForm($request, $form, TRUE);
if (!$form->isValid()) {
$this->throwApiProblemValidationException($form);
}
$em = $this->getDoctrine()->getManager();
$em->persist($company);
$em->flush();
$response = $this->createApiResponse($company, 201);
$companyUrl = $this->generateUrl(
'api_company_show',
['id' => $company->getId()] );
$response->headers->set('Location', $companyUrl);
return $response;
}
/**
* Process the form.
*
* #param \Symfony\Component\HttpFoundation\Request $request
* #param \Symfony\Component\Form\FormInterface $form
* #param boolean $removeExtraFields
* #param Company $currentCompany
*/
private function processForm(Request $request, FormInterface $form, $removeExtraFields = FALSE, $currentCompany = NULL)
{
$data = json_decode($request->getContent(), true);
$clearMissing = $request->getMethod() != 'PATCH';
$form->submit($data, $clearMissing);
}
/**
* Company
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="AppBundle\Repository\CompanyRepository")
*/
class Company
{
......
......
/**
* #var User
*
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\User")
*/
private $owners;
......
......
}
I tried adding __String() to my Company Entity but that didn't help.
/**
* Transform to string
*
* #return string
*/
public function __toString()
{
return (string) $this->getOwners();
}
I was able to figure this out. It was because Symfony(Doctrine) does not want an entire object back. I created a function in my controller to fix this.
/**
* You may receive an entire object for a relation from your api but when
* saving Doctrine only wants the ids.
*
* For Example your API returns:
* $data['owners'][0] = array('id' => 1, 'name' => 'Admin');
* $data['owners'][1] = array('id' => 2, 'name' => 'User');
*
* But it expects:
*
* $data['owners'][0] = 1;
* $data['owners'][1] = 2;
*
*
* #param array $data
* #param string $name
*/
private function convertRelationToDoctrineSafeArray(&$data, $name)
{
if (isset($data[$name]) && $data[$name]) {
foreach ($data[$name] as $key => $field) {
$fields[$key] = $field['id'];
}
unset($data[$name]);
$data[$name] = $fields;
}
}
Related
I was following the instructions of #crash and I get the value of my parameter passed in my fieldset. But sometimes it returns a null value. Here are my complete code
My RapportEffetForm :
<?php
/**
* #module Commun
* #subpackage Form\Admin
* #author Samuel NANGUI <nanguisamuel#gmail.com>
* #copyright Copyright (c) 2021 Nslabs
*/
namespace Commun\Form\Modules\Application;
use Commun\Form\Modules\Application\Fieldset\RapportEffetFieldset;
use Commun\Form\CommunForm;
class RapportEffetForm extends CommunForm
{
private $parameters;
public function __construct($params)
{
$this->parameters=$params;
parent::__construct('RapportEffetForm',$this->parameters,[]);
}
public function init() {
$myFieldset = $this->getFormFactory()->getFormElementManager()->get(RapportEffetFieldset::class, ['params' => $this->parameters]);
$this->setName('RapportEffetForm');
$this->setAttribute('class', 'form-saisie');
//$this->addFieldset(RapportEffetFieldset::class,['use_as_base_fieldset' => true]);
$this->addFieldsetWithParameters($myFieldset,['use_as_base_fieldset' => true]);
$this->addSubmitButton('next', 'Poursuivre', 'next', 'btn btn-vert w-100');
$this->addSubmitButton('previous', 'Retour', 'previous', 'btn btn-rouge w-100');
}
}
My RapportEffetFormFactory :
<?php
/**
* #module Commun
* #subpackage Form
* #author Samuel NANGUI <nanguisamuel#gmail.com>
* #copyright Copyright (c) 2020 Nslabs
*/
namespace Commun\Factory\Form;
use Interop\Container\ContainerInterface;
use Laminas\ServiceManager\Factory\FactoryInterface;
use Commun\Form\Modules\Application\RapportEffetForm;
class RapportEffetFormFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$params = $options['id'] ?? [];
unset($options['id']);
return new RapportEffetForm($params);
}
}
My RapportEffetFieldset :
<?php
/**
* #module Commun
* #subpackage Form\Admin
* #author Samuel NANGUI <nanguisamuel#gmail.com>
* #copyright Copyright (c) 2020 Nslabs
*/
namespace Commun\Form\Modules\Application\Fieldset;
use Commun\Model\Entity\Supervision;
use Laminas\InputFilter\InputFilterProviderInterface;
use Laminas\Hydrator\ReflectionHydrator;
use Commun\Form\Modules\Application\Fieldset\EffetRapportFieldset;
use Commun\Form\CommunFormFieldset;
class RapportEffetFieldset extends CommunFormFieldset implements InputFilterProviderInterface
{
private $mapper;
private $params;
public function __construct($mappers=[],$params=[], $options = [])
{
$this->mapper = $mappers;
$this->params = $params;
parent::__construct($this->mapper,'RapportEffetForm',$options);
$this->setHydrator(new ReflectionHydrator());
$this->setObject(new Supervision());
$this->setLabel('RapportEffetFieldset');
}
public function init() {
parent::init();
$myFieldset = $this->getFormFactory()->getFormElementManager()->get(EffetRapportFieldset::class, ['params' => $this->params]);
$this->addCollection('effets','', get_class(new $myFieldset()),1,[],'__index__',FALSE,FALSE);
$optionsNotation = $this->mapper['notations']->getOptions('idRefNotation','libelle','Sélectionner',null,['ordre']);
$this->addSelect('notationEffetPresent', 'Notation du présent rapport',$optionsNotation,['class' => 'form-control'],'champ-requis');
$this->addSelect('notationEffetPrecedent', 'Notation du rapport précédent',$optionsNotation,['class' => 'form-control champ-affiche', 'placeholder' => 'Choisir']);
$this->addTextarea('JustifNotationEffet', 'Justification', NULL, ['class' => 'form-control','rows' => 5]);
}
/**
* #return array
*/
public function getInputFilterSpecification()
{
return [
];
}
}
My RapportEffetFieldsetFactory :
<?php
/**
* #module Commun
* #subpackage Form
* #author Samuel NANGUI <nanguisamuel#gmail.com>
* #copyright Copyright (c) 2020 Nslabs
*/
namespace Commun\Factory\Form\Fieldset;
use Interop\Container\ContainerInterface;
use Laminas\ServiceManager\Factory\FactoryInterface;
use Commun\Form\Modules\Application\Fieldset\RapportEffetFieldset;
class RapportEffetFieldsetFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$params = $options['params'] ?? [];
unset($options['params']);
$mappers = ['notations' => $container->get('TREFNOTATION')];
return new RapportEffetFieldset($mappers,$params,$options);
}
}
My EffetRapportFieldset :
<?php
/**
* #module Commun
* #subpackage Form\Admin
* #author Samuel NANGUI <nanguisamuel#gmail.com>
* #copyright Copyright (c) 2020 Nslabs
*/
namespace Commun\Form\Modules\Application\Fieldset;
use Commun\Model\Entity\EffetProjet;
use Laminas\InputFilter\InputFilterProviderInterface;
use Laminas\Hydrator\ReflectionHydrator;
use Laminas\Filter\StripTags;
use Laminas\Filter\StringTrim;
use Commun\Form\CommunFormFieldset;
class EffetRapportFieldset extends CommunFormFieldset implements InputFilterProviderInterface
{
private $mapper;
private $inputFilter;
private $params;
public function __construct($mappers=[],$params=[], $options = [])
{
$this->mapper = $mappers;
$this->params = $params;
parent::__construct($this->mapper,'EffetRapportForm',$options);
$this->setHydrator(new ReflectionHydrator());
$this->setObject(new EffetProjet());
}
public function init() {
parent::init();
var_dump($this->params);
//die;
$idProjet = $this->params['id']; // I retrieve my param here like this. But I get this warning <<Notice: Undefined index: id in EffetRapportFieldset.php on line 45>>
$optionsEffetCadreLogique = $this->mapper['effetProjet']->getOptions('idEffetProjet','libelleEffet','Sélectionner',['idProjet' => $idProjet],['libelleEffet']);
$this->addSelect('idEffetProjet', 'Intitule de l\'effet',$optionsEffetCadreLogique,['class' => 'form-control champ-affiche'],'champ-requis');
$this->addText('valeurReference','Valeur de référence (a)',NULL,['class' => 'form-control champ_decimal champ-affiche'],'champ-requis');
$this->addText('valeurRecente','Valeur la plus récente (b)',NULL,['class' => 'form-control champ_decimal'],'champ-requis');
$this->addText('valeurCible','Cible finale (c)',NULL,['class' => 'form-control champ_decimal champ-calcule'],'champ-requis');
$this->addText('progresRealisation','Progrès vers la réalisation de la cible (% de réalisation) (d=b/c)',NULL,['class' => 'form-control champ_decimal champ-affiche'],'champ-requis');
$this->addTextarea('evaluation', 'Évaluation', NULL, ['class' => 'form-control','rows' => 3]);
}
/**
* #return array
*/
public function getInputFilterSpecification()
{
return [
];
}
}
My EffetRapportFieldsetFactory :
<?php
/**
* #module Commun
* #subpackage Form
* #author Samuel NANGUI <nanguisamuel#gmail.com>
* #copyright Copyright (c) 2020 Nslabs
*/
namespace Commun\Factory\Form\Fieldset;
use Interop\Container\ContainerInterface;
use Laminas\ServiceManager\Factory\FactoryInterface;
use Commun\Form\Modules\Application\Fieldset\EffetRapportFieldset;
class EffetRapportFieldsetFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$params = $options['params'] ?? [];
unset($options['params']);
$mappers = ['effetProjet' => $container->get('TEFFETPROJET')];
return new EffetRapportFieldset($mappers,$params,$options);
}
}
My CommunForm class here :
<?php
/**
* #module Commun
* #subpackage Form
* #author Samuel NANGUI <nanguisamuel#gmail.com>
* #copyright Copyright (c) 2020 Nslabs
*/
namespace Commun\Form;
use Laminas\Form\Form;
use Laminas\Hydrator\ClassMethodsHydrator;
use Laminas\InputFilter\InputFilter;
use Laminas\Form\Element\Select;
use Laminas\Form\Element\Hidden;
class CommunForm extends Form
{
protected $mapper;
public $params;
public function __construct($formName=null,$params=[],$mapper=[]) {
parent::__construct($formName);
$this->mapper = $mapper;
$this->params = $params;
$this->setHydrator(new ClassMethodsHydrator(false));
$this->setInputFilter(new InputFilter());
$this->setAttribute('class', 'form-horizontal');
//$this->setOption('params', $params);
}
public function populateSelect(\Laminas\Form\Element\Select $selectName,$optionValues=[]){
$selectName->setValueOptions($optionValues);
}
public function addFieldset($fieldset,$options=[]){
$this->add([
'type' => $fieldset,
'options' => $options,
]);
}
public function addFieldsetWithParameters($fieldset,$options=[]){
$this->add([
'type' => get_class(new $fieldset()),
'options' => $options,
]);
}
public function addSubmitButton($name,$label,$id='',$className=''){
$this->add([
'name' => $name,
'type' => 'submit',
'attributes' => [
'value' => $label,
'id' => $id,
'class' => $className,
]
]);
}
public function addSelect($name,$label){
$this->add([
'name' => $name,
'type' => Select::class,
'options' => [
'label' => $label,
'value_options' => [
'0' => 'French',
'1' => 'English',
'2' => 'Japanese',
'3' => 'Chinese',
],
],
]);
}
public function addFile($name,$label,$id='',$attributes=[],$labelClass=''){
$this->add([
'name' => $name,
'type' => 'file',
'options' => [
'label' => $label,
'id' => $id,
'label_attributes' => [
'class' => $labelClass
],
],
'attributes' => $attributes,
]);
}
public function addHiddenElement($name,$attributes=[]){
$this->add([
'name' => $name,
'type' => Hidden::class,
'attributes' => $attributes,
]);
}
public function addText($name,$label,$id='',$attributes=[],$labelClass=''){
$this->add([
'name' => $name,
'type' => 'text',
'options' => [
'label' => $label,
'id' => $id,
'label_attributes' => [
'class' => $labelClass
],
],
'attributes' => $attributes,
]);
}
}
and my CommunFieldset :
<?php
/**
* #module Commun
* #subpackage Form
* #author Samuel NANGUI <nanguisamuel#gmail.com>
* #copyright Copyright (c) 2021 Nslabs
*/
namespace Commun\Form;
use Laminas\Form\Element\Select;
use Laminas\Form\Fieldset;
use Laminas\Form\Element\Checkbox;
use Laminas\Form\Element\MultiCheckbox;
use Laminas\Form\Element\Button;
use Laminas\Form\Element\Hidden;
class CommunFormFieldset extends Fieldset
{
/**
* Shortcut for adding an input type text element
* #param string $name name of the item
* #param string $label label of the item
* #param string $id unique HTML id of the item
* #param array $attributes array of attributes to apply to the item
*/
//public $additionnalParams;
private $mapper;
public function __construct($mapper=[],$name=null,$options = []) {
//$this->additionnalParams = $options;
$this->mapper = $mapper;
parent::__construct($name, $options);
}
public function init(){
parent::init();
}
/**
* Shortcut for adding an input type text element
* #param string $name name of the item
* #param string $label label of the item
* #param string $id unique HTML id of the item
* #param array $attributes array of attributes to apply to the item
* #param string $labelClass label class(espacially for required item)
*/
public function addHiddenElement($name,$attributes=[]){
$this->add([
'name' => $name,
'type' => Hidden::class,
'attributes' => $attributes,
]);
}
public function addText($name,$label,$id='',$attributes=[],$labelClass=''){
$this->add([
'name' => $name,
'type' => 'text',
'options' => [
'label' => $label,
'id' => $id,
'label_attributes' => [
'class' => $labelClass
],
],
'attributes' => $attributes,
]);
}
/**
* Shortcut for adding an input type text element
* #param string $name name of the item
* #param string $label label of the item
* #param string $id unique HTML id of the item
* #param array $attributes array of attributes to apply to the item
* #param string $labelClass label class(espacially for required item)
*/
public function addFile($name,$label,$id='',$attributes=[],$labelClass=''){
$this->add([
'name' => $name,
'type' => 'file',
'options' => [
'label' => $label,
'id' => $id,
'label_attributes' => [
'class' => $labelClass
],
],
'attributes' => $attributes,
]);
}
public function addTextarea($name,$label,$id='',$attributes=[],$labelClass=''){
$this->add([
'name' => $name,
'type' => 'textarea',
'options' => [
'label' => $label,
'id' => $id,
'label_attributes' => [
'class' => $labelClass
],
],
'attributes' => $attributes,
]);
}
/**
* Shortcut for adding a select list type element
* #param string $name name of the select item
* #param string $label label of the select item
* #param array $valueOptions array values to populate the Select with
* #param array $attributes array of attributes to apply to the Select item
* #param string $labelClass label class(espacially for required item)
*/
public function addSelect($name,$label,$valueOptions=[],$attributes=[],$labelClass=''){
$this->add([
'name' => $name,
'type' => Select::class,
'options' => [
'label' => $label,
'value_options' => $valueOptions,
'label_attributes' => [
'class' => $labelClass
],
],
'attributes' => $attributes,
]);
}
public function addSelectFromTable($name,$label,$type,$attributes=[],$labelClass=''){
$this->add([
'name' => $name,
'type' => get_class($type) ,
'options' => [
'label' => $label,
'label_attributes' => [
'class' => $labelClass
],
],
//'label_attributes' => ['class' => $labelClass],
'attributes' => $attributes,
]);
}
/**
* Shortcut for adding a select list type element
* #param string $name name of the select item
* #param string $label label of the select item
* #param string $id id of the select item
* #param string $checkedValue value of checked item.
* #param string $unCheckedValue value of unchecked item.
* #param array $attributes attribute array.
* #param string $labelClass label class(espacially for required item)
*/
public function addCheckbox($name,$label,$id='',$checkedValue='',$unCheckedValue='',$attributes=[],$labelClass=''){
$this->setLabelAttributes(['class' => $labelClass]);
$this->add([
'name' => $name,
'type' => Checkbox::class,
'options' => [
'label' => $label,
'id' => $id,
'use_hidden_element' => true,
'checked_value' => $checkedValue,
'unchecked_value' => $unCheckedValue,
'label_attributes' => [
'class' => $labelClass
],
],
'attributes' => $attributes,
]);
}
public function addMultiCheckbox($name,$label,$id='',$valueOptions=[],$attributes=[],$labelClass=''){
$this->add([
'name' => $name,
'type' => MultiCheckbox::class,
'options' => [
'label' => $label,
'id' => $id,
'value_options' => $valueOptions,
'label_attributes' => [
'class' => $labelClass
],
],
'attributes' => $attributes,
]);
}
public function addButton($name,$label,$attributes=[]){
$this->add([
'name' => $name,
'type' => Button::class,
'options' => [
'label' => $label,
],
'attributes' => $attributes,
]);
}
/**
* Shortcut for adding a collection list type element
* #param string $name name of the select item
* #param string $label label of the select item
* #param string $targetElement name of the target fieldset
* #param boolean $isObject indicate if the variable is an instance of a class or just a string
* #param int $count number of visible row
* #param boolean $shouldCreateTemplate indicate if the html markup must be created
* #param boolean $allowAdd indicate if new item can to addeds
*/
private function getStringFromElement($element){
if(gettype($element)==='object'){
return get_class($element);
}elseif(gettype($element)==='string'){
return $element;
}else{
throw new \Exception('This type cannot be used with collection element');
}
}
public function addCollection($name,$label, $targetElement,$count=2,$attributes=[],$templatePlaceholder='__index__',$shouldCreateTemplate=true,$allowAdd=true){
$this->add([
'type' => \Laminas\Form\Element\Collection::class,
'name' => $name,
'options' => [
'label' => $label,
'count' => $count,
'should_create_template' => $shouldCreateTemplate,
'template_placeholder' => $templatePlaceholder,
'allow_add' => $allowAdd,
'target_element' => [
'type' => $this->getStringFromElement($targetElement),
],
],
'attributes' => $attributes,
]);
}
}
When I do a var_dump in my init() function in EffetRapportFielset, I get this
And in the same page I get also this :
I need to say that when I do echo on $this->parameters on my RapportEffetForm I get my correct parameter value.
I do not know why for the first time, the value is good, and the (2nd time ??) is null. Do not know also why this value is shown more than once.
Here are all my infos. Hope it helps you to also help me finding a solution.
Best regards !
My intelligent guess is, that the problem is your CommunForm::addFieldsetWithParameters() method. You're loosing the parameters, since you'r creating the fieldset a second time, without the parameters getting passed again.
Just use Laminas\Form\Form::add() to add the fieldset:
$myFieldset = $this->getFormFactory()
->getFormElementManager()
->get(RapportEffetFieldset::class, ['params' => $this->parameters]);
$this->add($myFieldset);
And you do the same thing within the collection. Just pass the object to the collection there as "target_element":
$myFieldset = $this->getFormFactory()
->getFormElementManager()
->get(EffetRapportFieldset::class, ['params' => $this->params]);
$this->add([
'type' => \Laminas\Form\Element\Collection::class,
'name' => 'effets',
'options' => [
'label' => '',
'count' => 1,
'should_create_template' => false,
'template_placeholder' => '__index__',
'allow_add' => false,
'target_element' => $myFieldset,
],
'attributes' => []
]);
Symfony version 2.8
I have a problem when I try to add new Collection(); in construct function of User Entity.
public function __construct()
{
$this->sectors = new Collection();
parent::__construct();
}
Sector has many to many relationship
/**
* #ORM\ManyToMany(targetEntity="UserBundle\Entity\Sectors", fetch="EAGER")
* #ORM\JoinTable(
* joinColumns={#ORM\JoinColumn(onDelete="CASCADE")},
* inverseJoinColumns={#ORM\JoinColumn(onDelete="CASCADE")}
* )
*/
public $sectors;
and getter/setter methods are
/**
* Add sector
*
* #param UserBundle\Entity\Sectors $sector
*
* #return User
*/
public function addSector(UserBundle\Entity\Sectors $sector)
{
$this->sectors[] = $sector;
return $this;
}
/**
* Remove sector
*
* #param UserBundle\Entity\Sectors $sector
*/
public function removeSector(UserBundle\Entity\Sectors $sector)
{
$this->sectors->removeElement($sector);
}
/**
* Get sectors
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getSectors()
{
return $this->sectors;
}
When in a FormType I do:
$builder
->add('sectors', EntityType::class, array(
'class' => 'UserBundle\Entity\Sectors',
'placeholder' => 'Select Sector ...',
'label' => 'Sector',
'required' => false,
'attr' => ['placeholder' => 'Select Sector ...', 'data-jcf' => '{"wrapNative": false, "wrapNativeOnMobile": false, "useCustomScroll": true, "multipleCompactStyle": true}'],
'multiple' => true,
'expanded' => false,
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('u')
->orderBy('u.name', 'ASC');
},
));
$formModify = function (FormInterface $form, \Doctrine\Common\Collections\ArrayCollection $sector, $factory) {
$output = [];
foreach($sector as $sec) {
$output[] = $sec->id;
}
$formOption = array(
'class' => 'UserBundle\Entity\UserAccreditation',
'multiple' => true,
'auto_initialize' => false,
'required' => false,
'expanded' => true,
'choice_attr' => function ($output) {
return ['class' => 'attr_checkbox'];
},
'query_builder' => function(EntityRepository $ertt) use ($output) {
$qb = $ertt->createQueryBuilder('g');
$qb->select(array('g'));
$qb->where('g.sector IN (:sector_id)');
$qb->setParameters( array('sector_id' => $output) );
$qb->orderBy('g.name', 'ASC');
return $qb;
},
);
$form->add($factory->createNamed('accreditationdata', EntityType::class, null, $formOption));
};
$builder->addEventListener(FormEvents::PRE_SET_DATA,function (FormEvent $event) use ($formModify,$factory) {
$data = $event->getData();
$form = $event->getForm();
if ($data != null) {
//print_r(get_object_vars($data->getSectors()));
$formModify($event->getForm(), $data->getSectors(),$factory);
}
}
);
$factory = $builder->getFormFactory();
$builder->get('sectors')->addEventListener(FormEvents::POST_SUBMIT,function (FormEvent $event) use ($formModify,$factory) {
$sector = $event->getForm()->getData();
//print_r($sector);
$formModify($event->getForm()->getParent(), $sector,$factory);
}
);
I get following error:
Fatal error: Cannot instantiate interface Doctrine\Common\Collections\Collection
Earlier I am using ArrayCollection instead of Collection, I have to do this because I am getting error
Type error: Argument 2 passed to UserBundle\Form\Type\ProfileAboutMeFormType::UserBundle\Form\Type{closure}() must be an instance of Doctrine\Common\Collections\ArrayCollection, instance of Doctrine\ORM\PersistentCollection given,
and by searching on google I found this solution on github link
https://github.com/doctrine/orm/issues/5946
but still I am facing the problem. can anyone tell me What goes wrong here ?
When someone creates a new user on our application, some of his own properties get overwritten by the new users properties. I have no clue yet, where to look for the mistake, since in the controller or entities, nothing was changed.
Here are some information: the user entity (we are using the FOS User Bundle)
class User extends BaseUser{
/**
* #Solr\Id
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #Solr\Field(type="string")
* #Assert\NotBlank()
* #var string
* #ORM\Column(type="string", length=32, nullable=false)
*/
protected $firstName;
/**
* #Solr\Field(type="string")
* #Assert\NotBlank()
* #var string
* #ORM\Column(type="string", length=32, nullable=false)
*/
protected $lastName;
/**
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\Agency", inversedBy="useragencies", cascade={"persist"})
* #ORM\JoinTable(name="user_user_agencies",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="iata8", referencedColumnName="iata8")})
* #var \AppBundle\Entity\Agency
**/
private $agencies;
/**
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\Product", inversedBy="users", cascade={"persist"})
* #ORM\JoinTable(name="user_user_products",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="product_id", referencedColumnName="id")})
* #var \AppBundle\Entity\Product
**/
private $products;
/**
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\Market", inversedBy="users", cascade={"persist"})
* #ORM\JoinTable(name="user_user_markets",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="market_id", referencedColumnName="id")})
* #var \AppBundle\Entity\Market
* #Solr\Field(type="string", getter="getId")
**/
private $markets;
/**
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\Airline", inversedBy="users", cascade={"persist"})
* #ORM\JoinTable(name="user_user_airlines",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="airline_id", referencedColumnName="id")})
* #var \AppBundle\Entity\Airline
* #Solr\Field(type="string", getter="getId")
**/
private $airlines;
...
The properties that get overwritten are products and airlines. There is no prePersist() or preUpdate() function for this entity!
The create controller
class CreateController extends Controller
{
/**
* #Security("has_role('ROLE_USER_INVITER')")
* #Route("/user/create/{employer}", defaults={"employer": 1}
* , requirements={"employer": "\d+"}, name="userBundle_create")
*/
public function createAction($employer, Request $request)
{
$currentUser=$this->container->get('security.token_storage')->getToken()->getUser();
// get employer Object
$em = $this->getDoctrine ()->getManager ();
$repository = $this->getDoctrine()
->getRepository('UserBundle:Employer');
$employerObj = $repository->findOneByIdInContext($employer, $currentUser);
$userManager = $this->get('fos_user.user_manager');
$user = $userManager->createUser();
$url = $this->get('router')->generate('userBundle_create', array(
'employer' => $employerObj->getId()
));
// generate form and handle
$form = $this->createForm(CreateType::class, $user
, array('employer' => $employerObj,
'action' => $url,)
);
$form->handleRequest($request);
if ($form->isValid()) {
$tokenGenerator = $this->container->get('fos_user.util.token_generator');
$user->setConfirmationToken($tokenGenerator->generateToken());
$user->setUsername($user->getEmail());
$user->setEnabled(false);
$user->setApprover($currentUser);
$user->setInviter($currentUser);
$user->addRole($user->getMainRole()->getName());
$userManager->updateUser($user);
if(count($user->getAgencies()) > 0){
$userId = rtrim($user->getId(),"_user");
$query = $em->createQuery("SELECT DISTINCT (a.market) FROM UserBundle\Entity\User u JOIN u.agencies a WHERE u.id = $userId");
$marketIds = $query->getResult();
$em = $this->getDoctrine ()->getManager ();
$repository = $this->getDoctrine()
->getRepository('AppBundle:Market');
$markets = $repository->findOneById($marketIds[0]);
$user->addMarket($markets);
$userManager->updateUser($user);
}
$this->addFlash(
'success',
'The user was created and an activation email was sent!'
);
return $this->redirectToRoute('userBundle_list');
}
return $this->render('UserBundle:User:create.html.twig', array(
'form' => $form->createView(),
'user'=>$user,
));
}
}
Here are more classes that may be useful for helping to point me in the right direction.
CreateType
class CreateType extends AbstractType
{
private $tokenStorage;
public function __construct(TokenStorageInterface $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => User::class,
'employer' => null
));
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$employer = $options['employer'];
$builder
->add('firstName', 'text', array('label' => 'label.firstname',
'translation_domain' => 'User',))
->add('lastName', 'text', array('label' => 'label.lastname',
'translation_domain' => 'User',))
;
$user = $this->tokenStorage->getToken()->getUser();
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($user, $employer){
$form = $event->getForm();
// show iata selection if empoyer is any agency
$employerArr = array(10, 11);
if (in_array($employer->getId(), $employerArr)) {
// only show iata based on user's employer
if($user->hasRoles(array('ROLE_AGENCY_TC_ONLY',
'ROLE_AGENCY_WAIVER_REQUEST_ONLY',
'ROLE_AGENCY_CORE_TEAM',
'ROLE_AGENCY',
'ROLE_AGENCY_MANAGEMENT',
'ROLE_AGENCY_SIGNEE','ROLE_CORPORATION_TRAVEL_MANAGER' ))){
$form
->add('agencies', EntityType::class, array(
'class' => 'AppBundle:Agency',
'query_builder' => function (EntityRepository $er) use ($user) {
return $er->createQueryBuilder('a')
->addOrderBy('a.id', 'ASC')
->andWhere('a.id IN (:ids)')
->setParameter('ids',$user->getAgencies());
},
'choice_label' => 'agencyName',
// 'data' => $user->getAgencies(),
'label' => 'label.iata',
'empty_value' => "label.select.agency",
'property' => 'id',
'expanded' => false, 'multiple' => true,
'required' => true,
'translation_domain' => 'User',
'choice_translation_domain' => 'User'));
} else {
// only show iata based on user's context
$form
->add('agencies', EntityType::class, array(
'class' => 'AppBundle:Agency',
'query_builder' => function (EntityRepository $er) use ($user) {
return $er->createQueryBuilder('a')
->addOrderBy('a.id', 'ASC')
->andWhere('a.market IN (:markets)')
->setParameter('markets',$user->getMarkets());
},
'choice_label' => 'agencyName',
'label' => 'label.iata',
'empty_value' => "label.select.agency",
'property' => 'id',
'expanded' => false, 'multiple' => true,
'required' => true,
'translation_domain' => 'User',
'choice_translation_domain' => 'User'));
}
// show market only if not agency user
} else {
// only show specific markets based on user's context
$form->add('markets', 'entity', array(
'class' => 'AppBundle:Market', 'property' => 'id',
'query_builder' => function (EntityRepository $er) use ($user) {
$markets = $user->getMarkets();
return $er->createQueryBuilder('m')
->addOrderBy('m.id', 'ASC')
->andWhere('m.id IN (?1)')
->setParameter(1,$markets);
},
// 'choice_value' => 'id',
'choice_label' => 'id', 'label' => 'label.markets',
'translation_domain' => 'User',
'expanded' => false, 'multiple' => true,));
}
// only show specific roles based on user's employer
$form->add('mainRole', 'entity', array(
'class' => 'UserBundle:Role',
'query_builder' => function (EntityRepository $er) use ($employer){
$roles = $employer->getRoles();
return $er->createQueryBuilder('r')
->orderBy('r.sort', 'ASC')
->andWhere('r.id IN (?1)')
->setParameter(1,$roles);
},
'choice_label' => 'translationKey',
'choices_as_values' => true, 'label' => 'label.role',
'expanded' => true, 'multiple' => false,
'translation_domain' => 'User',
'choice_translation_domain' => 'Role',));
// only show specific airlines based on user's context
$form->add('airlines', 'entity', array(
'class' => 'AppBundle:Airline', 'property' => 'id',
'query_builder' => function (EntityRepository $er) use ($user) {
$airlines = $user->getAirlines();
return $er->createQueryBuilder('a')
->addOrderBy('a.id', 'ASC')
->andWhere('a.id IN (?1)')
->setParameter(1,$airlines);
},
'choice_value' => 'id',
'data' => $user->getAirlines(),
'choice_label' => 'id', 'label' => 'label.airlines',
'translation_domain' => 'User',
'expanded' => false, 'multiple' => true,));
// only show specific products based on user's context
$form->add('products', 'entity', array(
'class' => 'AppBundle:Product', 'property' => 'id',
'query_builder' => function (EntityRepository $er) use ($user) {
$products = $user->getProducts();
return $er->createQueryBuilder('p')
->addOrderBy('p.id', 'ASC')
->andWhere('p.id IN (?1)')
->setParameter(1,$products);
},
'choice_value' => 'id',
'data' => $user->getProducts(),
'choice_label' => 'translationKey', 'label' => 'label.products',
'translation_domain' => 'User',
'expanded' => false, 'multiple' => true,
'choice_translation_domain' => 'AppBundle',));
});
}
public function getParent()
{
return 'FOS\UserBundle\Form\Type\RegistrationFormType';
}
public function getBlockPrefix()
{
return 'userBundle_create';
}
}
Your issue is caused by these to lines:
'data' => $user->getAirlines(),
and
'data' => $user->getProducts(),
To change the new user s airlines & products collection, symfony form uses the loggedin users airlines & products collection reference.
Clone the collection when setting it as default, to remove the reference to the logged in user.
'data' => clone $user->getAirlines(),
and
'data' => clone $user->getProducts(),
Hope it helps.
Wrong assumption: Your error is in CreateType class. You use the loggedin user s properties to populate agencies, airlines and products fields of your form:
$user = $this->tokenStorage->getToken()->getUser();
...
'query_builder' => function (EntityRepository $er) use ($user) {
You should instead use the user you edit. Add in your buildForm function:
$userEdited = $builder->getData();
and then change:
'query_builder' => function (EntityRepository $er) use ($userEdited) {
in all places.
Do not forget to change also:
$user->getMarkets()
to
$userEdited->getMarkets()
in your callbacks, same for ailines & products.
I have two entity that have manytomany relation
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Esame
*
* #ORM\Table(name="esame", indexes={#ORM\Index(name="id_tipologia_esame", columns={"id_tipologia_esame"}), #ORM\Index(name="id_analisi", columns={"id_analisi"})})
* #ORM\Entity(repositoryClass="AppBundle\Repository\EsameRepository")
*/
class Esame
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var \AppBundle\Entity\Nome_esame
*
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Nome_esame")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="id_tipologia_esame", referencedColumnName="id")
* })
*/
private $idTipologiaEsame;
/**
* #var \AppBundle\Entity\Analisi
*
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Analisi")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="id_analisi", referencedColumnName="id")
* })
*/
private $idAnalisi;
/**
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\TipologiaCampione", inversedBy="esami")
*/
private $campioni;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set idAnalisi
*
* #param \AppBundle\Entity\Analisi $idAnalisi
*
* #return Esame
*/
public function setIdAnalisi($idAnalisi)
{
$this->idAnalisi = $idAnalisi;
return $this;
}
/**
* Get idAnalisi
*
* #return int
*/
public function getIdAnalisi()
{
return $this->idAnalisi;
}
/**
* Constructor
*/
public function __construct()
{
$this->campioni = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add campioni
*
* #param \AppBundle\Entity\TipologiaCampione $campioni
*
* #return Esame
*/
public function addCampioni(\AppBundle\Entity\TipologiaCampione $campioni)
{
$this->campioni[] = $campioni;
return $this;
}
/**
* Remove campioni
*
* #param \AppBundle\Entity\TipologiaCampione $campioni
*/
public function removeCampioni(\AppBundle\Entity\TipologiaCampione $campioni)
{
$this->campioni->removeElement($campioni);
}
/**
* Get campioni
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getCampioni()
{
return $this->campioni;
}
/**
* Set idTipologiaEsame
*
* #param \AppBundle\Entity\Nome_esame $idTipologiaEsame
*
* #return Esame
*/
public function setIdTipologiaEsame(\AppBundle\Entity\Nome_esame $idTipologiaEsame = null)
{
$this->idTipologiaEsame = $idTipologiaEsame;
return $this;
}
/**
* Get idTipologiaEsame
*
* #return \AppBundle\Entity\Nome_esame
*/
public function getIdTipologiaEsame()
{
return $this->idTipologiaEsame;
}
}
and Entity 2
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* TipologiaCampione
*
* #ORM\Table(name="tipologia_campione")
* #ORM\Entity(repositoryClass="AppBundle\Repository\TipologiaCampioneRepository")
*/
class TipologiaCampione
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="tipologia", type="string", length=255, nullable=true)
*/
private $tipologia;
/**
* #var string
*
* #ORM\Column(name="matricola", type="string", length=255, nullable=true)
*/
private $matricola;
/**
* #var string
*
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\Esame",mappedBy="campioni")
*/
private $esami;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set tipologia
*
* #param string $tipologia
*
* #return TipologiaCampione
*/
public function setTipologia($tipologia)
{
$this->tipologia = $tipologia;
return $this;
}
/**
* Get tipologia
*
* #return string
*/
public function getTipologia()
{
return $this->tipologia;
}
/**
* Set matricola
*
* #param string $matricola
*
* #return TipologiaCampione
*/
public function setMatricola($matricola)
{
$this->matricola = $matricola;
return $this;
}
/**
* Get matricola
*
* #return string
*/
public function getMatricola()
{
return $this->matricola;
}
/**
* Constructor
*/
public function __construct()
{
$this->esami = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add esami
*
* #param \AppBundle\Entity\Esame $esami
*
* #return TipologiaCampione
*/
public function addEsami(\AppBundle\Entity\Esame $esami)
{
$this->esami[] = $esami;
return $this;
}
/**
* Remove esami
*
* #param \AppBundle\Entity\Esame $esami
*/
public function removeEsami(\AppBundle\Entity\Esame $esami)
{
$this->esami->removeElement($esami);
}
/**
* Get esami
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getEsami()
{
return $this->esami;
}
}
now i must save data and in my controller i write this:
for($i=0;$i<$form->get('numero_campioni')->getData();$i++) {
$campione=new TipologiaCampione();
$campione->setMatricola($form['matricola_'.$i]->getData());
$campione->setTipologia($form['tipologia_'.$i]->getData());
foreach($form['esame_'.$i]->getData() as $value){
$tipo_esame = $this->getDoctrine()
->getRepository('AppBundle:nome_esame')
->find($value->getId());
$esame=new Esame();
$esame->setIdAnalisi($analisi);
$esame->setIdTipologiaEsame($tipo_esame);
$em->persist($esame);
$em->flush();
$campione->addEsami($esame); -> this don't work
}
$em->persist($campione);
$em->flush();
}
I expect that $campione->addEsami($esame); creates a new record in my table esame_tipologia_campione for each $campione but it doesn't work ..
My form Type:
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Validator\Constraints\DateTime;
use AppBundle\Entity\anagrafica;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use AppBundle\Form\anagraficaType;
use Symfony\Component\Form\Extension\Core\Type\CurrencyType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use AppBundle\Form\EsameType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ButtonType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
class AnalisiType extends AbstractType {
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options) {
$province = array(
'AG' => 'Agrigento',
'AL' => 'Alessandria',
'AN' => 'Ancona',
);
$builder->add('ruminanti', ChoiceType::class, array(
'label' => false,
'mapped' => false,
'placeholder' => 'Tipologia di modulo',
'choices' => array('Ruminanti' => 'Ruminanti', 'Suini' => 'Suini'),
'required' => true,
'data' => ($options['data']->getTipoModulo() != NULL ? $options['data']->getTipoModulo() : ''),
'attr' => array(
'placeholder' => 'Provincia',
)))
->add('idLaboratorio', EntityType::class, array(
'label' => false,
'placeholder' => 'Laboratorio a cui inviare i dati',
'class' => 'AppBundle:Laboratorio',
'choice_label' => 'nome',
// 'data'=>5
))
// Dati proprietario
->add('privato', ChoiceType::class, array(
'label' => false,
'choices' => array('Privato' => 'Privato', 'Azienda' => 'Azienda'),
'data' => 'Privato',
'expanded' => true,
'multiple' => false,
'mapped' => false,
))
->add('Nome_proprietario', TextType::class, array(
'label' => false,
'mapped' => false,
'data' => ($options['data']->getIdProprietario() != NULL ? $options['data']->getIdProprietario()->getNome() : ''),
'attr' => array(
'placeholder' => 'Nome',
'novalidate' => 'novalidate'
)))
->add('Cognome_proprietario', TextType::class, array(
'label' => false,
'mapped' => false,
'data' => ($options['data']->getIdProprietario() != NULL ? $options['data']->getIdProprietario()->getCognome() : ''),
'attr' => array(
'placeholder' => 'Cognome',
'novalidate' => 'novalidate'
)))
->add('Ragione_sociale_proprietario', TextType::class, array(
'label' => false,
'mapped' => false,
'required' => false,
'data' => ($options['data']->getIdProprietario() != NULL ? $options['data']->getIdProprietario()->getRagioneSociale() : ''),
'attr' => array(
'placeholder' => 'Ragione Sociale',
'novalidate' => 'novalidate'
)))
->add('Via_proprietario', TextType::class, array(
'label' => false,
'mapped' => false,
'data' => ($options['data']->getIdProprietario() != NULL ? $options['data']->getIdProprietario()->getvia() : ''),
'attr' => array(
'placeholder' => 'Via'
)))
->add('Comune_proprietario', TextType::class, array(
'label' => false,
'mapped' => false,
'data' => ($options['data']->getIdProprietario() != NULL ? $options['data']->getIdProprietario()->getComune() : ''),
'attr' => array(
'placeholder' => 'Comune'
)))
->add('Provincia_proprietario', ChoiceType::class, array(
'label' => false,
'mapped' => false,
'data' => ($options['data']->getIdProprietario() != NULL ? $options['data']->getIdProprietario()->getProvincia() : ''),
'choices' => $province,
'placeholder' => 'Provincia'
))
->add('Telefono_proprietario', TextType::class, array(
'label' => false,
'mapped' => false,
'data' => ($options['data']->getIdProprietario() != NULL ? $options['data']->getIdProprietario()->gettel() : NULL),
'attr' => array(
'placeholder' => 'Telefono'
)))
->add('email_proprietario', EmailType::class, array(
'label' => false,
'mapped' => false,
'data' => ($options['data']->getIdProprietario() != NULL ? $options['data']->getIdProprietario()->getemail() : ''),
'attr' => array(
'placeholder' => 'E-mail'
)
))
->add('Cod_allev_proprietario', TextType::class, array(
'label' => false,
'mapped' => false,
'data' => ($options['data']->getIdProprietario() != NULL ? $options['data']->getIdProprietario()->getCodiceAllievo() : ''),
'attr' => array(
'placeholder' => 'Codice Allevamento'
)))
// Dati Veterinario
->add('Nome_veterinario', TextType::class, array(
'label' => false,
'mapped' => false,
'data' => ($options['data']->getIdVeterinario() != NULL ? $options['data']->getIdProprietario()->getNome() : ''),
'attr' => array(
'placeholder' => 'Nome'
)))
->add('Cognome_veterinario', TextType::class, array(
'label' => false,
'mapped' => false,
'data' => ($options['data']->getIdVeterinario() != NULL ? $options['data']->getIdProprietario()->getCognome() : ''),
'attr' => array(
'placeholder' => 'Cognome'
)))
->add('Via_veterinario', TextType::class, array(
'label' => false,
'mapped' => false,
'data' => ($options['data']->getIdVeterinario() != NULL ? $options['data']->getIdVeterinario()->getvia() : ''),
'attr' => array(
'placeholder' => 'Via'
)))
->add('Comune_veterinario', TextType::class, array(
'label' => false,
'mapped' => false,
'data' => ($options['data']->getIdVeterinario() != NULL ? $options['data']->getIdVeterinario()->getComune() : ''),
'attr' => array(
'placeholder' => 'Comune'
)))
->add('Provincia_veterinario', ChoiceType::class, array(
'label' => false,
'mapped' => false,
'data' => ($options['data']->getIdVeterinario() != NULL ? $options['data']->getIdVeterinario()->getProvincia() : ''),
'choices' => $province,
'attr' => array(
'placeholder' => 'Provincia'
)))
->add('Telefono_veterinario', TextType::class, array(
'label' => false,
'mapped' => false,
'data' => ($options['data']->getIdVeterinario() != NULL ? $options['data']->getIdVeterinario()->getTel() : NULL),
'attr' => array(
'placeholder' => 'Telefono'
)))
->add('email_veterinario', EmailType::class, array(
'label' => false,
'mapped' => false,
'data' => ($options['data']->getIdVeterinario() != NULL ? $options['data']->getIdVeterinario()->getEmail() : ''),
'attr' => array(
'placeholder' => 'E-mail'
)
))
->add('trattamenti', TextareaType::class, array(
'label' => false,
'attr' => array(
'placeholder' => 'Trattamenti(inserire ANAMNESI; SINTOMATOLOGIA; TRATTAMENTI)'
)
))
->add('vacinazione', TextareaType::class, array(
'label' => false,
'attr' => array(
'placeholder' => 'Vacinazioni(obbligatorio)'
)
))
->add('numero_campioni', NumberType::class, array(
'label' => false,
'attr' => array(
'placeholder' => 'Numero Totale di campioni'
)
));
//->add('save', SubmitType::class, array('label' => 'Create Task'));
$builder->add('idTipologiaEsame', EntityType::class, array(
'label' => false,
'mapped' => false,
'class' => 'AppBundle:Nome_esame',
'choice_label' => 'nome',
'group_by' => 'idCategoriaEsame.tipo',
))
->add('Aggiungi', ButtonType::class, array(
'attr' => array(
'class' => 'btn-primary col-md-2 conferma_esame'),
))
->add('Rimuovi', ButtonType::class, array(
'attr' => array(
'class' => 'btn-primary col-md-2 conferma_esame'),
));
// for($i=0;$i<$options['data']->getNumeroCampioni();$i++){
for ($i = 0; $i < 60; $i++) {
$builder->add('checkbox_' . $i, CheckboxType::class, array(
'label' => false,
'required' => false,
'mapped' => false,
'attr' => array(
'class' => 'check_box_table',
// 'class'=>'col-md-1 col-xs-3 allineare_sinistra',
)
))
->add('matricola_' . $i, TextType::class, array(
'label' => false,
'mapped' => false,
'required' => false,
'attr' => array(
'placeholder' => 'Matricola (FACOLTATIVA)',
// 'class'=>'col-md-2 col-xs-9 allineare_sinistra',
)))
->add('tipologia_' . $i, TextType::class, array(
'label' => false,
'mapped' => false,
'required' => false,
'attr' => array(
'placeholder' => 'Tipologia (FACOLTATIVA)',
// 'class'=>'col-md-2 col-md-offset-0 col-xs-9 col-xs-offset-3 allineare_sinistra',
)))
->add('esame_' . $i, EntityType::class, array(
'label' => false,
'mapped' => false,
'class' => 'AppBundle:Nome_esame',
'required'=>true,
'multiple'=>true,
'choice_label' => 'nome',
// 'disabled' => 'disabled',
'attr' => array(
'placeholder' => 'Esami',
'class' => 'max_width esame_row select_esame',
// 'class'=>'col-md-12 col-md-offset-0 col-xs-9 col-xs-offset-3 ',
)
))
->add('Stampa', ButtonType::class, array(
'disabled' => 'disabled',
'attr' => array(
'class' => 'btn-primary text-center',
)
))
->add('saveAndAdd', SubmitType::class, array('label' => 'Save and Add'))
;
}
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Analisi'
));
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix() {
return 'appbundle_analisi';
}
}
$esame entity and $campione entity are correctly saved.
Can anybody say to me what I'm doing wrong??
You need to create a Join Table
After that you need to choose which entity is the owner of the association (just after the manytomany chapter in the doc).
For exampre, if you may want to add "campioni" via the "esami" entity you should code a setter like this:
public function addCampioni(\AppBundle\Entity\TipologiaCampione($campioni) {
$campioni->addEsami($this);
$this->campioni[] = $campioni;
return $this;
}
Ciao!
Is there a way to save correctly in a relationship ManyToMany field entities in a form that is "multiple" and is part of a collection?
I looked everywhere but could not find a shred of example to make me understand how to do!
I cannot find the solution for this!
class Anagrafica
{
/**
* #ORM\ManyToMany(targetEntity="SubCategories", inversedBy="anagrafiche", cascade={"persist", "remove"})
* #ORM\JoinTable(name="AnCat")
**/
private $subCategories;
//..
public function __construct()
{
$this->subCategories = new \Doctrine\Common\Collections\ArrayCollection();
//..
}
/**
* Add subCategories
*
* #param \My\BusinessBundle\Entity\SubCategories $subCategories
* #return Anagrafica
*/
public function addSubCategory(\My\BusinessBundle\Entity\SubCategories $subCategories)
{
foreach ($subCategories as $subCategory) {
$subCategory->addAnagrafiche($this);
}
$this->subCategories = $subCategories;
}
*******
class SubCategories
{
/**
* #ORM\ManyToMany(targetEntity="Anagrafica", mappedBy="subCategories")
*/
private $anagrafiche;
public function __construct()
{
$this->anagrafiche = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add anagrafiche
*
* #param \My\BusinessBundle\Entity\Anagrafica $anagrafiche
* #return SubCategories
*/
public function addAnagrafiche(\My\BusinessBundle\Entity\Anagrafica $anagrafiche)
{
if (!$this->anagrafiche->contains($anagrafiche)) {
$this->anagrafiche->add($anagrafiche);
}
}
******
AnagraficaType:
//..
->add('subCategories', 'collection', array('type' => new SubCategoriesType(),
'allow_add' => true,
'allow_delete' => true,
'prototype' => true,
'prototype_name' => '__categ__',
'by_reference' => false
))
*******
SubCategoriesType:
->add('subCategory', 'entity', array(
'class' => 'CoffeeBusinessBundle:SubCategories',
'property' => 'subCategory',
'label' => 'Sotto Categorie',
'multiple' => true
))
Partially solved
If I enter the field collection directly and do these changes:
AnagraficaType:
->add('subCategories', 'collection', array(
'type' => 'entity',
'allow_add' => true,
'allow_delete' => true,
'prototype' => true,
'prototype_name' => '__categ__',
'by_reference' => false,
'options' => array(
'label' => 'Sotto Categorie',
'multiple' => true,
'class' => 'MyBusinessBundle:SubCategories',
'property' => 'subCategory'
)
))
Anagrafica entity:
public function addSubCategory(ArrayCollection $subCategories)
{
foreach ($subCategories as $subCategory) {
$subCategory->addAnagrafiche($this);
//var_dump($subCategory);
}
$this->subCategories = $subCategories;
}
Partially get the desired result, but if I add a field in the form subcategories (by collection) saves only the last field entered.
I did a var_dump ArrayCollection object received and in fact inside there are only data from the last field entered.
Any idea?