Action / GET with limited properties - api-platform.com

Certainly already asked but...
Having this entity
/**
* A form
*
* #ORM\Entity(repositoryClass=FormRepository::class)
*
* #ORM\Table(
* name="forms",
* options={"comment":"Table of the forms"},
* indexes={
* #ORM\Index(name="forms_idx_dofc", columns={"dateofcreation"}),
* #ORM\Index(name="forms_idx_dofu", columns={"dateofupdate"}),
* #ORM\Index(name="forms_idx_dofs", columns={"dateofsubmission"})
* }
* )
*
* #ApiResource(
* routePrefix="/",
* shortName="Forms",
* description="API Access : form Entity",
* collectionOperations={"GET"},
* itemOperations={"GET"},
* attributes={
* "normalization_context"={
* "groups"={
* "GET:FORM"
* }
* },
* "order"={
* "dateofsubmission",
* "dateofupdate",
* "dateofcreation"
* }
* }
* )
*
*/
class Form
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer", options={"comment":"Primary Key, Auto generated"})
*/
private $id;
/**
* #var datetime Date of creation of the form.
*
* #ORM\Column(type="datetime", options={"comment":"date of creation of the form"})
*
* #Assert\NotBlank(message="The date time when was created the form should not be blank")
* #Assert\DateTime(message="The data time when was created the form should be the type DateTime")
*
* #Groups({"GET:FORM"})
*
* #ApiFilter(OrderFilter::class, strategy="ASC")
*/
private $dateofcreation;
/**
* #var datetime Date of update of the form.
*
* #ORM\Column(type="datetime", options={"comment":"date of update of the form"})
*
* #Assert\NotBlank(message="The date time when was updated the form should not be blank")
* #Assert\DateTime(message="The data time when was updated the form should be the type DateTime")
*
* #Groups({"GET:FORM"})
*
* #ApiFilter(OrderFilter::class, strategy="ASC")
*/
private $dateofupdate;
/**
* #var person Person that has created the form.
*
* #ORM\ManyToOne(targetEntity=Person::class, inversedBy="forms")
* #ORM\JoinColumn(nullable=false)
*
* #Groups({"GET:FORM"})
*
* #ApiFilter(SearchFilter::class, properties={"createdBy.id":"exact","createdBy.givenname":"ipartial", "createdBy.familyname":"ipartial"})
* #ApiFilter(OrderFilter::class, strategy="ASC")
*/
private $createdBy;
...
I would like to have the possibility of having :
A base collectionOperations "GET" would return all the properties that have the #GROUP=GET:FORM
A alternate collectionOperations "GETDATES" would return all properties that have a #GROUP=GET:DATES
The operations being accessible (ideally) with different routes.
GET => # http://api/forms?createdBy.id=25 => All properties
GETDATES => http://api/formsLimited?createdBy.id=25 => only the dates
ps: I hope this is better for the readability.

Thanks to Grégoire Hébert(https://stackoverflow.com/users/4887997/gr%C3%A9goire-hebert) for the support (on Slack).
The solution is quite simple.
Create in the ApiResource() a collection operation with:
Method = GET
path (that will become a route)
the normalization context for the group to be applied to the wanted properties
It gives:
collectionOperations={"GET","GETLIMITED"={"method"="GET","path"="formslist","normalization_context"={"groups"="GET:LIMITED"}}},

Related

Laravel Swagger PHP Couldn't find constant array

darkaonline/l5-swagger: 8.0.2
PHP Version: 7.3.13
zircote/swagger-php: 3.1.0
OS: Windows
I created a Contract ref object.
Now in my ContractController I want to list an array of contracts.
How can I do it?
I got this error Couldn't find constant array when trying to add type=array in OA\Items
/**
* #OA\Info(title="Contract API", version="1")
*/
class ContractController extends Controller
{
/**
* #OA\Post(
* path="/api/v1/contract/list",
* tags={"contact"},
* summary="List Contract",
* operationId="list",
* #OA\Parameter(
* name="keyword",
* in="path",
* description="keyword to search contracts",
* required=false,
* #OA\Schema(
* type="string"
* )
* ),
* #OA\Parameter(
* name="lang_code",
* in="path",
* description="lang_code define language client used",
* required=false,
* #OA\Schema(
* type="string",
* )
* ),
* #OA\Response(
* response=200,
* description="successful",
* #OA\JsonContent(
* #OA\Items(
* type=array, #This is where I got the error
* ref="#/components/schemas/Contract"
* )
* )
* ),
* #OA\Response(
* response=400,
* description="Wrong"
* )
* )
*/
public function list(Request $request)
{
$contracts = Contract::factory()->count(10)->make();
return response()->json([
'message' => 'good',
'contracts' => $contracts
], 200);
}
}
/**
* #OA\Schema(
* description="Contract model",
* type="object",
* title="Contract model"
* )
*/
class Contract extends Model
{
use HasFactory;
/**
* The unique identifier of a product in our catalog.
*
* #var integer
* #OA\Property(format="int64", example=1)
*/
public $id;
/**
* #var string
* #OA\Property(format="string", example="contract 001")
*/
public $contract_title;
}
Use type="array", (with "s) instead of type=array,
I know its late but
Try to use
* #OA\MediaType(
* mediaType="application/json",
* #OA\Schema(
* type="array",
* #OA\Items(
* ref="#/components/schemas/Contract"
* ),
* )
* )
Insead of #OA\JsonContent

