Skip to content

Filtering by a relation's property #944

Description

@ymarillet

Hi,

This is affecting version 2.0.1 to current (2.0.3)

Having the following entities:

<?php

namespace AppBundle\Entity;

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

/**
 * @ApiResource(
 *     attributes={
 *          "normalization_context"={"groups"={"foo"}},
 *          "filters"={"foo.search_filter"}
 *     }
 * )
 * @ORM\Entity
 */
class Foo
{
    /**
     * @var int The entity Id
     *
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @var string Something else
     *
     * @ORM\OneToMany(targetEntity="Bar", mappedBy="foo")
     *
     * @Serializer\Groups({"foo"})
     */
    private $bars;

    public function __construct()
    {
        $this->bars = new ArrayCollection();
    }

    public function getId()
    {
        return $this->id;
    }

    /**
     * @return string
     */
    public function getBars()
    {
        return $this->bars;
    }

    /**
     * @param string $bars
     * @return static
     */
    public function setBars($bars)
    {
        $this->bars = $bars;
        return $this;
    }
}
<?php

namespace AppBundle\Entity;

use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation as Serializer;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * @ApiResource
 * @ORM\Entity
 */
class Bar
{
    /**
     * @var int The entity Id
     *
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @var Foo
     *
     * @ORM\ManyToOne(targetEntity="Foo", inversedBy="bars")
     * @ORM\JoinColumn(nullable=false, onDelete="CASCADE")
     * @Assert\NotBlank
     */
    private $foo;

    /**
     * @var string
     *
     * @ORM\Column(nullable=false)
     * @Assert\NotBlank
     *
     * @Serializer\Groups({"foo"})
     */
    private $prop = '';

    public function getId()
    {
        return $this->id;
    }

    /**
     * @return Foo|null
     */
    public function getFoo()
    {
        return $this->foo;
    }

    /**
     * @param Foo $foo
     * @return static
     */
    public function setFoo(Foo $foo)
    {
        $this->foo = $foo;
        return $this;
    }

    /**
     * @return string
     */
    public function getProp()
    {
        return $this->prop;
    }

    /**
     * @param string $prop
     * @return static
     */
    public function setProp($prop)
    {
        $this->prop = $prop;
        return $this;
    }
}

Services defined as:

services:
  app.entity.filter.foo:
      parent:    'api_platform.doctrine.orm.search_filter'
      arguments:
          - { bars.prop: 'ipartial' }
      tags:
          - { name: 'api_platform.filter', id: 'foo.search_filter' }

Having the following data:

AppBundle\Entity\Foo:
  foo1:
    id: 1
    bars: ["@bar1", "@bar2"]
  
AppBundle\Entity\Bar:
  bar1:
    id: 1
    prop: "toto"
    foo: "@foo1"
  bar2:
    id: 2
    prop: "tata"
    foo: "@foo1"

Having set the proper filters in order to run that simple query:
http://localhost/foos?bar.prop=toto

Will result:

{
  "@context": "/contexts/Foo",
  "@id": "/foos",
  "@type": "hydra:Collection",
  "hydra:member": [
    {
      "@id": "/foos/1",
      "@type": "Foo",
      "bars": [
        {
          "@id": "/bars/1",
          "@type": "Bar",
          "prop": "toto"
        }
      ]
    }
  ],
  "hydra:totalItems": 1,
  "...otherProps...": "...otherValues...."
}

I understand that the second Bar attached to foo1 gets filtered through the doctrine query, but since we're on the Foo endpoint:

  • is it still a valid behaviour ?
  • if so, how to tell api-platform/doctrine to fetch all relations upon filtering on them ?

Regards,
Yohann

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Fields

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions