I have five entities :
ProductA, ProductB, User, UserProductA and UserProductB. The two last ones are "intermediate" entites which contain the attributes of relationships between ProductA, ProductB and User.
I would like to make a ManyToOne relationship between UserProductA and UserProductB but it doesn't work. When I try to update the database, I get this error : Single id is not allowed on composite primary key in entity.
UserProductA (without the relationship) :
/**
* #ORM\Entity(repositoryClass="Gam\UserBundle\Entity\UserProductARepository")
*/
class UserProductA
{
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Gam\FicheBundle\Entity\ProductA")
*/
private $producta;
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Gam\UserBundle\Entity\User")
*/
private $user;
/**
* #ORM\Column(type="string", length=1, nullable=true)
*/
private $attribute;
etc...
}
UserProductB (without the relationship) :
/**
* #ORM\Entity(repositoryClass="Gam\UserBundle\Entity\UserProductBRepository")
*/
class UserProductB
{
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Gam\FicheBundle\Entity\ProductB")
*/
private $productb;
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Gam\UserBundle\Entity\User")
*/
private $user;
/**
* #ORM\Column(type="string", length=1, nullable=true)
*/
private $attribute;
etc...
}
How can I make it work ?
Related
I'm working with Symfony5. I have 2 entities with relationships, Character and Wedding.
Each Character can have many Wedding.
Each Wedding is related to 2 different Character.
/**
* #ORM\Entity(repositoryClass=CharacterRepository::class)
*/
class Character
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=50, nullable=true)
*/
private $firstName;
/**
* #ORM\Column(type="string", length=50, nullable=true)
*/
private $lastName;
[...]
And Wedding :
/**
* #ORM\Entity(repositoryClass=WeddingRepository::class)
*/
class Wedding
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=4, nullable=true)
*/
private $startYear;
/**
* #ORM\Column(type="string", length=4, nullable=true)
*/
private $endYear;
[...]
}
I tried to set 2 different ManyToOne relations in Wedding entity (persona1 and persona2) but persona1 and persona2 had the same inversedBy="weddings", so it's not working.
I tried 2 ManyToMany relations too, but Doctrine didn't like it :
// Character
/**
* #ORM\ManyToMany(targetEntity=Wedding::class, mappedBy="persona1")
*/
private $weddings1;
/**
* #ORM\ManyToMany(targetEntity=Wedding::class, mappedBy="persona2")
*/
private $weddings2;
// Wedding
/**
* #ORM\ManyToMany(targetEntity=Character::class, inversedBy="weddings1")
*/
private $persona1;
/**
* #ORM\ManyToMany(targetEntity=Character::class, inversedBy="weddings2")
*/
private $persona2;
The mappings App\Entity\Wedding#persona2 and App\Entity\Character#weddings are inconsistent with each other.
What is the good relationship, ManyToOne or ManyToMany, since each Wedding is related to 2 Characters ? How to make it works with Doctrine ?
Thanks for all suggestion !
Ash
I would suggest to have ManyToMany relation between Wedding and Character entities if there is no such specific reason or differentiation between character 1 and character 2
class Character
{
// ...
/**
* #ORM\ManyToMany(targetEntity=Wedding::class, mappedBy="characters")
*/
private $weddings;
}
class Wedding
{
// ...
/**
* #ORM\ManyToMany(targetEntity=Character::class, inversedBy="weddings")
*/
private $characters;
}
This way you can scale it in future if you have more characters to be assigned to a wedding
If there are any strict actions that need to be performed specific to character 1 or character 2 depends on your needs, then you can use OneToMany and ManyToOne as
class Character
{
// ...
/**
* #ORM\OneToMany(targetEntity=Wedding::class, mappedBy="characterA")
*/
private $weddingsA;
/**
* #ORM\OneToMany(targetEntity=Wedding::class, mappedBy="characterB")
*/
private $weddingsB;
}
class Wedding
{
// ...
/**
* #ORM\ManyToOne(targetEntity=Character::class, inversedBy="weddingsA")
*/
private $characterA;
/**
* #ORM\ManyToOne(targetEntity=Character::class, inversedBy="weddingsB")
*/
private $characterB;
}
I'm trying to get a legacy database into the doctrine mappings.
All the tables have a combined primary key. One ID and one "optios id".
The problem is that Optios ID always has to be set but the OneToOne relation with the same columns causes the column "Optios ID" to be set to null. I'm not sure what I'm doing wrong or is there a way around it?
PS: The 'Pack' relation is optional.
<?php
namespace CalendarBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="CalendarBundle\Repository\CategoryRepository")
* #ORM\Table(name="Categories")
*/
class Category
{
/**
* #ORM\Id
* #ORM\Column(type="integer", name="Category_id")
*/
private $id;
/**
* #ORM\Column(type="integer", name="Optios_id")
* #ORM\Id
*/
private $optiosId;
/**
* #ORM\Column(type="string", name="Name")
*/
private $name;
/**
* #ORM\Column(type="boolean", name="AvailableOnline")
*/
private $online;
/**
* #ORM\Column(type="integer", name="SequenceNumber", nullable=true)
*/
private $order;
/**
* #ORM\Column(type="integer", name="Parent_id")
*/
private $parentId;
/**
* One Category has Many Packs.
*
* #var Pack
*
* #ORM\OneToOne(targetEntity="Pack", inversedBy="category")
* #ORM\JoinColumns(
* #ORM\JoinColumn(name="Pack_id", referencedColumnName="Pack_id"),
* #ORM\JoinColumn(name="Optios_id", referencedColumnName="Optios_id"),
* )
*/
private $pack;
/**
* #ORM\Column(type="boolean", name="Deleted")
*/
private $deleted;
I'm newbie with PHP. I started work with symfony but i have this problem
/**
* #ORM\Entity
* #ORM\Table(name="fos_user")
*/
class User extends BaseUser
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #param \Doctrine\Common\Collections\Collection $carList
* #ORM\OneToMany(targetEntity="AppBundle\CarBundle\Entity\Car", mappedBy="name", cascade={"persist"})
*/
private $carList;
//getters and setters
}
*
* #ORM\Entity(repositoryClass="AppBundle\CarBundle\Repository\Entity\CarRepository")
* #ORM\Table(name="car")
*/
class Car
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*
*
*/
protected $id;
/**
* #ORM\Column(type="string", length=100)
* #ORM\ManyToOne(targetEntity="AppBundle\UserBundle\Entity\User" , inversedBy="carList")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
private $name;
//getters and setters
}
The stacktrace says:
Symfony\Component\Debug\Exception\ContextErrorException: Notice: Undefined index: name
at n/a
and when i run php bin/console doctrine:schema:validate
[Mapping] FAIL - The entity-class 'AppBundle\UserBundle\Entity\User'
mapping is invalid:
* The association AppBundle\UserBundle\Entity\User#carList refers to the owning side field AppBundle\CarBundle\Entity\Car#name which is not
defined as association, but as field.
*The association AppBundle\UserBundle\Entity\User#carList refers to the owning side field Appbundle\CarBundle\Entity\Car#name which does
not exist
I have no idea whats going on, can you help me?
You are mixing up association names with column names. When you create an association you don't need to manually add the columns for that association, doctrine will work that out for you.
This code (in the Car class) says that the $name field is a normal text column in the car table, which of course is wrong
* #ORM\Column(name="name",type="string", length=100)
What you're describing is that one user can own many cars, and many cars can belong to one user. I'd then call the associations owner and cars, but you are of course free to call them whatever you want. Note that you do not need to define the join columns.
/**
* #ORM\Entity
* #ORM\Table(name="fos_user")
*/
class User extends BaseUser
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #param \Doctrine\Common\Collections\Collection $cars
* #ORM\OneToMany(targetEntity="AppBundle\CarBundle\Entity\Car", mappedBy="owner", cascade={"persist"})
*/
private $cars;
public function __construct()
{
$this->cars = new \Doctrine\Common\Collections\ArrayCollection();
}
//getters and setters
}
/**
*
* #ORM\Entity(repositoryClass="AppBundle\CarBundle\Repository\Entity\CarRepository")
* #ORM\Table(name="car")
*/
class Car
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="AppBundle\UserBundle\Entity\User" , inversedBy="cars")
*/
private $owner;
//getters and setters
}
Read more: Doctrine association mapping
Hope it makes sense :)
I have got a problem with OneToMany relation, I have user which can donate blood so he can have many blood donations, my application works fine but in my profiler I have 2 errors.
From Users Entity:
The association AppBundle\Entity\Users#userDonation refers to the owning side field AppBundle\Entity\UserDonates#id which is not defined as association, but as field.
The association AppBundle\Entity\Users#userDonation refers to the owning side field AppBundle\Entity\UserDonates#id which does not exist.
and from UserDonates:
The mappings AppBundle\Entity\UserDonates#userId and AppBundle\Entity\Users#userDonation are inconsistent with each other.
Here are my entities:
UserDonates:
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="Users", inversedBy="userDonation")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
protected $userId;
/**
* #var string
*
* #ORM\Column(name="place", type="string", length=255)
*/
private $place;
/**
* #var date
* #ORM\Column(name="donation_date", type="date")
*/
private $donation_date;
/**
* #var string
* #ORM\Column(name="donation_type", type="string", length=255)
*/
private $donation_type;
/**
* #var integer
* #ORM\Column(name="blod_donated", type="integer")
*/
private $blood_donated;
Users:
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\OneToMany(targetEntity="UserDonates", mappedBy="id", cascade={"persist","remove"})
*/
protected $userDonation;
/**
* #ORM\OneToOne(targetEntity="UserInfo", cascade={"persist","remove"})
*/
private $profil;
//__construct() from FOSUserBundle
public function __construct(){
parent::__construct();
}
Users entity is also related to UserInfo with OneToOne relation.
I see two issues here.
The association AppBundle\Entity\Users#userDonation refers to the owning side field AppBundle\Entity\UserDonates#id which is not defined as association, but as field.
The inverse side of your User::$userDonation association is not the id field, but the userId field in the UserDonation entity. The mapping should look like this:
/**
* Here! -----------------------------------------------v
* #ORM\OneToMany(targetEntity="UserDonates", mappedBy="userId", cascade={"persist","remove"})
*/
protected $userDonation;
As a side note, I'd suggest naming the userId attribute user instead; after all it will contain an actual user object, and not just a user's ID.
The association AppBundle\Entity\Users#userDonation refers to the owning side field AppBundle\Entity\UserDonates#id which does not exist.
Your UserDonates::$id attribute is private. All properties managed by Doctrine need to be protected in order for Doctrine to be able to populate them with data.
i have a OneToOne relation between my entity User and UserMeta
i would like to have access to UserMeta in User but set the foreign key in the UserMeta table in my mysql database:
class User implements UserInterface{
/**
* #ORM\Column(type="integer", unique=true)
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\OneToOne(targetEntity="Foo\Bar\Entity\UserMeta", cascade={"persist"}, inversedBy="id_user")
* #ORM\JoinColumn(nullable=true)
* #ORM\Column(name="id_pro")
*/
private $proData;
}
class UserMeta{
/**
* #ORM\Column(type="integer", unique=true)
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\OneToOne(targetEntity="Foo\Bar\Entity\User", mappedBy="id_pro")
* #ORM\JoinColumn(nullable=true)
* #ORM\Column(name="id_user")
*/
private $user;
}
Anyway to do that with doctrine ? I think i misunderstood mapped and inversed properties.
You mapping configuration is wrong.
In your User Class, it should read:
/**
* #ORM\OneToOne(targetEntity="Foo\Bar\Entity\UserMeta", cascade={"persist"}, inversedBy="user")
* #ORM\JoinColumn(nullable=true)
*/
private $proData;
and in your UserMeta Class, it should read:
/**
* #ORM\OneToOne(targetEntity="Foo\Bar\Entity\User", mappedBy="proData")
* #ORM\JoinColumn(nullable=true)
*/
private $user;
You also don't need the #ORM\Column directive since Doctrine2 will automatically do it for you.