Daniel Gasser
Daniel Gasser

Reputation: 5133

Doctrine2 Save Many To One Objects

The relation is: MailTemplate may be used by many EMail but EMail is associated only to one MailTemplate.

The problem occurs when trying to insert new records. The error is:

Cannot access empty property

and appears in the setEmail() method

Definition of MailTemplate:

/**
* @Entity
* @Table(name="MailTemplate")
*/

class MailTemplate
{

    /**
     * @Id
     * @Column(type="integer", options={"unsigned":true})
     * @GeneratedValue(strategy="AUTO")
     */
    protected $mailtemplateID;

    /**
     * @ManyToOne(targetEntity="EMail", inversedBy="MailTemplate")
     * @JoinColumn(name="emailID", referencedColumnName="emailID")
     **/
    protected $email = null;
    // ...
    public function setEmail(EMail $email)
    {
        $this->$email = $email;
    }
}

Definition of EMail:

/**
* @Entity
* @Table(name="EMail")
*/

class EMail
{

    /**
     * @Id
     * @Column(type="integer", options={"unsigned":true})
     * @GeneratedValue(strategy="AUTO")
     */
    protected $emailID;
    // ...
}

Then, I try to create my objects like so:

$mail_template = new MailTemplate();
$email = new EMail();

//... Adding values with the usual setter methods

$entity_manager->persist($email);
$entity_manager->flush($email);

$mail_template->setEmail($email);

$entity_manager->persist($mail_template);
$entity_manager->flush($mail_template);

I also tried with the __construct() method like so:

// Inside the MailTemplate class
public function __construct(EMail $email)
{
    $this->$email = $email;
}

But I always get the error mentioned above. What am I missing?

Edit (on noobie-php's comment). I've added this to the EMail entity:

/**
 * @Id
 * @Column(type="integer", options={"unsigned":true})
 * @GeneratedValue(strategy="AUTO")
 * @OneToMany(targetEntity="MailTemplate", mappedBy="EMail")
 * @JoinColumn(name="mailtemplateID", referencedColumnName="mailtemplateID")
 */
protected $emailID;

But still the same error occurs...

Upvotes: 0

Views: 85

Answers (2)

Daniel Gasser
Daniel Gasser

Reputation: 5133

So, finally (as I tought) it was a stupid error.

I had to change the following things:

In the EMail entity:

  • Changed @OneToMany into @ManyToOne.
  • Added inversedBy="EMail"
  • Added cascade={"persist"}

In the MailTemplate entity:

  • Changed @ManyToOne into @OneToMany.
  • Changed inversedBy="MailTemplate" into mappedBy="MailTemplate"

Then one may work with the constructor or a setter to fill data.

Upvotes: 0

Marcel Djaman
Marcel Djaman

Reputation: 1286

Because of the inversedBy="MailTemplate" you have to do in Email entity class :

/**
* @Entity
* @Table(name="EMail")
*/

use Doctrine\Common\Collections\ArrayCollection;

class EMail
{

    /**
     * @Id
     * @Column(type="integer", options={"unsigned":true})
     * @GeneratedValue(strategy="AUTO")
     */
    protected $emailID;

   /**
     * @OneToMany(targetEntity="EMailTemplate", mappedBy="email")
     **/
    protected $mailTemplates = [];

    public function __construct()
    {
        parent::__construct();
        $this->mailTemplates = new ArrayCollection();
    }

    // getter and setters

MailTemplate.php

/**
 * @Entity
 * @Table(name="MailTemplate")
 */
 class MailTemplate
 {

        /**
         * @Id
         * @Column(type="integer", options={"unsigned":true})
         * @GeneratedValue(strategy="AUTO")
         */
        protected $mailtemplateID;

        /**
         * @ManyToOne(targetEntity="EMail")
         * @JoinColumn(name="emailID", referencedColumnName="emailID", nullable=true)
         **/
        protected $email = null;
        // ...
        public function setEmail(EMail $email)
        {
            $this->$email = $email;
        }
    }

Or simply remove inversedBy in $email property annotation on class MailTemplate

Upvotes: 1

Related Questions