dongping4273 2016-12-20 17:38
浏览 55
已采纳

在Symfony2中嵌入表单集合时出错

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);
  • 写回答

1条回答 默认 最新

  • doumiao0498 2016-12-20 18:43
    关注

    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.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?
  • ¥15 求daily translation(DT)偏差订正方法的代码
  • ¥15 js调用html页面需要隐藏某个按钮
  • ¥15 ads仿真结果在圆图上是怎么读数的
  • ¥20 Cotex M3的调试和程序执行方式是什么样的?
  • ¥20 java项目连接sqlserver时报ssl相关错误
  • ¥15 一道python难题3
  • ¥15 牛顿斯科特系数表表示
  • ¥15 arduino 步进电机
  • ¥20 程序进入HardFault_Handler