Api-platform filter annotation for Many To Many
Asked Answered
U

1

12

I've follow the implementation of filters with annotation to load only the sources concern for one user. Very usefull, work properly.

https://api-platform.com/docs/core/filters/#using-doctrine-filters

BUT : I want to do the same in my entity with an ManyToMany relationship and not ManyToOne like this :

<?php

namespace App\Entity;

use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Annotation\ApiSubresource;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;
use App\Annotation\UserAware;

/**
 *
 * @ApiResource(routePrefix="/api")
 * @ORM\Entity
 * @ORM\Table(name="albums")
 * @UserAware(userFieldName="user_owner")
 * @UserAware(userFieldName="album_access_user")
 */
class Album
{
    //...

    /**
     * @ORM\ManyToOne(targetEntity="User")
     * @ORM\JoinColumn(nullable=false, name="user_owner", referencedColumnName="id")
    */
    public $userOwner;

    /**
     * @ORM\ManyToMany(targetEntity="User", inversedBy="albums")
     * @ORM\JoinTable(name="album_access")
     * @ORM\JoinTable(
     *  name="album_access",
     *  joinColumns={
     *      @ORM\JoinColumn(name="album_access_album", referencedColumnName="id")
     *  },
     *  inverseJoinColumns={
     *      @ORM\JoinColumn(name="album_access_user", referencedColumnName="id")
     *  }
     * )
    */
    private $accesses;

    //...
}

AS there is a JoinTable now and not just a JoinColum, i have to adapt the UserFilterConfigurator.php Event but i've no idea how to do that to give him the table and not juste the column...

Here is the logic error i get because i ask for the Entity Table and not the Join Table for now :

An exception occurred while executing 'SELECT DISTINCT o0_.id AS id_0, o0_.id AS id_1 FROM albums o0_ WHERE (o0_.album_access_user = '4') ORDER BY o0_.id ASC LIMIT 30':\n\nSQLSTATE[42703]: Undefined column: 7 ERROR:  column o0_.album_access_user does not exist\nLINE 1: ...id_0, o0_.id AS id_1 FROM albums o0_ WHERE (o0_...

How can I get that for ManyToMany <=> how can i pass the good (join)table + (join) column ??

Unclassical answered 23/11, 2018 at 19:35 Comment(0)
P
0

You can't access the join table unless you write a native SQL query.

You can, though, ask to find all Albums where a particular user is part of the Album::$accesses collection.

In general terms, you can use :entity IS MEMBER OF collection DQL, as described in the docs (use browser search function to look for "member of"):

<?php
$query = $em->createQuery('SELECT u.id FROM CmsUser u WHERE :groupId MEMBER OF u.groups');
$query->setParameter('groupId', $group);
$ids = $query->getResult();

You didn't publish your filter code, so I can't give you the exact query, but it would be along the lines of:

$query = $em->createQuery('SELECT a FROM Album a WHERE :user MEMBER OF a.accesses');
$query->setParameter('user', $user); // assuming $user instanceof User, or $user is User's ID
/** @var Album[] $albums */
$albums = $query->getResult();

The one restriction is that you can't pass multiple $user values into a single x MEMBER OF y statement. You must add multiple separate x MEMBER OF y statements, one for each user you want to look for. This is where switching to a native query becomes a viable option if you don't need Doctrine's platform portability.

Picnic answered 9/7 at 2:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.