It covers the main features of the API Platform framework: we will install the framework, design an API data model as a set of tiny plain old PHP classes and learn how to get:
A fully featured dev environment with Symfony Flex and React containers, HTTP/2 and HTTPS support and a cache proxy
Pagination, data validation, access control, relation embedding, filters and error handling
Support for modern REST API formats: JSON-LD/Hydra, OpenAPI/Swagger, JSONAPI, HAL, JSON…
GraphQL support
An API responding in a just few milliseconds thanks to the builtin invalidation based cache mechanism
A dynamically created Material Design admin interface (a la Sonata / EasyAdmin – but 100% client-side) built with React
This nice tool allows to automatically and dynamically build a fully featured administration interface (CRUD, pagination, relations…) for any API supporting the Hydra hypermedia vocabulary (more formats supported soon, see at the end of this article). 0 line of code required!
Let’s discover the bunch of new features that this version brings.
Getting Started
Assuming that you have an API exposing a Hydra documentation, you just have to initialize the following React component to get your admin:
import React from 'react';
import { HydraAdmin } from '@api-platform/admin';
export default () => <HydraAdmin entrypoint="https://api.example.com"/>;
For instance, create a new app with Facebook’s create-react-app, replace the content of src/App.js with the previous snippet and run yarn add @api-platform/admin. You’re done!
If you get an error related to multiple versions of React being loaded, just remove the react and react-dom packages from your project’s package.json and run yarn install again.
If you don’t have a JSON-LD / Hydra API yet, here is the code of the one I’ll use in the following examples. This API has been created using the API Platform’s distribution:
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiProperty;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ApiResource
*/
class Person
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column
* @ApiProperty(iri="http://schema.org/name")
*/
public $name;
/**
* @var Greeting[]
*
* @ORM\OneToMany(targetEntity="Greeting", mappedBy="person", cascade={"persist"})
*/
public $greetings;
public function __construct()
{
$this->greetings = new ArrayCollection();
}
public function getId()
{
return $this->id;
}
public function addGreeting(Greeting $greeting)
{
$greeting->person = $this;
$this->greetings->add($greeting);
}
public function removeGreeting(Greeting $greeting)
{
$greeting->person = null;
$this->greetings->removeElement($greeting);
}
}
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiProperty;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ApiResource
* @ORM\Entity
*/
class Greeting
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column
* @Assert\NotBlank
* @ApiProperty(iri="http://schema.org/name")
*/
public $name = '';
/**
* @ORM\ManyToOne(targetEntity="Person", inversedBy="greetings")
*/
public $person;
public function getId(): ?int
{
return $this->id;
}
}
Yes, you just need those two tiny PHP classes to get a hypermedia API. Learn more about the API component by reading the getting started guide. But, really, any API with a Hydra documentation will do the job regardless of the server-side programming language.
Native Support for to-Many Relations
API Platform Admin supports to-one relations since its very first release. However it was mandatory to customize the component used for to-many relations. This isn’t the case anymore. Our API documentation parser gained support for cardinalities and can now extract them if the API documentation includes OWL’s maxCardinality properties.
If no cardinality is provided, the admin will use a to-many widget by default.
Thanks to this new feature, here is how the edition screen of the Person resource looks like this:
The admin is able to guess that the Person resource is related to many Greeting ones and use the appropriate Admin On Rest component.
Detection of More Schema.org’s Types (name, url and email)
API Platform Admin is able to guess the widget to use depending of the type of a resource’s property. It supports:
Numbers (http://www.w3.org/2001/XMLSchema#float and http://www.w3.org/2001/XMLSchema#integer ranges)
Dates (http://www.w3.org/2001/XMLSchema#date and http://www.w3.org/2001/XMLSchema#dateTime ranges)
In this new release, Admin also supports some types of the popular Schema.org vocabulary:
As shown in the previous screenshots (e.g. Greetings select box), if a property has the type http://schema.org/name, this property will be used instead of the ID when displaying this relation
If a property has the type http://schema.org/url, the URL will be clickable when displayed in the admin
If a property has the type http://schema.org/email, the HTML input will be of type email and a basic validation will occur (this was already working in v0.1)
Support for Read-only Resources
The version 0.1 wasn’t able to deal with read-only resource (no POST nor PUT operation). We have improved the API doc parser to support owl:equivalentClass properties. Now, if the API documentation provide those properties, the admin will be builded even if the resource is read-only (of course in this case you will only be able to browse resources, and not to edit them).
Easier and Deeper Customization
Morgan Auchedé did an excellent work to make the Admin fully and easily customizable. You can now override any generated React component by a custom one, or one from Admin On Rest, or from MUI React. You can just replace (or ad, or remove) a specific input or field. But you can also replace a whole list, a show view, a creation or edition form or a remove button.
Here is an example of full customization, courtesy of Morgan:
The parser has been designed to be able to be parse other formats such as a GraphQL schema or Swagger/Open API. The api-doc-parser library provides an intermediate representation that is populated by the specific format parser. It’s this representation that is used by the parser as well as by our React and Vue.js Progressive Web App generator.
It means that when converters from other formats than Hydra to this intermediate representation will be available (Pull Requests welcome), both tools we’ll support those formats. As you may know, the server part of API Platform now supports GraphQL. You can guess which format we’ll implement next in the api-doc-parser!
API Platform is a framework designed to make the creation of API-based information systems easier. It provides server-side tooling to create modern hypermedia and Linked Data APIs in just a few minutes. This new version introduces client-side tools to bootstrap Single-Page Applications using ReactJS by consuming the autogenerated documentation of the API.
The changelog is huge, more than 200 commits by dozens of developers have been merged. I think we can say that this release will be great!
Let’s review the most interesting new features. If you just want to try it, the demo has been upgraded to use this new version and you can download it on GitHub.
It means that any API Platform API can now have an admin for free! The admin is fully customizable, a follow up post will come.
A React/Redux Webapp Generator
The admin is dynamic, no code generation happens. But sometimes it’s interesting to be able to generate some code to bootstrap a project. It’s exactly what the new api-platform-generate-crud tool does. It parses the Hydra documentation and generates a basic ReactJS webapp with the following features:
generation of the suitable HTML5 input type (number, date…) according to the type of the API property
display of the server-side validation errors under the related input (if using API Platform Core)
client-side validation (required attributes)
the generated HTML is compatible with Bootstrap and includes mandatory classes
the generated HTML code is accessible to people with disabilities (ARIA support)
the Redux and the React Router configuration is also generated
Thanks to Piotr Synowiec for his contributions and fixes to those frontend tools!
Builtin HTTP Cache Invalidation System
Exposing a hypermedia API has many advantages. One of them is the ability to know exactly which resources are included in HTTP responses created by the API. We used this specificity to make API Platform apps blazing fast.
When the new cache mechanism is enabled, API Platform collects identifiers of every resources included in a given HTTP response (including lists, embedded documents and subresources) and returns them in a special HTTP header called Cache-Tags.
A cache reverse proxy supporting cache tags (Varnish, CloudFlare, Fastly…) must be put in front of the web server and store all responses returned by the API with a high TTL. When a resource is modified, API Platform takes care of purging all responses containing it in the proxy’s cache. It means that after the first request, all subsequent requests will not touch the web server, and will be served instantly from the cache. It also means that the content served will always be fresh, because the cache is purged in real time.
The support for most specific cases such as the invalidation of collections when a document is added or removed or for relationships and inverse relations is built-in.
We also included Varnish in the Docker setup provided with the distribution of API Platform, so this new feature works out of the box.
Integration with Varnish and the Doctrine ORM is shipped with the core library. You can easily implement the support for any other proxy or persistence system.
A detailed blogpost about this feature will follow.
Per Resource Authorization Mechanism
Thanks to the API Platform’s events and the extension system, it was already easy to configure basic authorization rules. In the version 2.1, we introduced an easy way to configure fine grained authorization rules directly from resource classes.
In the following example, only the logged in admins can access all operations related to the SecuredResource. However, regular users owning a specific resource can also access it:
<?php
namespace AppBundle\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\ORM\Mapping as ORM;
/**
* @ApiResource(
* attributes={"access_control"="has_role('ROLE_ADMIN')"},
* itemOperations={
* "get"={"method"="GET", "access_control"="object.getOwner() == user"}
* }
* )
* @ORM\Entity
*/
class Secured
{
/**
* @ORM\Column(type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
public $id;
/**
* @ORM\Column(type="text")
*/
public $owner;
}
Under the hood, this new feature uses Symfony’s access control expressions. The object variable value is the current resource (or collection of resources) while the user variable contains an instance of the Symfony’s user currently logged in.
Subresources Support
Having the ability to expose subresources was one of the most requested features. It was already possible to use such URL patterns thanks to custom operations, but it was a bit complicated to do.
Fortunately Antoine Bluchet rolled up this sleeves and did an excellent job! As of API Platform 2.1, subresources are a first class citizen:
/**
* @ApiResource
*/
class Product {
/**
* @ApiSubresource
*/
public $reviews;
}
The previous snippet is enough to expose through http://example.com/products/1/reviews the list of RelatedDummies resources related to the Dummy #1.
The documentations will also reflect the availability of this new URL.
New Filters
API Platform comes with 3 new useful filters that you will love.
property_filter
Baptiste Meyer contributed 2 of them. The first one, api_platform.serializer.property_filter, lets the client specify which properties the API must return.
When a resource is configured to use it, you can use the URL /products/1?properties[]=price&properties[]=currency to only serialize the properties “foo” and “bar” of this entity (all other properties will be ignored).
It’s also possible to list the properties of embedded resources with the following format: /products/1?properties[]=price&properties[brand][]=name.
group_filter
The second one, api_platform.serializer.group_filter is similar, but instead of choosing properties one by one, you can pass a list of serialization groups to apply using a URL like: /products/1?groups[]=detailed.
Those two filters allow to easily reduce the size of the returned resources to only include relevant data.
exists_filter
The last new filter, api_platform.doctrine.orm.exists_filter, was contributed by Teoh Han Hui. It allows to filter a collection on the existence of a specified value: /products?brand[exists]=0.
A Revamped API Doc UI
API Platform has a nice UI built with Swagger UI that is available for every URL of the API when requesting it from a browser (or any client sending a Accept: text/html HTTP header). In API Platform 2.1, we upgraded Swagger UI to its new major version (3.0), a full rewrite in ReactJS (API Platform + React = ❤️) including a bunch of UX improvements.
Laury Sorriaux took this opportunity to propose a great custom stylesheet improving the overall user experience and respecting our color scheme. It also contains an animation featuring our cute spider (he will get a name soon, stay tuned)!
Last but not least, Daniel Kiesel contributed to improve the integration with OAuth (and FOSOAuthBundle): it’s now possible to login with OAuth from the UI by just adding a few lines of config.
Brand New Docker Setup
One of the coolest features of API Platform 2 was the ability to run the app locally by just typing docker-compose up and to deploy apps in a breath with Kubernetes or Docker Swarm.
In API Platform 2.1, we dramatically improved the Docker support:
All images are now using Alpine Linux (reduce the size, improve the security)
Nginx and PHP-FPM are now used instead of Apache and mod_php
Varnish has been added (see the section about the cache invalidation mechanism)
The Docker Compose file has been upgraded to the format v3
Many compatibility problems with Windows have been fixed
The performance when using Docker for Mac or Docker for Windows has been dramatically improved
This Docker setup supports any Symfony-based application. Just copy/paste it in your Symfony project.
Improving the Docker configuration was a hard and collaborative work. I want to especially thanks Jacques Lefebvre, Teoh Han Hui and Antoine Bluchet for the large numbers of hours they spent to make this possible.
Integration in Symfony Flex
You can’t have missed it, Symfony 4 will come with an exciting tool to install and manage your projects: Symfony Flex. API Platform is already officially supported by Flex and can’t be easier to install: just type composer req api
Fabien Potencier (the creator of Symfony) recorded a screencast showing how API Platform and Flex fit well together:
Impressive isn’t it? Flex only works with API Platform 2.1+. Older versions aren’t supported.
Of course, many other new features, fixes and improvements (especially regarding performance) have been merged, you can read the full changelog to learn more.
Next steps before the stable release:
Testing, testing and testing again. Please try the new features, upgrade your existing projects and run your tests suites against this new version! Report any problem on GitHub. It’s very very helpful to us!
Update the documentation and write new articles for the new features. They are already many pull requests opened, reviewing and improving them is much appreciated.
Learn how to use API Platform and Symfony to create super easily rich web and mobile applications relying on React (JS) for their presentational layer.
In just a few minutes, we will create a hypermedia API thanks to API Platform, Symfony and Doctrine. We will do it step by step, and the API will be 100% functional with support for pagination, validation, filters, resources embedding. The API will be automatically documented using Swagger and Hydra and beautiful user interface for developers will be available. HTTP cache, authorization and authentication can then be added in a breath.
Then, we will introduce all new client-side tools for API Platform:
A fully featured JavaScript (Single Page App) administration system with a modern user interface (Material Design) ; built on top of Admin On Rest (React and Redux). This admin is builded dynamically thanks to the API discoverability (Hydra).
A raw React, Redux and React Router code generator to bootstrap fully-featured Single Page Applications and native mobile apps thanks to the API documentation exposed by API Platform (client-side and server-side validation, on fields error, Twitter Bootstrap compatibility, a11y support…)
API Platform is new open source PHP framework dedicated to the creation of modern web APIs.
It allows to bootstrap a fully featured API (pagination, validation, filtering, sorting, automatically generated documentation, HTTP cache, OAuth and JWT auth…) in just a few minutes.
It exposes out of the box popular API formats including Swagger, JSON-LD, Hydra, HAL, JSONAPI and Schema.org.
It is extensible and can be specialized with ease. Because it is built on top of the industry-leading Symfony framework, it already counts hundreds of available extensions (bundles).
In this talk, I’ll show how to create a hypermedia API in just a few lines of codes, then take a look to the main features of the framework.
API Platform is a PHP 7 framework dedicated to the creation of modern and powerful web APIs. It is especially adapted to build API-centric information systems relying on hypermedia, Linked Data; and consumed by Single-Page Applications (using Javascript libraries such as React or Angular) and mobile apps.
API Platform 2 has been built with 3 strong opinions in mind:
Creating an API must be an easy and quick process: any web developper should be able to create a REST API in just a few minutes including CRUD support, data validation, filtering and sorting, autogenerated documentation, OAuth and JWT authentication, CORS and other security HTTP headers, caching…
Modern open formats must be supported out of the box, without requiring any extra work for the developper: Swagger/OpenAPI, JSON-LD, Hydra, HAL, API Problem (RFC 7807) and Schema.org are supported out of the box, the powerful abstraction layer of the framework easily allows adding support for other emerging API formats (JSONAPI and GraphQL support is in progress)
Every feature of the framework must be extensible, overridable and modular
API Platform v2 is a massive rewrite of the framework, with tons of new features and bug fixes. The whole design has been rethinked, but let’s take a tour of the major new features and changes:
Revamped Config and Metadata: Exposing an API is a Matter of Seconds
Thanks to the new configuration system and the new metadata component, to create a high grade hypermedia API you just have to modelize your data model as a set of PHP classes then to add some annotations. Example:
<?php
// src/AppBundle/Entity/Book.php
namespace AppBundle\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* A book.
*
* @ApiResource
* @ORM\Entity
*/
class Book
{
/**
* @var int The id of this book.
*
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
public $id;
/**
* @var string|null The ISBN number if this book (or null if doesn't have one).
*
* @ORM\Column(nullable=true)
* @Assert\Isbn
*/
public $isbn;
/**
* @var string The title of this book.
*
* @ORM\Column
* @Assert\NotBlank
*/
public $title;
// Prefer private properties, accessors and mutators in real applications
}
This single class is enough to get a working API with the following features:
Hypermedia relations are handled out of the box. Leveraging any other feature of API Platform is just a matter of adding a few lines of configuration. Learn more in our getting started guide.
If you don’t like annotations, you can use XML or YAML configuration files instead. If you don’t like the Doctrine ORM (or doesn’t want to tight the exposed data model to the internal model of the database); or if you don’t want to use the Symfony validator, you can create adapters to hook your custom code and use your preferred libraries. API Platform is designed to be fully extensible.
Docker Integration
API Platform’s official distribution is shipped with a Docker setup adapted to API devlopment. It includes a Apache + PHP 7 and a MySQL image. To get an API Platform app up and running on your computer, type the following commands in the main directory:
$ docker-compose up -d # Download, build and run Docker images
$ docker-compose exec web bin/console doctrine:schema:create # Create the MySQL schema, only required one time
The app is up and running, browse http://localhost to get started.
Since its first release, API Platform comes with a handy code generator allowing to bootstrap a whole PHP data model including classes, properties, getters and setters, full PHPDoc, Doctrine mappings, API Platform’s external vocabulary mappings and validation annotations.
This generator has been updated to match the new configuration format of API Platform 2 and to allow generating custom classes and properties.
The following config file contains a selection of Schema.org’s types and properties. When using the generator to create the corresponding data model, a working API is created without writing a single line of PHP:
types:
Book:
parent: false # Generate only one class, not the full hierarchy from Schema.org
properties:
isbn: ~
name: ~
description: ~
author: { range: Text }
dateCreated: ~
Review:
parent: false
properties:
reviewBody: ~
rating: { range: Integer, nullable: false } # This is a custom field that doesn't exist in the vocab
itemReviewed: { range: Book, nullable: false, cardinality: '(*..1)' }
Content Negotiation and Built-in Support for JSON-LD, Hydra, HAL, YAML, CSV and XML
API Platform now natively supports content negotiation (only JSON-LD and Hydra was previously supported) as well as most popular API formats. To be able to retrieve or send resources in a specifc format, you enable them in the configuration file:
# app/config/config.yml
api_platform:
formats:
jsonld: ['application/ld+json']
jsonhal: ['application/hal+json']
xml: ['application/xml', 'text/xml']
json: ['application/json']
yaml: ['application/x-yaml']
csv: ['text/csv']
html: ['text/html'] # This is the API Platform UI
API Platform 2 generates an extensive Swagger 2/OpenAPI documentation. All URLs and types are automatically described thanks to our powerful metadata extraction system.
A web interface built on top of Swagger UI is also automatically available. Request any API’s URL using a web browser and (thanks to the Accept header sent by the browser), API Platform will display the request sent to the API and the received response in a nice web interface. It will also display a human-readable documentation of the current operation.
Browse the homepage to see the documentation of all available operations, including the description of resources and properties extracted from PHP metadata. Use the sandbox to play with your API.
New Filters and Extension Mechanism
Several new built-in filters have been added. In addition to the existing search, date and range filters, the following are now available:
Filters are now implemented using the brand new extension system. This system allows to hook to the database query generation process and to customize them. It’s particularly useful to implement security features.
Secure by default, tested against OWASP’s recommendations for REST APIs
API Platform 2 follows OWASP’s security recommendations for all its built-in features. We created a test suite to ensure that all recommendations applying to API Platform are followed and documented.
API Platform 2 is also compatible with PHP PM. When using it, API response times are divided by 10.
Availability as Standalone Components, Decoupled from Symfony and Doctrine
API Platform is designed as a set of standalone PHP components: the metadata system; JSON-LD, Hydra, Swagger, HAL serializers, Doctrine and Symfony components bridges…
All those components can be used separately to create your own APIs. For now, the Core library must be downloaded, but a subtree split to allow specific component installation will be available for the 2.1 version. Specific classes can already be used separately of the standard distribution, and without Symfony.
Doctrine has never been mandatory to use API Platform, but the set of interfaces to implement to use another persistence system has been rethought and is now documented.
We also used Scrutinizr and SensioLabs Insight to detect bad practices and improve the overall quality of our code base. API Platform is rated 8.7/10 on Scrutinizr and has the Platinum medal (best rating) on Insight.
The release of API Platform v2 is just the first step! We’re already working on new features and some of them are already ready to be merged in the 2.1 branch including:
This morning I was speaking about the API Platform framework at the Take Off Conf in my hometown of Lille. Take a look at my slides, and learn how to create a fully featured hypermedia API in a few minutes!