Symfony 3 表单集合调用非对象上的成员函数 add()

Symfony 3 form collection Call to a member function add() on a non-object

我正在尝试了解如何在 sf 3 中使用表单集合,但我在遵循 sf 网站的教程时遇到了问题,因为它给我带来了错误,我设法理解了我做错了什么我希望你能帮助我。

要约实体

<?php

namespace Zenith\OfferGeneratorBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\Common\Collections\ArrayCollection;
use Zenith\productsBundle\Entity\products;
/**
 * Offer
 *
 * @ORM\Table(name="offer")
 * @ORM\Entity(repositoryClass="Zenith\OfferGeneratorBundle\Repository\OfferRepository")
 */
class Offer
{
    /**
     * @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;

    /**
     * @var  string
     *
     * @ORM\ManyToMany(targetEntity="ProductCollection", inversedBy="offer", cascade={"persist"})
     */
    private $products;


    /**
     * @var \DateTime
     *
     * @Gedmo\Timestampable(on="create")
     * @ORM\Column(name="createdAt", type="datetime")
     */
    private $createdAt;

    /**
     * @var \DateTime
     *
     * @Gedmo\Timestampable(on="update")
     * @ORM\Column(name="modifiedAt", type="datetime")
     */
    private $modifiedAt;

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set name
     *
     * @param string $name
     *
     * @return Offer
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    /**
     * Get name
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Set createdAt
     *
     * @param \DateTime $createdAt
     *
     * @return Offer
     */
    public function setCreatedAt($createdAt)
    {
        $this->createdAt = $createdAt;

        return $this;
    }

    /**
     * Get createdAt
     *
     * @return \DateTime
     */
    public function getCreatedAt()
    {
        return $this->createdAt;
    }

    /**
     * Set modifiedAt
     *
     * @param \DateTime $modifiedAt
     *
     * @return Offer
     */
    public function setModifiedAt($modifiedAt)
    {
        $this->modifiedAt = $modifiedAt;

        return $this;
    }

    /**
     * Get modifiedAt
     *
     * @return \DateTime
     */
    public function getModifiedAt()
    {
        return $this->modifiedAt;
    }

    /**
     * Add product
     *
     * @param \Zenith\OfferGeneratorBundle\Entity\ProductCollection $product
     *
     * @return Offer
     */
    public function addProduct(ProductCollection $product)
    {
        $product->addOffer($this);

        $this->products->add($product);
    }

    /**
     * Remove product
     *
     * @param \Zenith\OfferGeneratorBundle\Entity\ProductCollection $product
     */
    public function removeProduct(\Zenith\OfferGeneratorBundle\Entity\ProductCollection $product)
    {
        $this->products->removeElement($product);
    }

    /**
     * Get products
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getProducts()
    {
        return $this->products;
    }
}

ProductCollection 实体

<?php

namespace Zenith\OfferGeneratorBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Product
 *
 * @ORM\Table(  )
 * @ORM\Entity(repositoryClass="Zenith\OfferGeneratorBundle\Repository\ProductRepository")
 */
class ProductCollection
{
    /**
     * @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;

    /**
     * @var int
     *
     * @ORM\Column(name="price", type="integer")
     */
    private $price;

    /**
     * @var int
     *
     * @ORM\Column(name="quantity", type="integer")
     */
    private $quantity;

    /**
     * @var  string
     *
     * @ORM\ManyToMany(targetEntity="Offer", mappedBy="products")
     */
    private $offer;

    /**
     * @var int
     *
     * @ORM\ManyToMany(targetEntity="Zenith\ProductBundle\Entity\Product")
     */
    private $product;
    /**
     * Constructor
     */
    public function __construct()
    {
        $this->offer = new \Doctrine\Common\Collections\ArrayCollection();
        $this->product = new \Doctrine\Common\Collections\ArrayCollection();
    }

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set name
     *
     * @param string $name
     *
     * @return ProductCollection
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    /**
     * Get name
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Set price
     *
     * @param integer $price
     *
     * @return ProductCollection
     */
    public function setPrice($price)
    {
        $this->price = $price;

        return $this;
    }

    /**
     * Get price
     *
     * @return integer
     */
    public function getPrice()
    {
        return $this->price;
    }

    /**
     * Set quantity
     *
     * @param integer $quantity
     *
     * @return ProductCollection
     */
    public function setQuantity($quantity)
    {
        $this->quantity = $quantity;

        return $this;
    }

    /**
     * Get quantity
     *
     * @return integer
     */
    public function getQuantity()
    {
        return $this->quantity;
    }

    /**
     * Add offer
     *
     * @param \Zenith\OfferGeneratorBundle\Entity\Offer $offer
     *
     * @return ProductCollection
     */
    public function addOffer(\Zenith\OfferGeneratorBundle\Entity\Offer $offer)
    {
        if (!$this->offer->contains($offer)) {
            $this->offer->add($offer);
        }
    }

