Check if entry exists in database with custom validation constraint - php

So in my Symfony application I have an Entity called Post.
My Post Entity has the following properties:
post_start,post_end and many more.
ENTITY:
/**
* #ORM\Entity
* #ORM\Table(name="post")
*/
class Post
{
/**
* #var int
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
private $id;
/**
* #var DateType
* #ORM\Column(type="date")
*/
private $post_start;
/**
* #var DateType
* #ORM\Column(type="date")
* #Assert\GreaterThanOrEqual(propertyPath="post_start")
*/
private $post_end;
.....
}
FORMTYPE:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add(
'post_start',
DateType::class,
[
'widget' => 'single_text',
'format' => 'dd.MM.yyyy',
'required' => true,
'attr' => [
'class' => 'form-control input-inline datepicker',
'data-provide' => 'datepicker',
'data-date-format' => 'dd.mm.yyyy',
]
]
);
$builder->add(
'post_end',
DateType::class,
[
'widget' => 'single_text',
'format' => 'dd.MM.yyyy',
'required' => true,
'attr' => [
'class' => 'form-control input-inline datepicker',
'data-provide' => 'datepicker',
'data-date-format' => 'dd.mm.yyyy'
]
]
);
$builder->add('submit', SubmitType::class, [
'label' => 'save post',
'attr' => array('class' => 'btn btn-success')
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Post::class
]);
}
When I submit the form, I want to check if the database already has an entry with the same startdate and enddate and of cource from the same user.
1. If YES -> Show error message
2. If NO -> Create post request.
When the entry already exists, but it's from a different user, just go ahead and create the post.
I wanted to do that with a custom validator constraint. But what happens next I have to somehow compare the data with each other
ContainsEqualDate:
/**
* #Annotation
*/
class ContainsEqualDate extends Constraint
{
public $message = 'Post request is already exists.';
public function getTargets()
{
return self::CLASS_CONSTRAINT;
}
}
ContainsEqualDateValidator:
class ContainsEqualDateValidator extends ConstraintValidator
{
/**
* #var ORMUserRepository
*/
private $userRepository;
/**
* #var ORMPostRepository
*/
private $postRepository;
/**
* #param ORMUserRepository $userRepository
* #param ORMPostRepository $postRepository
*/
public function __construct(ORMUserRepository $userRepository, ORMPostRepository $postRepository)
{
$this->userRepository = $userRepository;
$this->postRepository = $postRepository;
}
/**
* Checks if the passed value is valid.
*
* #param mixed $value The value that should be validated
* #param Constraint $constraint The constraint for the validation
*/
public function validate($value, Constraint $constraint)
{
$userId = $this->getUser();
$postExists = $this->postRepository->findBy(array(
'post_start' => $value,
'app_user_id' => $userId
));
}
/**
* #return User
*/
private function getUser(): User
{
return $this->storage->getToken()->getUser();
}
}
}

#Max Trui, you have not mentioned how are the User and Post entities are related in your database.
If you have UserId in Post Entity, you can do Following.
$userId = $this->userRepository->getUser()->getId();
$entryExists = ($this->postRepository->findBy(array('post_start' => $value, 'user_id' => $userId)) == null) ? true : false;
you can replace 'post_start' with the dynamic fieldname value(post_start or post_end), which you can provide from where you call validator.
If you want to check for both dates at the same time, provide both values in validator.

Related

Symfony2 setSelected value of Entity Type

