Doctrine 2 where two associations exists query - sql

I have two entities related, and I need a query that checks if entityOne have two different relations (extra column as diff field) to entityTwo.
A simple "WHERE entityTwo.diff_field = 1 AND entityTwo.diff_field = 2" don't work.
How can I achive this?
Thanks
UPDATE:
$query = $this->createQueryBuilder('one');
$query->addSelect('two')->leftJoin('one.two', 'two');
$query->where('two.id = :a')->setParameter('a',1);
$query->andWhere('two.id = :b')->setParameter('b',2);
EntityOne
class EntityOne {
/**
* #ORM\Id
* #ORM\Column(type="integer", nullable=false);
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\OneToMany(targetEntity="EntityTwo", mappedBy="one")
*/
protected $two;
}
EntityTwo
class EntityTwo {
/**
* #ORM\Id
* #ORM\Column(type="integer", nullable=false);
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\ManyToMany(targetEntity="EntityOne", inversedBy="two", cascade={"persist"})
* #ORM\JoinTable(name="one_two_xref")
*/
protected $one;
}

I think you need two EXISTS subqueries.
You want (I think) to select entityOnes which have
a linked entityTwo with diffType 1 and also a linked entityTwo with difftype 2.
If you scroll down to 'EXISTS in WHERE clause with correlated Subquery' in this documentation:
http://docs.doctrine-project.org/en/2.1/reference/dql-doctrine-query-language.html
I think what you need is a similar query but with two separate EXISTS subqueries, something like :
WHERE EXISTS (SELECT EntityTwo ... DiffType = 1)
AND EXISTS (SELECT EntityTwo ... DiffType = 2)

Related

ManyToMany with composite key with api-platform

