i am trying to create a oneToMany relationship. Since Doctrine only offers ManyToOne Unidirectional im using that. Somehow the validation of the mapping fails and I am not able to spot my mistake:
Validation Error:
[Mapping] FAIL - The entity-class 'Strego\TippBundle\Entity\BetRound'
mapping is invalid:
* The association Strego\TippBundle\Entity\BetRound#userStatus refers to the owning side field
Strego\TippBundle\Entity\UserBetRoundStatus#betRound which does not
exist.
My First Entity (BetRound):
<?php
namespace Strego\TippBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\Collection as Collection;
use Strego\AppBundle\Entity\Base as BaseEntity;
/**
* Strego\TippBundle\Entity\BetRound
*
* #ORM\Table()
* #ORM\Entity
*/
class BetRound extends BaseEntity {
//......
/**
*
* #var Collection
* #ORM\OneToMany(targetEntity="UserBetRoundStatus", mappedBy="betRound", cascade={"all"})
*/
protected $userStatus;
}
My related Entity(UserBetRoundStatus)
<?php
namespace Strego\TippBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Strego\AppBundle\Entity\Base as BaseEntity;
/**
* Strego\TippBundle\Entity\Game
*
* #ORM\Table
* #ORM\Entity
* #UniqueEntity(fields={"user", "betRound"}, message="Unique Entity Validator Fails for UserStatus", groups="unique")
*
*/
class UserBetRoundStatus extends BaseEntity {
// .....
/*
* #var BetRound
* #ORM\ManyToOne(targetEntity="BetRound", inversedBy="userStatus")
* #ORM\JoinColumn(name="betround_id", referencedColumnName="id", nullable=false)
* #Assert\NotNull()
*/
protected $betRound;
}
I have found the issue:
/** <--------- you need two *
* #var BetRound
* #ORM\ManyToOne(targetEntity="BetRound", inversedBy="userStatus")
* #ORM\JoinColumn(name="betround_id", referencedColumnName="id", nullable=false)
* #Assert\NotNull()
*/
protected $betRound;
Related
The persist method dont work in inheritance class,although I have set the property cascade in annotation (cascade="all").
/**
* #ORM\Entity
* #ORM\InheritanceType("JOINED")
* #ORM\DiscriminatorColumn(name="tipo", type="string")
* #ORM\DiscriminatorMap({"menu" = "Menu", "enquete" = "Enquete"})
*/
abstract class Widget{
/**
* #ORM\Id
*/
protected $id;
}
/**
* #ORM\Entity
*/
class Enquete extends Widget{
/**
* #var ArrayCollection
* #ORM\OneToMany(targetEntity="Admin\Model\Alternativa", mappedBy="enquete", cascade="all")
*/
protected $alternativas;
}
/**
* #ORM\Entity
*/
class Alternativa{
/**
* #ORM\ManyToOne(targetEntity="Admin\Model\Enquete", inversedBy="alternativas")
* #ORM\joinColumn(name="Enquete_id", referencedColumnName="id")
*/
protected $enquete;
}
I Use persist in cascade but dont work:
$enquete->addAlternativa(New Alternativa());
$entityManager->persist($enquete);
$entityManager->flush();
The result is the follow error:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'Enquete_id' cannot be null
How can I do this?
My Entities:
Product entity
/**
* #ORM\Entity
* #ORM\Table(name="products")
*/
class Product
{
/**
* #ORM\Id()
* #ORM\Column(name="id", type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
* #var int
*/
private $id;
/**
* #ORM\Column(type="string", length=512)
* #var string
*/
private $name;
/**
* (??)
* #var ArrayCollection
*/
private $images;
}
Article entity
/**
* #ORM\Entity
* #ORM\Table(name="articles")
*/
class Article
{
/**
* #ORM\Id()
* #ORM\Column(name="id", type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
* #var int
*/
private $id;
/**
* #ORM\Column(type="string", length=512)
* #var string
*/
private $title;
/**
* (??)
* #var ArrayCollection
*/
private $images;
}
Image entity
/**
* #ORM\Entity
* #ORM\Table(name="images")
*/
class Image
{
/**
* #ORM\Id()
* #ORM\Column(name="id", type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
* #var int
*/
private $id;
/**
* #ORM\Column(type="string", length=512)
* #var string
*/
private $name;
/**
* #ORM\Column(type="string", length=1024)
* #var string
*/
private $path;
}
I don't know how to create a link tables with additional fields like the picture. Which association should I use? How to manage these relations in entities?
Usually when you need a many to many approach Doctrine let you define such behaviour with a simple annotation.
#ORM\ManyToMany(targetEntity="full_qualified_namespace")
#ORM\JoinTable(
name="game_schemas_players",
joinColumns={#ORM\JoinColumn(name="this_field_name", referencedColumnName="id")},
inverseJoinColumns={#ORM\JoinColumn(name="that_field_anem", referencedColumnName="id")}
)
This will instruct Doctrine to create a relation the current entity and the target entity.
But that's not your case. For what I can see from your model you need to add some field on the 'middle' entity.
Here what you may want to do:
class Product
{
[...]
/**
* #var ArrayCollection | ProductImage[]
*
* #ORM\OneToMany(targetEntity="ProductImage", mappedBy="product")
*/
private $productImages;
}
class Image
{
[...]
/**
* #var ArrayCollection | ProductImage[]
*
* #ORM\OneToMany(targetEntity="ProductImage", mappedBy="image")
*/
private $productImages;
}
as you can see as defined here either Product and Image have a oneToMany relation with a middle entity which will be named ProductImage**.
The last step will be to implement such entity:
class ProductImage
{
[...]
/**
* #var Image
*
* #ORM\ManyToOne(targetEntity="Image", mappedBy="image")
* #ORM\JoinColumn(name="image_id", referencedColumnName="id")
*/
private $image;
/**
* #var Product
*
* #ORM\ManyToOne(targetEntity="Product", mappedBy="product")
* #ORM\JoinColumn(name="product_id", referencedColumnName="id")
*/
private $product;
/**
* #ORM\Column(type="string", length=1024)
* #var string
*/
private $position;
}
The owning side of the relation both for Product and Image is still ProductImage.
As a side note in your entity is common practice to implement an add method in this fashion:
public function __contructor(){
$this->productImages = new ArrayCollection();
}
/**
* Add ProductImage
*
* #param ProductImage $productImage
* #return $this
*/
public function addDocument(ProductImage $productImage)
{
$productImage->addProductImage($productImage);
$this->documents->add($document);
return $this;
}
and then you can use such method with the following approach:
$product = new Product();
$image = new Image();
$productImage = new ProductImage($product,$image);
$product->addProductImage($productImage);
Don't forget to provide the usual setter method as Doctrine need them to initialize the entity.
Hope it helps, Regards.
The data model:
The entities:
Pet:
/**
* #ORM\Entity
* #ORM\Table(name="pet")
* #ORM\InheritanceType("JOINED")
* #ORM\DiscriminatorColumn(name="pet_type", type="string")
*/
abstract class Pet
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
*/
protected $id;
/**
* #ORM\OneToMany(
* targetEntity="Collar",
* mappedBy="pet",
* cascade={"persist", "remove"},
* orphanRemoval=TRUE
* )
* #ORM\JoinColumn(name="collars", referencedColumnName="id")
*/
protected $collars;
/**
* #ORM\Column(type="integer")
*/
protected $age;
}
Cat:
/**
* #ORM\Entity
* #ORM\Table(name="cat")
*/
class Cat extends Pet
{
/**
* #ORM\Column(type="decimal")
*/
private $purringDecibels;
}
Collar:
/**
* #ORM\Entity
* #ORM\Table(name="collar")
*/
class Collar
{
/**
* #ORM\Id
* #ORM\Column(name="id", type="integer")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="Pet", inversedBy="collars")
* #ORM\JoinColumn(name="pet", referencedColumnName="id", nullable=false)
*/
private $pet;
/**
* #ORM\Column(type="string", length="255")
*/
private $color;
}
The problem:
The generated tables are fine except pet: It lacks the collars column, therefore the bidirectionality is broken. While the pet ids do get stored on the collar table, I cannot fetch collars from a pet (i.e. $pet->getCollars()) as it always returns an empty collection.
What am I missing out here?
PS:
The validate console helper says all (mapping & db) is OK.
Yes, I have my getters and setters (i.e. adders and removers)
I know about the infamous performance impact of the combination between a CTI and this kind of relationship.
You do not need to have a "collars" column on the pet table. It is a one-to-many relationship, so the only table that need to "know" about pets are the collar table.
A bidirectional relationship does not mean you need two columns on two tables.
Your map seems correct.
I am new with Doctrine2 and need some help.
I have 2 Entities: LocationEntity and RatingEntity
RatingEntity
<?php
use Doctrine\ORM\Mapping as ORM;
/**
* Rating
*
* #ORM\Entity
* #ORM\Table(name="`RATING`")
*/
class RatingEntity {
/**
*
* #var int
* #ORM\Id
* #ORM\Column(name="`ID`", type="integer", nullable=false)
* #ORM\GeneratedValue(strategy="SEQUENCE")
* #ORM\SequenceGenerator(sequenceName="RATING_ID_SEQ", initialValue=1, allocationSize=1)
*/
protected $id;
/**
*
* #var int
* #ORM\Column(name="`LOCATION_ID`", type="integer")
*/
protected $locationId;
/**
* #var LocationEntity
* #ORM\ManyToOne(targetEntity="LocationEntity", inversedBy="ratings")
* #ORM\JoinColumn(name="`LOCATION_ID`", referencedColumnName="`ID`")
*/
protected $location;
/**
* #return the $location
*/
public function getLocation() {
return $this->location;
}
/**
* #param field_type $location
*/
public function setLocation($location) {
$this->location = $location;
}
and LocationEntity
<?php
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
/**
* Location
*
* #ORM\Entity
* #ORM\Table(name="`LOCATION`")
*/
class LocationEntity {
/**
*
* #var int
* #ORM\Id
* #ORM\Column(name="`ID`", type="integer", nullable=false)
* #ORM\GeneratedValue(strategy="SEQUENCE")
* #ORM\SequenceGenerator(sequenceName="LOCATION_ID_SEQ", initialValue=1, allocationSize=1)
*/
protected $id;
/**
*
* #var ArrayCollection
* #ORM\OneToMany(targetEntity="RatingEntity", mappedBy="location", cascade={"persist"}, fetch="LAZY")
*/
protected $ratings;
/**
* #return the $ratings
*/
public function getRatings() {
return $this->ratings;
}
/**
* #param \Doctrine\Common\Collections\ArrayCollection $ratings
*/
public function setRatings($ratings) {
$this->ratings = $ratings;
}
/**
* Never forget to initialize all your collections!
*/
public function __construct() {
$this->ratings = new ArrayCollection();
}
If I get locations, i get ratings for location as Array,
but if I want to get Rating and Location for it, I get NULL only in getLocation().
Can somebody help?
I don't think that you need the locationId property in your Rating entity as the column is already mapped using the location property. Try removing the locationId section and see if it doesn't work as expected.
I'm trying to make a Field of a Object slugable.
Model looks like:
namespace myBundle\Bundles\BlogBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Gedmo\Mapping\Annotation as Gedmo;
/**
* myBundle\Bundles\BlogBundle\Entity\Category
*
* #ORM\Table()
* #ORM\Entity
*/
class Category
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string $title
*
* #Gedmo\Sluggable
* #ORM\Column(name="title", type="string", length=255)
*/
private $title;
/**
* #Gedmo\Slug(separator="-", updatable=false, unique=true)
* #ORM\Column(name="slug", type="string", length=255, unique=true)
*/
private $slug;
// other properties and methods
The Fixtures:
namespace myBundle\Bundles\BlogBundle\DataFixtures\ORM;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use tooMuch\Bundles\BlogBundle\Entity\Category;
class LoadCategoryData extends AbstractFixture implements OrderedFixtureInterface
{
public function load($manager)
{
$this->generateCategory($manager);
}
public function generateCategory($manager)
{
for ($i=0; $i < 10; $i++) {
$category = new Category();
$category->setTitle('Category '.$i);
$manager->persist($category);
$manager->flush();
$this->addReference('category'.$i, $category);
unset($category);
}
}
schema create:
# sf doctrine:schema:create
ATTENTION: This operation should not be executed in a production environment.
Creating database schema...
Database schema created successfully!
but then when I'm trying to add the fixtures:
# sf doctrine:fixtures:load
> purging database
> loading myBundle\Bundles\BlogBundle\DataFixtures\ORM\LoadCategoryData
[PDOException]
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'slug' cannot be null
doctrine:fixtures:load [--fixtures[="..."]] [--append] [--em="…"]
#
any ideas?
The problem isn't in the fixtures, it's in Slug generation itself. If it's properly set up, you should never have $slug as null
Are you sure you have Sluggable listener attached?