This might wound like a silly question, but I'm stuck. I've the following field in a form of my Symfony2 application:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('match_team1','entity', array(
'class' => 'MyAppBundle:Team',
'expanded' => false,
'multiple' => false,
'label' => 'Team 1',
'mapped' => true,
'property' => 'name'
));
}
Match Class
class Match
{
/**
* #var integer
*/
private $id;
/**
* #var integer
*/
private $match_number;
/**
* #var string
*/
private $match_type;
/**
* #var \DateTime
*/
private $match_date;
/**
* #var string
*/
private $match_status;
/**
* #var string
*/
private $match_team1;
/**
* Set matchTeam1
*
* #param string $matchTeam1
*
* #return Match
*/
public function setMatchTeam1($matchTeam1)
{
$this->match_team1 = $matchTeam1;
return $this;
}
/**
* Get matchTeam1
*
* #return string
*/
public function getMatchTeam1()
{
return $this->match_team1;
}
Edit function:
private function createEditForm(Match $entity)
{
$form = $this->createForm(new MatchType(), $entity, array(
'action' => $this->generateUrl('match_update', array('id' => $entity->getId())),
'method' => 'PUT',
));
$form->add('submit', 'submit', array('label' => 'Update'));
return $form;
}
But when I update the form the selected value from the drop down does not stay. In the database I can see the entry but in the form it's not being displayed. Can anyone help me to set the selected value?

Symfony 2 Set Embedded Entity Form Data

Currently I have embedded entity forms in a form. And I would like the underlying data to auto populate the address fields when a user selects a project. However using the form events as shown below in the entities and the corresponding ajax code specified in the Symfony 2 documentation, the address fields are never populated in the corresponding ajax response.
Using var_dump I can see that the address is grabbed and sent to the data option when I add the address field. But it never shows up in the form response when the form is submitted with just the selected project.
Is this the proper way to do it or am I missing some vital piece somewhere? Or does symfony not do this and should I do it via jquery/ajax?
TransactionUser
class TransactionUser
{
/**
* #var string
*
* #ORM\Column(name="id", type="guid")
* #ORM\Id
*/
private $id;
/**
* The associated transaction to this TransactionUser.
*
* #var \Acme\BaseBundle\Entity\Transaction $transaction
*
* #ORM\ManyToOne(targetEntity="Acme\BaseBundle\Entity\Transaction", inversedBy="transactionUsers", cascade={"all"})
*/
private $transaction;
/**
* The Project that this TransactionUser is associated with.
*
* #var \Acme\BaseBundle\Entity\Project
*
* #ORM\ManyToOne(targetEntity="Acme\BaseBundle\Entity\Project", inversedBy="transactionUsers", cascade={"all"})
*/
private $project;
}
Transaction
class Transaction
{
/**
* #var string
*
* #ORM\Column(name="id", type="guid")
* #ORM\Id
*/
private $id;
/**
* #var \Acme\BaseBundle\Entity\Address
*
* #ORM\ManyToOne(targetEntity="Acme\BaseBundle\Entity\Address", cascade={"persist"}, inversedBy="propertyAddressTransactions")
*/
private $propertyAddress;
/**
* #ORM\OneToMany(targetEntity="Acme\BaseBundle\Entity\TransactionUser", mappedBy="transaction", cascade={"all"})
*/
private $transactionUsers;
}
Address
class Address
{
/**
* The database id for the Address.
*
* #var string
*
* #ORM\Column(name="id", type="guid")
* #ORM\Id
*/
private $id;
/**
* The first line of the street address.
*
* #var string
*
* #ORM\Column(name="streetAddressLine1", type="text")
*/
private $streetAddressLine1;
/**
* The Transactions that list this address as the property address.
*
* #ORM\OneToMany(targetEntity="Acme\BaseBundle\Entity\Transaction", mappedBy="propertyAddress")
*/
private $propertyAddressTransactions;
}
Project
class Project
{
/**
* #var string
*
* #ORM\Column(name="id", type="guid")
* #ORM\Id
*/
private $id;
/**
* #ORM\OneToMany(targetEntity="Acme\BaseBundle\Entity\TransactionUser", mappedBy="project", cascade={"all"})
* \Doctrine\Common\Collections\ArrayCollection
*/
private $transactionUsers;
}
NewTransactionFormType
class NewTransactionFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('project', EntityType::class, array(
'class' => 'AcmeBaseBundle:Project',
'required' => false,
'optional' => true,
'label' => 'Select Project',
'placeholder' => 'Select Project',
'property' => 'projectName',
'query_builder' => function (EntityRepository $er) {
$queryBuilder = $er->createQueryBuilder('p');
return $queryBuilder;
},
));
$builder->add('transaction', NewTransactionSubFormType::class);
$builder->get('transaction')->add('propertyAddress', AddressFormType::class);
//Listeners on project to set the address
$formModifier = function (FormInterface $form, Project $project = null) {
$address = null;
if (!is_null($project) && !is_null($project->getId())) {
$address = $project->getFirstTransactionAddress();
}
$form->get('transaction')->add('propertyAddress', AddressFormType::class, array(
'data' => $address
));
};
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formModifier) {
// this would be your entity, i.e. Transaction
$data = $event->getData();
$formModifier($event->getForm(), $data->getProject());
}
);
$builder->get('project')->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)
$project = $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(), $project);
}
);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Acme\BaseBundle\Entity\TransactionUser',
));
}
}
NewTransactionSubFormType
class NewTransactionSubFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name', TextType::class, array(
'label' => 'Name',
'attr' => array(
'class' => '',
'placeholder' => 'Name',
),
'required' => true,
));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Acme\BaseBundle\Entity\Transaction',
));
}
}
AddressFormType
class AddressFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('streetAddressLine1', TextType::class, array(
'label' => 'Street Address Line 1',
'attr' => array(
'class' => '',
'placeholder' => 'Street Address Line 1',
),
'required' => true,
));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Acme\BaseBundle\Entity\Address',
));
}
}

