"nelmio/api-doc-bundle": "^3.6#dev"
I need response with model with property product which eque one model Product and property count, but when I use Mode annotation I faced with probem, response model generated like array Product. What I'm doing wrong ?
* #SWG\Response(
* response=200,
* description="Json collection object Products",
* #SWG\Schema(
* type="object",
* properties={
* #SWG\Property(property="product",
* #Model(type=Product::class, groups={Product::SERIALIZED_GROUP_LIST})),
* #SWG\Property(property="count", type="integer")
* }
* )
* )
{
"product": [
{
"id": 0
}
],
"count": 0
}
I expected result like this:
{
"product":
{
"id": 0
},
"count": 0
}
Related
I am trying to add annotations for a model which has references of child nodes. But those child nodes are being called strings. The same code works just fine if it is referencing a different class. Is there any way this can be accomplished?
class Foo
{
private int $id;
/**
* #OA\Property(
* type="array",
* #OA\Items(
* ref=#Model(type=Foo::class),
* )
* ),
* #var array<Foo>
*/
private array $children;
}
Result
{
"id": 0,
"children": "string"
}
Expected
{
"id": 0,
"children": [{
"id": 0,
"children": [{}]
}]
}
I am having a json request
{
applicant_info:{
"email": "jhon.doe#gmail.com",
"given_name": "jhon",
"family_name": "doe"
},
productId: 12
}
Having a dto class as below:
class Dto
{
/**
* #var int
* #SerializedName("product_id")
*/
public $productId;
/**
* #var Collection
* #SerializedName("applicant_info")
*/
public $applicantInfo = [
'email',
'givenName',
'familyName'
];
}
Now when I use below to deserialize I am not sure how to convert given_name and family_name from request to
givenName and familyName like I have converted product_id and applicant_info to productId and applicantInfo using #SerializedName
$serializer->deserialize(
$request->getContent(),
Dto::class,
self::FORMAT_JSON
);
Any help will be really appreciated
I do not manage to create a custom route for a collection, my entity is named File.
here is my Entity annotation :
/**
* #ApiResource(
*
* normalizationContext={"groups"={"file"},"enable_max_depth"=true},
* denormalizationContext={"groups"={"file-write-customers"},"enable_max_depth"=true},
* attributes={"force_eager"=false},
* itemOperations={
* "get",
* "put",
* "get_mandate_pdf"={
* "method"="POST",
* "path"="/files/{id}/mandate-pdf",
* "controller"=FileCreatePdfController::class,
* },
* },
* collectionOperations={
* "stats"={
* "method"="GET",
* "path"="/files/stats",
* "controller"=FileStatsController::class,
* }
* },
* )
* #ApiFilter(SearchFilter::class, properties={"status": "exact", "sponsor": "exact"})
* #ApiFilter(DateFilter::class, properties={"updatedAt"})
* #ORM\Entity
* #ORM\Table(name="cases")
*/
The controller file
<?php
namespace App\Controller;
use App\Entity\File;
class FileStatsController
{
public function __invoke(File $data): File
{
return $data;
}
}
however i have this error when i reach /files/stats, it seems that api plaform is expecting an Id .
For some reasons if i switch the method from GET to POST the route is working
{
"#context": "\/contexts\/Error",
"#type": "hydra:Error",
"hydra:title": "An error occurred",
"hydra:description": "The identifier id is missing for a query of App\\Entity\\File",
"trace": [
{
"namespace": "",
"short_class": "",
"class": "",
"type": "",
"function": "",
"file": "\/srv\/api\/vendor\/doctrine\/orm\/lib\/Doctrine\/ORM\/ORMException.php",
"line": 309,
"args": []
},
I manage to find the solution , in my Controller if i remove the typed variable $data
namespace App\Controller;
class FileStatsController
{
public function __invoke($data)
{
return $data;
}
}
I manage to properly retreive the data
in addition, the method get is mandatory in the ApiRessource annotations
collectionOperations={
"get",
* "stats"={
* "method"="GET",
* "path"="/stats",
* "controller"=FileStatsController::class,
* }
* }
I have currently this entity and I want to show my property firedDate in my JSON even is the value is null.
/**
* #ApiResource(normalizationContext={"groups"={"employee"}})
* #ApiFilter(DateFilter::class, properties={"dateProperty": DateFilter::INCLUDE_NULL_BEFORE_AND_AFTER})
* #ORM\Table(name="employee")
*/
class Employee
{
// ...
/**
* #ORM\Column(type="datetime", nullable=true)
* #Groups({"employee"})
*/
private $firedDate;
public function getFiredDate(): ?\DateTimeInterface
{
return $this->firedDate;
}
// ...
}
Currently, when the value is null, it's not shown in the response.
I think I found the right solution to this problem.
Set skip_null_values in false in your normalizationContext:
* #ApiResource(
* itemOperations={
* "get" = {
* //...
* }
* "put" = {
* //...
* },
* "patch" = {
* //...
* }
* },
* collectionOperations={
* "get",
* "post" = {
* //...
* }
* },
* normalizationContext={
* "skip_null_values" = false,
* "groups" = {"object:read"}
* },
* denormalizationContext={"groups" = {"object:write"}}
* )
Are you under PHP 7.0 or above?
In PHP 7.1 you can have nullable return types for functions, so your
public function getFiredDate(): ?\DateTime
{
return $this->firedDate;
}
With the ? before \DateTime, the function will return null as well.
On ApiPlatform 3 the default has changed from skip_null_values=false to skip_null_values=true.
If you don't want having to set this on each resource, and would like to have the default as it as on ApiPlatform < 3, you can simply set it on the global config:
api_platform:
defaults:
normalization_context:
skip_null_values: false
Or if you use PHP based configuration:
return static function (Symfony\Config\ApiPlatformConfig $apiConfig): void {
$apiConfig
->defaults()
->normalizationContext(['skip_null_values' => false]);
}
Maybe your entity is missing a getter like this one?
public function getFiredDate(): \DateTime
{
return $this->firedDate;
}
Just get the solution from a friend on github, here is it:
* #ApiResource(
* itemOperations={"get"},
* )
BEFORE:
{
"#context": "/contexts/Employee",
"#id": "/employees/1",
"#type": "Employee",
"id": 1,
"name": "Oliver",
"hired": "2019-10-10T00:00:00+00:00",
"experience": 0,
"salary": "1200.00",
"job": {
"#id": "/employee_jobs/1",
"#type": "EmployeeJob",
"id": 1,
"name": "Mécanicien"
}
}
AFTER:
{
"#context": "/contexts/Employee",
"#id": "/employees/1",
"#type": "Employee",
"id": 1,
"name": "Oliver",
"hired": "2019-10-10T00:00:00+00:00",
"experience": 0,
"salary": "1200.00",
"firedDate": null,
"job": {
"#id": "/employee_jobs/1",
"#type": "EmployeeJob",
"id": 1,
"name": "Mécanicien"
}
}
Symfony 4. I have two entities, Cat and Owner.
class Cat
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
* #Groups("cats")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
* #Groups("cats")
*/
private $name;
/**
* #ORM\ManyToMany(targetEntity="App\Entity\Owner", mappedBy="cat")
* #Groups("cats")
*/
private $owners;
}
class Owner
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
* #Groups("cats")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
* #Groups("owners")
*/
private $name;
}
My API endpoint needs to return 2 keys, owners (a list of all owners), and cats (a list of all cats, with their owners).
public function index()
{
$repository = $this->getDoctrine()->getRepository(Owner::class);
$owners = $repository->findAll();
$repository = $this->getDoctrine()->getRepository(Cat::class);
$cats = $repository->findAll();
return $this->json([
'owners' => $owners,
'cats' => $cats,
], 200, [], ['groups' => ['owners', 'cats']]);
}
This works, but with 1 problem: the cats list contains the full owner information for each owner, i.e.:
{
"owners": [
{
"id": 1,
"name": "John Smith"
}
],
"cats": [
{
"id": 1,
"name": "Miaow",
"owners": [
{
"id": 1,
"name": "John Smith"
}
]
}
]
}
What I want is for the owners key in the cat object to only return the owner's id, like this:
{
"owners": [
{
"id": 1,
"name": "John Smith"
}
],
"cats": [
{
"id": 1,
"name": "Miaow",
"owners": [
1
]
}
]
}
You can use a getter for a specific group and with a specific serialized name.
In Cat:
/**
* #Groups("cats")
* #SerializedName("owners")
*/
public function getOwnersIds(): iterable
{
return $this->getOwners()->map(function ($owner) {
return $owner->getId();
})->getValues();
}
Override the mapping of a field.
See doctrine documentation:
https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/inheritance-mapping.html