How to upload a file in swagger-php array

I want to uplaod a file in swagger-php in the json requestBody How can upload with the help of swagger anonations
Trying from lot of hours but not luck how can send and file in application/json array Can you help if any information about this so then i will solve my problem i have not concept about this
when this code generate in the terminal also not have any error and not shown in the request body in the swagger ui
/**
* #OA\Post(
* path="/products/save",
* tags={"Product"},
* summary="Post bulk products",
* description="Return bulk products",
* #OA\RequestBody(
* required=true,
* description="Bulk products Body",
* #OA\JsonContent(
* #OA\Property(
* property="products",
* #OA\Items(
* #OA\Property(property="first_name", type="string"),
* #OA\Property(property="last_name", type="string"),
* #OA\Property(property="email", type="string"),
* #OA\Property(property="phone", type="string"),
* #OA\Property(property="resume", type="string", format="base64"),
* ),
* )
* )
* ),
* )
*/
I want to this type of swagger-ui body so that user can fill attribut and
the resume add in base64 format
{
"products": [
{
"first_name": "string",
"last_name": "string",
"email": "string",
"phone": "string",
"resume": "string" ==> here i will send base64 format of resume file
}
]
}
``
You may use #OA\Property(property="file", type="string", format="binary"), to define a file property:
/**
* #OA\Schema(
* schema="ProductRequest",
* required={"products"},
* #OA\Property(
* property="products",
* type="array",
* #OA\Items(
* #OA\Property(property="first_name", type="string"),
* #OA\Property(property="last_name", type="string"),
* #OA\Property(property="email", type="string"),
* #OA\Property(property="phone", type="string"),
* #OA\Property(property="resume", type="string", format="binary"),
* ),
* )
* )
*/
Then you have to set a media type on your RequestBody using #OA\MediaType:
/**
* #OA\RequestBody(
* request="Product",
* required=true,
* description="Bulk products Body",
* #OA\MediaType(
* mediaType="multipart/form-data",
* #OA\Schema(ref="#/components/schemas/ProductRequest")
* )
* )
*/
And finally on your #OA\Post:
/**
* #OA\Post(
* path="/products/save",
* tags={"Product"},
* summary="Post bulk products",
* description="Return bulk products",
* #OA\RequestBody(ref="#/components/requestBodies/Product"),
* #OA\Response(response=200, ref="#/components/responses/Product")
* )
*/
See also Swagger docs on File data type and File upload for more info.
Update: If you don't want separate declarations just merge them like this:
/**
* #OA\Post(
* path="/products/save",
* tags={"Product"},
* summary="Post bulk products",
* description="Return bulk products",
* #OA\RequestBody(
* required=true,
* description="Bulk products Body",
* #OA\MediaType(
* mediaType="multipart/form-data",
* #OA\Schema(
* #OA\Property(
* property="products",
* type="array",
* #OA\Items(
* #OA\Property(property="first_name", type="string"),
* #OA\Property(property="last_name", type="string"),
* #OA\Property(property="email", type="string"),
* #OA\Property(property="phone", type="string"),
* #OA\Property(property="resume", type="string", format="binary"),
* )
* )
* )
* )
* )
* )
*/
You may also want an approach with PHP classes
So you can define a model like that:
/**
* #OA\Schema(
* schema="User",
* required={"first_name", "last_name" // and so on}
* )
*/
class User
{
/**
* #OA\Property(type="string")
*/
public $first_name;
/**
* #OA\Property(type="string")
*/
public $last_name;
// add your other fields bellow
}
after you can define for example the body of a POST request as follows:
<?php
/**
* #OA\Schema(
* schema="CreateUsers",
* required={"users"}
* )
*/
class CreateUsers
{
/**
* #var array
* #OA\Property(ref="#/components/schemas/User")
*/
public $users;
}
And lastly create the your Request in your documentation for example:
/**
* #OA\Post(
* path="YOUR ROUTE URL",
* operationId="createUsers",
* tags={"Users"},
* #OA\RequestBody(
* required=true,
* #OA\MediaType(
* mediaType="application/json",
* #OA\Schema(ref="#/components/schemas/CreateUsers")
* )
* ),
* summary="Create a collection of users",
* description="Create a collection of users"
* )
**/
EDIT 1:
If you want a request that have a file to the request body you way do:
/**
* #OA\Post(
* path="YOUR ROUTE URL",
* operationId="createUsers",
* tags={"Users"},
* #OA\RequestBody(
* required=true,
* #OA\MediaType(
* mediaType="multipart/form-data", // here we need to change from "application/json" to "multipart/form-data" in order to make our file visible
* #OA\Schema(ref="#/components/schemas/CreateUsers")
* )
* ),
* summary="Create a collection of users",
* description="Create a collection of users"
* )
**/
And make your field in your PHP class:
/**
* #OA\Schema(
* schema="User",
* required={"first_name", "last_name", "file" // and so on}
* )
*/
class User
{
/**
* #OA\Property(type="string")
*/
public $first_name;
/**
* #OA\Property(type="string")
*/
public $last_name;
/**
* #OA\Property(description="file to upload", type="string", format="file")
*/
public $file;
// add your other fields bellow
}
You can see an example here: swagger-php/Examples/petstore.swagger.io/controllers/PetController.php

