I'm trying to load Doctrine entities but it keeps creating the tables without any regard for the annotations I've provided. What I really want to do is put a unique constraint on $email but just to prove something's funny, I changed the size of the $email field to 200.
I'm trying to run the ./vendor/bin/doctrine orm:schema:create --dump-sql. I get the following output:
CREATE TABLE user (
id INT AUTO_INCREMENT NOT NULL,
email VARCHAR(255) NOT NULL,
unverifiedEmail VARCHAR(255) DEFAULT NULL,
unverifiedEmailHash VARCHAR(255) DEFAULT NULL,
passwordHash VARCHAR(255) NOT NULL,
passwordResetHash VARCHAR(255) DEFAULT NULL,
PRIMARY KEY (id)
) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
I formatted it pretty, but changed nothing else.
Here's my entity at vendor/redacted/user-entity/src/User.php
namespace Redacted\User\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="user")
*/
class User
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(name="id", type="integer")
* #var int
*/
protected $id;
/**
* #ORM\Column(name="email", type="string", length=255, unique=true)
* #var string
*/
protected $email;
/**
* #ORM\Column(name="unverifiedEmail", type="string", length=255, nullable=true)
* #var string
*/
protected $unverifiedEmail;
/**
* #ORM\Column(name="unverifiedEmailHash", type="string", length=255, nullable=true)
* #var string
*/
protected $verifyEmailHash;
/**
* #var string
* At this time, http://php.net/manual/en/function.password-hash.php recommends using 255 length for hashes
* #ORM\Column(name="passwordHash", type="string", length=255)
*/
protected $passwordHash;
/**
* #var string
* #ORM\Column(name="passwordResetHash", type="string", length=255, nullable=true)
*/
protected $passwordResetHash;
/**
* #return mixed
*/
public function getUnverifiedEmail()
{
return $this->unverifiedEmail;
}
/**
* #param mixed $unverifiedEmail
*/
public function setUnverifiedEmail($unverifiedEmail)
{
$this->unverifiedEmail = $unverifiedEmail;
}
/**
* #return mixed
*/
public function getVerifyEmailHash()
{
return $this->verifyEmailHash;
}
/**
* #param mixed $verifyEmailHash
*/
public function setVerifyEmailHash($verifyEmailHash)
{
$this->verifyEmailHash = $verifyEmailHash;
}
/**
* #return string
*/
public function getEmail()
{
return $this->email;
}
/**
* #param string $email
*/
public function setEmail($email)
{
$this->email = $email;
}
/**
* #return string
*/
public function getPasswordHash()
{
return $this->passwordHash;
}
/**
* #param string $passwordHash
*/
public function setPasswordHash($passwordHash)
{
$this->passwordHash = $passwordHash;
}
/**
* #return string
*/
public function getPasswordResetHash(): string
{
return $this->passwordResetHash;
}
/**
* #param string $passwordResetHash
*/
public function setPasswordResetHash(string $passwordResetHash)
{
$this->passwordResetHash = $passwordResetHash;
}
/**
* #return mixed
*/
public function getId()
{
return $this->id;
}
/**
* #param mixed $id
*/
public function setId($id)
{
$this->id = $id;
}
public function toArray()
{
return [
'email' => $this->getEmail(),
'id' => $this->getId()
];
}
}
And here's my cli-config.php.
require __DIR__.'/vendor/autoload.php';
$paths = array(__DIR__."/vendor/redacted/user-entity/src");
$isDevMode = false;
// the connection configuration
$dbParams = array(
'driver' => 'pdo_mysql',
'user' => 'root',
'password' => 'redacted',
'dbname' => 'user'
);
$config = Setup::createAnnotationMetadataConfiguration($paths, $isDevMode, null, null, false);
$entityManager = EntityManager::create($dbParams, $config);
return ConsoleRunner::createHelperSet($entityManager);
One more thing I should mention: I have never got this working before in several projects. We just have so many on the go and they all have this issue and I'm getting around to resolve it, but I did have this working in tons of ZF2 projects, but they don't share this setup scheme.
As #malarzm said above, you may need to clear your cache. Here are the commands I run any time I change doctrine configurations in my ZF2 app:
rm -Rf data/DoctrineModule/cache/*
rm -Rf data/DoctrineORMModule/Proxy/*
Related
I have a problem with doctrine. I have two entities.
FriendRequest
class FriendRequest
{
/** #ORM\Id #ORM\Column(type="integer") #ORM\GeneratedValue **/
protected $id;
/**
* First person from friendship
*
* #ORM\OneToOne(targetEntity="User")
* #ORM\JoinColumn(name="id", referencedColumnName="id")
*/
protected $from;
/**
* Second person from friendship
*
* #ORM\OneToOne(targetEntity="User")
* #ORM\JoinColumn(name="id", referencedColumnName="id")
*/
protected $to;
/**
* #return mixed
*/
public function getId()
{
return $this->id;
}
/**
* #return mixed
*/
public function getFrom()
{
return $this->from;
}
/**
* #param mixed $from
*/
public function setFrom($from)
{
$this->from = $from;
}
/**
* #return mixed
*/
public function getTo()
{
return $this->to;
}
/**
* #param mixed $to
*/
public function setTo($to)
{
$this->to = $to;
}
}
And User
/**
* #ORM\Entity #ORM\Table(name="users")
*/
class User
{
/** #ORM\Id #ORM\Column(type="integer") #ORM\GeneratedValue **/
protected $id;
/** #ORM\Column(type="string") **/
protected $email;
/** #ORM\Column(type="string") **/
protected $password;
/** #ORM\Column(type="string") **/
protected $name;
/** #ORM\Column(type="string") **/
protected $surname;
/** #ORM\Column(type="date") **/
protected $date;
/** #ORM\Column(type="string") **/
protected $sex;
/**
* #return mixed
*/
public function getSex()
{
return $this->sex;
}
/**
* #param mixed $sex
*/
public function setSex($sex)
{
$this->sex = $sex;
}
/**
* #return mixed
*/
public function getId()
{
return $this->id;
}
/**
* #param mixed $id
*/
public function setId($id)
{
$this->id = $id;
}
/**
* #return mixed
*/
public function getEmail()
{
return $this->email;
}
/**
* #param mixed $email
*/
public function setEmail($email)
{
$this->email = $email;
}
/**
* #return mixed
*/
public function getPassword()
{
return $this->password;
}
/**
* #param mixed $password
*/
public function setPassword($password)
{
$this->password = $password;
}
/**
* #return mixed
*/
public function getName()
{
return $this->name;
}
/**
* #param mixed $name
*/
public function setName($name)
{
$this->name = $name;
}
/**
* #return mixed
*/
public function getSurname()
{
return $this->surname;
}
/**
* #param mixed $surname
*/
public function setSurname($surname)
{
$this->surname = $surname;
}
/**
* #return mixed
*/
public function getDate()
{
return $this->date;
}
/**
* #param mixed $date
*/
public function setDate($date)
{
$this->date = $date;
}
}
I tried to create the new friendship request.
$from = $this->entity_manager->getRepository(User::class)->findOneBy(
["id" => $my_id]
);
$to = $this->entity_manager->getRepository(User::class)->findOneBy(
["id" => $target_user_id]
);
/** #var FriendRequest $friend_request */
$friend_request = new FriendRequest();
$friend_request->setFrom($from);
$friend_request->setTo($to);
$this->entity_manager->persist($friend_request);
$this->entity_manager->flush();
But it does not work. Doctrine shows me error:
An exception occurred while executing 'INSERT INTO friendRequest (id) VALUES (?)' with params [186]:
SQLSTATE[HY000]: General error: 1364 Field 'from' doesn't have a default value.
I tried to print $from ad $to, but they are correct. Is there someone who know what does it mean? I spent a lot of time with it, but I dont know...
I think your issue comes from the declaration of the $from and $to attributes in the FriendRequest entity class, if you try to update your database model you are going to get an error like this:
[Doctrine\ORM\Mapping\MappingException]
Duplicate definition of column 'id' on entity 'FriendRequest' in a field or discriminator column mapping.
Since you have assigned the same name 'id' for two different attributes. Probably you have in your database two columns From and To, but they are not mapping with your model, that's why you get an error saying from doesn't have a default value. Since the column name in the database are not sync with the name of the attributes in your entity.
Assuming you already have a FriendRequest table and you are using 'from' and 'to' as the column names this should be the update of the FriendRequest entity class.
class FriendRequest
{
/** #ORM\Id #ORM\Column(type="integer") #ORM\GeneratedValue **/
protected $id;
/**
* First person from friendship
*
* #ORM\OneToOne(targetEntity="User")
* #ORM\JoinColumn(name="from", referencedColumnName="id")
*/
protected $from;
/**
* Second person from friendship
*
* #ORM\OneToOne(targetEntity="User")
* #ORM\JoinColumn(name="to", referencedColumnName="id")
*/
protected $to;
...
}
I would like to use a VichUploaderBundle for upload files in my symfony 3.2.3 project (PHP 5.6). I try lot of thing but nothing upload run. But the persistance layer run perfeclty with my database.
config.yml
knp_gaufrette:
stream_wrapper: ~
adapters:
fileupload_adapter:
local:
directory: %kernel.root_dir%/../web/
create: true
filesystems:
fileupload_fs:
adapter: fileupload_adapter
# VichUploaderBundle Configuration
vich_uploader:
db_driver: orm
twig: true
storage: gaufrette
mappings:
tgmedia_file:
uri_prefix: web
upload_destination: fileupload_fs
namer: vich_uploader.namer_origname
Entity
namespace MediaBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use TweedeGolf\MediaBundle\Model\AbstractFile;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
* #ORM\Entity
* #Vich\Uploadable
* #ORM\HasLifecycleCallbacks
* #ORM\Table
*/
class FileUpload
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* NOTE: This is not a mapped field of entity metadata, just a simple property.
*
* #Vich\UploadableField(mapping="tgmedia_file", fileNameProperty="imageName")
*
* #var File
*/
protected $imageFile;
/**
* #ORM\Column(type="string", length=255)
*
* #var string
*/
private $imageName;
/**
* #ORM\Column(type="datetime")
*
* #var \DateTime
*/
protected $updatedAt;
/**
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* #return File|null
*/
public function getImageFile()
{
return $this->imageFile;
}
/**
* If manually uploading a file (i.e. not using Symfony Form) ensure an instance
* of 'UploadedFile' is injected into this setter to trigger the update. If this
* bundle's configuration parameter 'inject_on_load' is set to 'true' this setter
* must be able to accept an instance of 'File' as the bundle will inject one here
* during Doctrine hydration.
*
* #param File|\Symfony\Component\HttpFoundation\File\UploadedFile $image
*
* #return Product
*/
public function setImageFile(File $image = null)
{
$this->imageFile = $image;
if ($image) {
// It is required that at least one field changes if you are using doctrine
// otherwise the event listeners won't be called and the file is lost
$this->updatedAt = new \DateTimeImmutable();
}
return $this;
}
/**
* #param string $imageName
*
* #return FileUpload
*/
public function setImageName($imageName)
{
$this->imageName = $imageName;
return $this;
}
/**
* #return string|null
*/
public function getImageName()
{
return $this->imageName;
}
/**
* Set updatedAt
*
* #param \DateTime $updatedAt
*
* #return FileUpload
*/
public function setUpdatedAt($updatedAt)
{
$this->updatedAt = $updatedAt;
return $this;
}
/**
* Get updatedAt
*
* #return \DateTime
*/
public function getUpdatedAt()
{
return $this->updatedAt;
}
}
The formType
<?php
namespace MediaBundle\Form;
use MediaBundle\Entity\File;
use MediaBundle\Entity\FileUpload;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Vich\UploaderBundle\Form\Type\VichFileType;
use Vich\UploaderBundle\Form\Type\VichImageType;
class FileUploadType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('imageName')
->add('imageFile', VichImageType::class, [
'required' => false,
'allow_delete' => true,
'download_link' => true,
'mapped' => false,
'data_class' => null
])
->add('submit', SubmitType::class);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => FileUpload::class,
'csrf_protection' => false,
));
}
}
Controller
<?php
namespace MediaBundle\Controller;
use MediaBundle\Entity\File;
use MediaBundle\Entity\FileUpload;
use MediaBundle\Entity\Product;
use MediaBundle\Form\FileType;
use MediaBundle\Form\FileUploadType;
use MediaBundle\Form\ProductType;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class MainController extends Controller
{
public function indexAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$fileUploaded = new FileUpload();
$form = $this->createForm(FileUploadType::class, $fileUploaded, array(
'action' => $this->generateUrl('media_main')
));
$form->handleRequest($request);
if ($form->isSubmitted())
{
$fileUploaded->setUpdatedAt(new \DateTime());
$fileUploaded->setImageFile($form->get('imageFile')->getData());
$em->persist($fileUploaded);
$em->flush();
}
return $this->render('MediaBundle:main:index.html.twig', array(
'form' => $form->createView()
));
}
}
Where is my error ? What wrong ?
uri_prefix: /project/web/fileupload_fs
upload_destination: '%kernel.root_dir%/../web/fileupload_fs'
uri_prefix begins from www folder.
and change controller like that
if ($form->isSubmitted() && $form->isValid())
{
$em->persist($fileUploaded);
$em->flush();
}
I have the following:
User have one group, group can have many users
User
<?php namespace Application\Model;
use Doctrine\Common\Collections;
use Doctrine\ORM\Mapping as ORM;
/**
* User model
* Read-only entity
* #ORM\Table(name="VLOGGER_WEBCALENDAR_USR")
* #ORM\Entity
* #package Application\Model
*/
class User
{
/**
* #var int
* #ORM\Id
* #ORM\Column(name="USR_ID", type="integer")
*/
protected $id;
/**
* #var string
* #ORM\Column(name="USR_LOGIN", type="string")
*/
protected $login;
/**
* #var string
* #ORM\Column(name="USR_CODE", type="string")
*/
protected $code;
/**
* #var int
* #ORM\Column(name="GRP_ID", type="integer")
*/
protected $groupId;
/**
* #var string
* #ORM\Column(name="GRP_CODE", type="string")
*/
protected $groupCode;
/**
* #var User\Group
* #ORM\ManyToOne(targetEntity="Application\Model\User\Group",fetch="EAGER")
* #ORM\JoinColumn(name="GRP_ID", referencedColumnName="GRP_ID")
*/
protected $group;
/**
* #var Event
* #ORM\OneToMany(targetEntity="Application\Model\Event", mappedBy="user")
* #ORM\JoinColumn(name="USR_ID", referencedColumnName="USR_ID")
*/
protected $events;
/**
* Constructor
*/
public function __construct()
{
$this->events = new Collections\ArrayCollection();
}
/**
* #return string
*/
public function getCode()
{
return $this->code;
}
/**
* #param string $code
* #return User
*/
public function setCode($code)
{
$this->code = $code;
return $this;
}
/**
* #return Event
*/
public function getEvents()
{
return $this->events;
}
/**
* #param Event $events
* #return User
*/
public function setEvents($events)
{
$this->events = $events;
return $this;
}
/**
* #return User\Group
*/
public function getGroup()
{
return $this->group;
}
/**
* #param User\Group $group
* #return User
*/
public function setGroup($group)
{
$this->group = $group;
return $this;
}
/**
* #return string
*/
public function getGroupCode()
{
return $this->groupCode;
}
/**
* #param string $groupCode
* #return User
*/
public function setGroupCode($groupCode)
{
$this->groupCode = $groupCode;
return $this;
}
/**
* #return int
*/
public function getGroupId()
{
return $this->groupId;
}
/**
* #param int $groupId
* #return User
*/
public function setGroupId($groupId)
{
$this->groupId = $groupId;
return $this;
}
/**
* #return mixed
*/
public function getId()
{
return $this->id;
}
/**
* #param mixed $id
* #return User
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* #return string
*/
public function getLogin()
{
return $this->login;
}
/**
* #param string $login
* #return User
*/
public function setLogin($login)
{
$this->login = $login;
return $this;
}
}
Group
<?php namespace Application\Model\User;
use Application\Model;
use Doctrine\Common\Collections;
use Doctrine\ORM\Mapping as ORM;
/**
* User group model
* Read-only entity
* #ORM\Table(name="VLOGGER_WEBCALENDAR_GRP")
* #ORM\Entity
* #package Application\Model
*/
class Group
{
/**
* #var int
* #ORM\Id
* #ORM\Column(name="GRP_ID", type="integer")
*/
protected $id;
/**
* #var string
* #ORM\Column(name="GRP_CODE", type="string")
*/
protected $code;
/**
* #var Collections\ArrayCollection
* #ORM\OneToMany(targetEntity="Application\Model\User", mappedBy="group")
* #ORM\JoinColumn(name="GRP_ID", referencedColumnName="GRP_ID")
*/
protected $users;
/**
* Constructor
*/
public function __construct()
{
$this->users = new Collections\ArrayCollection();
}
/**
* #return mixed
*/
public function getCode()
{
return $this->code;
}
/**
* #param mixed $code
* #return Group
*/
public function setCode($code)
{
$this->code = $code;
return $this;
}
/**
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* #param int $id
* #return Group
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* #return mixed
*/
public function getUsers()
{
return $this->users;
}
/**
* #param mixed $users
* #return Group
*/
public function setUsers($users)
{
$this->users = $users;
return $this;
}
}
When I try to retrieve the relation from the groups, it works great, but when I slect the users and try to get their group, Doctrine create some proxy objects and the result is an empty object with only the relationship key filled.
Can someone point me to the good direction ?
Here my code:
$query = $em->createQueryBuilder()
->select('u')
->from('Application\Model\User', 'u');
$data = $query->getQuery()->getResult();
$data = reset($data);
var_dump($data->getGroup()); // proxy
###########################
$query = $em->createQueryBuilder()
->select('g')
->from('Application\Model\User\Group', 'g');
$data = $query->getQuery()->getResult();
$data = reset($data);
var_dump($data->getUsers()); // ok
you don't need the $GRP_ID in the User Entity - it's already mapped with the $group relation. Doctrine handles the IDs automatically.
Also your naming-convention looks a bit weird. Normally you should use lowe-camel-case (to save you from strange errors)
Example:
$USR_CODE should be $usrCode -> to match your getter/setter: setUsrCode(), getUsrCode().
just noticed: you don't have any setters. You have to define setters for your attributes, with the naming-convention (look at my example above)
Edit:
you can map the column with the doctrine orm notation:
/**
*
* #ORM\Column(name="USR_CODE", type="string")
*/
private $usrCode;
And yes, you need setters otherwise doctrine won't be able to set the values.
You also need addUser() and removeUser() functions (since user is a Collection):
public function addUsers(Collection $users)
{
foreach($users as $user)
{
if( ! $this->users->contains($user))
{
$this->users->add($user);
$user->setGroup($this);
}
}
}
public function removeUsers(Collection $users)
{
foreach($users as $user)
{
if($this->users->contains($user)){
$this->users->remove($user);
$user->setGroup(null);
}
}
}
I have following entities:
User
/**
* Users
*
* #ORM\Table(name="users")
* #ORM\Entity(repositoryClass="Users\Entity\Repository\UsersRepository")
* #Annotation\Name("user")
* #Annotation\Hydrator("Zend\Stdlib\Hydrator\ClassMethods")
*/
class User
{
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=100, nullable=false)
* #Annotation\Filter({"name":"StringTrim"})
* #Annotation\Validator({"name":"StringLength", "options":{"min":2, "max":100}})
* #Annotation\Attributes({"type":"text","class":"form-control"})
* #Annotation\Options({"label":"Full name:"})
*/
private $name;
/**
* #var User\Entity\UserItem
*
* #ORM\OneToMany(targetEntity="User\Entity\UserItem", mappedBy="user")
* #Annotation\Exclude()
*/
private $items;
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #Annotation\Exclude()
*/
private $id;
public function __construct()
{
$this->vessels = new ArrayCollection();
}
public function setName($name)
{
$this->name = $name;
return $this;
}
public function getName()
{
return $this->name;
}
public function getId()
{
return $this->id;
}
public function getItems()
{
return $this->items
}
public function setItems($items)
{
$this->itemr = $items;
return $this;
}
Item
/**
* Items
* #ORM\Entity
* #ORM\Table(name="items")
* #ORM\Entity(repositoryClass="User\Entity\Repository\ItemsRepository")
* #Annotation\Name("item")
* #Annotation\Hydrator("Zend\Stdlib\Hydrator\ClassMethods")
*/
class Item
{
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=100, nullable=false)
* #Annotation\Filter({"name":"StringTrim"})
* #Annotation\Validator({"name":"StringLength", "options":{"min":2, "max":100}})
* #Annotation\Attributes({"type":"text","class":"form-control"})
* #Annotation\Options({"label":"Name:"})
*/
private $name;
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #Annotation\Exclude()
*/
private $id;
And finally entity keepeing relation between those two
UserItem
/**
* UserItem
*
* #ORM\Table(name="users_items")
* #ORM\Entity(repositoryClass="User\Entity\Repository\UserItemsRepository")
* #Annotation\Name("user_item")
* #Annotation\Hydrator("Zend\Stdlib\Hydrator\ClassMethods")
*/
class UserItem{
/**
* #var Users\Entity\User
*
* #ORM\ManyToOne(targetEntity="Users\Entity\User", inversedBy="items")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
* #Annotation\Exclude()
*/
private $user;
/**
* #var User\Entity\Item
*
* #ORM\ManyToOne(targetEntity="User\Entity\Item", inversedBy="users")
* #ORM\JoinColumn(name="item_id", referencedColumnName="id")
* #Annotation\Type("DoctrineModule\Form\Element\ObjectSelect")
*/
private $item;
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #Annotation\Exclude()
*/
private $id;
With this entities i can create and edit User and Item. Form are generated from annotations.
My question is how can i generate form for assigning items to user. Preferably as select field(s) with multiple selection. And after submitting doctrine should save the relations.
I wrote this form to represent items to select:
class ItemsForm extends Form
{
public function __construct($entityManager, $name = null)
{
parent::__construct('items');
$this->setAttribute('method', 'post');
$this->add(array(
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'name' => 'items',
'attributes' => array(
'id' => 'selectItems',
'multiple' => true,
'data-placeholder' => 'Items'
),
'options' => array(
'object_manager' => $entityManager,
'target_class' => 'User\Entity\Item',
'property' => 'name',
),
)
);
}
}
And now i do not know how to preselect items user has already assigned.
In select field in value you must have id from items. After submit you can do something like that
foreach($post['items'] as $itemId)
{
$userItem = new UserItem();
$userItem->user = $this->getEntityManager()->getReference('User', $userId);
$userItem->item = $this->getEntityManager()->getReference('Item', $itemId);
$this->getEntityManager()->save($userItem);
}
I'm working on a survey project and I got 3 Entities, survey(umfrage), surveyQuestion(umfrageFrage) and surveyAnswer(umfrageAntwort).
Here are the entities(removed all unnecessary fields):
namespace Umfrage\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
/**
* Umfrage
*
* #ORM\Table(name="umfrage")
* #ORM\Entity
*/
class Umfrage
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var Fragen
*
* #ORM\OneToMany(targetEntity="Umfrage\Entity\UmfrageFrage", mappedBy="umfrage", cascade={"persist","remove"})
*/
private $fragen;
public function __construct() {
$this->fragen = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set fragen
*
* #param \Umfrage\Entity\UmfrageFrage $fragen
*
* #return UmfrageFrage
*/
public function setFragen($fragen)
{
$this->fragen = $fragen;
return $this;
}
/** Get fragen
*
* #param \Umfrage\Entity\UmfrageFrage $fragen
*
* #return UmfrageFrage
*/
public function getFragen() {
return $this->fragen;
}
public function addFragen(Collection $fragen)
{
foreach ($fragen as $frage) {
$frage->setUmfrage($this);
$this->fragen->add($frage);
}
}
public function removeFragen(Collection $fragen)
{
foreach ($fragen as $frage) {
$frage->setUmfrage(null);
$this->fragen->removeElement($frage);
}
}
}
The Questions:
namespace Umfrage\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
/**
* UmfrageFrage
*
* #ORM\Table(name="umfrage_frage")
* #ORM\Entity
*/
class UmfrageFrage
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var \Umfrage\Entity\Umfrage
*
* #ORM\ManyToOne(targetEntity="Umfrage\Entity\Umfrage", inversedBy="fragen")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="umfrage_id", referencedColumnName="id")
* })
*/
private $umfrage;
/**
* #var Antworten
*
* #ORM\OneToMany(targetEntity="Umfrage\Entity\UmfrageAntwort", mappedBy="umfrageFrage", cascade={"all"})
*/
private $antworten;
public function __construct() {
$this->antworten = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set umfrage
*
* #param \Umfrage\Entity\Umfrage $umfrage
*
* #return UmfrageFrage
*/
public function setUmfrage(\Umfrage\Entity\Umfrage $umfrage = null)
{
$this->umfrage = $umfrage;
return $this;
}
/**
* Get umfrage
*
* #return \Umfrage\Entity\Umfrage
*/
public function getUmfrage()
{
return $this->umfrage;
}
/**
* Set antworten
*
* #param \Umfrage\Entity\UmfrageAntwort $antworten
*
* #return UmfrageAntwort
*/
public function setAntworten($antworten)
{
$this->antworten = $antworten;
return $this;
}
/** Get antworten
*
* #param \Umfrage\Entity\UmfrageAntwort $antworten
*
* #return UmfrageAntwort
*/
public function getAntworten() {
return $this->antworten;
}
public function addAntworten(Collection $antworten)
{
foreach ($antworten as $antwort) {
$antwort->setUmfrageFrage($this);
$this->antworten->add($antwort);
}
}
public function removeAntworten(Collection $antworten)
{
foreach ($antworten as $antwort) {
$this->antworten->removeElement($antwort);
}
}
}
The Answers:
namespace Umfrage\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
/**
* UmfrageAntwort
*
* #ORM\Table(name="umfrage_antwort")
* #ORM\Entity
*/
class UmfrageAntwort
{
/**
* #var integer
*
* #ORM\Column(name="id", type="bigint", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var \Umfrage\Entity\UmfrageFrage
*
* #ORM\ManyToOne(targetEntity="Umfrage\Entity\UmfrageFrage", inversedBy="antworten")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="umfrage_frage_id", referencedColumnName="id")
* })
*/
private $umfrageFrage;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set umfrageFrage
*
* #param \Umfrage\Entity\UmfrageFrage $umfrageFrage
*
* #return UmfrageFrage
*/
public function setUmfrageFrage($umfrageFrage)
{
$this->umfrageFrage = $umfrageFrage;
return $this;
}
/**
* Get umfrageFrage
*
* #return \Umfrage\Entity\UmfrageFrage
*/
public function getUmfrageFrage()
{
return $this->umfrageFrage;
}
}
The Controller action:
public function editAction()
{
$id = (int) $this->params()->fromRoute('id', 0);
if (!$id) {
return $this->redirect()->toRoute('umfrage', array('action'=>'add'));
}
$umfrage = $this->getEntityManager()->find('Umfrage\Entity\Umfrage', $id);
$form = new UmfrageForm($this->getEntityManager());
$form->setHydrator(new DoctrineEntity($this->getEntityManager(),'Umfrage\Entity\Umfrage'));
$form->bind($umfrage);
$request = $this->getRequest();
if ($request->isPost()) {
$form->setData($request->getPost());
if ($form->isValid()) {
$this->getEntityManager()->persist($umfrage);
$this->getEntityManager()->flush();
// Redirect to overview
return $this->redirect()->toRoute('umfrage');
}
}
$this->layout('layout/umfrage_backend');
return new ViewModel(array(
'id' => $id,
'form' => $form
));
}
And the view:
<?php
// module/Umfrage/view/umfrage/umfrage/edit.phtml:
use Doctrine\Common\Util\Debug;
$title = 'Umfrage bearbeiten';
$this->headTitle($title);
?>
<h1><?php echo $this->escapeHtml($title); ?></h1>
<?php
$form = $this->form;
$form->setAttribute('action', $this->url(
'umfrage',
array(
'action' => 'edit',
'id' => $this->id,
)
));
echo $this->ztbForm($form);
?>
Adding a Survey works fine, Deleting also, the Survey and its related Questions/Answers are removed from the DB. Only the Update actions doesn't work as expected. Survey and Questions are updated, but for the Answers I receive an Insert, instead of an Update, which results in duplicate entries in the DB. What's wrong with the Mapping(Code)?
Thanks in advance for your help!