I have created a custom endpoint using API Platform. Here is the annotation I have used:
/**
* We only want the POST option for now.
*
* #ApiResource(
* itemOperations={},
* collectionOperations={"post"={
* "method"="POST",
* "controller"=PairingController::class,
* "path"="/devices/pairing",
* "defaults"={"_api_receive"=false}
* }},
* )
*
*
*/
class Pairing
{
...
The controller I am calling executes some custom logic. I am happy with how things are working so far. But the documentation generated by API Platform is now inaccurate. It says:
/devices/pairing Creates a Pairing resource.
... which is no longer true, since my controller does not generate a pairing. (It calls out to a different API instead, asking that API to do some stuff.)
So here's my question: How do I change my annotation to allow me to write a custom piece of documentation for this endpoint?
You can use the swagger_context key to change any Swagger field, including description (the one you are looking for): https://api-platform.com/docs/core/swagger/#changing-operations-in-the-swagger-documentation
It didn't works for me, here is how I did it with openapi_context:
"openapi_context"={
"summary"="test",
},
Related
I am working on a Symfony 5 + API Platform project. I am still fighting with API Filters. I made this work before setting up a fake API route from some controller. But, since there is an API Platform out of the box feature that allow this, I would like to "make" this work.
First of all, the entity filters are being ignored and API Platform is aware of that. According to Symfony Profiler > API Platform > Resource Metadata:
And according to Data Providers tab in the same page:
What I have tried so far is adding #ApiFilter() annotation to Question entity like API documentation explains:
// ...
use Symfony\Component\Serializer\Annotation\Groups;
/**
* #ORM\Entity(repositoryClass=QuestionRepository::class)
* #ApiResource(normalizationContext={"groups"={"question"}})
* #ApiFilter(SearchFilter::class, properties={"status": "partial"})
*/
class Question
{
// ...
/**
* #ORM\Column(type="string", length=255)
* #Groups("question")
*/
private $status;
// ...
}
I also have tried to specify the filter on the needed property to be filtered. (Thanks to #EugeneRuban from a previous question).
So that, why does API Platform ignores the filter?
Edit: This is what the Logs shows:
I'm in the process of fixing up an API, and I'd like to deprecate some old routes. I'm basically moving the endpoints around, but want to encourage new consumers to use the new routes. However, I need to support the old routes for a short period during this transition. Below is an example of something that I want. I would like the new url documented and the old one either marked as deprecated or removed from the documentation entirely. Is there an easy way to do this, or am I stuck during the transition?
/**
* Adds a new Item
*
* This creates a new item
*
* #url POST /:id/patch {#deprecated}
* #url PATCH /:id
*/
Move deprecated routes to a new method which internally calls the old method for functionality mark it as deprecated through description with the help of HTML if needed. Here is an example
/**
* Adds a new Item
*
* This creates a new item
*
* #url PATCH /{id}
*/
function patchItem($id)
{
//actual process here
}
/**
* Adds a new Item [DEPRECATED]
*
* This creates a new item
*
* #url POST /{id}/patch
*/
function deprecatedPatchItem($id)
{
return $this->patchItem($id);
}
Once you decided to remove the deprecated simply delete the new method
I am using request object in twig extension class to get the current route. For instance, having the following url:
http://www.localhost/project/user/page/2
Inside of the twig extension I'm able to get user/page/2 string and do something with it.
The problem arises when I wanna get the default route using the same method, which I have to do. For example, accessing the following url:
http://www.localhost/project/user
I want to get user/page/1 string inside the twig extension class, and not just user.
The controller looks like this:
/**
* #Route(name="user",
* default="user/page/1")
*/
Is there a way to achieve that? Or do I have to stop using default routes?
Write a comment if you need more explanation, it's 9AM here in Poland and I'm sleeping yet.
The #Route documentation explains that you can do this for set a default page number:
/**
* #Route("/project/user/page/{page}",
* name="user",
* defaults={"page" = 1},
* requirements={"page" = "\d+"}
* )
*/
I'm using annotation to set my routes and method types. Is there a way to only allow certain types of post data. Currently I'm doing the following:
/**
* #Route("/myurl", requirements={"varID" = "\d+"} )
* #Method({"POST"})
* #Template()
*/
But if a varID gets submitted with a string value then it goes through anyway... I'm guessing due partly to there being no {varID} in the route? Is there a way to validate POST data like this in Symfony?
Change annotation into this:
/**
* #Route("/myurl/{varID}", requirements={"varID" = "\d+"} )
* #Method({"POST"})
* #Template()
*/
You must tell symfony wich part of url is yours varID variable to allow engine to check datatype. Than you get an exception:
No route found for "GET /myurl/somestring"
404 Not Found - NotFoundHttpException
1 linked Exception:
First let me say that the new API Explorer in Restler is great. Very happy about its addition. Now, in typical fashion, let me complain about something that isn't working for me ...
The fact that Restler can return results in multiple formats is a very nice feature but I'm currently not using it (choosing to only use JSON as my return format). In the API Explorer I'd like all references to .json to not show up as this just complicates the look of the service architecture.
Here's a quick example:
class Users {
/**
* Preferences
*
* Preferences returns a dictionary of name-value pairs that provide input to applications that want to make user-specific decisions
*
* #url GET /{user_id}/preferences
**/
function preferences ($user_id , $which = 'all') {
return "$which preferences for {$user_id}";
}
/**
* GET Sensors
*
* Get a list of all sensors associated with a user.
*
* #url GET /{user_id}/sensor
**/
function sensor ($user_id) {
return "sensor";
}
/**
* GET Sensors by Type
*
* #param $user_id The user who's sensors you are interested in
* #param $type The type of sensor you want listed.
*
* #url GET /{user_id}/sensor/{type}
**/
function sensor_by_type ($user_id, $type) {
return "specific sensor";
}
/**
* ADD a Sensor
*
* #param $user_id The user who you'll be adding the sensor to
*
* #url POST /sensor
**/
function postSensor() {
return "post sensor";
}
}
In this example the API Explorer looks like this:
The basic problem I'd like to remove is remove all ".json" references as the calling structure without the optional .json works perfectly fine.
Also, for those that DO want the .json showing up there's a secondary problem of WHERE does this post-item modifier show up? In the example above you have .json attaching to the "users" element in the GET's and to the "sensor" element in the PUT. This has nothing to do with the HTTP operation but rather it seems to choose the element which immediately precedes the first variable which may not be intuitive to the user and actually isn't a requirement in Restler (at least its my impression that you can attache .json anywhere in the chain and get the desired effect).
We are using safer defaults that will work for everyone, but made it completely configurable.
if you prefer .json to be added at the end, add the following to index.php (gateway)
use Luracast\Restler\Resources;
Resources::$placeFormatExtensionBeforeDynamicParts = false;
If you prefer not to add .json extension, add the following to index.php
use Luracast\Restler\Resources;
Resources::$useFormatAsExtension = false;