New fields not persisted in database after overriding FormType when register a new user

I am overriding the form type to register a user. All looks ok, but when I submit my form the new fields are not persisted in database.
I followed the documentation.
My ProfileType:
<?php
namespace Application\Sonata\UserBundle\Form\Type;
//use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
//use Sonata\UserBundle\Model\UserInterface;
use Sonata\UserBundle\Form\Type\ProfileType as BaseType;
class ProfileType extends BaseType
{
private $class;
/**
* #param string $class The User class name
*/
public function __construct($class)
{
$this->class = $class;
}
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
$builder
->add('username', null, array(
'label' => 'Pseudo',
'required' => false
))
->add('firstname', null, array(
'label' => 'Prénom'
))
->add('lastname', null, array(
'label' => 'Nom'
))
->add('email', 'email', array(
'label' => 'Email'
))
->add('dateOfBirth', 'birthday', array(
'label' => 'Date d\'anniversaire',
'required' => false,
'data' => new \DateTime("01/01/1980")
))
->add('plainPassword', 'password', array(
'label' => 'Password'
))
->add('phone', null, array(
'label' => 'Téléphone',
'required' => false
))
->add('adress', null, array(
'label' => 'Adresse',
'required' => false
))
->add('zip', null, array(
'label' => 'Code postale',
'required' => false
))
->add('city', null, array(
'label' => 'Ville',
'required' => false
))
->add('newsletter', 'checkbox', array(
'label' => 'newsletter',
'required' => false
))
#hidden
->add('website', 'hidden', array(
'label' => 'website',
'required' => false
))
->add('biography', 'hidden', array(
'label' => 'biography',
'required' => false
))
->add('locale', 'hidden', array(
'label' => 'locale',
'required' => false
))
->add('timezone', 'hidden', array(
'label' => 'Timezone',
'required' => false
))
->add('gender', 'hidden', array(
'label' => 'Civilité',
'required' => false
))
;
// var_dump($builder);
}
/**
* {#inheritdoc}
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Application\Sonata\UserBundle\Entity\User',
'intention' => 'profile',
'label' => 'Edit Profile'
));
}
// public function getParent()
// {
// return 'fos_user_registration';
// }
/**
* {#inheritdoc}
*/
public function getName()
{
return 'application_sonata_user_profile';
}
}
My user class:
<?php
namespace Application\Sonata\UserBundle\Entity;
use Sonata\UserBundle\Entity\BaseUser as BaseUser;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints as DoctrineAssert;
/**
* Application\Sonata\UserBundle\Entity\User
*
* #ORM\Table(name="fos_user_user", indexes={#ORM\Index(name="search_idx", columns={"username", "email"})}))
* #ORM\Entity()
* #DoctrineAssert\UniqueEntity(fields={"username"}, message="username.already.exist" )
* #DoctrineAssert\UniqueEntity(fields={"email"}, message="email.already.exist" )
*/
class User extends BaseUser
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string
*
* #ORM\Column(name="zip", type="string", length=255, nullable=true)
*/
protected $zip;
/**
* #var string
*
* #ORM\Column(name="adress", type="text", nullable=true)
*/
protected $adress;
/**
* #var string
*
* #ORM\Column(name="city", type="string", length=255, nullable=true)
*/
protected $city;
/**
* #var boolean
*
* #ORM\Column(name="newsletter", type="boolean", nullable=true)
*/
private $newsletter;
/**
* Get id
*
* #return integer $id
*/
public function getId()
{
return $this->id;
}
/**
* Set zip
*
* #param string $zip
* #return FosUserUser
*/
public function setZip($zip)
{
$this->zip = $zip;
return $this;
}
/**
* Get zip
*
* #return string
*/
public function getZip()
{
return $this->zip;
}
/**
* Set adress
*
* #param string $adress
* #return FosUserUser
*/
public function setAdress($adress)
{
$this->adress = $adress;
return $this;
}
/**
* Get adress
*
* #return string
*/
public function getAdress()
{
return $this->adress;
}
/**
* Set city
*
* #param string $city
* #return FosUserUser
*/
public function setCity($city)
{
$this->city = $city;
return $this;
}
/**
* Get city
*
* #return string
*/
public function getCity()
{
return $this->city;
}
/**
* Set Newsletter
*
* #param boolean $newsletter
* #return FosUserUser
*/
public function setNewsletter($newsletter)
{
$this->newsletter = $newsletter;
return $this;
}
/**
* Get Newsletter
*
* #return boolean
*/
public function getNewsletter()
{
return $this->newsletter;
}
}
Thank you for your help.
If you have a just created properties of the entity and you are using the metadata cache, the doctrine still doesn't aware about these new properties. Just try to clear the metadata cache.

