Call to a member function getRepository() on a non-object - mongodb

I am new In symfony2 with mongoDB, I am creating one relationship with document relation using ODM. I facing above issue when I creating form type, My file code as below
File path: /src/AppBundle/Form/Type/ProductFormType.php
<?php
namespace AppBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class ProductFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name', 'text', array('label' => 'Product Name'))
->add('description', 'textarea',array('label' => 'Description'))
->add('Category', 'document', array(
'label'=>'Product Category',
'class' => 'AppBundle:Category',
'property' => 'name',
))
->add('save', 'submit');
}
public function getName()
{
return 'product';
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Document\Product'
));
}
}
?>
File: src/AppBundle/Document/product.php
<?php
namespace AppBundle\Document;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
use Symfony\Component\Validator\Constraints as Assert;
/** #ODM\Document */
class Product
{
/** #ODM\Id */
private $id;
/** #ODM\String */
protected $name;
/** #ODM\String */
protected $description;
/** #ODM\ReferenceOne(targetDocument="Category", cascade="all") */
private $Category;
public function getId() { return $this->id; }
public function getName() { return $this->name; }
public function setName($name) { $this->name = $name; }
/**
* Set category
*
* #param AppBundle\Document\Category $category
* #return self
*/
public function setCategory(\AppBundle\Document\Category $category)
{
$this->Category = $category;
return $this;
}
/**
* Get category
*
* #return AppBundle\Document\Category $category
*/
public function getCategory()
{
return $this->Category;
}
public function getDescription() { return $this->description; }
public function setDescription($description) { $this->description = $description; }
}
File src/Appbundle/Docment/Category.php
<?php
namespace AppBundle\Document;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;
//** #ODM\Document */
class Category
{
/** #ODM\Id */
protected $id;
/** #ODM\String */
protected $cat_id;
/** #ODM\String */
protected $categoryname;
/** #ReferenceMany(targetDocument="Product" mappedBy="category") */
private $products;
public function __construct()
{
$this->products = new ArrayCollection();
}
/**
* Add product
*
* #param \AppBundle\Document\Product $product
*
* #return Category
*/
public function addProduct(\AppBundle\Document\Product $product)
{
$this->products[] = $product;
return $this;
}
/**
* Remove product
*
* #param \AppBundle\Document\Product $product
*/
public function removeProduct(\AppBundle\Document\Product $product)
{
$this->products->removeElement($product);
}
/**
* Get products
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getProducts()
{
return $this->products;
}
public function getId()
{
return $this->id;
}
public function getCat_id() { return $this->cat_id; }
public function setCat_id($cat_id) { $this->cat_id = $cat_id; }
public function getDescription() { return $this->categoryname; }
public function setDescription($categoryname) { $this->categoryname = $categoryname; }
}
I also tried Following process :
getter-setter for MongoDB
php app/console doctrine:mongodb:generate:documents AppBundle
Then clear cache and set developer enviroment
can anybody have a solutions, Please help me.
Thanks in Advance

Related

How to return entity object type from EntityType class in form?

Every time I try to send data from form and use doctrine manager I have an error:
As you can see, this problem is according to user_type. I have another entity UserType in which I have this attribute and I want to use it in register form.
I have controller and I want to add all form input into database and then error occurs.
I would like to point out that I don't want to get and set each attribute manually via for instance:
$name = $form['name']->getData();
$userDetails->setName($name);
Because I think that by using entity manager it is supposed to do automatically like this:
UserController.php:
public function register(Request $request){
$user = new User();
$userType = new UserType();
$userDetails = new UserDetails();
$form = $this->createForm(RegisterFormType::class, $user);
$form->handleRequest($request);
if($form->isSubmitted()){
$userDetails = $form->getData();
$em=$this->getDoctrine()->getManager();
$em->persist($userDetails);
$em->flush();
dd($form->getData());
My form in RegisterFormType.php:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
-> add('name',TextType::class,[
'data_class' => UserDetails::class,
'attr' => [
"placeholder" => 'Name'
],
])
-> add('surname',TextType::class,[
'data_class' => UserDetails::class,
'attr' => [
"placeholder" => 'Surname'
],
])
->add('email',TextType::class,[
'attr' => [
"placeholder" => 'Email'
]
])
->add('password',PasswordType::class,[
'attr' => [
"placeholder" => 'Password'
]
])
->add('confirmPassword',PasswordType::class,[
'attr' => [
"placeholder" => 'Confirm Password'
]
])
/* ->add('user_type',ChoiceType::class, [
'help' => 'Do you want to perform? Choose Artist account type. Do you want to employ artist? Choose Firm.',
'label' => "Account type",
'choices' => [
'None' => 0,
'firm' => 1,
'artist' => 2
],
'attr' => [
"class" => 'choice'
]
])*/
->add('user_type',EntityType::class, [
'class' => UserType::class,
'choice_label'=>'type',
/*'choice_label'=>'type',
'choice_value' => function ($entity) {
return $entity ? $entity->getId() : '';
},*/
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => User::class,
]);
}
After submitting input in form I get this data:
The problem is user_type sends as a string I suppose, but should as an object. Am I right?
In User.php
<?php
namespace App\Entity;
use App\Repository\UserRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass=UserRepository::class)
* #ORM\Table(name="`user`")
*/
class User extends UserDetails
{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
*/
private $email;
/**
* #ORM\Column(type="string", length=255)
*/
private $password;
private $confirmPassword;
/**
* #ORM\OneToOne(targetEntity=UserType::class, cascade={"persist", "remove"})
* #ORM\JoinColumn(nullable=false)
*/
private $user_type;
/**
* #ORM\OneToOne(targetEntity=UserDetails::class, cascade={"persist", "remove"})
* #ORM\JoinColumn(nullable=false)
*/
private $user_details;
/**
* #ORM\OneToMany(targetEntity=UserToOffert::class, mappedBy="user_", orphanRemoval=true)
*/
private $user_to_offert;
/**
* #ORM\OneToMany(targetEntity=Skill::class, mappedBy="user_", orphanRemoval=true)
*/
private $skill;
/**
* #ORM\OneToMany(targetEntity=Requirement::class, mappedBy="user_id", orphanRemoval=true)
*/
private $requirement;
public function __construct()
{
$this->user_to_offert = new ArrayCollection();
$this->skill = new ArrayCollection();
$this->requirement = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
public function getPassword(): ?string
{
return $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
public function getUserType(): ?string
{
return $this->user_type;
}
public function setUserType(string $user_type): self
{
$this->user_type = $user_type;
return $this;
}
public function getUserDetails(): ?UserDetails
{
return $this->user_details;
}
public function setUserDetails(UserDetails $user_details): self
{
$this->user_details = $user_details;
return $this;
}
/**
* #return mixed
*/
public function getConfirmPassword()
{
return $this->confirmPassword;
}
/**
* #param mixed $confirmPassword
*/
public function setConfirmPassword($confirmPassword): void
{
$this->confirmPassword = $confirmPassword;
}
/**
* #return Collection|UserToOffert[]
*/
public function getUserToOffert(): Collection
{
return $this->user_to_offert;
}
public function addUserToOffert(UserToOffert $userToOffert): self
{
if (!$this->user_to_offert->contains($userToOffert)) {
$this->user_to_offert[] = $userToOffert;
$userToOffert->setUser($this);
}
return $this;
}
public function removeUserToOffert(UserToOffert $userToOffert): self
{
if ($this->user_to_offert->removeElement($userToOffert)) {
// set the owning side to null (unless already changed)
if ($userToOffert->getUser() === $this) {
$userToOffert->setUser(null);
}
}
return $this;
}
/**
* #return Collection|Skill[]
*/
public function getSkill(): Collection
{
return $this->skill;
}
public function addSkill(Skill $skill): self
{
if (!$this->skill->contains($skill)) {
$this->skill[] = $skill;
$skill->setUser($this);
}
return $this;
}
public function removeSkill(Skill $skill): self
{
if ($this->skill->removeElement($skill)) {
// set the owning side to null (unless already changed)
if ($skill->getUser() === $this) {
$skill->setUser(null);
}
}
return $this;
}
/**
* #return Collection|Requirement[]
*/
public function getRequirement(): Collection
{
return $this->requirement;
}
public function addRequirement(Requirement $requirement): self
{
if (!$this->requirement->contains($requirement)) {
$this->requirement[] = $requirement;
$requirement->setUser($this);
}
return $this;
}
public function removeRequirement(Requirement $requirement): self
{
if ($this->requirement->removeElement($requirement)) {
// set the owning side to null (unless already changed)
if ($requirement->getUser() === $this) {
$requirement->setUser(null);
}
}
return $this;
}
}
UserDetails.php:
<?php
namespace App\Entity;
use App\Repository\UserDetailsRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass=UserDetailsRepository::class)
*/
class UserDetails
{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
*/
private $name;
/**
* #ORM\Column(type="string", length=255)
*/
private $surname;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $description;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $photo;
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getSurname(): ?string
{
return $this->surname;
}
public function setSurname(string $surname): self
{
$this->surname = $surname;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(?string $description): self
{
$this->description = $description;
return $this;
}
public function getPhoto(): ?string
{
return $this->photo;
}
public function setPhoto(?string $photo): self
{
$this->photo = $photo;
return $this;
}
public function __toString() {
return $this->name;
}
}
In UserType.php:
<?php
namespace App\Entity;
/**
* #ORM\Entity(repositoryClass=UserTypeRepository::class)
*/
class UserType
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=100)
*/
private $type;
public function getId(): ?int
{
return $this->id;
}
public function getType(): ?string
{
return $this->type;
}
public function setType(string $type): self
{
$this->type = $type;
return $this;
}
public function __toString() {
return $this->type;
}
}
If I remove __toString method I get an error:
Any ideas what am I doing wrong? Thank you for your time in advance. Have a nice day!

