la_f0ka
la_f0ka

Reputation: 1773

How do you save a record with a OneToMany relationship field with Doctrine 2?

how do you save a record (from a service) that has one of it's properties set as a OneToMany relationship with another entity?

I have the following service class for my users:

namespace Federico\Entity;
use Federico\Entity\User;
/**
 * Description of UserService
 *
 * @author fiodorovich
 */
class UserService {
protected $em;

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

public function saveUser($user) {
    if ($user['id'] != null) { //update 
        $entity = $this->getUser($user['id']);

        //do something

        if (!$entity)
            throw new Exception('Error saving user!');
    } else { //insert 
        $entity = new User();

        foreach ($user as $k => $v) {
            if ($k !== 'submit') {
                if ($k == 'password') {
                    //echo $this->_salt;die;
                    $entity->$k = $this->createPass($v);
                } else {
                    $entity->$k = $v;
                }
            }
        }
    }
    $this->em->persist($entity);
    $this->em->flush(); //save the user
}

//do something else...
}

But when I try saving the user and the countries property (a collection which refers to a OneToMany relationship oneUser-manyCountries) is set I get a "Class does not exist" exception.

EDIT: User and Countries entities

namespace Federico\Entity;
use Doctrine\Common\Collections\ArrayCollection;
/**
 * Description of User
 * @Table(name="users")
 * @Entity
 * @author fiodorovich
 */
class User 
{
/**
 * @var integer
 * @Id @Column (name="id", type="integer", nullable=false)
 * @GeneratedValue(strategy="AUTO")
 * 
 */
private $id;

/**
 * @Column(type="string",length=60,nullable=true, unique=true)
 * @var string
 */
private $email;

/**
 * @Column(type="string",length=60,nullable=true)
 * @var string
 */
private $password;

/**
 * @Column(type="string",length=60,nullable=true,unique=true)
 * @var string
 */
private $url;

/**
 * @Column(type="string",length=60,nullable=true,unique=true)
 * @var string
 */
private $responsable;

/**
 * @Column(type="string",length=20,nullable=true)
 * @var string
 */
private $role;

/**
 *
 * @var datetime
 * @Column(type="datetime", nullable=false)
 */
private $created;

/**
 * 
 * @param \Doctring\Common\Collections\Collection $property
 * @OneToMany(targetEntity="Countries",mappedBy="user", cascade={"persist", "remove"})
 */
private $countries;

public function __construct()
{
    $this->created = new \DateTime(date('Y-m-d H:i:s'));
    $this->countries = new ArrayCollection();

}

public function __get($property) 
{
    return $this->$property;
}

public function __set($property, $value)
{
    $this->$property = $value;
}

public function getCountries()
{
    return $this->countries;
}
}

And Countries entity:

namespace Federico\Entity;
/**
 * @Table(name="countries")
 * @Entity
 * @author fiodorovich
 * 
 */
class Countries {
/**
 * @var integer
 * @Id @Column (name="id", type="integer", nullable=false)
 * @GeneratedValue(strategy="AUTO")
 * 
 */
private $id;

/**
 *
 * @var string
 * @Column(type="string") 
 */
private $countryName;

/**
 *
 * @var User
 * @ManyToOne(targetEntity="User", inversedBy="id") 
 * @JoinColumns({
 *  @JoinColumn(name="user_id", referencedColumnName="id")
 * })
 */
private $user;


public function __get($property) 
{
    return $this->$property;
}

public function __set($property, $value)
{
    $this->$property = $value;
}

}

Upvotes: 1

Views: 4735

Answers (2)

Rene Terstegen
Rene Terstegen

Reputation: 8046

I do not see a line of code where you add a country to a user. If you want to add a country to a user keep in mind your $this->countries is a collection and you need to threat it that way. The magical setter you use will not work for collections.

To add a country to a user you also have to add the user to the country:

$User->countries->add($CountryObject);
$CountryObject->user = $User;

Afterwards save it to the database:

$EntityManager->persist($User);
$EntityManager->persist($CountryObject);
$EntityManager->flush();

Good luck!

@la_f0ka

You have two options here. In your previous approach your magical setter didn't work properly, but your magical getter was fine. You can just keep using $user->email instead of $user->getEmail(). Both are fine. Some say the magical getter is a bit slower, but I never noticed it.

Just don't access your attributes public. This ruins your encapsulation which is one of the biggest powers of Object Orriented programming.

Upvotes: 0

Jamie Krasnoo
Jamie Krasnoo

Reputation: 85

Read the documentation Working With Associations. Especially the section Association Management Methods. That should give you an idea as to how to add a record to an association. You didn't put up the User class/entity so I'm assuming you're initializing the "countries" field in __construct. Also, your error indicates that the autoloader is having trouble finding the User class or the Country class, of which I did not see you import in the 'use' statement in your example. The error could be for that and may be what is keeping you from moving forward.

Upvotes: 1

Related Questions