Doctrine :: Relation ManyToOne will not work - php

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.

Related

Missing value for primary key

I am upgrading from doctrine 2.3 to 2.5 and some of the relationships have broken.
I had a look other stack overflow questions. But there is only one id annotation is these classes and the join columns are named after their db column names, not their variable name on the entity
/**
* #Entity
* #Table(name="iso_country_shipping_display")
*/
class IsoCountryShippingDisplay {
/**
* #Id
* #GeneratedValue
* #Column(name="iso_country_shipping_display_id", type="integer", nullable=false)
*/
private $id;
/**
* #ManyToOne(targetEntity="namespace\Website")
* #JoinColumn(name="website_id", referencedColumnName="base_website_id", nullable=false, unique=false)
* #var Website
*/
private $baseWebsite;
/**
* #var IsoCountry
* #ManyToOne(targetEntity="namespace\IsoCountry")
* #JoinColumn(name="iso_3", referencedColumnName="iso_3", nullable=false, unique=false)
*/
private $isoCountry;
/**
* #return IsoCountry
*/
public function getIsoCountry()
{
return $this->isoCountry;
}
}
/**
* #Entity
* #Table(name="iso_country")
*/
class Website
{
/**
* #Id
* #Column(name="website_id", type="integer", nullable=false)
* #var integer
* #GeneratedValue
*/
protected $id;
/**
* #return int
*/
public function getId()
{
return $this->id;
}
}
I got the error message Missing value for primary key id on namespace\Website. I am not sure why I am getting this on doctrine 2.5 but not on 2.3.
Add * #GeneratedValue value annotation to the Website Entity.

How to constrain saving id number as a value of field in ManyToOne Doctrine relation?

I have ManyToOne relation defined below.
Persisting owning side object, with inversed object setted in there, resulting in saving row in db of owning side where column that I expect to have value of id foreign key (integer) instead it save name (string) field of inversed table side.
In other words:
column iptra_documents.document_category_id contains value from iptra_document_category.name. I'm expecting to have iptra_document_category.id value in iptra_documents.document_category_id
Owning side:
/**
* #ORM\Table(name="iptra_documents")
*/
class IptraDocuments
{
/**
* #var int
*
* #ORM\Column(name="document_id", type="integer", unique=true)
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $documentId;
/**
* #var IptraDocumentCategory
* #ORM\Column(name="document_category_id")
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\IptraDocumentCategory", inversedBy="id")})
*/
private $documentCategory;
//.....
public function setCategory(IptraDocumentCategory $documentCategory)
{
$this->documentCategory = $documentCategory;
}
Inverse side:
/**
* #ORM\Entity
* #ORM\Table(name="iptra_document_category")
*/
class IptraDocumentCategory
{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(name="id", type="integer")
*/
private $id;
/**
* #ORM\Column(name="parent_id", type="integer")
*/
private $parentId;
/**
* #ORM\Column(name="name", type="string")
*/
private $name;
/**
* #ORM\OneToMany(targetEntity="AppBundle\Entity\IptraDocuments", mappedBy="documentCategory")
*/
private $iptraDocuments;
According to the docs, you don't need #ORM\Column but #ORM\JoinColumn to define "Many" side
/**
* #var IptraDocumentCategory
*
* #ORM\JoinColumn(name="category_id", referencedColumnName="id")
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\IptraDocumentCategory", inversedBy="id")})
*/
private $documentCategory;

No identifier/primary key specified for Abstract Class

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

Doctrine. Why i get persistentCollection and an empty array on ManyToMany?

This is my Entity:
/**
* Productgeneral
* #ORM\Table(name="ProductGeneral", indexes={#ORM\Index(name="category_id", columns={"category_id"})})
* #ORM\Entity
*/
class Productgeneral {
//some cols
/**
* #var integer
*
* #ORM\Column(name="product_id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $productId;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\Productimg", inversedBy="product")
* #ORM\JoinTable(name="producttoimg",
* joinColumns={
* #ORM\JoinColumn(name="product_id", referencedColumnName="product_id")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="img_id", referencedColumnName="img_id")
* }
* )
*/
private $img;
/**
* Constructor
*/
public function __construct() {
$this->img = new \Doctrine\Common\Collections\ArrayCollection();
}
//getter & setters
}
/**
* Productimg
* #ORM\Table(name="ProductImg")
* #ORM\Entity
*/
class Productimg {
/**
* #var integer
*
* #ORM\Column(name="img_id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $imgId;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\Productgeneral", mappedBy="img")
*/
private $product;
/**
* Constructor
*/
public function __construct() {
$this->product = new \Doctrine\Common\Collections\ArrayCollection();
}
//getters & setters
}
When I run:
*$this->getDoctrine()->getRepository('AppBundle:Productgeneral')->findAll();*
I get every column with its correct value but img; which returns a PersistentCollection instead of an array of all the images.
Am I doing something wrong? Or have I just misunderstand the behavior of the relationship?
The default Doctrine behaviour is to lazy fetch mapped entities so when you make a dump of your entity it appears to be null because the data have not been loaded.
If you call the getImg method then doctrine will query your database to load the related Productimg entities linked to your product.
Once an ArrayCollection is persisted and managed by the entity manager it becomes a PersistentCollection it behaves exactly has an ArrayCollection

ManyToOne relation Symfony2

I have a many to one relation between my entities.
An application can have activities
<?php
namespace AppAcademic\ApplicationBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Activity
*
* #ORM\Table()
* #ORM\Entity
*/
class Activity
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="AppAcademic\ApplicationBundle\Entity\Application", inversedBy="activity")
* #ORM\JoinColumn(name="application_id", referencedColumnName="id", onDelete="CASCADE")
*/
private $application;
/**
* #var string
*
* #ORM\Column(name="title", type="string", length=255)
*/
private $title;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
public function setApplication($application)
{
$this->application = $application;
return $this;
}
public function getApplication()
{
return $this->application;
}
/**
* Set title
*
* #param string $title
* #return Activity
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get title
*
* #return string
*/
public function getTitle()
{
return $this->title;
}
}
And the application
/**
* Application
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="AppAcademic\ApplicationBundle\Entity\ApplicationRepository")
*/
class Application
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\OneToMany(targetEntity="AppAcademic\ApplicationBundle\Entity\Activity", mappedBy="application")
*/
protected $activities;
...
}
I have this in the profiler:
AppAcademic\ApplicationBundle\Entity\Application
The mappings AppAcademic\ApplicationBundle\Entity\Application#activities and AppAcademic\ApplicationBundle\Entity\Activity#application are inconsistent with each other.
AppAcademic\ApplicationBundle\Entity\Application
The mappings AppAcademic\ApplicationBundle\Entity\Application#activities and AppAcademic\ApplicationBundle\Entity\Activity#application are inconsistent with each other.
AppAcademic\ApplicationBundle\Entity\Activity
The association AppAcademic\ApplicationBundle\Entity\Activity#application refers to the inverse side field AppAcademic\ApplicationBundle\Entity\Application#activity which does not exist.
For the mapping annotation ManyToOne on the Activity::$application property, the attribute
inversedBy="activity"
This should be
inversedBy="activities"

Categories