It is necessary to generate the swagger json correctly

The problem is that I need the documentation to show that it is possible to transfer the field colums in the form of an array and in it the following fields (name, description, created_at, updated_at, author). json is successfully generated but in the swagger-editor documentation it is not visible these fields
/**
* #SWG\Get(path="/articles",
* tags={"Article"},
* summary="Get all Articles",
* description="Show list of Articles",
* operationId="all",
* produces={"application/json"},
* #SWG\Parameter(
* name="columns",
* in="query",
* description="get specific columns",
* required=false,
* type="array",
* collectionFormat="multi",
* #SWG\Items(
* type="string",
* #SWG\Property(property="name", type="string"),
* #SWG\Property(property="description", type="string"),
* #SWG\Property(property="author", type="string"),
* #SWG\Property(property="created_at", type="string"),
* #SWG\Property(property="updated_at)", type="string")
* )
* ),
* #SWG\Response(response="200"),
* #SWG\Response(response=500)
* ),
* )
*/

How can i use multiples values for a#Assert\EqualTo Validation Field Entity

I'm using Symfony\Component\Validator\Constraints as Assert For validate the value of a field.
Problem is I need to accept two o more values for this field of my entity.
/**
* #var integer
* #Assert\EqualTo(
* value=1,
* message="Invalid State",
* groups={"Update"}
* )
* #Column(name="pgsStatus", type="integer")
*/
private $status;
It works perfect, but i tried something like this
/**
* #var integer
* #Assert\EqualTo(
* value={1,11},
* message="Invalid State",
* groups={"Update"}
* )
* #Column(name="pgsStatus", type="integer")
*/
private $status;
or this
/**
* #var integer
* #Assert\EqualTo(
* value=1,
* message="Invalid State",
* groups={"Update"}
* )
* #Assert\EqualTo(
* value=11,
* message="Invalid State",
* groups={"Update"}
* )
* #Column(name="pgsStatus", type="integer")
*/
private $status;
And doesn't work.
I've looked in documentation and I don't find another validation or another way for doing this.
Thanks!!
The Choice Validator is the way to go here:
/**
* #var integer
* #Assert\Choice(
* choices={1,11},
* groups={"Update"}
* )
* #Column(name="pgsStatus", type="integer")
*/
probably use the Choice validator or use the Callback validator

#AssociationOverride and #AttributeOverride in new Doctrine 2.3

As per title, what's the purpose of the new annotation #AssociationOverride and #AttributeOverride?
The only thing I can find on Doctrine website is:
#AssociationOverride and #AttributeOverride (useful for Trait and
MappedSuperclass)
By looking at the code in the commit, we can see that it is used to override a field mapping already defined in a mapped superclass / trait.
The tests included in the commit demonstrate this behaviour:
Mapped superclass
/**
* #MappedSuperclass
*/
class User
{
/**
* #Id
* #GeneratedValue
* #Column(type="integer", name="user_id", length=150)
*/
protected $id;
/**
* #Column(name="user_name", nullable=true, unique=false, length=250)
*/
protected $name;
/**
* #var ArrayCollection
*
* #ManyToMany(targetEntity="Group", inversedBy="users", cascade={"persist", "merge", "detach"})
* #JoinTable(name="users_groups",
* joinColumns={#JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#JoinColumn(name="group_id", referencedColumnName="id")}
* )
*/
protected $groups;
/**
* #var Address
*
* #ManyToOne(targetEntity="Address", cascade={"persist", "merge"})
* #JoinColumn(name="address_id", referencedColumnName="id")
*/
protected $address;
...
}
Subclass using #AssociationOverride
/*
* #Entity
* #AssociationOverrides({
* #AssociationOverride(name="groups",
* joinTable=#JoinTable(
* name="users_admingroups",
* joinColumns=#JoinColumn(name="adminuser_id"),
* inverseJoinColumns=#JoinColumn(name="admingroup_id")
* )
* ),
* #AssociationOverride(name="address",
* joinColumns=#JoinColumn(
* name="adminaddress_id", referencedColumnName="id"
* )
* )
* })
*/
class Admin extends User
{
...
}
Subclass using #AttributeOverride
/**
* #Entity
* #AttributeOverrides({
* #AttributeOverride(name="id",
* column=#Column(
* name = "guest_id",
* type = "integer",
* length = 140
* )
* ),
* #AttributeOverride(name="name",
* column=#Column(
* name = "guest_name",
* nullable = false,
* unique = true,
* length = 240
* )
* )
* })
*/
class Guest extends User
{
...
}

Resources