I'm having problems to define an association mapping and I don't know what to do to solve.
I want build a relation Many to Many between two objects but not only for one field.
One table refers to persons and the other to image, the target of this relation is represent when a person has been tagged by other person for this image
I need something like this:
| Tagged | Tagger | Photo |
| person_id_1 | person_id_2 | image_id_1 |
| person_id_3 | person_id_2 | image_id_1 |
| person_id_2 | person_id_4 | image_id_2 |
I try it using many to many relations like this:
/**
* #ORM\ManyToMany(targetEntity="Media")
* #ORM\JoinTable(name="persons_tagged",
* joinColumns={
* #ORM\JoinColumn(name="user_tagged", referencedColumnName="id"),
* #ORM\JoinColumn(name="user_tagger", referencedColumnName="id")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="media_id",referencedColumnName="id")
* }
* )
**/
private $employeeTagged;
When I try to update the schema by console, the table in DB it is created but without foreign keys because an exception of foreign key definition is threw and I have to create the foreign keys manually.
Someone has had a similar problem or a way to solve it? thanks
Create a new entity which has link to image, link to tagger (user), link to tagged (user).
You might also want to add created datetime, updated datetime, portion of image this person is in, description/text, etc.
Related
I have a table like below in Room, in a Android application, I use Raw Query to get data. Can it be sorted by second value in array sorting_field?
---------------------------------------------
| id | other_fields | sorting_field |
---------------------------------------------
| 1001 | … | ["24","0.02","2"] |
---------------------------------------------
Initially I did the sorting part in Repository with Transformations.switchMap, inside the function a MutableLiveData> and applied Collections.sort.
It worked like a charm:
Collections.sort(list, (o1, o2) -> Double.compare(Double.valueOf(o1.sorting_field().get(positionInList)), Double.valueOf(o2.sorting_field().get(positionInList))));
After Paging implementation, I took the sorting logic out, moved to queries builder and here I am.
I have an entity called Item which has a ManyToMany connection with a JoinTable to an entity called Tags
This is working well. The problem is, that I need the tags in the exact order as they are chosen, not sorted by tag id, as I get them now when I call getTags() on the Item class. Is there a way to do that?
Use the join table to define that order.
Item_id | Tags_id | Order
--------+---------+------
1 | 1 | 2
1 | 2 | 1 <-- order for tags of item 1
1 | 3 | 3
-------+---------+------
2 | 42 | 1
2 | 1 | 2 <-- order for tags of item 2
-------+---------+------
3 | 3 | 1 <-- order for tags of item 3
... And the entities equivalent :
You are going from
//MToM : Many To Many
//OToM : One To Many
//MToO : Many To One
[Item] -MToM-> [Tags]
[Tags] -MToM-> [Item]
To
[Item] -OToM-> [ItemTags] -MToO-> [Tags]
[Tags] -OToM-> [ItemTags] -MToO-> [Item]
And, in your entities classes :
class Item
{
// some properties ...
/**
* #OneToMany(targetEntity="ItemTags", mappedBy="Item")
*/
private $ItemTags; //array
//more properties, and get/set
}
class Tags
{
// some properties ...
/**
* #OneToMany(targetEntity="ItemTags", mappedBy="Tags")
*/
private $ItemTags; //array
//more properties, and get/set
}
class ItemTags
{
/**
* #ManyToOne(targetEntity="Item", inversedBy="ItemTags")
* #JoinColumn(name="Item_id", referencedColumnName="id")
* ^-----^-------------------------^^---- Make sure to use the same than in your table !
*/
private $Item; // single Item
/**
* #ManyToOne(targetEntity="Tags", inversedBy="ItemTags")
* #JoinColumn(name="Tags_id", referencedColumnName="id")
* ^-----^-------------------------^^---- Make sure to use the same than in your table !
*/
private $Tags; // single Tags
private $Order;
// get/set and stuff
}
I am using Symfony3.4 and have the following relationship in the database between House and Type entities:
house
+----------------------------------------------+
| id | title | description |
+----------------------------------------------+
| 1 | some title 1 | some description 1 |
+----------------------------------------------+
| 2 | some title 2 | some description 2 |
+----------------------------------------------+
type
+----------------+
| id | name |
+----------------+
| 1 | shortstay |
+----------------+
| 2 | rent |
+----------------+
| 4 | sell |
+----------------+
house_types
+-----------------------------------+
| id | house_id | type_id | price |
+-----------------------------------+
| 1 | 1 | 2 | 1000 |
+-----------------------------------+
| 2 | 1 | 3 | 1000000 |
+-----------------------------------+
| 3 | 2 | 1 | 100 |
+-----------------------------------+
| 4 | 2 | 3 | 200000 |
+-----------------------------------+
Here are my entities:
House entity
class House extends EntityBase
{
/**
* #ORM\OneToMany(targetEntity="AppBundle\Entity\HouseHasTypes", mappedBy="houses", cascade={"persist","remove"})
*/
protected $hasTypes;
Type entity
class Type extends EntityBase
{
/**
* #ORM\OneToMany(targetEntity="AppBundle\Entity\HouseHasTypes", mappedBy="types", cascade={"persist","remove"})
*/
protected $hasHouses;
HouseHasTypes entity
class HouseHasTypes extends EntityBase
{
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\House", cascade={"persist"}, fetch="EAGER")
* #ORM\JoinColumn(name="house_id", referencedColumnName="id", nullable=true)
*/
protected $houses;
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Type", cascade={"persist","remove"}, fetch="EAGER" )
* #ORM\JoinColumn(name="type_id", referencedColumnName="id",nullable=true)
*/
protected $types;
/**
* #var int
*
* #ORM\Column(name="price", type="integer")
*/
protected $price;
I did not quite get the difference between ManyToOne and OneToOne relationship. Which one should mine be?
Also, what would be the easiest way to handle inserting new data into the 2 entities (House and HouseHasTypes). Right now I can render the checkboxes for each row in type table as follows:
$builder
...
->add('hasTypes', EntityType::class, array(
'required' => true,
'class' => Type::class,
'expanded' => true,
'multiple' => true,
))
And the in the controller I am planning to make a foreach(){} for each of the checked Types and setHouse() and setPrice() there. Is there any other more efficient way to do this?
How can I render as many textboxes as there are the abovementioned EntityType checkboxes to define a price for each Type selected? I am currently hardcoding three html input text elements and hiding them with javascript based on checked checkboxes. If I make a custom form, how can I tell it to render 3 text inputs (since there're 3 rows in the entity table)
Sorry for asking so many questions. Any help would be much appreciated
Your database model seems correct.
To define you the OneToMany, ManyToOne and OneToOne relationship, I made you little examples:
Imagine we have two entities: USER and ORDER.
OneToMany:
An user can do 0, 1 or many orders right ? It means that One user can be linked To 0, 1 or Many orders.
USER(id:1) --> ORDER(id:1)
--> ORDER(id:3)
--> ORDER(id:8)
ManyToOne:
An order can be done by one and only one user right ? It means that Many orders can be linked To One user.
ORDER(id:1) --> USER(id:1)
ORDER(id:3) --> USER(id:1)
ORDER(id:8) --> USER(id:1)
OneToOne:
Now imagine we have two others entities: USER and EMAIL.
An user can have one and only one email address and an email address can have one an only one user right ? It means that One user can be linked To One email address and One email address can be linked To One user.
USER(id:1) --> EMAIL(id:6)
USER(id:3) --> EMAIL(id:7)
USER(id:8) --> EMAIL(id:1)
Hope I was clear.
For your others questions, Symfony will automatically insert data on form submit if you have correctly defined your getter and setter in entities no needs to do a foreach
I have three tables:
game columns: id | name (eg. 1 | Halo)
own columns: id | type_id | type_name (eg. 1 | 1 | on wishlist)
user columns: id | name (eg. 1 | Tomek)
Now what I have is a ManyToMany connection between those tables:
User (table user_own)
/**
* #ORM\ManyToMany(targetEntity="Own")
* #ORM\JoinTable(
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="type_id", referencedColumnName="id")}
* )
*/
Own (table own_game)
/**
* #ORM\ManyToMany(targetEntity="Game")
* #ORM\JoinTable(
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="game_id", referencedColumnName="id")}
* )
*/
My query:
public function getOwned() {
return $this->getEntityManager()
->createQuery('
SELECT u, o, g FROM AcmeGoBundle:User u
JOIN u.owners o
JOIN u.games g
')
->getResult();
}
I can retrieve games owned by particular user, but I can't connect type of ownership. How can I do this?
To crate ManyToMany with additional column with some data you need to create this by hand.
Doctrine ManyToMany relation crates a join table with id's of joined entities. So you need to create by your own Entity named ex. UserOwns with OneToMany relation to User and another OneToMany relation Own. Then you can add additional field with your data inside.
Check that question: Doctrine2: Best way to handle many-to-many with extra columns in reference table
I have two tables in my database: user and media_contact. The media_contact table has a user_id, so, obviously, my intent is to be able to select media contacts based on a user.
The problem I'm having is that this fails:
// VNN/PressboxBundle/Entity/User.php
// $this in this case is a User object with id 26
$customContacts = $em->getRepository('VNNPressboxBundle:MediaContact')->findByUser($this);
This gives me nothing. $customContacts is empty. But:
mysql> select * from media_contact where user_id=26;
+-----+-------------+-----------------------+---------------+---------+
| id | name | email | media_area_id | user_id |
+-----+-------------+-----------------------+---------------+---------+
| 177 | Jason Swett | jason.swett#gmail.com | NULL | 26 |
| 183 | Sam | sam#sam.com | NULL | 26 |
+-----+-------------+-----------------------+---------------+---------+
2 rows in set (0.00 sec)
It should really be returning two objects. I really don't understand why this is happening.
Here are my annotations:
// User.php
/**
* #ORM\OneToMany(targetEntity="MediaContact", mappedBy="user")
*/
private $mediaContacts;
-
// MediaContact.php
/**
* #ORM\ManyToOne(targetEntity="User", inversedBy="mediaContacts")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
private $user;
What could be going wrong?
You have to use $this->getId() instead of $this in order for it to work:
$customContacts = $em->getRepository('VNNPressboxBundle:MediaContact')->findByUser($this->getId());