Reputation: 1256
I'm trying to embed a collection of forms in a symfony2 application. I have to simple entities : Shop
and Address
whith a Shop which has multiple address. I follow the Symfony2 documentation but I get the error :
Neither the property "address" nor one of the methods "getAddress()", "address()", "isAddress()", "hasAddress()", "__get()" exist and have public access in class "AppBundle\Entity\Address". 500 Internal Server Error - NoSuchPropertyException
It seems to me that it is trying to access the address
preoperty of my Address Entity
.
Here is my Shop Entity
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;
use AppBundle\Entity\Address;
use UserBundle\Entity\Seller;
/**
* Shop
*
* @ORM\Table(name="app_shop")
* @ORM\Entity(repositoryClass="AppBundle\Repository\ShopRepository")
*/
class Shop
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
* @ORM\Column(name="shopName", type="string", length=255)
*/
private $shopName;
/**
* @var string
* @ORM\Column(name="description", type="text", nullable=true)
*/
private $description;
/**
* @var string
* @ORM\Column(name="ownerName", type="string", length=255)
*/
private $ownerName;
/**
* @ORM\ManyToOne(targetEntity="UserBundle\Entity\Seller", cascade={"refresh"}, fetch="EAGER")
* @ORM\JoinColumn(nullable=false, onDelete="NO ACTION")
* @Assert\Valid()
*/
private $owner;
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Address", mappedBy="shop")
* @Assert\Valid()
*/
private $address;
/**
* @ORM\Column(type="string", nullable=true)
* @Assert\Length(
* min = 9,
* max = 10,
* minMessage = "Le numéro siret doit contenir 10 chiffres",
* maxMessage = "Le numéro siret doit contenir 10 chiffres"
* )
*/
private $siret;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Image")
* @ORM\JoinColumn(nullable=true)
*/
private $image;
public function __construct()
{
$this->address = new ArrayCollection();
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set shopName
*
* @param string $shopName
* @return Shop
*/
public function setShopName($shopName)
{
$this->shopName = $shopName;
return $this;
}
/**
* Get shopName
*
* @return string
*/
public function getShopName()
{
return $this->shopName;
}
/**
* Set shopName
*
* @param string $description
* @return Shop
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
* @return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set ownerName
*
* @param string $ownerName
* @return Shop
*/
public function setOwnerName($ownerName)
{
$this->ownerName = $ownerName;
return $this;
}
/**
* Get ownerName
*
* @return string
*/
public function getOwnerName()
{
return $this->ownerName;
}
/**
* Set siret
*
* @param string $siret
* @return Shop
*/
public function setSiret($siret)
{
$this->siret = $siret;
return $this;
}
/**
* Get siret
*
* @return string
*/
public function getSiret()
{
return $this->siret;
}
/**
* Set address
*
* @param ArrayCollection $address
*
* @return Address
*/
public function setAddress(ArrayCollection $address)
{
$this->address = $address;
return $this;
}
/**
* Get address
*
* @return \AppBundle\Entity\Address
*/
public function getAddress()
{
return $this->address;
}
/**
* Set owner
*
* @param \UserBundle\Entity\Seller $owner
*
* @return Owner
*/
public function setOwner(Seller $owner = null)
{
$this->owner = $owner;
return $this;
}
/**
* Get owner
*
* @return \UserBundle\Entity\Sellers
*/
public function getOwner()
{
return $this->owner;
}
/**
*
* @param Image $image
* @return \AppBundle\Entity\Shop
*/
public function setImage(Image $image)
{
$this->image = $image;
return $this;
}
/**
*
*/
public function getImage()
{
return $this->image;
}
}
Here is my Address Entity
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Adress
*
* @ORM\Table(name="app_address")
* @ORM\Entity(repositoryClass="AppBundle\Repository\AddressRepository")
*/
class Address
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="street", type="string", length=255)
* @Assert\Length( min = 5 ,
* max = 200,
* minMessage = "L'adresse doit faire au minimum {{ limit }} caractères.",
* maxMessage = "L'adresse doit faire au maximum {{ limit }} caractères.")
*
*/
private $street;
/**
* @ORM\Column(type="string", length=5)
* @Assert\Regex(
* pattern="/^\d{4,5}$/",
* match=true,
* message="Le format n'est pas correct"
* )
*/
private $postalCode;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $city;
/**
* @var string
*
* @ORM\Column(name="country", type="string", length=255 , nullable=true)
* @Assert\Length( min = 3 ,
* max = 50,
* minMessage = "Le pays doit faire au minimum {{ limit }} caractères.",
* maxMessage = "L'adresse doit faire au maximum {{ limit }} caractères.")
*
*/
private $country;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Shop", inversedBy="address")
* @ORM\JoinColumn(name="shop_id", referencedColumnName="id")
*/
private $shop;
/**
* Get id
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Set street
*
* @param string $street
*
* @return Address
*/
public function setStreet($street)
{
$this->street = $street;
return $this;
}
/**
* Get street
*
* @return string
*/
public function getStreet()
{
return $this->street;
}
/**
* Set postalCode
* @return Address
*/
public function setPostalCode($postalCode)
{
$this->postalCode = $postalCode;
return $this;
}
/**
* Get postalCode
*/
public function getPostalCode()
{
return $this->postalCode;
}
/**
*
* @param string
* @return \AppBundle\Entity\Address
*/
public function setCity($city = null)
{
$this->city = $city;
return $this;
}
/**
*
*/
public function getCity()
{
return $this->city;
}
/**
*
* @param string
* @return \AppBundle\Entity\Address
*/
public function setCountry($country = null)
{
$this->country = $country;
return $this;
}
/**
*
*/
public function getCountry()
{
return $this->country;
}
/**
*
* @param Shop
* @return \AppBundle\Entity\Address
*/
public function setShop($shop = null)
{
$this->shop = $shop;
return $this;
}
/**
*
*/
public function getShop()
{
return $this->shop;
}
public function __toString() {
return $this->street." ".$this->postalCode." ".$this->city;
}
}
I created two formType in order to manage my entities :
ShopType.php
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use AppBundle\Form\AddressType;
use AppBundle\Entity\Shop;
use AppBundle\Entity\Address;
class ShopType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('shopName', TextType::class, array('label' => 'Nom du magasin *', 'required' => true, 'error_bubbling' => true))
->add('ownerName', TextType::class, array('label' => 'Nom du gérant *', 'required' => true, 'error_bubbling' => true))
->add('address', CollectionType::class, array( 'entry_type' => AddressType::class,
'allow_add' => true,
'label' => 'Adresse *',
'required' => true
));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => Shop::class,
));
}
}
AddressType.php
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use AppBundle\Entity\Address;
class AddressType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('address', TextType::class, array('label' => 'Adresse*', 'required' => true))
->add('CodePostal', TextType::class, array('label' => 'Code postal*', 'required' => true, 'error_bubbling' => true))
->add('Ville', TextType::class, array('label' => 'Ville', 'required' => false, 'error_bubbling' => true))
->add('Pays', 'choice', array(
'choices' => array(
'FR' => 'France',
'SU' => 'Suisse',
'BE' => 'Belgique'
)
))
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => Address::class,
));
}
public function getName()
{
return 'addresse';
}
}
In my controller, I'm instanciating my form as following :
$shop = $shopRepo->findOneByOwner($user);
if ($shop == null){
$shop = new Shop();
}
$form = $this->createForm(ShopType::class , $shop);
Upvotes: 1
Views: 414
Reputation: 2694
This error is occurred due to this line at AddressType
class:
->add('address', TextType::class, array('label' => 'Adresse*', 'required' => true))
You are trying to access address
property of Address
entity, but it doesn't contain it. The same is related to other fields: CodePostal
=> postalCode
etc
Also at your Shop
entity you have address
field annotated as OneToMany
relation which is ok, and at the same time you have setAddress(ArrayCollection $address)
method, but instead you should have:
public function addAddress(Address $address)
{
$this->address->add($address);
return $this;
}
and optional
public function removeAddress(Address $address)
{
$this->address->remove($address);
return $this;
}
Btw I suggest to rename property address
into addresses
to highlight that it should contain collection but not single entity.
Upvotes: 3