    /**
     * Remove offer
     *
     * @param \Zenith\OfferGeneratorBundle\Entity\Offer $offer
     */
    public function removeOffer(\Zenith\OfferGeneratorBundle\Entity\Offer $offer)
    {
        $this->offer->removeElement($offer);
    }

    /**
     * Get offer
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getOffer()
    {
        return $this->offer;
    }

    /**
     * Add product
     *
     * @param \Zenith\ProductBundle\Entity\Product $product
     *
     * @return ProductCollection
     */
    public function addProduct(\Zenith\ProductBundle\Entity\Product $product)
    {
        $this->product[] = $product;

        return $this;
    }

    /**
     * Remove product
     *
     * @param \Zenith\ProductBundle\Entity\Product $product
     */
    public function removeProduct(\Zenith\ProductBundle\Entity\Product $product)
    {
        $this->product->removeElement($product);
    }

    /**
     * Get product
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getProduct()
    {
        return $this->product;
    }
}

当我尝试在提交后使用表单添加内容时,出现以下错误。

Error: Call to a member function add() on a non-object
500 Internal Server Error - FatalErrorException

堆栈跟踪:

{
    $product->addOffer($this);
    $this->products->add($product);
}
/**

根据此处的一个答案,我更改了代码,但我收到另一个错误,我认为它来自我在其中一个字段上使用的数据转换器。

<?php

namespace Zenith\OfferGeneratorBundle\Form\DataTransformer;

use Zenith\ProductBundle\Entity\Product;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;

class ProductNameTransformer implements DataTransformerInterface
{
    private $manager;

    public function __construct(ObjectManager $manager)
    {
        $this->manager = $manager;
    }

    /**
     * Transforms an object (issue) to a string (number).
     *
     * @param  Issue|null $issue
     * @return string
     */
    public function transform($issue)
    {
        if (null === $issue) {

            return '';
        }

        return $issue->getId();
    }

    /**
     * Transforms a string (number) to an object (issue).
     *
     * @param  string $issueNumber
     * @return Issue|null
     * @throws TransformationFailedException if object (issue) is not found.
     */
    public function reverseTransform($issueNumber)
    {
        // no issue number? It's optional, so that's ok
        if (!$issueNumber) {
            return;
        }

        $issue = $this->manager
            ->getRepository('ProductBundle:Product')
            // query for the issue with this id
            ->findByName($issueNumber)
        ;

        if (null === $issue) {
            // causes a validation error
            // this message is not shown to the user
            // see the invalid_message option
            throw new TransformationFailedException(sprintf(
                'An issue with number "%s" does not exist!',
                $issueNumber
            ));
        }

        return $issue;
    }
}

Notice: Array to string conversion
500 Internal Server Error - ContextErrorException

Stack Trace
in vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php at line 67   -
    public function bindValue($param, $value, $type = \PDO::PARAM_STR)
    {
        try {
            return parent::bindValue($param, $value, $type);
        } catch (\PDOException $exception) {
            throw new PDOException($exception);
        }
at ErrorHandler ->handleError ('8', 'Array to string conversion', '/var/www/f.dev/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php', '67', array('param' => '1', 'value' => array(object(Product)), 'type' => '2')) 
at PDOStatement ->bindValue ('1', array(object(Product)), '2') 
in vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php at line 67   + 
at PDOStatement ->bindValue ('1', array(object(Product)), '2') 
in vendor/doctrine/dbal/lib/Doctrine/DBAL/Statement.php at line 120   + 
at Statement ->bindValue ('1', array(object(Product)), 'string') 
in vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php at line 277   + 
at BasicEntityPersister ->executeInserts () 
in vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php at line 1018   + 
at UnitOfWork ->executeInserts (object(ClassMetadata)) 
in vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php at line 378   + 
at UnitOfWork ->commit (null) 
in vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php at line 356   + 
at EntityManager ->flush () 
in src/Zenith/OfferGeneratorBundle/Controller/OfferController.php at line 118   + 
at OfferController ->newOfferSubmitedAction (object(Request)) 
at call_user_func_array (array(object(OfferController), 'newOfferSubmitedAction'), array(object(Request))) 
in vendor/symfony/symfony/src/Symfony/Component/HttpKernel/HttpKernel.php at line 139   + 
at HttpKernel ->handleRaw (object(Request), '1') 
in vendor/symfony/symfony/src/Symfony/Component/HttpKernel/HttpKernel.php at line 62   + 
at HttpKernel ->handle (object(Request), '1', true) 
in vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php at line 169   + 
at Kernel ->handle (object(Request)) 
in web/app_dev.php at line 30   + 

您需要在 __construct 中初始化您的产品集合,否则您将尝试调用 add 空值(产品将被初始化为空值)。

public function __construct()
{
    $this->products = new ArrayCollection();
}