Пользовательская или ApiPlatform фильтрация вложенных ресурсов не работает в сущности с составным первичным ключом - PullRequest
0 голосов
/ 28 октября 2019

Версия (-ы) платформы API : 2.4.5

Описание
Пользовательская или ApiPlatform фильтрация вложенных ресурсов не работает в объекте с составным основнымключ

Как воспроизвести
Создайте объект A с составным ключом и добавьте отношение ManyToOne к объекту B. Создайте объект B с одним ключом id и другими полями. Создание настраиваемого фильтра или фильтра api-платформы в объекте A для поля из объекта B (может быть первичным ключом объекта B или нет)

Дополнительный контекст
Фильтрация работаеткогда у объекта A есть один ключ идентификатора.

Пример объектов * ENTITY A

<?php

namespace App\Entity;


use Doctrine\ORM\Mapping as ORM;
use ApiPlatform\Core\Annotation\ApiResource; 
use ApiPlatform\Core\Annotation\ApiFilter;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter;
use Symfony\Component\Serializer\Annotation\Groups; 
use Symfony\Component\Validator\Constraints as Assert; 
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\OrderFilter;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\NumericFilter;
use App\Filter\TipoSancionFilter;

/**
 * AntecedentesOSanciones
 *
 * @ORM\Entity
 * @ApiResource(
 *  normalizationContext={"groups"={"getCollectionAntecedentes"}},
 * )
 * @ApiFilter(SearchFilter::class , properties={"codTipoSancion.codTipoSancion":"exact", "codTipoSancion.nombreSancion":"exact"})
  */
class AntecedentesOSanciones
{
    /**
     * @var \PadronEscribanos
     *
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="NONE")
     * @ORM\ManyToOne(targetEntity="PadronEscribanos" , inversedBy="antecedentes")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="matricula", referencedColumnName="matricula")
     * })
     * @Groups({ "getCollectionAntecedentes"})
     */

    private $matricula;

    /**
     * @var int
     *
     * @ORM\Column(name="renglon", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="NONE")
     * @Groups({"getCollectionAntecedentes"})
     */
    private $renglon;


    /**
     * @var \TiposSanciones
     *
     * @ORM\ManyToOne(targetEntity="TiposSanciones")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="cod_tipo_sancion", referencedColumnName="cod_tipo_sancion")
     * })
     * @Groups({"getCollectionAntecedentes"})
     */
    private $codTipoSancion;

    public function getRenglon(): ?int
    {
        return $this->renglon;
    }
    public function setRenglon($renglon): self
    {
        $this->renglon = $renglon; 
        return $this;
    }

    public function getCodTipoSancion(): ?TiposSanciones
    {
        return $this->codTipoSancion;
    }

    public function setCodTipoSancion(?TiposSanciones $codTipoSancion): self
    {
        $this->codTipoSancion = $codTipoSancion;

        return $this;
    }

    public function getMatricula(): ?PadronEscribanos
    {
        return $this->matricula;
    }

    public function setMatricula(?PadronEscribanos $matricula): self
    {
        $this->matricula = $matricula;

        return $this;
    }


}

* ENTITY B

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use ApiPlatform\Core\Annotation\ApiResource; 
use Symfony\Component\Serializer\Annotation\Groups;

/**
 * TiposSanciones
 *
 * @ORM\Entity
 * @ApiResource
 */
class TiposSanciones
{
    /**
     * @var int
     *
     * @ORM\Column(name="cod_tipo_sancion", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     * @Groups({"getCollectionAntecedentes"})
     */
    private $codTipoSancion;

    /**
     * @var string
     *
     * @ORM\Column(name="nombre_sancion", type="string", length=36, nullable=false)
     * @Groups({"getCollectionAntecedentes"})
     */
    private $nombreSancion;


    public function getCodTipoSancion(): ?int
    {
        return $this->codTipoSancion;
    }

    public function getNombreSancion(): ?string
    {
        return $this->nombreSancion;
    }

    public function setNombreSancion(string $nombreSancion): self
    {
        $this->nombreSancion = $nombreSancion;

        return $this;
    }


}

** ОШИБКАВЫХОД * Пример get url: http://localhost:8282/api/antecedentes_o_sanciones?codTipoSancion.codTipoSancion=4

