Этот вопрос на GitHub
Я пытаюсь добавить второе поле в параметры без пользовательского контроллера для объекта с несколькими первичными ключами и получаю ошибку ...
Теперь пошагово:
Таблица БД:
create table measure_types
(
id varchar(10) not null,
language_iso_code varchar(2) not null,
label varchar(255) null,
created_at datetime not null,
updated_at datetime null,
constraint measure_types_id_language_iso_code_uindex
unique (id, language_iso_code),
constraint measure_types_languages_iso_code_fk
foreign key (language_iso_code) references languages (iso_code)
);
alter table measure_types
add primary key (id, language_iso_code);
src / Entity / MeasureType. php
namespace Api\Entity;
use DateTime;
use DateTimeInterface;
use Doctrine\ORM\Mapping as ORM;
use Exception;
/**
* @ORM\Table(
* name="measure_types",
* indexes={
* @ORM\Index(name="measure_types_uindex", columns={"id", "language_iso_code"})
* },
* uniqueConstraints={
* @ORM\UniqueConstraint(name="measure_types_uindex", columns={"id", "language_iso_code"})
* }
* )
* @ORM\Entity(repositoryClass="Klarstein\Api\Repository\MeasureTypeRepository")
* @ORM\HasLifecycleCallbacks
*/
class MeasureType
{
/**
* @ORM\Id()
* @ORM\Column(type="string", length=10)
*/
private string $id;
/**
* @ORM\Id()
* @ORM\ManyToOne(targetEntity="Language", fetch="EAGER")
* @ORM\JoinColumn(name="language_iso_code", referencedColumnName="iso_code")
*/
private Language $language;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private string $label;
/**
* @ORM\Column(type="datetime")
*/
private DateTimeInterface $createdAt;
/**
* @ORM\Column(type="datetime", nullable=true)
*/
private ?DateTimeInterface $updatedAt;
public function __construct()
{
$this->createdAt = new DateTime();
}
/**
* @ORM\PreUpdate
*
* @throws Exception
*/
public function onPutHandler(): void
{
$this->updatedAt = new DateTime();
}
// ... under this comment getters and setters
}
config /api/measure_type.yaml
resources:
Api\Entity\MeasureType:
properties:
id:
identifier: true
language:
identifier: true
attributes:
pagination_items_per_page: 25
collectionOperations:
get:
normalization_context:
groups: ['v1_get_collection']
post:
normalization_context:
groups: ['v1_post_collection_response']
denormalization_context:
groups: ['v1_post_collection_request']
itemOperations:
get:
method: 'GET'
normalization_context:
groups: ['v1_get_item']
put:
normalization_context:
groups: ['v1_put_item_response']
denormalization_context:
groups: ['v1_put_item_request']
delete:
denormalization_context:
groups: ['v1_delete_item']
Это работа на текущий момент:
![api-platform screenshot](https://i.stack.imgur.com/6mnru.png)
Но я хочу показать в do c, что я ожидаю 2 параметра в качестве идентификатора.
Что я делаю:
Добавление: path: '/measure_types/id={id};language={language}'
в config/api/measure_type.yaml
resources:
Api\Entity\MeasureType:
properties:
id:
identifier: true
language:
identifier: true
attributes:
pagination_items_per_page: 25
collectionOperations:
get:
normalization_context:
groups: ['v1_get_collection']
post:
normalization_context:
groups: ['v1_post_collection_response']
denormalization_context:
groups: ['v1_post_collection_request']
itemOperations:
get:
method: 'GET'
path: '/measure_types/id={id};language={language}'
normalization_context:
groups: ['v1_get_item']
put:
normalization_context:
groups: ['v1_put_item_response']
denormalization_context:
groups: ['v1_put_item_request']
delete:
denormalization_context:
groups: ['v1_delete_item']
Следующий шаг: у меня есть SwaggerEventRequire
Декоратор:
src / Swagger / SwaggerEventRequireDecorator. php
namespace Api\Swagger;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Yaml\Yaml;
final class SwaggerEventRequireDecorator implements NormalizerInterface
{
private const SWAGGER_DECORATIONS = __DIR__ . '/../../config/swagger/';
private NormalizerInterface $decorated;
public function __construct(NormalizerInterface $decorated)
{
$this->decorated = $decorated;
}
public function normalize($object, string $format = null, array $context = [])
{
$docs = $this->decorated->normalize($object, $format, $context);
$customDefinition = $this->loadDefinitions();
foreach ($customDefinition as $path => $methods) {
foreach ($methods as $method => $parameters) {
foreach ($parameters as $paramKey => $paramValues) {
if (empty($paramValues['name'])) {
continue;
}
if (empty($docs['paths'][$path]) || empty($docs['paths'][$path][$method])) {
continue;
}
// e.g. remove an existing event parameter
$docs['paths'][$path][$method]['parameters'] = array_values(
array_filter(
$docs['paths'][$path][$method]['parameters'],
function ($param) use ($paramKey) {
return $param['name'] !== $paramKey;
}
)
);
// e.g. add the new definition for event
$docs['paths'][$path][$method]['parameters'][] = $paramValues;
}
}
}
return $docs;
}
public function supportsNormalization($data, string $format = null)
{
return $this->decorated->supportsNormalization($data, $format);
}
private function loadDefinitions(): array
{
$result = [];
$finder = new Finder();
$finder
->files()
->in(self::SWAGGER_DECORATIONS)
->name('*.yaml');
foreach ($finder as $file) {
$yaml = Yaml::parseFile(self::SWAGGER_DECORATIONS . $file->getFilename());
if (empty($yaml)) {
continue;
}
$result = array_unique(array_merge($result, $yaml), SORT_REGULAR);
}
return $result;
}
}
и файл конфигурации украшения: config / swagger / measure_type .yaml
/measure_types/id={id};language={language}:
get:
id:
name: 'id'
description: 'Measure type ID'
in: 'path'
required: true
type: 'string'
example: 'ml'
language:
name: 'language'
description: 'Language ISO code'
in: 'path'
required: true
type: 'string'
example: 'de'
В результате я получил рабочую форму в do c, но неверный результат:
![api-platform screenshot](https://i.stack.imgur.com/bw4yT.png)
Я хочу использовать его без собственного контроллера, потому что у меня есть много объектов с мульти Первичные ключи и добавление контроллеров для каждого из них займет много времени
Что я делаю не так?