ManyToMany with composite key with api-platform - api

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

Related

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.

Doctrine ManyToOne with join table - filter results

I have a Customer entity and User entity with a JOIN relationship table customers_users.
In the Customer entity I have this.
/**
* #var User
*
* #ORM\ManyToMany(targetEntity="Entity\User")
* #ORM\JoinTable(name="customers_users",
* joinColumns={#ORM\JoinColumn(name="customer_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id", unique=true)}
* )
*
*/
private $users;
I want that when a customer is created I can assign the users to it and actually it works well, however I want filter the users to show only those that don't are assigned to none customer.
For example, I have two customers and two users and the first customer has assigned two users; then when I edit the second customer, two users appear to be assigned to it but when I select these and I send the form, it throws the following exception:
An exception occurred while executing 'INSERT INTO customers_users (customer_id, user_id) VALUES (?, ?)' with params [2, 1]:
SQLSTATE[23505]: Unique violation: 7 ERROR: duplicate key value violates unique constraint "uniq_2763c6cca76ed395"
DETAIL: Key (user_id)=(1) already exists.
/**
* #var User
*
* #ORM\ManyToMany(targetEntity="Entity\User", inversedBy="customers")
* #ORM\JoinTable(name="customers_users",
* joinColumns={#ORM\JoinColumn(name="customer_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id", unique=true)}
* )
*
*/
private $users;
and in the User entity, in customers annotation you should put:
* #ORM\ManyToMany(targetEntity="Entity\Customer", inversedBy="users")
(...)
What I actually did in this situation, is:
// UserAdmin.php that extends SonataAdminBundle's User admin
/**
* {#inheritdoc}
*/
public function createQuery($context = 'list')
{
/** #var QueryBuilder $query */
$query = parent::createQuery();
$request = Request::createFromGlobals();
// Could not find another way to detect that admin list is created from
// sonata_type_model_list parent.
// Of course, this applies only to sonata_type_model_list field type.
if ($request->query->get('pcode') == 'demo.admin.customer') {
$alias = $query->getRootAliases()[0];
$query->leftJoin($alias . '.customers', 'c');
// $query-> ... do filtering here
}
return $query;
}
This way I could filter Users in any way I wanted.

Doctrine 2 where two associations exists query

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)