Doctrine Mapping Exception in Zend Framework 2's Project while using hydrator

I am trying to implement doctrine hydrator in my zend 2 project. I am using doctrine's official documentation
I am getting two warning and one error. Following is the warning at top of page.
Warning: Missing argument 2 for DoctrineModule\Stdlib\Hydrator\DoctrineObject::__construct(), called in /path/to/my/project/module/Notes/src/Notes/Form/AssignForm.php on line 16 and defined in /path/to/my/project/vendor/doctrine/doctrine-module/src/DoctrineModule/Stdlib/Hydrator/DoctrineObject.php on line 71
Notice: Undefined variable: targetClass in /path/to/my/project/vendor/doctrine/doctrine-module/src/DoctrineModule/Stdlib/Hydrator/DoctrineObject.php on line 76
Here is the error:
An error occurred
An error occurred during execution; please try again later.
Additional information:
Doctrine\Common\Persistence\Mapping\MappingException
File:
/path/to/my/project/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/MappingException.php:96
Message:
Class '' does not exist
Here is my entity:
use Doctrine\ORM\Mapping as ORM;
/** #ORM\Entity */
class Assigned{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
protected $id;
/** #ORM\Column(type="string")
* #access protected
*/
protected $loan_number;
/** #ORM\Column(type="string")
* #access protected
*/
protected $claim_status;
/** #ORM\Column(type="datetime")
* #access protected
*/
protected $hold_date;
/** #ORM\Column(type="datetime")
* #access protected
*/
protected $vsi_date;
/** #ORM\Column(type="integer")
* #access protected
*/
protected $hold_status;
/** #ORM\Column(type="integer")
* #access protected
*/
protected $vsi_status;
/**
* #param string $id
* #return Assign
*/
// id should be auto incremental in database.
/*
public function setId($id)
{
$this->id = $id;
return $this;
}
*/
/**
* #return string $id;
*/
public function getId()
{
return $this->id;
}
/**
* #param string $loan_number
* #access public
* #return Assigned
*/
public function setLoanNumber($loan_number)
{
$this->loan_number = $loan_number;
return $this;
}
/**
* #return string $loan_number
*/
public function getLoanNumber()
{
return $this->loan_number;
}
/**
* #param string $claim_status
* #access public
* #return Assigned
*/
public function setClaimStatus($claim_status)
{
$this->claim_status = $claim_status;
return $this;
}
/**
* #return string $claim_status;
*/
public function getClaimStatus()
{
return $this->claim_status;
}
/**
* #param datetime $hold_date
* #access public
* #return Assigned
*/
public function setHoldDate($hold_date)
{
$this->hold_date = new \DateTime($hold_date);
return $this;
}
/**
* #return datetime $hold_date;
*/
public function getHoldDate()
{
return $this->hold_date;
}
/**
* #param datetime $vsi_date
* #access public
* #return Assigned
*/
public function setVsiDate($vsi_date)
{
$this->vsi_date = new \DateTime($vsi_date);
return $this;
}
/**
* #return datetime $vsi_date;
*/
public function getVsiDate()
{
return $this->vsi_date;
}
/**
* #param integer $hold_status
* #access public
* #return Assigned
*/
public function setHoldStatus($hold_status)
{
$this->hold_status = $hold_status;
return $this;
}
/**
* #return integer $hold_status;
*/
public function getHoldStatus($hold_status)
{
return $this->hold_status;
}
/**
* #param integer $vsi_status
* #access public
* #return Assigned
*/
public function setVsiStatus($vsi_status)
{
$this->vsi_status = $vsi_status;
return $this;
}
/**
* #return integer $vsi_status;
*/
public function getVsiStatus()
{
return $this->vsi_status;
}
}
Here is my Controller
<?php
namespace Notes\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Doctrine\ORM\EntityManager;
use Application\Entity\Assigned;
use Notes\Form\AssignForm;
use Notes\Form\NotesFieldset;
class NotesController extends AbstractActionController
{
protected $objectManager;
public function indexAction()
{
return new ViewModel();
}
public function addAction()
{
// Get your ObjectManager from the ServiceManager
$objectManager = $this->getOBjectManager();
$form = new AssignForm($objectManager);
// Create a new, empty entity and bind it to the form
$assigned = new Assigned();
$form->bind($assigned);
if ($this->request->isPost()) {
$form->setData($this->request->getPost());
if ($form->isValid()) {
$objectManager->persist($assigned);
$objectManager->flush();
}
}
return array('form' => $form);
}
public function getOBjectManager(){
if(!$this->objectManager){
$this->objectManager = $this->getServiceLocator()
->get('Doctrine\ORM\EntityManager');
}
return $this->objectManager;
}
}
Here is my form class:
<?php
namespace Notes\Form;
use Doctrine\Common\Persistence\ObjectManager;
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator;
use Zend\Form\Form;
use Notes\Form\NotesFieldset;
class AssignForm extends Form
{
public function __construct(ObjectManager $objectManager)
{
parent::__construct('assigned');
// The form will hydrate an object of type "BlogPost"
$this->setHydrator(new DoctrineHydrator($objectManager));
// Add the user fieldset, and set it as the base fieldset
$notesFieldset = new NotesFieldset($objectManager);
$notesFieldset->setUseAsBaseFieldset(true);
$this->add($notesFieldset);
// … add CSRF and submit elements …
// Optionally set your validation group here
}
}
Here is the Fieldset class
<?php
namespace Notes\Form;
use Application\Entity\Assigned;
use Doctrine\Common\Persistence\ObjectManager;
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator;
use Zend\Form\Fieldset;
use Zend\InputFilter\InputFilterProviderInterface;
class NotesFieldset extends Fieldset implements InputFilterProviderInterface
{
protected $inputFilter;
public function __construct(ObjectManager $objectManager)
{
parent::__construct('assigned');
$this->setHydrator(new DoctrineHydrator($objectManager))
->setObject(new Assigned());
$this->add(array(
'type' => 'Zend\Form\Element\Hidden',
'name' => 'id'
));
$this->add(array(
'type' => 'Zend\Form\Element\Text',
'name' => 'loan_number',
'options' => array(
'label' => 'Loan Number'
)
));
$this->add(array(
'type' => 'Zend\Form\Element\Text',
'name' => 'claim_status',
'options' => array(
'label' => 'Claim Status'
)
));
$this->add(array(
'type' => 'Zend\Form\Element\Text',
'name' => 'hold_date',
'options' => array(
'label' => 'Hold Date'
)
));
$this->add(array(
'type' => 'Zend\Form\Element\Text',
'name' => 'vsi_date',
'options' => array(
'label' => 'VSI Date'
)
));
$this->add(array(
'type' => 'Zend\Form\Element\Text',
'name' => 'hold_status',
'options' => array(
'label' => 'Hold Status'
)
));
$this->add(array(
'name' => 'vsi_status',
'attributes' => array(
'type' => 'text',
),
'options' => array(
'label' => 'VSI Status',
),
));
$this->add(array(
'name' => 'submit',
'attributes' => array(
'type' => 'submit',
'value' => 'Go',
'id' => 'submitbutton',
),
));
}
/**
* Define InputFilterSpecifications
*
* #access public
* #return array
*/
public function getInputFilterSpecification()
{
return array(
'id' => array(
'required' => false
),
'name' => array(
'required' => true
),
'loan_number' => array(
'required' => true
),
'claim_status' => array(
'required' => true
),
'hold_date' => array(
'required' => true
),
'hold_status' => array(
'required' => true
),
'vsi_date' => array(
'required' => true
),
'hold_status' => array(
'required' => true
),
);
}
}
It is saying : Class '' does not exist. But the class name is not given in the message.
Beside this
I am using these library for doctrine in my composer.
"doctrine/doctrine-orm-module": "0.7.*",
"doctrine/migrations": "dev-master",
"doctrine/common": "2.4.*#dev",
"doctrine/annotations": "1.0.*#dev",
"doctrine/data-fixtures": "1.0.*#dev",
"doctrine/cache": "1.0.*#dev",
"zf-commons/zfc-user-doctrine-orm": "dev-master",
Please tell me what is missing in my implementation. I have got one open issue in github for doctrine with incomplete example docs. Here is link of issue. If this is the case, then please suggest me ho to implement correctly.
Your missing the target class parameter:
$this->setHydrator(new DoctrineHydrator($objectManager));
Should be:
$this->setHydrator(
new DoctrineHydrator(
$objectManager,
'the\target\entity' // <-- the target entity class name
)
);
The targetClass is used within the DoctrineObject to fetch the metadata of the hydrated entity. You can see this in DoctrineModule\Stdlib\Hydrator\DoctrineObject::__construct():
$this->metadata = $objectManager->getClassMetadata($targetClass);

