composer create-project symfony/skeleton <REPO>
composer require api
- Modify
.env
for DB connection php bin/console doctrine:database:create && php bin/console doctrine:schema:create
- Start symfony server :
symfony server:start
- Added
composer require symfony/maker-bundle --dev
- NOTE if
/api
is showing 404, installcomposer require symfony/apache-pack
- NOTE Post & Category Entities are disabled, Enable them to test.
- Add
Symfony profiler
bycomposer req symfony/web-profiler-bundle
/composer require profiler --dev
and verify URLs byphp bin/console debug:router
, then just go to<URL>/_profiler
php bin/console doctrine:schema:drop --full-database --force
- Remove everything
SymfonyCasts (https://symfonycasts.com/screencast/api-platform)
- Test api response directly in browser by http://api.platform.local/api/cheese_listings/2.jsonld
- Api platform uses
config/routes/api_platform.yaml
uses thetype
to dynamically add routes based on classes having@ApiResource()
- JSON docs :
http://api.platform.local/docs.json
@id
- known as IRI- Every URL is a resource, you can check main entrypoint by
curl -X GET 'http://api.platform.local/' -H "accept:application/ld+json"
- Operations (GET, POST, GET(1), DELETE, PUT) :
-
- Collection Operations - See in swagger, where Entity does not have
{id}
, i.e you are getting a collection or adding to the collection (GET
,POST
)
- Collection Operations - See in swagger, where Entity does not have
-
- Item Operations
- From Object to Json => Serialize
- From Json to Object => Deserialize
- From Object to Array => Normalization - Reading data from API
- From Array to Object => Denormalization - Sending data to API
composer req nesbot/carbon
- for date/time utility managementswagger_definition_name
is the part below in swagger GUI (Schemas) sectionSerializedName
used to change json output in swagger GUI- Added
@ApiFilter
on class, new filters element appears on swagger GUI for GET Collection - When using
PropertyFiler
, check URLhttp://api.platform.local/yo-single-cheezzyy/1.jsonld?properties[]=title&properties[]=shortDescription
in API Tester for specified fields in paramaters - To view configs of api platform, run
php bin/console debug:config api_platform
-
- See list of available formats (added in
api_platform.yaml
)
- See list of available formats (added in
formats:
jsonld:
mime_types:
- application/ld+json
json:
mime_types:
- application/json
html:
mime_types:
- text/html
- Can also add for specific Entity, see
CheeseListing.php
-"formats"
- For validation input JSON data, use
@Assert\
in Entity - Relationship between users & cheese listings
-
- Users :
1 User has 1/∞ Cheese
- Users :
-
- Cheese :
1 Cheese has 1 User
- Cheese :
- Saving a new chees will be - POST cheeses,
"owner"
should be"@id"
of hydra member
{
"title": "Faker Cloud",
"price": 4552,
"owner": "/list-of-users/5",
"description": "faker.js - generate massive amounts of fake data in the browser and node.js"
}
-
Display all cheese related to a user by assigning
$cheeseListings
inUser.php
to the"user:read"
group -
Display user in cheese GET by assigning
"cheese_listing:read",
to the$email
inUser.php
-
Updating a user by using the cheese PUT operation - Use @Assert\Valid() for validating FK properties found un
User.php
{
"owner": {
"@id" : "/list-of-users/14",
"email" : "[email protected]"
}
}
- Creating a New user and assigning an existing cheese listing with it by POST in User, If you are using the Object version, you must configure the Entity, add group to the properties &
cascade={"persist"}
{
"email": "[email protected]",
"password": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"cheeseListings": [
"/yo-single-cheezzyy/26"
]
}
OR
{
"email": "[email protected]",
"password": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"cheeseListings": [
{
"title": "Apprendre grâce à plusieurs formats",
"description": "Vous cherchez une formation complète pour apprendre de A à Z ou une vidéo pour découvrir un nouvel outil ? Vous devriez trouver votre bonheur",
"price": 9614
}
]
}
- User have multiple cheese listing, you can remove some by
FROM
{
"cheeseListings": [
"/yo-single-cheezzyy/4",
"/yo-single-cheezzyy/27"
]
}
TO
{
"cheeseListings": [
"/yo-single-cheezzyy/27"
]
}
- Filter by FK, add filter
"owner.email"
is CLSearchFilter::class
section - CL is like a child of User, you can add
@ApiSubresource()
so that you have a URL/list-of-users/<ID>/cheese_listing
for getting list of CL of the user with
- https://symfony.com/doc/current/components/serializer.html (The Serializer Component)
- https://api-platform.com/docs/core/serialization/ (The Serialization Process)
- https://api-platform.com/docs/core/operations/ (Operations)
- https://api-platform.com/docs/core/filters/ (Filters)
- Post :
1 Post has 1 Category
- Category :
1 Category has 1/∞ Post
- Enabling crud endpoints can be done in 2 ways, need to modify
config/api_platform.yaml
-
- Using
Entity
, checksrc/Entity/Post.php
- Using
-
- Using
yaml
, checkconfig/api_platform/resources.yaml
- Using
- To activate API CRUD endpoints of an Entity, add
@ApiResource()
in class phpdocs - To insert into Post with Swagger - "POST
/api/posts
"
{
"title": "A web interface allows you to interact with the API",
"slug": "linkedin-skill-assessments-quizzes",
"content": "You want a method with behavior similar to a virtual method--it is meant to be overridden --expect that it does not have a method body. It just has a method signature.",
"createdAt": "2021-08-14",
"updatedAt": "2021-08-14",
"category" : "/api/categories/2"
}
normalizationContext
concerns more theGET
and is related to when you are reading data from your API, so ALL endpoints that are tiggered will JSON response based on the"groups"
they are connected to, i.eread.post.collection
* @ApiResource(
* normalizationContext={
* "groups": {
* "read.post.collection"
* }
* }
* )
.
.
class Post
.
.
* @Groups(
* {
* "read.post.collection"
* }
* )
*/
private $title;
- Collection operations :
GET
&POST
- Item operations :
GET
&PUT
&DELETE
&PATCH
itemOperations
forput
hasdenormalization_context
with groupwrite.post.item
and so does attribute$id
,$slug
and$category
* "put": {
* "denormalization_context": {
* "groups": {
* "write.post.item"
* }
* }
* }
- So if you do a
PUT
with the following,content
will NOT be updated
{
"title": "Alternative Method",
"slug": "api_platform.jsonld.normalizer.item",
"content": "Just like other Symfony and API Platform components, the Serializer component can be configured using annotations, XML or YAML.",
"category": "/api/categories/2"
}
- Using validation - rule on Insert only, will prevent from POST title < 5 characters & will allow PUT < 5 characters
- Validation on relationship between entity uses
@Assert\Valid()
- Use for testing on API Swagger
{
"title": "API Platform, c’est trop swag !",
"slug": "creer-facilement-une-api-rest-avec-symfony-api-platform",
"content": "Afin de découvrir la création avec API Platform , configurer une nouvelle application Symfony Flex.",
"category": {
"name": "MERN"
}
}
- On Class
* collectionOperations={
* "get",
* "post": {
* "validation_groups": {
* "create.post.item"
* }
* }
* },
-
- On attribute
$title
- On attribute
* @Assert\Length(min=5, groups={"create.post.item"})
-
- ManyToOne in
Post.php
- ManyToOne in
* )
* @Assert\Valid()
* @ORM\ManyToOne(targetEntity=Category::class, inversedBy="posts", cascade={"persist"})
*/
private $category;
-
$name
inCategory.php
* @Assert\Length(min=5, groups={"create.post.item"})
*/
private $name;