I am using Api Platform.
I have two entities Player and Team and one entity PlayerHasTeam to represent in the database the date on which the player joined a team.
This is my PlayerHasTeam entity :
/**
* #ApiResource(
* collectionOperations={
* "get",
* "post"
* },
* itemOperations={
* "get",
* "put",
* "delete"
* }
* )
* #ORM\Table(name="playerHasTeam")
* #ORM\Entity
*/
class PlayerHasTeam
{
/**
* #var Player
*
* #ORM\ManyToOne(targetEntity="App\Entity\Player", inversedBy="id")
* #ORM\JoinColumn(referencedColumnName="idPlayer", name="idPlayer", nullable=false)
*
* #ORM\Id
*/
private $player;
/**
* #var Team
*
* #ORM\ManyToOne(targetEntity="App\Entity\Team", inversedBy="id")
* #ORM\JoinColumn(referencedColumnName="idTeam", name="idTeam", nullable=false)
*
* #ORM\Id
*/
private $team;
/**
* #var DateTime
*
* #ORM\Column(name="joinedAt", type="datetime", nullable=false)
*/
private $joinedAt;
(Getters and Setters)
The problem is the following, I need to do GET, PUT and DELETE request on this Composite Entity.
Api-platform defines the following routes :
GET /player_has_teams
POST /player_has_teams
GET /player_has_teams/{id}
PUT /player_has_teams/{id}
DELETE /player_has_teams/{id}
I cannot use the 3 last because I don't have a generated id.
I want to do my requests with a route like /player_has_teams/{idPlayer}/{idTeam}
It seems that api-platform does not handle this case.
Do you have any suggestions ?
Thank you
Ok, I found a solution.
I just have to call my route like this
GET /player_has_teams/player=1;team=1
PUT /player_has_teams/player=1;team=1

Doctrine NOT EXIST condition with ManyToMany relation

I have 2 entities with a many-to-many relation as this:
User
{
/**
* #var Group[]
*
* #ORM\ManyToMany(targetEntity="Group", inversedBy="users")
* #ORM\JoinTable(
* name="user_group",
* joinColumns={
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="group_id", referencedColumnName="id")
* }
* )
*/
protect $groups
}
Group
{
/**
* #var User[]
*
* #ORM\ManyToMany(targetEntity="User", mappedBy="groups")
*/
private $users;
}
This creates 3 tables on DB:
user
group
user_group
Is possible to manipulate user_group in a DQL? I'm trying something like this:
SELECT *
FROM user u
WHERE EXISTS
(SELECT ug.user_id FROM user_group ug WHERE ug.user_id = u.id AND ug.group_id = 3)
This doesn't work since it should be written as Entities. I could run this with Native SQL but I wanted to be sure that there's no better solution for this
The solution from Jonathan Martinez worked but I found this to be more straightforward (specially because I could use NOT MEMBER OF as well):
$query = $em->createQuery('SELECT u.id FROM User u WHERE :groupId MEMBER OF u.groups');
$query->setParameter('groupId', $group);
More on this, here:
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html#dql-select-examples
You can try this:
$em = $this->getDoctrine()->getManager();
$query = $em->createQueryBuilder('u')
->select('u')
->from('AppBundle:User', 'u')
->innerJoin('u.groups', 'g', 'WITH', 'g.user_id = u.id')

Doctrine - Missing value for primary key

I have this entity:
/**
* Class ParserURLs
* #package AppBundle\Entity
* #ORM\Entity(repositoryClass="AppBundle\Entity\ParserURLsRepository")
*/
class ParserURLs
{
/**
* #ORM\Id
* #ORM\Column(type="string", length=50)
*/
protected $external_id;
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Parser")
*/
protected $parser;
...
}
Any I try to get results filtering by $parser, like this:
$query = $this->doctrine->getManager()->createQuery(
'SELECT u
FROM AppBundle:ParserURLs u
WHERE u.parser = :parser')
->setParameter('parser', $this->parser);
$result = $query->getResult();
But Doctrine tell me: Missing value for primary key parser on AppBundle\Entity\ParserURLs
I think that the problem es because the multiple primary key external_id-parser but now, I only want search by one of their. It's not possible in Doctrine? I need this primary keys.
Thanks you in advance
Looks like you are missing name property in your annotations. Your definition should look like this:
/**
* #var string
*
* #ORM\Column(name="id", type="string", length=9)
* #ORM\Id
*/
private $id;
Where name="id" is your name of the field from you DB
If your ID has autoincrement you have to add this line:
#ORM\GeneratedValue(strategy="AUTO")

Doctrine2 - get group which hasn't hidden person

The first entity called BUNDLE
/**
* #var \Doctrine\Common\Collections\Collection of \Akademie\Course\Course
* #ManyToMany(targetEntity="Akademie\Course\Course", mappedBy="bundles")
*/
private $courses;
The second entity is called COURSE
/**
* #var \Doctrine\Common\Collections\Collection of \Akademie\Bundle\Bundle
* #ManyToMany(targetEntity="Akademie\Bundle\Bundle", inversedBy="courses")
*/
private $bundles;
/**
* #var \Doctrine\Common\Collections\Collection of \Akademie\Course\CourseDate
* #OneToMany(targetEntity="Akademie\Course\CourseDate", mappedBy="course")
*/
private $courseDates;
/**
* #var int
* #Column(type="boolean")
*/
private $hidden;
and the third is called COURSEDATE
/**
* #var \Akademie\Course\Course
* #ManyToOne(targetEntity="Akademie\Course\Course", inversedBy="courseDates")
* #JoinColumn(nullable=false)
*/
private $course;
/**
* #var \DateTime
* #Column(type="datetimetz", nullable=true)
*/
private $beginDate;
I have parameter course and I need to get all bundles, which contains this course. What's more, all other courses in that bundle has to have courseDate newer than current date and can't be hidden. Otherwise I don't want to get this bundle. I hope it is clear now...
I am not familiar with MEMBER OF but i think you are better of with an INNER JOIN.
DQL:
SELECT group
FROM path\to\entity\Group group
INNER JOIN group.persons person
INNER JOIN person.city city
WHERE person.hidden = FALSE AND city.name = :name
QueryBuilder:
$em->createQueryBuilder()
->select('group')
->from('path\to\entity\Group', 'group')
->innerJoin('group.persons', 'person')
->innerJoin('person.city', 'city')
->where('person.hidden = FALSE')
->andWhere('city.name = :name')
->setParameter('name', $yourName)
->getQuery()->getResult();
I assumed that your person entity has an attribute called hidden and that your person-city relationship is bidirectional.

Doctrine- one of associations doesn't work proper

I have problem with associations in Doctrine 2
I have two associations which look the same. One works fine, the second one work in weird way. I'll explain it a bit later.
Here is my main entity- Product:
**
* Product
*
* #ORM\Table(name="product", indexes={
* #ORM\Index(name="category_index", columns={"category_id"}),
* #ORM\Index(name="partner_index", columns={"partner_id"})
* })
* #ORM\Entity
*/
class Product
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255, nullable=false)
*/
private $name;
/**
* #var Category
*
* #ORM\ManyToOne(targetEntity="Category")
* #ORM\JoinColumn(name="category_id", referencedColumnName="id")
*/
private $categoryId;
/**
* #var Partner
*
* #ORM\ManyToOne(targetEntity="Partner")
* #ORM\JoinColumn(name="partner_id", referencedColumnName="id")
*/
private $partnerId;
}
Category Entity:
/**
* Category
*
* #ORM\Table(name="category")
* #ORM\Entity
*/
class Category
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="category_name", type="string", length=100, nullable=false)
*/
private $categoryName;
}
Partner Entity:
/**
* Partner
*
* #ORM\Table(name="partner")
* #ORM\Entity
*/
class Partner
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=150, nullable=false)
*/
private $name;
}
As you can see I have two identical associations:
Product#categoryId
Product#partnerId
The first one- categoryId works as it should, but the second one- partnerId doesn't:
First thing I noticed is that Doctrine create proxy class with Partner Entity,
while Category Entity doesn't need proxy class to work, so one of
this doesn't work proper.I just started with Doctrine so I might be
wrong.
I have 4 records in Partner table. When I try to modify Product
record manually, in partner_id field I can't set 1-4, I can set
something like this:
(empty)
1 - 1
2 - 2
3 - 3
4 - 4
(empty)
1 - 1
2 - 2
3 - 3
4 - 4
First time I see something like this.
And the last thing I noticed:
$query = $em->createQuery('
SELECT pp.name, p.id
FROM Application\Entity\Product AS p
LEFT JOIN Application\Entity\Partner AS pp WITH p.partner_id = pp.id GROUP by p.partner_id
');
$items = $query->getResult();
Shows me error:
Doctrine\ORM\Query\QueryException: [Semantical Error] line 0, col 148 near 'partner_id =': Error: Class Application\Entity\Product has no field or association named partner_id in
Thanks for any help and tips.
Edit
So, the question is. Why does Doctrine create proxy class for Partner Entity, but not for Category?
As far as I know Doctrine will only create proxies when functionality for the entity it belongs to is used.
You can also manually generate the proxies using the command line tools.
About the error:
You should use partnerId instead of partner_id. Partner_id is the name of your database column, not of the attribute defined in your Product entity.
$query = $em->createQuery('
SELECT pp.name, p.id
FROM Application\Entity\Product AS p
LEFT JOIN Application\Entity\Partner AS pp WITH p.partnerId = pp.id GROUP by p.partnerId
');
$items = $query->getResult();
Have a good look at the DQL documentation:
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html
Maybe it will give you some extra insights about the difference between SQL and DQL.