Please forgive me as I am a beginner to doctrine. I am writing an application to parse some sports data.
I have a simple OneToMany Team in relationship to Players.
class Team
{
/**
* #ORM\OneToMany(targetEntity="Player", mappedBy="team")
*/
protected $players;
However, I am now creating my Game entity which should have exactly two team objects--a visiting and a home team. To me this seems as two unique one-to-many relationships, but maybe I am overthinking and it would easier as a many-to-many relationship instead.
I would appreciate help in correctly building the entities for this configuration.
In Game class you should create two object with ManyToOne like this:
/**
* #var Team
*
* #ORM\ManyToOne(targetEntity="Team")
*/
private $homeTeam;
/**
* #var Team
*
* #ORM\ManyToOne(targetEntity="Team")
*/
private $awayTeam;
Related
I am looking for a clear explanation of how the relations work in Doctrine 2. I've been trying now for days to set up a OneToOne relation in Symfony3, and have read basically every thread and all the documentation, and i simply do not understand. The last few hours i've been bruteforcing my way into a OneToOne relation, with no luck.
Here's the problem i'm dealing with:
My user entity has a Team (which is itself an Entity)
/**
* #ORM\OneToOne(targetEntity="Gluckez\bballBundle\Entity\Team",
mappedBy="Owner")
* #ORM\Column(name="team_id")
*/
private $team;
And My Team has an Owner, which refers to the User:
/**
* #var User $Owner
* #ORM\OneToOne(targetEntity="Application\Sonata\UserBundle\Entity\User",
inversedBy="team_id")
* #ORM\JoinColumn(name="Owner_id", referencedColumnName="id")
*/
protected $Owner;
Now in my User table, i can see the relations, which do point to the right team. but doctrine complains about the inverse side User#team, that does not exist (even though i'm pretty sure i've defined it?)
I've tried countless times to change the inversedby, mappedby, name, referencedcolumnName, as well as dropping and recreating the database and tables. updating the doctrine schema's. i'm out of idea's.
Not a single answer out there, nor the documentation of doctrine points me in the right direction. I realize that there's a lot of threads out there on this, but none of them are clear, or even answered.
Try it like this:
Owner entity
/**
* #ORM\OneToOne(targetEntity="Gluckez\bballBundle\Entity\Team", mappedBy="owner")
*/
private $team;
Team entity
/**
* #ORM\OneToOne(targetEntity="Application\Sonata\UserBundle\Entity\User", inversedBy="team")
*/
protected $owner;
As reference: Association Mapping
I am using symfony2 with the Doctrine entities and I have a problem with the next:
I know I could solve the problem putting an ID to the "club_has_torneo" and turning it into an entity, but to me creating an entity for that looks like something that should not be done. So I wanted to know if there is a way to solve this issue or if I have to do what I think I have to.
Thank you in advance.
I guess I'll submit my own two cents worth.
ORM stands for Object Relational Mapper. The basic idea is to figure out how to map your objects without worrying too much about the database schema. So you have three domain model entities: torneo, club and nadador. Great. Figure out how your application will use these entities. Don't worry about how the relations will end up being stored.
Once you have a working domain model then worry about persistence. The three domain entities clearly map to three doctrine entities. As far as the relations go, I personally am not a big fan of composite primary keys. I think they just complicate things while adding little value. So I would make Doctrine entities for your two has tables and just given them their own primary database id.
Note that these are Doctrine entities not domain entities. Your application code should never need to deal with these relational doctrine entities at all. So in my opinion
creating an entity for that looks like something that should not be
done
does not apply here. It is just a persistence detail.
I think the best solution is indeed to make a entity for your club_has_torneo table. This ClubHasTorneo entity has club_id and torneo_id as composite keys and holds the owning side of a many-to-many relationship between your ClubHasTorneo entity and Nadador entity. This relationship can be done with a join table using the 3 keys. Check the code below on how to do that.
Your database scheme will look exactly like you drew it.
Your ClubHasTorneo entity would look something like this:
<?php
namespace Application\Entity;
use Application\Entity\Club;
use Application\Entity\Torneo;
use Application\Entity\Nadador;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Entity
* #ORM\Table(name="club_has_torneo")
*/
class ClubHasTorneo
{
/** MANY-TO-ONE BIDIRECTIONAL, OWNING SIDE
* #var Club
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Application\Entity\Club", inversedBy="clubHasTorneos", cascade={"persist"})
* #ORM\JoinColumn(name="club_id", referencedColumnName="id")
*/
protected $club;
/** MANY-TO-ONE BIDIRECTIONAL, OWNING SIDE
* #var Torneo
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Application\Entity\Torneo", inversedBy="clubHasTorneos")
* #ORM\JoinColumn(name="torneo_id", referencedColumnName="id")
*/
protected $torneo;
/** MANY-TO-MANY BIDIRECTIONAL, OWNING SIDE
* #var Collection
* #ORM\ManyToMany(targetEntity="Application\Entity\Nadador", inversedBy="clubHasTorneos")
* #ORM\JoinTable(name="club_has_torneo_has_nadador",
* joinColumns={
* #ORM\JoinColumn(name="club_id", referencedColumnName="club_id"),
* #ORM\JoinColumn(name="torneo_id", referencedColumnName="torneo_id")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="nadador_id", referencedColumnName="id")
* }
* )
*/
protected $natadors;
public function __construct()
{
$this->natadors = new ArrayCollection();
}
// setters and getters
}
my 5 cents
If you want your implementation to match the drawn table structure, then (in my opinion) you need create an entity out of the 'club_has_torneo' table (for 'club_has_torneo_has_matador' you don't need to).
The rationale being that if you try to achieve this without creating the entity, you would need to create the entity associations so, that the 'natador' table references the 'club' and 'torneo' directly - in which case the actual database relations wouldn't match with your drawn table relationship anymore (i.e. the natador wouldn't have relationship to the 'club_has_torneo' table).
I'm trying to add a OneToMany bidirectional association on two tables: Course and Certified
There was already a OneToMany relation but Unidirectional.
So I modified both entities to make it bidirectional and added the property on the course side
Here are the two Entities:
/**
* Course
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="ME\ExamsBundle\Entity\CourseRepository")
*/
class Course
{
/**
* #ORM\OneToMany(targetEntity="ME\ExamsBundle\Entity\Certified", mappedBy="course")
* #ORM\JoinColumn(nullable=true)
*/
private $certified;
//getters and setters...
}
/**
* Certified
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="ME\ExamsBundle\Entity\CertifiedRepository")
*/
class Certified
{
/**
* #ORM\ManyToOne(targetEntity="ME\ExamsBundle\Entity\Course", inversedBy="certified")
* #ORM\JoinColumn(nullable=false)
*/
private $course;
// getters and setters...
}
But when i use the command
doctrine:schema:update -- dump-sql
It tells me that there's nothing to update.
I tried to
clear the metadata cach
remove the nullable on both sides
drop the database and recreate it
But the property certified never appeared in the course table in the database.
I'm kind of stuck here, so any help would be greatly appreciated.
Thanks in advance
Tom
A bidirectional relation in Doctrine isn't different from a one-directional one from a SQL-point-of-view: that's because Doctrine can infer the inverse relation reversing the foreign key from the other table. Adding a new colum to your Course table would be a not normalized form, or worse it will have no sense.
The response of the Doctrine's command is all right.
Please study some more on normalized forms of databases: https://en.wikipedia.org/wiki/Database_normalization
I have 2 linked entities: User and Acess. I want my doctrine User entity to have a field that informs me if the user has acesses or not.
I can't do a simple OneToMany relationship between the two tables, because there is thousands of acesses and it would be too costly to get thousands of records from the database once I only need to know if there is any.
What I would want is a field linked to a native query like:
select * from accesses where user = <whatever> limit 1
More specifically, something like:
/**
* USer
*
* #ORM\Table(name="user")
* #ORM\Entity
*/
class User {
/**
* #ORM\Column(name="user_id", type="bigint", nullable=false)
* #ORM\Id
*/
private $id;
/**
* #ORM\Column(name="name", type="string", length=300, nullable=false)
* #Assert\NotBlank()
*/
private $name;
/**
* #ORM\Query="select exists (select id_acesses from accesses where user = "$id" limit 1)"
*/
private $hasAcesses;
}
Is this possible ? is there another way to do this ?
Edit:
based on #Otanaught answer below, I have done some tests:
Using a OneToMany relation with EXTRA_LAZY fetch:
user-getAccesses()->isEmpty() selected the whole collection
user-getAccesses()->count() used count(*) in the database which took 243ms to return
for comparasion my query above who did what I want took 12ms in average with peeks of 2ms or even 1ms.
Maybe the good folks at doctrine could implement this at isEmpty for extra lazy queries ?
Thanx #Otanaught
Doctrine does not provide an annotation that allows you to specify a query for a property of an entity (Annotation reference). You could create a custom method in your repository to implement the check. Did you measure how costly the relation would be? With correct relations and indexes this should be a none issue, because doctrine lazy loads the relation? Check the doctrine documentation about extra lazy collections.
I joust started playing around with Doctrine ORM library, and Im learning about all associations between tables.
So Im stuck with differences in Unidirectional and Bidirectional relation.
As I get it, Unidirectional relation has primary key only on one side, and that side is owning side right?
And Bidirectional relation have primary key in both tables and therefore you can have relation from both sides, and set constrains on both sides.
Now, Im reading through Doctrine documentation about relations and there you have:
Unidirectional and Bidirectional associations.
But they produce the same SQL, and the same tables with the same primary key-s and constrains. So I dont really see any difference in those two. And both examples have primary key on one side.
As I get it the true Bidirectional relation should have primary keys in both tables pointing to the other table right? And with given example on Doctrine documentation that is not the case. Both examples give the same result and are the same.
So what I did, is this, lets say I have User and Card Entity, and want relation to be OneToOne Bidirectional.
/**
* #Entity
* #Table(name="users")
*/
class User
{
/**
* #Id
* #GeneratedValue
* #Column(type="bigint")
*/
protected $id;
/**
* #OneToOne(targetEntity="Card", mappedBy="User")
* #JoinColumn(name="card_id", referencedColumnName="id")
*/
protected $card;
/**
* #Column(name="user_name", type="string")
*/
protected $userName;
/**
* #Column(name="user_pass", type="string")
*/
protected $userPass;
}
/**
* #Entity
* #Table(name="cards")
*/
class Card
{
/**
* #Id
* #GeneratedValue
* #Column(type="bigint")
*/
protected $id;
/**
* #OneToOne(targetEntity="User", inversedBy="Card")
* #JoinColumn(name="user_id", referencedColumnName="id")
*/
protected $user;
/**
* #Column(name="post_title", type="string")
*/
protected $cardType;
}
The difference here is I wrote #JoinColumn in both objects/entities. And in Doctrine example there is only one.
Now I would get what I think is Bidirectional relation. If i look at EER diagram, I can see one line pointing from user to card, and the other from card to user.
So basicly did I get this right?
Is the Doctrine documentation wrong? :D
How would Bidirectional OneToOne relation look in EER diagram?
Thanks!
The only difference is in the PHP class interface, i.e. in the presence or absence of the property that points back to the owner (e.g. the $customer property in the mentioned Doctrine example). In other words Doctrine just needs to know whether it should take care about a single property ($shipping) or two properties ($cart and $customer). There is no other difference. Therefore, the SQL code is the same (because one foreign key is sufficient for representing any 1:N relationship) and there would no difference in EER diagram neither (because in EER you typically do not solve such PHP-related implementation details).
Unidirectional and bidirectional have nothing to do with the background algorithm how to create these connections in the database layer.
All they talk about is how the connections can be used. In an unidirectional relationship you can access the target only from one site. An bidirectional relationship allows the connection to be called from two (both) sides.
So in an unidir. rel. model_a can get to model_b, but model_b cant get to model_a (without extra work).
If you now use a bidir. rel both models can access each other without problems
In doctrine terms, a unidirectional relationship defines a
$modelA->getModelB() method, but not a $modelB->getModelA() method, whereas a bidirectional relationship defines both methods (or accessors, however you want to call them)
in an uml diagram it would look like this:
unidirectional
modelA --X------> modelB
bidirectional
modelA <--------> modelB