[
   {
      matricula:{
         matricula:325,
         nombres:"AIDEE MARIA DEL ROSARIO",
         apellidos:"COSTAMAGNA"
      },
      renglon:1,
      codTipoSancion:{
         codTipoSancion:1,
         nombreSancion:"SUSPENSIÓN "
      }
   },
   {
      matricula:{
         matricula:325,
         nombres:"AIDEE MARIA DEL ROSARIO",
         apellidos:"COSTAMAGNA"
      },
      renglon:2,
      codTipoSancion:{
         codTipoSancion:1,
         nombreSancion:"SUSPENSIÓN "
      }
   },
   {
      matricula:{
         matricula:325,
         nombres:"AIDEE MARIA DEL ROSARIO",
         apellidos:"COSTAMAGNA"
      },
      renglon:3,
      codTipoSancion:{
         codTipoSancion:1,
         nombreSancion:"SUSPENSIÓN "
      }
   },
   {
      matricula:{
         matricula:325,
         nombres:"AIDEE MARIA DEL ROSARIO",
         apellidos:"COSTAMAGNA"
      },
      renglon:4,
      codTipoSancion:{
         codTipoSancion:4,
         nombreSancion:"DESTITUCIÓN "
      }
   },
   {
      matricula:{
         matricula:325,
         nombres:"AIDEE MARIA DEL ROSARIO",
         apellidos:"COSTAMAGNA"
      },
      renglon:5,
      codTipoSancion:{
         codTipoSancion:4,
         nombreSancion:"DESTITUCIÓN "
      }
   },
   {
      matricula:{
         matricula:570,
         nombres:"MARCELO MIGUEL",
         apellidos:"GILETTA"
      },
      renglon:1,
      codTipoSancion:{
         codTipoSancion:1,
         nombreSancion:"SUSPENSIÓN "
      }
   },
   {
      matricula:{
         matricula:570,
         nombres:"MARCELO MIGUEL",
         apellidos:"GILETTA"
      },
      renglon:2,
      codTipoSancion:{
         codTipoSancion:2,
         nombreSancion:"SUSPENSIÓN PREVENTIVA "
      }
   },
   {
      matricula:{
         matricula:570,
         nombres:"MARCELO MIGUEL",
         apellidos:"GILETTA"
      },
      renglon:3,
      codTipoSancion:{
         codTipoSancion:4,
         nombreSancion:"DESTITUCIÓN "
      }
   },
   {
      matricula:{
         matricula:652,
         nombres:"MARIA COVADONGA SUSANA",
         apellidos:"MARCUZZI"
      },
      renglon:1,
      codTipoSancion:{
         codTipoSancion:2,
         nombreSancion:"SUSPENSIÓN PREVENTIVA "
      }
   },
   {
      matricula:{
         matricula:652,
         nombres:"MARIA COVADONGA SUSANA",
         apellidos:"MARCUZZI"
      },
      renglon:2,
      codTipoSancion: {
         codTipoSancion: 1,
         nombreSancion: "      SUSPENSIÓN      "
      }
   }
]

** ОЖИДАЕМЫЙ ВЫХОД * Пример get url: http://localhost:8282/api/antecedentes_o_sanciones?codTipoSancion.codTipoSancion=4

[
   {
      matricula:{
         matricula:325,
         nombres:"AIDEE MARIA DEL ROSARIO",
         apellidos:"COSTAMAGNA"
      },
      renglon:4,
      codTipoSancion:{
         codTipoSancion:4,
         nombreSancion:"DESTITUCIÓN "
      }
   },
   {
      matricula:{
         matricula:325,
         nombres:"AIDEE MARIA DEL ROSARIO",
         apellidos:"COSTAMAGNA"
      },
      renglon:5,
      codTipoSancion:{
         codTipoSancion:4,
         nombreSancion:"DESTITUCIÓN "
      }
   },
   {
      matricula:{
         matricula:570,
         nombres:"MARCELO MIGUEL",
         apellidos:"GILETTA"
      },
      renglon:3,
      codTipoSancion:{
         codTipoSancion:4,
         nombreSancion:"DESTITUCIÓN "
      }
   }
]

** SQL Doctrine выполняет:

SELECT 
  ...
FROM 
  sec_antecedentes_o_sanciones s0_ 
  LEFT JOIN sec_padron_escribanos s1_ ON s0_.matricula = s1_.matricula 
  LEFT JOIN sec_tipos_sanciones s2_ ON s0_.cod_tipo_sancion = s2_.cod_tipo_sancion 
WHERE 
  s0_.matricula IN (
    SELECT 
      s3_.matricula AS sclr_40 
    FROM 
      sec_antecedentes_o_sanciones s3_ 
      LEFT JOIN sec_padron_escribanos s4_ ON s3_.matricula = s4_.matricula 
      LEFT JOIN sec_tipos_sanciones s5_ ON s3_.cod_tipo_sancion = s5_.cod_tipo_sancion 
    WHERE 
      s5_.cod_tipo_sancion = '4'
  ) 
ORDER BY 
  s0_.matricula ASC, 
  s0_.renglon ASC 
LIMIT 
  10

Как вы можете видеть, проблема в том, что предложение WHERE для sql select в строке, которую пишет api-platform: s0_.matricula IN .., чем, запрос доставляет мне все "antecedentes_o_sanciones", гдеучаствующая матрикула имеет, по крайней мере, один cod_tipo_sancion = 4. Когда я делаю этот тест с сущностями с первичными ключами single_id, фильтр работает отлично.

...