Found entity of type Doctrine\Common\Collections\ArrayCollection on association (array), but expecting (something else)

The error I get is:
Found entity of type Doctrine\Common\Collections\ArrayCollection on association model\StoreBundle\Entity\campaign#campaignOperatingSystems, but expecting model\StoreBundle\Entity\campaignOS
Here is campaignOS summerized:
/**
* model\StoreBundle\Entity\campaignOS
* #ORM\Table(name="campaign_os")
* #ORM\Entity
*/
class campaignOS extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('OS', 'entity', array(
'class' => 'modelStoreBundle:listOS',
'property' => 'OsName',
'multiple' => 'true',
'expanded' => 'true'
));
}
/**
* #var integer $id
*
* #ORM\Column(name="campaign_os_id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
public function getId()
{
return $this->id;
}
/**
* #ORM\ManyToOne( targetEntity="campaign", inversedBy="campaignOperatingSystems" )
* #ORM\JoinColumn( name="campaign_os_id", referencedColumnName="campaign_id" )
*/
private $campaign;
public function setCampaign( \model\StoreBundle\Entity\campaign $ourCampaign )
{
$this->$campaign = $ourCampaign;
}
public function getCampaign()
{
return $this->$campaign;
}
/**
* #ORM\OneToOne( targetEntity="listOS" )
* #ORM\JoinColumn( name="campaign_os_id", referencedColumnName="os_id" )
*/
private $os;
public function setOS( \model\StoreBundle\Entity\listOS $campaignOS )
{
$this->os = $campaignOS;
}
public function getOS()
{
return $this->os;
}
}
Campaign summarized:
/**
* model\StoreBundle\Entity\campaign
*
* #ORM\Table(name="campaign")
* #ORM\Entity
*/
class campaign extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('Name', 'text', array( 'label' => 'Campaign Name' ));
//$builder->add('CampaignDescription', 'textarea', array( 'label' => 'Campaign Description' ));
$builder->add('CampaignOperatingSystems', new campaignOS(), array( 'label' => 'Campaign OS' ));
/* $builder->add('CampaignOperatingSystems', 'entity', array(
'class' => 'modelStoreBundle:campaignOS',
'property' => 'OS.OsName',
'multiple' => 'true',
'expanded' => 'true',
'label' => 'Campaign OS'
)); */
}
/**
* #var integer $id
*
* #ORM\Column(name="campaign_id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
public function __construct()
{
$this->campaignOperatingSystems = new ArrayCollection();
}
/**
* #ORM\OneToMany(targetEntity="campaignOS", mappedBy="campaign")
* * , cascade={"persist", "remove"})
* #var ArrayCollection $campaignOperatingSystems
*/
protected $campaignOperatingSystems;
public function addCampaignOperatingSystem(\model\StoreBundle\Entity\campaignOS $campaignOperatingSystems)
{
$this->campaignOperatingSystems[] = $campaignOperatingSystems;
/* foreach( $campaignOperatingSystems as $campaignOS )
{
$campaignOS->setCampaign( $this );
} */
return $this;
}
public function removeCampaignOperatingSystem(\model\StoreBundle\Entity\campaignOS $campaignOperatingSystems)
{
$this->campaignOperatingSystems->removeElement($campaignOperatingSystems);
}
public function getCampaignOperatingSystems()
{
return $this->campaignOperatingSystems;
}
}
This is what displays and persists:
public function newAction( Request $request )
{
//create a campaign
$campaign = new campaign();
// get the form
$form = $this->createForm( new campaign(), $campaign );
if ($request->getMethod() == 'POST') {
$form->bindRequest($request);
if ($form->isValid()) {
// perform some action, such as saving the task to the database
//get our data manager
$em = $this->getDoctrine()->getManager();
//make it presistent
$em->persist($campaign);
//update the DB
$em->flush();
return $this->redirect($this->generateUrl('displayDB'));
}
}
return $this->render('modelStoreBundle:DisplayDB:newCampaign.html.twig', array(
'form' => $form->createView(),
));
}
Here is the stack trace:
Stack Trace
in /vagrant/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php at line 753
$state = $this->getEntityState($entry, self::STATE_NEW);
if ( ! ($entry instanceof $assoc['targetEntity'])) {
throw new ORMException(
sprintf(
'Found entity of type %s on association %s#%s, but expecting %s',
get_class($entry),
at UnitOfWork ->computeAssociationChanges (array('fieldName' => 'campaignOperatingSystems', 'mappedBy' => 'campaign', 'targetEntity' => 'model\StoreBundle\Entity\campaignOS', 'cascade' => array(), 'orphanRemoval' => false, 'fetch' => '2', 'type' => '4', 'inversedBy' => null, 'isOwningSide' => false, 'sourceEntity' => 'model\StoreBundle\Entity\campaign', 'isCascadeRemove' => false, 'isCascadePersist' => false, 'isCascadeRefresh' => false, 'isCascadeMerge' => false, 'isCascadeDetach' => false), object(PersistentCollection))
in /vagrant/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php at line 651
at UnitOfWork ->computeChangeSet (object(ClassMetadata), object(campaign))
in /vagrant/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php at line 383
at UnitOfWork ->computeScheduleInsertsChangeSets ()
in /vagrant/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php at line 673
at UnitOfWork ->computeChangeSets ()
in /vagrant/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php at line 273
at UnitOfWork ->commit (null)
in /vagrant/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php at line 355
at EntityManager ->flush (null)
in kernel.root_dir/cache/dev/jms_diextra/doctrine/EntityManager.php at line 362
at EntityManager ->flush ()
in /vagrant/src/model/StoreBundle/Controller/DisplayDBController.php at line 65
at DisplayDBController ->newAction (object(Request))
The signature of these methods
public function addCampaignOperatingSystem(\model\StoreBundle\Entity\campaignOS $campaignOperatingSystems)
public function removeCampaignOperatingSystem(\model\StoreBundle\Entity\campaignOS $campaignOperatingSystems)
Says that you expect, in input, a single object of type campaignOS but you're passing to one of these an ArrayCollection (of campaignOS, I suppose).
So the error is into signature or - probably - into your logic.
Maybe you want an operation like setCompaignOperationSystem ?

Categories