Passing parent entity Id into child form

Good day,
I got entity ScheduledCommand into relation OneToMany to ScheduledCommandLimitRange
/**
* #ORM\MappedSuperclass (repositoryClass="Synolia\SyliusSchedulerCommandPlugin\Repository\ScheduledCommandRepository")
* #ORM\Table("scheduled_command")
*/
class ScheduledCommand implements ScheduledCommandInterface
{
/**
* #var int|null
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #var string
* #ORM\Column(type="string")
*/
private $name = '';
/**
* #var string
* #ORM\Column(type="string")
*/
private $command = '';
/**
* #var int
* #ORM\Column(type="integer")
*/
private $priority = 0;
/**
* #ORM\OneToMany(targetEntity="ScheduledCommandLimitRange", mappedBy="scheduledCommand", orphanRemoval=true, cascade={"persist"})
* #ORM\JoinColumn(nullable=false)
*/
private $commandLimitRanges;
public function getId(): ?int
{
return $this->id;
}
public function getName(): string
{
return $this->name;
}
public function setName(string $name): ScheduledCommandInterface
{
$this->name = $name;
return $this;
}
public function getCommand(): string
{
return $this->command;
}
public function setCommand(string $command): ScheduledCommandInterface
{
$this->command = $command;
return $this;
}
public function getPriority(): int
{
return $this->priority;
}
public function setPriority(int $priority): ScheduledCommandInterface
{
$this->priority = $priority;
return $this;
}
public function getCommandLimitRanges(): ?Collection
{
return $this->commandLimitRanges;
}
public function setCommandLimitRanges(Collection $commandLimitRange): ?Collection
{
$this->commandLimitRanges = $commandLimitRange;
return $this->commandLimitRanges;
}
}
This is my ManyToOne class:
/**
* #ORM\Entity(repositoryClass="Synolia\SyliusSchedulerCommandPlugin\Repository\ScheduledCommandLimitRangeRepository")
* #ORM\Table(name="scheduled_command_limit_range")
*/
class ScheduledCommandLimitRange implements ScheduledCommandLimitRangeInterface
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #var \DateTime|null
* #ORM\Column(type="datetime", nullable=true)
*/
private $timeFrom;
/**
* #var \DateTime|null
* #ORM\Column(type="datetime", nullable=true)
*/
private $timeTo;
/**
* #ORM\ManyToOne(targetEntity="ScheduledCommand", inversedBy="commandLimitRanges")
*/
private $scheduledCommand;
public function getId(): ?int
{
return $this->id;
}
public function getTimeFrom(): ?\DateTime
{
return $this->timeFrom;
}
public function setTimeFrom(?\DateTime $timeFrom): ScheduledCommandLimitRangeInterface
{
$this->timeFrom = $timeFrom;
return $this;
}
public function getTimeTo(): ?\DateTime
{
return $this->timeTo;
}
public function setTimeTo(?\DateTime $timeTo): ScheduledCommandLimitRangeInterface
{
$this->timeTo = $timeTo;
return $this;
}
public function getScheduledCommand(): ?ScheduledCommand
{
return $this->scheduledCommand;
}
public function setScheduledCommand(ScheduledCommand $scheduledCommand): ?ScheduledCommand
{
$this->scheduledCommand = $scheduledCommand;
return $this;
}
I got ScheduledCommandType that is has CollectionType in one field, that has entry_type of CommandLimitType.
final class ScheduledCommandType extends AbstractType
{
/**
* #SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('name')
->add('command', CommandChoiceType::class)
->add('arguments')
->add('cronExpression')
->add('commandLimitRanges', CollectionType::class, [
'label' => 'sylius.ui.scheduled_command_limit',
'entry_type' => CommandLimitType::class,
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
'inherit_data' => true,
'entry_options' => array(
'scheduledCommand' => 'id'),
])
->add('logFile')
->add('priority')
->add('executeImmediately')
->add('enabled')
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => ScheduledCommand::class,
]);
}
}
This is my entry Type:
class CommandLimitType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('timeTo', DateTimeType::class, [
'widget' => 'single_text',
])
->add('timeFrom', DateTimeType::class, [
'widget' => 'single_text'
])
->add('scheduledCommand', HiddenType::class)
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setRequired(['scheduledCommand']);
$resolver->setDefaults([
'data_class' => ScheduledCommandLimitRange::class,
]);
}
}
I had a problem, that when I want to submit this form value CommandLimitRange parentId was null, so i tried to pass into child form parent Id as hidden field. But still got after submit there is stil error:
Cannot read index "0" from object of type "Synolia\SyliusSchedulerCommandPlugin\Entity\ScheduledCommand" because it doesn't implement \ArrayAccess.
What is correct way to pass parent entity Id into entry so that after submit correct parentId is linked to row in db?
Thank you very much
I have found my solution. Okay, so here is few problems, that I did not clearly understand before.
First and foremost - I had only basic setter, instead add / remove method.
public function addCommandLimitRange(ScheduledCommandLimitRange $commandLimitRange): self
{
if (!$this->commandLimitRanges->contains($commandLimitRange)) {
$this->commandLimitRanges[] = $commandLimitRange;
$commandLimitRange->setScheduledCommand($this);
}
return $this;
}
public function removeCommandLimitRange(ScheduledCommandLimitRange $commandLimitRange): self
{
if ($this->commandLimitRanges->removeElement($commandLimitRange)) {
// set the owning side to null (unless already changed)
if ($commandLimitRange->getScheduledCommand() === $this) {
$commandLimitRange->setScheduledCommand(null);
}
}
return $this;
}
Next I needed to make my property an ArrayCollection object in constructor:
public function __construct()
{
$this->commandLimitRanges = new ArrayCollection();
}
And last to get proper delete instead running update with null on parentId I needed to ad orphan_removal option into annotation.
/**
* #ORM\OneToMany(targetEntity="ScheduledCommandLimitRange", mappedBy="scheduledCommand", cascade={"persist"}, orphanRemoval=true)
*/
private $commandLimitRanges;

Symfony 4 - choice_value FormType not working

This is the method in my controller:
public function parentCat($parentId,$manOrWomen,Request $request){
$pr=new Product();
$products=$this->getDoctrine()->getRepository(Product::class)->listProductsParentCategory($parentId,$manOrWomen);
$form=$this->createForm(SearchProductType::class,$pr,['parentId'=>$parentId,'manOrWomen'=>$manOrWomen]);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()){
$price=$request->request->get('search_product','price');
$name=$request->request->get('search_product','name');
$products=$this->getDoctrine()->getRepository(Product::class)->listSearchedProd($parentId,$manOrWomen,$price['price']
,$name['name']);
//$products=$this->getDoctrine()->getRepository(Product::class)->listSearchedProd($productPrice);
return $this->render('list_products/index.html.twig',['controller_name' => 'ListProductsController',
'form1'=>$form->createView(),'products'=>$products]);
}
else{
return $this->render('list_products/index.html.twig',['controller_name' => 'ListProductsController','form1'=>$form->createView()
,'products'=>$products]);
}
}
This is my Product class(Pruduct Entity):
class Product
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
*/
private $name;
/**
* #ORM\Column(type="text")
*/
private $description;
/**
*
* #ORM\Column(type="string", length=255)
* #Assert\Image(mimeTypes={"image/jpeg","image/png"})
*/
private $image;
/**
* #ORM\Column(type="integer")
*/
private $price;
/**
* #var Category[] | ArrayCollection
* #ORM\ManyToOne(targetEntity="App\Entity\Category")
* #ORM\JoinColumn(name="category_id", referencedColumnName="id")
*/
private $category;
/**
* #var ManOrWomen[] | ArrayCollection
* #ORM\ManyToOne(targetEntity="App\Entity\ManOrWomen")
* #ORM\JoinColumn(name="manorwomen_id", referencedColumnName="id")
*/
private $manorwomen;
/**
* #param \DateTime $createdDate
*
* #ORM\Column(name="createdDate", type="datetime")
*/
private $createdDate;
/**
* Product constructor.
*/
public function __construct()
{
$this->createdDate=new \DateTime('now');
$this->category = new ArrayCollection();
$this->manorwomen=new ArrayCollection();
$this->undercategory=new ArrayCollection();
$this->parentCategory=new ArrayCollection();
}
public function getId()
{
return $this->id;
}
public function getName()
{
return $this->name;
}
public function setName($name): self
{
$this->name = $name;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(string $description): self
{
$this->description = $description;
return $this;
}
public function getImage(): ?string
{
return $this->image;
}
public function setImage(string $image): self
{
$this->image = $image;
return $this;
}
public function getPrice()
{
return $this->price;
}
public function setPrice($price): self
{
$this->price = $price;
return $this;
}
/**
* #return Category[]|ArrayCollection
*/
public function getCategory()
{
return $this->category;
}
/**
* #param Category[]|ArrayCollection $category
*/
public function setCategory($category): void
{
$this->category = $category;
}
/**
* #return ManOrWomen[]|ArrayCollection
*/
public function getManorwomen()
{
return $this->manorwomen;
}
/**
* #param ManOrWomen[]|ArrayCollection $manorwomen
*/
public function setManorwomen($manorwomen): void
{
$this->manorwomen = $manorwomen;
}
/**
* #return DateTime
*/
public function getCreatedDate(): DateTime
{
return $this->createdDate;
}
/**
* #param DateTime $createdDate
*/
public function setCreatedDate(DateTime $createdDate): void
{
$this->createdDate = $createdDate;
}
This is my FormType for class Product:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$parentId = $options['parentId'];
$manOrWomen=$options['manOrWomen'];
$builder
->add('price',EntityType::class,[
'class'=>Product::class,
'choice_label'=>'price',
'choice_value' => 'price',
'placeholder'=>'Default',
'query_builder' => function (EntityRepository $er) use ($parentId,$manOrWomen) {
return $er->createQueryBuilder('product')
->innerJoin('product.category','c')
->addSelect('c')
->innerJoin('product.manorwomen','m')
->addSelect('m')
->where('c.parent_id=:parentId')
->andWhere('m.id=:manOrWomen')
->setParameters(['parentId'=>$parentId,'manOrWomen'=>$manOrWomen]);
},
'expanded'=>false,
'multiple'=>false
])
->add('name',EntityType::class,[
'class'=>Product::class,
'choice_label'=>'name',
'choice_value' => 'name',
'placeholder'=>'Default',
'query_builder' => function (EntityRepository $er) use ($parentId,$manOrWomen) {
return $er->createQueryBuilder('product')
->innerJoin('product.category','c')
->addSelect('c')
->innerJoin('product.manorwomen','m')
->addSelect('m')
->where('c.parent_id=:parentId')
->andWhere('m.id=:manOrWomen')
->setParameters(['parentId'=>$parentId,'manOrWomen'=>$manOrWomen]);
},
'expanded'=>false,
'multiple'=>false
])
->add('submit',SubmitType::class)
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Product::class
]);
$resolver->setRequired(
['parentId','manOrWomen']
);
}
I have problem with the request:
"price" => "44" (This is the price for the current item.This is okay.)
"name" => "44" (This must be the name of current item.)
I have 'choice_value'=>'name' but I get the price instead name.
If I change first choice_value with another value,the second choice_value becomes equal to her.Why?
When I remove addSelect from first EntityType works fine,but if I add more one EntityType,then I have the same problem - thirth EntityType value becomes equal to second value ('name').
I would say your entity is returning the price in the getter of the name or the setter of the price is setting the value of name.

Cannot insert multiple values with entity form when multiple is true

It throws an error when I submit the form with multiple=true: When is false everything works as expected and one value is inserted to the table.
Catchable Fatal Error: Argument 1 passed to AppBundle\Entity\CustomersProducts::setProducts() must be an instance of AppBundle\Entity\Products, instance of Doctrine\Common\Collections\ArrayCollection given, called in /var/www/html/app/vendor/symfony/symfony/src/Symfony/Component/PropertyAccess/PropertyAccessor.php on line 556 and defined
Products.php
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use AppBundle\Entity\Products;
/**
* Products
*
* #ORM\Table(name="products")
* #ORM\Entity(repositoryClass="AppBundle\Repository\ProductsRepository")
*/
class Products
{
/**
* #ORM\OneToMany(targetEntity="CustomersProducts", mappedBy="products")
*/
private $products;
public function __toString() {
return $this->name;
}
public function addProducts(Products $request)
{
$this->products->add($request);
return $this;
}
public function removeProducts(Products $request)
{
$this->products->removeElement($request);
return $this;
}
public function __construct() {
$this->products= new ArrayCollection();
}
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return Products
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
}
CustomersProducts.php
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use AppBundle\Entity\Customers;
use AppBundle\Entity\Products;
/**
* CustomersProducts
*
* #ORM\Table(name="customers_products")
* #ORM\Entity(repositoryClass="AppBundle\Repository\CustomersProductsRepository")
*/
class CustomersProducts
{
/**
* #ORM\ManyToOne(targetEntity="Customers", inversedBy="customers")
* #ORM\JoinColumn(name="customer_id", referencedColumnName="id")
*/
private $customers;
public function getCustomers()
{
return $this->customers;
}
public function setCustomers(Customers $customer) // Please add a Use statement on top of your document
{
$this->customers = $customer;
return $this;
}
/**
* #ORM\ManyToOne(targetEntity="Products", inversedBy="products")
* #ORM\JoinColumn(name="product_id", referencedColumnName="id")
*/
private $products;
public function getProducts()
{
return $this->products;
}
public function setProducts(Products $products) // Please add a Use statement on top of your document
{
var_dump($products->getName()); die();
$this->products = $products;
return $this;
}
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="version", type="string", length=255)
*/
private $version;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set version
*
* #param string $version
* #return CustomersProducts
*/
public function setVersion($version)
{
$this->version = $version;
return $this;
}
/**
* Get version
*
* #return string
*/
public function getVersion()
{
return $this->version;
}
}
CustomersProductsType.php
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class CustomersProductsType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('version')
->add('customers', 'entity', array(
'class' => 'AppBundle:Customers',
'multiple' =>false,
'property' => 'name',
))
->add('products', 'entity', array(
'class' => 'AppBundle:Products',
'multiple' =>true,
'property' => 'name',
))
;
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\CustomersProducts'
));
}
}
UPDATE:
After the change I'made from the suggestion now I get the following error:
Found entity of type Doctrine\Common\Collections\ArrayCollection on association AppBundle\Entity\CustomersProducts#products, but expecting AppBundle\Entity\Product
You have to rename entity Products to Product, because class that representing one database row (an entity) should have singular name.
Grammatically incorrect method name addProducts:
public function addProducts(Products $request)
refactor it to:
public function addProduct(Product $product) {
if ($this->products->contains($product)) {
return;
}
$this->products->add($product);
}
The same with remove method:
public function removeProducts(Products $request)
refactor to:
public function removeProduct(Product $product) {
if (!$this->products->contains($product)) {
return;
}
$this->products->removeElement($product);
}
Changes to CustomersProducts
/**
* #ORM\ManyToOne(targetEntity="Product", inversedBy="products")
* #ORM\JoinColumn(name="product_id", referencedColumnName="id")
*/
private $product;
public function getProduct()
{
return $this->product;
}
public function setProduct(Product $product)
{
$this->product = $product;
}
You can find similar example and explanation in the article

