I am trying implement this mapping strategy. I defined abstract class with id and other fields. but I keep getting following error:
No identifier/primary key specified for Entity "AppBundle\Entity\AbstractItem". Every Entity must have an identifier/primary key. (500 Internal Server Error)
This is my class. As you can see, unique identifier $id was specified
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\InheritanceType("JOINED")
* #ORM\DiscriminatorColumn(name="type", type="string")
* #ORM\DiscriminatorMap({"post" = "Post", "group" = "Group"})
*/
class AbstractItem
{
/**
* #var int
*
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var \DateTime
*/
protected $published;
protected $object;
protected $target;
/**
* #return mixed
*/
public function getId()
{
return $this->id;
}
}
This abstract class shouldn't be an actual entity in the database.
Try to put #ORM\MappedSuperClass instead of #ORM\Entity
try this please:
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
Instead of this:
/**
* #var int
*
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
You need to specify the column id inside comment
Related
can u help me with simple inheritance on Doctrine2?
I have basic class for all users:
/**
* Class User
*
* #ORM\Entity
* #ORM\Table(name="users")
* #InheritanceType("SINGLE_TABLE")
*/
class User
{
/**
* #ORM\Id()
* #ORM\Column(name="id", type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
* #var int
*/
private $_id;
/**
* #ORM\Column(name="email", type="string")
* #var int
*/
private $_email;
/**
* #ORM\Column(name="name", type="string")
* #var int
*/
private $_name;
/**
* #ORM\Column(name="password", type="string")
* #var int
*/
private $_password;
...
}
And I have child class:
/**
* Class Parent
*
* #ORM\Entity
* #ORM\Table(name="parents")
*/
class Parent extends User
{
/**
* #ORM\Id()
* #ORM\Column(name="id", type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
* #var int
*/
private $_id;
/**
* #ORM\Column(name="user_id", type="integer")
* #var int
*/
private $_user_id;
/**
* #ORM\Column(name="address", type="string")
* #var int
*/
private $_address;
...
}
How insert Parent.user_id after save User?
And are all the annotations correct?
I use laravel-doctrine and catch next exception:
File mapping drivers must have a valid directory path, however the given path [/var/www/app/Entities] seems to be incorrect!
I am trying to add a ManyToOne column to an already existing table with rows in it.
I want it to be nullable=false!
Since it is not nullable, I'm trying to set a default value, but there is no option to do it.
If I don't set a default value, the shema update crashes and is not able to create the foreign key since there is no row with id of 0 in the table I created
The code of the table refered by the foreign key:
<?php
namespace MyBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints;
/**
* #ORM\Table(name="authority")
* #ORM\Entity()
*/
class Authority
{
/**
* #var int
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string
* #Constraints\NotBlank(message="name cannot be blank.")
* #ORM\Column(type="string")
*/
protected $name;
/**
* #var \DateTime
*
* #ORM\Column(name="created_at", type="datetime", nullable=true)
*/
protected $createdAt;
/**
* Authority constructor.
*/
public function __construct()
{
$this->createdAt = new \DateTime();
}
}
The code of the table where I want to add the foreign key:
/**
* #var Authority
* #ORM\ManyToOne(targetEntity="MyBundle\Entity\authority", cascade={"persist"})
* #ORM\JoinColumn(referencedColumnName="id", nullable=false)
*/
protected $authority;
I tried:
protected $authority = 1;
or
* #ORM\JoinColumn(referencedColumnName="id", nullable=false, default=1)
or
public function __construct()
{
$this->authority = 1;
}
I don't want to have to change the database manually.
/**
* #var Authority
* #ORM\ManyToOne(targetEntity="MyBundle\Entity\authority", cascade={"persist"})
* #ORM\JoinColumn(referencedColumnName="id", nullable=false, columnDefinition="INT DEFAULT 1")
*/
protected $authority;
This do the trick in auto generated migration class.
You can set the default for the primary key of the referenced table. Look at the options={"default"=1}:
/**
* #ORM\Table(name="authority")
* #ORM\Entity()
*/
class Authority
{
/**
* #var int
* #ORM\Id
* #ORM\Column(type="integer", options={"default"=1})
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
#ORM\ManyToOne(targetEntity="App\Entity\Enumeration\TypeCompte")
#ORM\JoinColumn(name="IdTypeCompte", referencedColumnName="Id", nullable=false, columnDefinition="INT DEFAULT 1")
*/
private $typeCompte;
I got a ParentClass like this
/** #ORM\MappedSuperclass */
class BaseValue
{
/**
* #var int
*
* #ORM\Id
* #ORM\Column(name="id", type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var field
* #ORM\OneToMany(targetEntity="Field", mappedBy="value", cascade="all")
*/
protected $field;
/**
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* #param int $id
*/
public function setId($id)
{
$this->id = $id;
}
/**
* #return field
*/
public function getField()
{
return $this->field;
}
/**
* #param field $field
*/
public function setField($field)
{
$this->field = $field;
}
}
And a child like this
* #ORM\Entity
* #ORM\Table(name="integers")
*/
class Integer extends BaseValue
{
/**
* #var integer
*
* #ORM\Column(name="value", type="integer", nullable=true)
*/
protected $value;
/**
* #return string
*/
public function getValue()
{
return $this->value;
}
/**
* #param string $value
*/
public function setValue($value)
{
$this->value = $value;
}
}
Now I would like to relate the child in another class like this
* #ORM\Entity
* #ORM\Table(name="fields")
*/
class Field
{
/**
* #var int
*
* #ORM\Id
* #ORM\Column(name="id", type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var
* #ORM\ManyToOne(targetEntity="BaseValue", mappedBy="field", cascade="all")
* #ORM\JoinColumn(name="vid", referencedColumnName="id")
*/
protected $value; // but it does not work
It always gets me the following error:
[Doctrine\Common\Annotations\AnnotationException]
[Creation Error] The annotation #ORM\ManyToOne declared on property zmpim\Entity\Field::$value does not have a property named "mappedBy". Available properties: targetEntity, cascade, fetch, inversedBy
Both got mappedby,.. so the error seems to be senseless
Update:
A field has got values and labels. The values get inherited from BaseValue into IntegerValue, StringValue and later others...
My OneToMany Relation is a parent class of inheritance.
like this, now:
/** #ORM\MappedSuperclass */
class BaseValue
{
/**
* #var int
*
* #ORM\Id
* #ORM\Column(name="id", type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var Field
* #ORM\OneToMany(targetEntity="Field", mappedBy="field", cascade="persist", orphanRemoval=true )
*/
protected $field;
And this is my ManyToOne:
/**
*
* #ORM\Entity
* #ORM\Table(name="fields")
*/
class Field
{
/**
* #var int
*
* #ORM\Id
* #ORM\Column(name="id", type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var int|null
* #ORM\ManyToOne(targetEntity="BaseValue", inversedBy="value")
* #ORM\JoinColumn(name="vid", referencedColumnName="id", onDelete="CASCADE")
*/
protected $value;
It still give me an error, but now it is:
[Doctrine\ORM\ORMException]
Column name id referenced for relation from zmpim\Entity\Field towards zmpim\Entity\BaseValue does not exist.
Your Entity Field is the inversed side of your mapping so instead of using MappedBy declaration you have to use this
/**
* Inversed side
* #var int|null
* #ORM\ManyToOne(targetEntity="BaseValue", inversedBy="field")
* #ORM\JoinColumn(name="[your_name]", referencedColumnName="[id]", onDelete="CASCADE")
*/
protected $value;
To understand well inversedSide and MappedBy attributes you can read this:
Doctrine inverse and owning side
After reading again you are aware of your relationnal problem between the two of your entities, but if you declare ManyToOne annotation, you have to set inversedBy attribute or you'll get an error. And this is what you have.
You can't declare ManyToOne annotation with mappedBy attribute because it does not exist and throw an exception by Doctrine.
To resume :
ManyToOne association =>
* #ORM\ManyToOne(targetEntity="[yourEntity]", inversedBy="[Field]")
Be careful this side require the declaration of this :
* #ORM\JoinColumn(name="[your_name]", referencedColumnName="[id]", onDelete="CASCADE")
OneToMany =>
* #ORM\OneToMany(targetEntity="[An_Entity]",
* mappedBy="[Field]", cascade={"persist"}, orphanRemoval=true)
EDIT from your answer :
Your mapping is still incorrect, your data in InversedBy And mappedBy need to be switched.
In my web application, which is built with Symfony2, contains the following entities:
/**
* #ORM\Entity
* #ORM\Table
*/
class Entity
{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(name="id", type="integer")
*/
private $id;
/**
* #ORM\OneToMany(targetEntity="MappedSuperclass", mappedBy="entity", cascade={"persist", "remove"})
*/
private $mappedSuperclasses;
}
/**
* #ORM\MappedSuperclass
*/
abstract class MappedSuperclass
{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(name="id", type="integer")
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="Entity", inversedBy="mappedSuperclasses")
* #ORM\JoinColumn(name="entity_id", referencedColumnName="id", nullable=false)
*/
protected $entity;
}
/**
* #ORM\Entity
* #ORM\Table(name="table_1")
*/
class Subclass1 extends MappedSuperclass
{
/**
* #ORM\Column(name="unique_member", type="string")
*/
private $uniqueMember;
}
/**
* #ORM\Entity
* #ORM\Table(name="table_2")
*/
class Subclass2 extends MappedSuperclass
{
/**
* #ORM\Column(name="unique_member", type="string")
*/
private $uniqueMember; // This is different from Subclass1
}
I'll explain this a bit. An Entity has a collection of MappedSuperclass. MappedSuperclass is an abstract class which contains some common variables for its subclasses. Subclass1 and Subclass2 are subclasses of MappedSuperclass. When an Entity is removed from database, the items in $mappedSuperclasses should be removed together, that's why the cascade={"persist", "remove"} is set.
However, when I try to delete an Entity, I got the following error:
ContextErrorException: Notice: Undefined index: entity in C:\project\vendor\doctrine\orm\lib\Doctrine\ORM\Persisters\BasicEntityPersister.php line 1753
If I change the targetEntity of Entity::$mappedSuperclasses to Subclass1 or Subclass2, it will work. Is my set up impossible to achieve ON DELETE CASCADE? What am I missing?
I solved this problem by setting the ON DELETE action to database level:
/**
* #ORM\Entity
* #ORM\Table
*/
class Entity
{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(name="id", type="integer")
*/
private $id;
}
/**
* #ORM\MappedSuperclass
*/
abstract class MappedSuperclass
{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(name="id", type="integer")
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="Entity")
* #ORM\JoinColumn(name="entity_id", referencedColumnName="id", nullable=false, onDelete="CASCADE")
*/
protected $entity;
}
Sources: [1] [2]
Im answering year after the issue was resolved but I had the same problem. Error occurs when I tried to empty count arrayCollection.
So the solution was to check if $this->entity is array and then return its length.
I have two entity called PictureTag and Tag, here's the relationship:
/**
* #ORM\Entity
* #ORM\Table(name="picture_tag")
* #ORM\HasLifecycleCallbacks()
*/
class PictureTag
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
*
* #ORM\OneToOne(targetEntity="App\MainBundle\Entity\Tag", inversedBy="id")
* #ORM\JoinColumn(name="tag_id", referencedColumnName="id", nullable=false)
*/
private $tag;
}
/**
* #ORM\Entity
* #ORM\Table(name="tag")
* #ORM\HasLifecycleCallbacks()
*/
class Tag
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\ManyToOne(targetEntity="App\MainBundle\Entity\PictureTag", inversedBy="tag")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
* #ORM\Column(name="tag", type="string", nullable=true)
*/
private $tag;
}
Basically I wanted the tag table to contain all the unique tags, so there are no duplicate in the tag. And i wanted picturetag to have a joincolumn that points to the id of the tag. So here's my code in the controller:
foreach ($image->tags as $tag) {
$existingTag = $em->getRepository('AppMainBundle:InstagramTag')->findOneByTag($tag);
$instaPictureTag = new PictureTag();
if ($existingTag) {
$instaPictureTag->setTag($existingTag);
} else {
$instagramTag = new Tag();
$instagramTag->setTag($tag);
$em->persist($instagramTag);
$instaPictureTag->setTag($instagramTag);
}
$instaPictureTag->setPicture($instaShopPicture);
$em->persist($instaPictureTag);
}
So the relationship is basically:
One picture is going to have many tags. And one tag will belong to many pictures.
Picture tag here is the intermediary table.
Basically I am doing a check if the tag already exists in the tag table, if it is then I set the picturetag to be associated with this tag, if not then create one. However doing so generates the following error:
Fatal error: Call to a member function setValue() on a non-object in /Users/MyName/Sites/App/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php on line 2625
Any idea why this is?
As I understand, you want implement OneToMany bidirectional relation between PictureTag and Tag.
Please try:
/**
* #ORM\Entity
* #ORM\Table(name="picture_tag")
* #ORM\HasLifecycleCallbacks()
*/
class PictureTag
{
/**
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="DynamicSolutions\Bundle\ProsAndConsBundle\Entity\Tag", inversedBy="pictureTags")
* #ORM\JoinColumn(name="tag_id", referencedColumnName="id", nullable=false)
*/
private $tag;
}
/**
* #ORM\Entity
* #ORM\Table(name="tag")
* #ORM\HasLifecycleCallbacks()
*/
class Tag
{
/**
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\OneToMany(targetEntity="PictureTag", mappedBy="tag")
*/
private $pictureTags;
/**
* #var string
* #ORM\Column(name="tag", type="string", nullable=true)
*/
private $tag;
}