I appear to be having a problem creating a simple One to Many relationship between my blog and my blog_link_tag join table. I'm almost there however I keep on receiving the following mapping error from Doctrine and I'm wondering if anyone can point out where I'm going wrong?
The association Acme\BlogBundle\Entity\Blog#tags refers to the owning side field Acme\BlogBundle\Entity\BlogLinkTag#blog_id which does not exist.
Below is the table structure I'm using with unnecessary fields removed.
CREATE TABLE `blog` (
`id` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `blog_link_tag` (
`id` int(3) NOT NULL AUTO_INCREMENT,
`blog_id` int(3) NOT NULL,
`tag_id` int(3) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Blog.php
<?php
namespace Acme\BlogBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Blog
*
* #ORM\Table(name="blog")
* #ORM\Entity(repositoryClass="Acme\BlogBundle\Entity\BlogRepository")
* #ORM\HasLifecycleCallbacks
*/
class Blog {
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #ORM\OneToMany(targetEntity="BlogLinkTag", mappedBy="blog_id")
*/
protected $tags;
public function __construct() {
$this->tags = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId() {
return $this->id;
}
/**
* Add tags
*
* #param \Acme\BlogBundle\Entity\BlogLinkTag $tags
* #return Blog
*/
public function addTag(\Acme\BlogBundle\Entity\BlogLinkTag $tags) {
$this->tags[] = $tags;
return $this;
}
/**
* Remove tags
*
* #param \Acme\BlogBundle\Entity\BlogLinkTag $tags
*/
public function removeTag(\Acme\BlogBundle\Entity\BlogLinkTag $tags) {
$this->tags->removeElement($tags);
}
/**
* Get tags
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getTags() {
return $this->tags;
}
/**
* Set tags
*
* #param integer $tags
* #return Blog
*/
public function setTags($tags) {
$this->tags = $tags;
return $this;
}
}
BlogLinkTag.php
<?php
namespace Acme\BlogBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* BlogLinkTag
*
* #ORM\Table(name="blog_link_tag")
* #ORM\Entity
*/
class BlogLinkTag
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var integer
* #ORM\Column(name="blog_id", type="integer", nullable=false)
* #ORM\ManyToOne(targetEntity="Blog", inversedBy="blog")
* #ORM\JoinColumn(name="blog_id", referencedColumnName="blog_id")
*/
private $blogId;
/**
* #var integer
*
* #ORM\Column(name="tag_id", type="integer", nullable=false)
*/
private $tagId;
/**
* Get id
*
* #return integer
*/
public function getId() {
return $this->id;
}
/**
* Set blogId
*
* #param integer $blogId
* #return BlogLinkTag
*/
public function setBlogId($blogId) {
$this->blogId = $blogId;
return $this;
}
/**
* Get blogId
*
* #return integer
*/
public function getBlogId() {
return $this->blogId;
}
/**
* Set tagId
*
* #param integer $tagId
* #return BlogLinkTag
*/
public function setTagId($tagId) {
$this->tagId = $tagId;
return $this;
}
/**
* Get tagId
*
* #return integer
*/
public function getTagId() {
return $this->tagId;
}
}
Take a look at the official documentation about association mapping here.
Try this :
In BlogLinkTag
/**
* #var integer
* #ORM\ManyToOne(targetEntity="Blog", inversedBy="tags") //put the name of the variable in the other entity here
* #ORM\JoinColumn(name="blog_id", referencedColumnName="id") //reference of the column targetted here
*/
private $blog;
In Blog :
/**
* #ORM\OneToMany(targetEntity="BlogLinkTag", mappedBy="blog") //put the name of the variable in the other entity here
*/
protected $tags;
Related
Hi guys i have two objects Point and Subpoint when i got from the repository with custom DQL The point i want to order the Points by field ord and the Subpoints to field ord.
Here is the Entities:
namespace George\ArchitectureBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Model\Translatable\Translatable;
use Doctrine\Common\Collections\ArrayCollection;
use Gedmo\Mapping\Annotation as Gedmo;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
use Symfony\Component\HttpFoundation\File\File;
/**
* Point
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="George\ArchitectureBundle\Entity\PointRepository")
* #Vich\Uploadable
*/
class Point
{
use Translatable;
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var Object
* #Gedmo\SortableGroup
* #ORM\ManyToOne(targetEntity="George\ObjectsBundle\Entity\Object", inversedBy="architecturespoints")
* #ORM\JoinColumn(name="object_id", referencedColumnName="id")
*/
private $object;
/**
* #ORM\OneToMany(targetEntity="George\ArchitectureBundle\Entity\Subpoint", mappedBy="point")
*/
private $subpoints;
/**
* #var integer
* #Gedmo\SortablePosition
* #ORM\Column(name="ord", type="integer")
*/
private $ord;
/**
* #var \DateTime
* #Gedmo\Timestampable(on="update")
* #ORM\Column(name="updated", type="datetime")
*/
private $updated;
/**
* #var \DateTime
* #Gedmo\Timestampable(on="create")
* #ORM\Column(name="created", type="datetime")
*/
private $created;
public function __construct()
{
$this->subpoints = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* #return Object
*/
public function getObject()
{
return $this->object;
}
/**
* #param Object $object
*/
public function setObject($object)
{
$this->object = $object;
}
/**
* #return int
*/
public function getOrd()
{
return $this->ord;
}
/**
* #param int $ord
*/
public function setOrd($ord)
{
$this->ord = $ord;
}
/**
* #return \DateTime
*/
public function getUpdated()
{
return $this->updated;
}
/**
* #return \DateTime
*/
public function getCreated()
{
return $this->created;
}
/**
* #return mixed
*/
public function getSubpoints()
{
return $this->subpoints;
}
/**
* NOTE: This is not a mapped field of entity metadata, just a simple property.
*
* #Vich\UploadableField(mapping="point_image", fileNameProperty="imageName")
*
* #var File
*/
private $imageFile;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*
* #var string
*/
private $imageName;
/**
* 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
*/
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->setModefied(new \DateTime('now')) ;
}
}
/**
* #return File
*/
public function getImageFile()
{
return $this->imageFile;
}
/**
* #param string $imageName
*/
public function setImageName($imageName)
{
$this->imageName = $imageName;
}
/**
* #return string
*/
public function getImageName()
{
return $this->imageName;
}
}
Subpoint:
namespace George\ArchitectureBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;
use Knp\DoctrineBehaviors\Model\Translatable\Translatable;
use Gedmo\Mapping\Annotation as Gedmo;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
use Symfony\Component\HttpFoundation\File\File;
/**
* Subpoint
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="George\ArchitectureBundle\Entity\SubpointRepository")
* #Vich\Uploadable
*/
class Subpoint
{
use Translatable;
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var Points
* #Gedmo\SortableGroup
* #ORM\ManyToOne(targetEntity="George\ArchitectureBundle\Entity\Point", inversedBy="subpoints")
*/
private $point;
/**
* #var integer
* #Gedmo\SortablePosition
* #ORM\Column(name="ord", type="integer")
*/
private $ord;
/**
* #var \DateTime
* #Gedmo\Timestampable(on="update")
* #ORM\Column(name="updated", type="datetime")
*/
private $updated;
/**
* #var \DateTime
* #Gedmo\Timestampable(on="create")
* #ORM\Column(name="created", type="datetime")
*/
private $created;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* #return Points
*/
public function getPoint()
{
return $this->point;
}
/**
* #param Points $point
*/
public function setPoint($point)
{
$this->point = $point;
}
/**
* NOTE: This is not a mapped field of entity metadata, just a simple property.
*
* #Vich\UploadableField(mapping="point_image", fileNameProperty="imageName")
*
* #var File
*/
private $imageFile;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*
* #var string
*/
private $imageName;
/**
* 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
*/
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->setModefied(new \DateTime('now')) ;
}
}
/**
* #return File
*/
public function getImageFile()
{
return $this->imageFile;
}
/**
* #param string $imageName
*/
public function setImageName($imageName)
{
$this->imageName = $imageName;
}
/**
* #return string
*/
public function getImageName()
{
return $this->imageName;
}
/**
* #return \DateTime
*/
public function getUpdated()
{
return $this->updated;
}
/**
* #return \DateTime
*/
public function getCreated()
{
return $this->created;
}
/**
* #return int
*/
public function getOrd()
{
return $this->ord;
}
/**
* #param int $ord
*/
public function setOrd($ord)
{
$this->ord = $ord;
}
}
Repository Point and here i want when i got the Point to be oredered by ord and the subpoints to be ordered by ord:
namespace George\ArchitectureBundle\Entity;
/**
* PointRepository
*
* This class was generated by the Doctrine ORM. Add your own custom
* repository methods below.
*/
class PointRepository extends \Doctrine\ORM\EntityRepository
{
public function getPointsByObject($object)
{
$em = $this->getEntityManager();
$query = $em->createQuery("SELECT p FROM George\ArchitectureBundle\Entity\Point p WHERE p.object =".$object." ORDER BY p.ord ASC");
return $query->getResult();
}
}
But when i put in the creatQuery in Point repository
"SELECT p FROM George\ArchitectureBundle\Entity\Point p WHERE p.object =".$object." ORDER BY p.ord ASC, p.subpoints.ord ASC "
I got error:
[Semantical Error] line 0, col 107 near 'ord ASC ': Error: Class George\ArchitectureBundle\Entity\Point has no field or association named subpoints.ord
EDIT
The solution to the problem is this with query builder with guidance of #Yoshi and #Veve:
public function getPointsByObject($object)
{
$em = $this->getEntityManager();
// $query = $em->createQuery("SELECT p FROM George\ArchitectureBundle\Entity\Point p left join George\ArchitectureBundle\Entity\Subpoint s WITH s.point = p WHERE p.object =".$object." ORDER BY p.ord ASC, s.ord ASC");
$qb = $em->createQueryBuilder();
$qb->select('p')
->from('George\ArchitectureBundle\Entity\Point','p')
->where(' p.object =:object')
->leftJoin('George\ArchitectureBundle\Entity\Subpoint', 's', 'WITH', 's.point = p')
->orderBy('p.ord','ASC')
->orderBy('s.ord','ASC');
$qb->setParameters(array(
'object' => $object
));
$query= $qb->getQuery();
return $query->getResult();
}
You have to join the subpoint to order by one of its attributes:
"SELECT p FROM George\ArchitectureBundle\Entity\Point p
JOIN George\ArchitectureBundle\Entity\Subpoint s WITH s.point = p.id
WHERE p.object =".$object."
ORDER BY p.ord ASC, s.ord ASC"
And as Yoshi commented, you should use the queryBuilder and add your parameters with it instead of building your query by hand.
I am currently facing one problem with mapping I hope some one would helpe me.
I have two table describe bellow..
unitid(primary_key, column_1)
For example data here
unitid(1,22)
unitid (2,33)
mappaths(primary key, forign_key (column_1), forign_key(column_1))
For example data here
mappaths (1,22,33)
mappaths (2,33,22)
unitid has some kind of units defines while this mappaths table define the specific paths based on the unitid
Now when I run the doctrain2 mapping It give me some kind these entities pluse these following mapping information
Entity class
<?php
namespace ApiMaps\ApiMapBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Mappaths
*
* #ORM\Table(name="mappaths", indexes={#ORM\Index(name="idx_45b7519fa3995845", columns={"ref_unitids1"}), #ORM\Index(name="idx_45b7519f3a9009ff", columns={"ref_unitids2"})})
* #ORM\Entity
*/
class Mappaths
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="SEQUENCE")
* #ORM\SequenceGenerator(sequenceName="mappaths_id_seq", allocationSize=1, initialValue=1)
*/
private $id;
/**
* #var integer
*
* #ORM\Column(name="normalvalue", type="smallint", nullable=true)
*/
private $normalvalue;
/**
*
* #var \Unitids
* #ORM\ManyToOne(targetEntity="Unitids",cascade={"all"},fetch="LAZY")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="ref_unitids2", referencedColumnName="databaseid")
* })
*/
private $refUnitids2;
/**
* #var \Unitids
* #ORM\ManyToOne(targetEntity="Unitids",cascade={"all"},fetch="LAZY")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="ref_unitids1", referencedColumnName="databaseid")
* })
*/
private $refUnitids1;
/**
* Set normalvalue
*
* #param integer $normalvalue
*
* #return Mappaths
*/
public function setNormalvalue($normalvalue)
{
$this->normalvalue = $normalvalue;
return $this;
}
/**
* Get normalvalue
*
* #return integer
*/
public function getNormalvalue()
{
return $this->normalvalue;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set refUnitids1
*
* #param \ApiMaps\ApiMapBundle\Entity\Unitids $refUnitids1
*
* #return Mappaths
*/
public function setRefUnitids1(\ApiMaps\ApiMapBundle\Entity\Unitids $refUnitids1 = null)
{
$this->refUnitids1 = $refUnitids1;
return $this;
}
/**
* Get refUnitids1
*
* #return \ApiMaps\ApiMapBundle\Entity\Unitids
*/
public function getRefUnitids1()
{
return $this->refUnitids1;
}
/**
* Set refUnitids2
*
* #param \ApiMaps\ApiMapBundle\Entity\Unitids $refUnitids2
*
* #return Mappaths
*/
public function setRefUnitids2(\ApiMaps\ApiMapBundle\Entity\Unitids $refUnitids2 = null)
{
$this->refUnitids2 = $refUnitids2;
return $this;
}
/**
* Get refUnitids2
*
* #return \ApiMaps\ApiMapBundle\Entity\Unitids
*/
public function getRefUnitids2()
{
return $this->refUnitids2;
}
}
and mappaths.php
<?php
namespace ApiMaps\ApiMapBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Mappaths
*
* #ORM\Table(name="mappaths", indexes={#ORM\Index(name="idx_45b7519fa3995845", columns={"ref_unitids1"}), #ORM\Index(name="idx_45b7519f3a9009ff", columns={"ref_unitids2"})})
* #ORM\Entity
*/
class Mappaths
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="SEQUENCE")
* #ORM\SequenceGenerator(sequenceName="mappaths_id_seq", allocationSize=1, initialValue=1)
*/
private $id;
/**
* #var integer
*
* #ORM\Column(name="normalvalue", type="smallint", nullable=true)
*/
private $normalvalue;
/**
*
* #var \Unitids
* #ORM\ManyToOne(targetEntity="Unitids",cascade={"all"},fetch="LAZY")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="ref_unitids2", referencedColumnName="databaseid")
* })
*/
private $refUnitids2;
/**
* #var \Unitids
* #ORM\ManyToOne(targetEntity="Unitids",cascade={"all"},fetch="LAZY")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="ref_unitids1", referencedColumnName="databaseid")
* })
*/
private $refUnitids1;
/**
* Set normalvalue
*
* #param integer $normalvalue
*
* #return Mappaths
*/
public function setNormalvalue($normalvalue)
{
$this->normalvalue = $normalvalue;
return $this;
}
/**
* Get normalvalue
*
* #return integer
*/
public function getNormalvalue()
{
return $this->normalvalue;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set refUnitids1
*
* #param \ApiMaps\ApiMapBundle\Entity\Unitids $refUnitids1
*
* #return Mappaths
*/
public function setRefUnitids1(\ApiMaps\ApiMapBundle\Entity\Unitids $refUnitids1 = null)
{
$this->refUnitids1 = $refUnitids1;
return $this;
}
/**
* Get refUnitids1
*
* #return \ApiMaps\ApiMapBundle\Entity\Unitids
*/
public function getRefUnitids1()
{
return $this->refUnitids1;
}
/**
* Set refUnitids2
*
* #param \ApiMaps\ApiMapBundle\Entity\Unitids $refUnitids2
*
* #return Mappaths
*/
public function setRefUnitids2(\ApiMaps\ApiMapBundle\Entity\Unitids $refUnitids2 = null)
{
$this->refUnitids2 = $refUnitids2;
return $this;
}
/**
* Get refUnitids2
*
* #return \ApiMaps\ApiMapBundle\Entity\Unitids
*/
public function getRefUnitids2()
{
return $this->refUnitids2;
}
}
now when I run the project it give me the following error
37. public static function missingPrimaryKeyValue($className, $idField)
38. {
39. return new self(sprintf("Missing value for primary key %s on %s", $idField, $className));
40. }
41. }
It seems to me that this primary key of unitsid could not get by mapping
Any solution would be appreciated
First I think you haven't understand the ORM (object relational mapping) concept in your entities you don't map these relations by foreign keys, doctrine will do it for you, in the entities layer you have to map objects and only objects
Second you need to map your entities relations by using orm annotations or xml configuration to describe those relations if they are oneToOne or ManyToOne or OneToMany or ManyToMany relation
Third You are having this error because you haven't set a value to the entity id, to do that you have two options : auto generate the id or set it manually before persisting object
see this
I'm trying to add a simple comment entity, with the "postedOn" attribute as a Datetime. Whenever I try to add a comment, I get this error :
Error: Call to undefined method Symfony\Component\Validator\Constraints\DateTime::format() in /var/www/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeType.php line 53
Any idea ?
Here's the entity code :
<?php
namespace AOFVH\FlyBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Comment
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="AOFVH\FlyBundle\Entity\CommentRepository")
*/
class Comment
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var integer
*
* #ORM\Column(name="rating", type="integer")
*/
private $rating;
/**
* #ORM\Column(type="datetime", nullable=true)
*/
protected $postedon;
/**
* #var string
*
* #ORM\Column(name="text", type="text")
*/
private $text;
/**
* #var $commenter
*
* #ORM\ManyToOne(targetEntity="AOFVH\UserBundle\Entity\User", inversedBy="comments", cascade={"persist", "merge"})
*/
private $commenter;
/**
* #var $commenter
*
* #ORM\ManyToOne(targetEntity="AOFVH\FlyBundle\Entity\Flight", inversedBy="comments", cascade={"persist", "merge"})
*/
private $flight;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set rating
*
* #param integer $rating
* #return Comment
*/
public function setRating($rating)
{
$this->rating = $rating;
return $this;
}
/**
* Get rating
*
* #return integer
*/
public function getRating()
{
return $this->rating;
}
/**
* Set text
*
* #param string $text
* #return Comment
*/
public function setText($text)
{
$this->text = $text;
return $this;
}
/**
* Get text
*
* #return string
*/
public function getText()
{
return $this->text;
}
/**
* Set commenter
*
* #param \AOFVH\UserBundle\Entity\User $commenter
* #return Comment
*/
public function setCommenter(\AOFVH\UserBundle\Entity\User $commenter = null)
{
$this->commenter = $commenter;
return $this;
}
/**
* Get commenter
*
* #return \AOFVH\UserBundle\Entity\User
*/
public function getCommenter()
{
return $this->commenter;
}
/**
* Set flight
*
* #param \AOFVH\FlyBundle\Entity\Flight $flight
* #return Comment
*/
public function setFlight(\AOFVH\FlyBundle\Entity\Flight $flight = null)
{
$this->flight = $flight;
return $this;
}
/**
* Get flight
*
* #return \AOFVH\FlyBundle\Entity\Flight
*/
public function getFlight()
{
return $this->flight;
}
Here are the postedOn getters and setters
/**
* Set postedon
*
* #param \DateTime $postedon
* #return Comment
*/
public function setPostedon($postedon)
{
$this->postedon = $postedon;
return $this;
}
/**
* Get postedon
*
* #return \DateTime
*/
public function getPostedon()
{
return $this->postedon;
}
}
I think it's your mapping in your entity, you don't use "datetime" doctrine format else your form type will try to generate a date with a string for example but for me "postedOn must always be defined on a new comment.You can update your entity constructor with : $this->setPostedOn(new \Datetime()); or you can use TimestampableTrait
i working with Symfony2 and Doctrine ORM using MySql.
When i try uo use:
php app/console doctrine:migration:diff
i have this error:
[Doctrine\DBAL\Schema\SchemaException]
The table with name 'blog.post' already exists.
My code in Post.php (i use annotation) is:
namespace Blog\ModelBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Post
*
* #ORM\Table()
* #ORM\Entity
*/
class Post extends Timestampable
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="title", type="string", length=150)
* #Assert\NotBlank
*/
private $title;
/**
* #var string
*
* #ORM\Column(name="body", type="text")
* #Assert\NotBlank
*/
private $body;
/**
* #var Author
* #ORM\ManyToOne (targetEntity="Author", inversedBy="posts")
* #ORM\JoinColumn (name="author_id", referencedColumnName="id", nullable=false)
* #Assert\NotBlank
*/
private $author;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set title
*
* #param string $title
* #return Post
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get title
*
* #return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set body
*
* #param string $body
* #return Post
*/
public function setBody($body)
{
$this->body = $body;
return $this;
}
/**
* Get body
*
* #return string
*/
public function getBody()
{
return $this->body;
}
/**
* Set author
*
* #param \Blog\ModelBundle\Entity\Author $author
* #return Post
*/
public function setAuthor(Author $author)
{
$this->author = $author;
return $this;
}
/**
* Get author
*
* #return \Blog\ModelBundle\Entity\Author
*/
public function getAuthor()
{
return $this->author;
}
}
I try to define * #ORM\Table(name="Post").
Can you help me with this type of error.
Sorry for my bad english.
Your mapping looks incorrect. The ManyToOne declaration does not need an inversedBy attribute if you're not using a join table. You also do not need to specify the #var since it already knows it's using the entity. Try this:
/**
* #ORM\ManyToOne(targetEntity="Author")
* #ORM\JoinColumn(name="author_id", referencedColumnName="id")
**/
private $author;
One other thing to do is to check that you're not trying to declare the same entity in another bundle, this will also cause the "table already exists" error.
Also, to avoid using full path entity references in the getter and setter, just include the entity in the use statemnets at the top of the class, then you only need write the entity name:
/**
* set Author
*
* #param Author $author
*
* #return Post
/**
I am trying to build a log of some action performed on some site using Symfony2 and Doctrine. I have 2 tables Sites and Logs. The Logs table will contain a siteid which is a foreign key to the id column of sites table. The Logs table can have multiple logs for same site.
When I try to insert an entry in the log table I get siteid is null error.
Here is my code:
Sites Entity:
<?php
namespace A\SHB\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Sites
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="A\SHB\Entity\SitesRepository")
*/
class Sites
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var ArrayCollection $siteLog
*
* #ORM\OneToMany(targetEntity="Logs", mappedBy="log", cascade={"persist"})
* #ORM\OrderBy({"siteid" = "ASC"})
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="log_id", referencedColumnName="siteid")
* })
*/
private $siteLog;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Constructor
*/
public function __construct()
{
$this->siteLog = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add siteLog
*
* #param \A\SHB\Entity\SiteLog $siteLog
* #return Sites
*/
public function addSiteLog(\A\SHB\Entity\SiteLog $siteLog)
{
$this->siteLog[] = $siteLog;
return $this;
}
/**
* Remove siteLog
*
* #param \A\SHB\Entity\SiteLog $siteLog
*/
public function removeSiteLog(\A\SHB\Entity\SiteLog $siteLog)
{
$this->siteLog->removeElement($siteLog);
}
/**
* Get siteLog
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getSiteLog()
{
return $this->siteLog;
}
}
Logs Entity:
<?php
namespace A\SHB\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Logs
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="A\SHB\Entity\LogsRepository")
*/
class Logs
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var integer
*
* #ORM\Column(name="siteid", type="integer")
*/
private $siteid;
/**
* #var integer
*
* #ORM\Column(name="dateline", type="integer")
*/
private $dateline;
/**
* #var Log
*
* #ORM\ManyToOne(targetEntity="Sites")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="site_id", referencedColumnName="id")
* })
*/
private $log;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set siteid
*
* #param integer $siteid
* #return Logs
*/
public function setSiteid($siteid)
{
$this->siteid = $siteid;
return $this;
}
/**
* Get siteid
*
* #return integer
*/
public function getSiteid()
{
return $this->siteid;
}
/**
* Set dateline
*
* #param integer $dateline
* #return Logs
*/
public function setDateline($dateline)
{
$this->dateline = $dateline;
return $this;
}
/**
* Get dateline
*
* #return integer
*/
public function getDateline()
{
return $this->dateline;
}
/**
* Set log
*
* #param \A\SHB\Entity\Log $log
* #return Logs
*/
public function setLog(\A\SHB\Entity\Log $log = null)
{
$this->log = $log;
return $this;
}
/**
* Get log
*
* #return \A\SHB\Entity\Log
*/
public function getLog()
{
return $this->log;
}
}
Controller :
public function indexAction()
{
$sites = $this->getDoctrine()->getRepository('ASHB:Sites')->findAll();
foreach ($sites as $site)
{
$host = $site->getForum();
// Do something ....
$log = new Logs();
$log->setSiteid($site->getId());
$log->setDateline($temp['dateline']);
$em = $this->getDoctrine()->getManager();
$em->persist($log);
$em->flush();
}
return $this->render('ASHB:Default:index.html.twig', array('sites' => $output, 'counters' => $counters));
}
Now when I run this code, I get the following error:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'siteid' cannot be null"
If I var_dump $log, before $em->persist($log);, the siteid is there. I am not sure what is wrong and why the siteid is getting set to null.
Update 1:
I tried to make the following changes and still get the same error:
/**
* #var Log
*
* #ORM\ManyToOne(targetEntity="Sites", inversedBy="siteLog")
*/
private $log;
OneToMany doesn't need a JoinColumn. So it should look like, according to the documentation.
class Sites
{
/**
* #ORM\OneToMany(targetEntity="Logs", mappedBy="log")
*/
private $site_log;
}
class Logs
{
/**
* #ORM\ManyToOne(targetEntity="Sites", inversedBy="site_log")
* #ORM\JoinColumn(name="site_id", referencedColumnName="id")
*/
private $log;
}
orderBy and cascade were ignored for simplicity.
you have problem in your sturcture,
Remove this from Logs Entity
/**
* #var integer
*
* #ORM\Column(name="siteid", type="integer")
*/
private $siteid;
And then replace this part
/**
* #var Log
*
* #ORM\ManyToOne(targetEntity="Sites")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="site_id", referencedColumnName="id")
* })
*/
private $log;
with
/**
* #var Log
*
* #ORM\ManyToOne(targetEntity="Sites" inversedBy="logs")
*/
private $site;
And in your sites entity replace this with
/**
* #var ArrayCollection $siteLog
*
* #ORM\OneToMany(targetEntity="Logs", mappedBy="logs", cascade={"persist"})
* #ORM\OrderBy({"siteid" = "ASC"})
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="log_id", referencedColumnName="siteid")
* })
*/
private $logs;
with
/**
* #var ArrayCollection $siteLog
*
* #ORM\OneToMany(targetEntity="Logs", mappedBy="site", cascade={"persist"})
* #ORM\OrderBy({"siteid" = "ASC"})
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="log_id", referencedColumnName="id")
* })
*/
private $logs;
And then use proper setters and getters for these new feilds mean pass object to setter functions, for the class they are being mapped for(if you dont know this part write in comment i will do it as well)