Doctrine2 inverse persistance not working in nested forms

I am creating a MotorsAds entity to which I am linking with MotorsAdsFile entity. For each MotorsAds, we could attach many MotorsAdsFile.
My objective is creating a form for MotorsAds which allows adding MotorsAdsFile just through a click on a button. Here, I am trying to implement the embeded forms.
My problem is that I got that error:
An exception occurred while executing 'INSERT INTO MotorsAdsFile (filename, motors_id) VALUES (?, ?)' with params ["5493b613839d7_2012-07-02 22.06.00.jpg", null]:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'motors_id' cannot be null
Probably, the MotorsAds object is not persisted yet: that's why the Column 'motors_id' is null. Could you help in this issue?
Have I missed something?
1. Definition of the entities
MotorsAdsFile
<?php
namespace Minn\AdsBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\Validator\Constraints as Assert;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
* #ORM\Entity
* #Vich\Uploadable
*/
class MotorsAdsFile {
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
public $id;
/**
* #Assert\File(
* maxSize="5M",
* mimeTypes={"image/png", "image/jpeg"}
* )
* #Vich\UploadableField(mapping="motors_files", fileNameProperty="filename")
*/
protected $file;
/**
* #ORM\Column(type="string", length=255, name="filename")
* #var string $filename
*/
protected $filename;
/**
* #ORM\ManyToOne(targetEntity="Minn\AdsBundle\Entity\MotorsAds", inversedBy="files")
* #ORM\JoinColumn(nullable=false,onDelete="CASCADE")
*/
private $motors;
/**
* #param File|\Symfony\Component\HttpFoundation\File\UploadedFile $file
*/
public function setFile(File $file) {
$this->file = $file;
}
/**
* #return File
*/
public function getFile() {
return $this->file;
}
/**
* #param string $filename
*/
public function setFilename($filename) {
$this->filename = $filename;
}
/**
* #return string
*/
public function getFilename() {
return $this->filename;
}
/**
* Set motors
*
* #param \Minn\AdsBundle\Entity\MotorsAds $motors
* #return MotorsAds
*/
public function setMotors(\Minn\AdsBundle\Entity\MotorsAds $motors) {
$this->motors = $motors;
return $this;
}
/**
* Get motors
*
* #return \Minn\AdsBundle\Entity\MotorsAds
*/
public function getMotors() {
return $this->motors;
}
}
MotorsAds
<?php
namespace Minn\AdsBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Component\Validator\Constraints as Assert;
/**
* MotorsAds
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="Minn\AdsBundle\Entity\MotorsAdsRepository")
* #ORM\HasLifecycleCallbacks()
*/
class MotorsAds {
// ...
/**
* #ORM\OneToMany(targetEntity="Minn\AdsBundle\Entity\MotorsAdsFile",
* mappedBy="motors",
* cascade={"persist", "remove"})
* #ORM\JoinColumn(nullable=true)
*/
private $files;
public function __construct() {
$this->files = new \Doctrine\Common\Collections\ArrayCollection();
$this->favorites = new \Doctrine\Common\Collections\ArrayCollection();
}
public function getFiles() {
return $this->files;
}
public function addFile(MotorsAdsFile $file) {
$this->files[] = $file;
return $this;
}
public function removeFile(MotorsAdsFile $file) {
$this->files->removeElement($file);
}
// ...
}
2. The forms
MotorsAdsFileType
class MotorsAdsFileType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('file', 'file',array('required' => false));
}
public function setDefaultOptions(OptionsResolverInterface $resolver) {
$resolver->setDefaults(array(
'data_class' => 'Minn\AdsBundle\Entity\MotorsAdsFile'
));
}
public function getName() {
return 'MotorsAdsFiletype';
}
}
MotorsAdsType
class MotorsAdsType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
// ...some code here
$builder->add('files','collection',array('type'=> new MotorsAdsFileType(),
'allow_add'=> true,
'allow_delete' => true,
'by_reference' => true));
}
public function setDefaultOptions(OptionsResolverInterface $resolver) {
$resolver->setDefaults(array(
'data_class' => 'Minn\AdsBundle\Entity\MotorsAds'
));
}
public function getName() {
return 'MotorsAdstype';
}
}
I
I found the solution...
Two things have to be done:
(1)
public function buildForm(FormBuilderInterface $builder, array $options) {
// ...some code here
$builder->add('files','collection',array('type'=> new MotorsAdsFileType(),
'allow_add'=> true,
'allow_delete' => true,
'by_reference' => false)); // it has to be set to false and not true
}
(2)
public function addFile(MotorsAdsFile $file) {
$file->setMotors($this); // you have to add this line too
$this->files[] = $file;
return $this;
}