SlideShare a Scribd company logo
REST easy with API
Platform
Antonio Perić-Mažar, Locastic

12.04.2019., #DevConMu
REST easy with API Platform
Antonio Perić-Mažar
CEO @ Locastic
Co-Founder @ Blockada
antonio@locastic.com
@antonioperic
Locastic
• We help clients create amazing web and mobile apps (since 2011)
• mobile development
• web development
• UX/UI
• Training and Consulting
• Shift Conference, Symfony Croatia
• www.locastic.com t: @locastic
REST easy with API Platform
Why API?
The web has changed
• Javascript web apps are standard (SPA)
• Users spend more time on using mobile devices than desktop or TV.
• Linked Data and the semantic web are a reality
REST easy with API Platform
APIs are the heart of this new web
• Central point to access data (R/W data)
• Encapsulate business logic
• Same data and same features for desktops, mobiles, TVs and etc
• It is stateless (PHP Sessions make horizontal scaling harder)
Client Apps
• HTML5 (SPA), mobile apps, TVs, Cars etc.
• Holds all the presentation logic
• Is downloaded first (SPA, shell model)
• Queries the API to retrieve and modify data using asynchronous requests
• Is 100% composed of HTML, JavaScript and assets (CSS and etc)
• Can be hosted on a CDN
REST easy with API Platform
Immediate benefits
• Speed (even on mobile)
• Scalability and robustness
• Development comfort
• Long term benefits
Formats, standards, patterns
HTTP + REST + JSON
• Work everywhere
• Lightweight
• Stateless
• HTTP has a powerful caching model
• Extensible (JSON-LD, Hydra, Swagger, HAL…)
• High quality tooling
HATEOAS / Linked Data
• Hypermedia as the Engine of Application State
• Hypermedia: IRI as identifier
• Ability to reference external data (like hypertext links)
• Auto discoverable <=> Generic clients
REST easy with API Platform
JSON-LD (JSON for Linked Data)
• Standard: W3C recommandation (since 2014)
• Machine readable data
• Easy to use: looks like a typical JSON document
• Already used by Gmail, GitHub, BBC, Microsoft, US gov…
• Compliant with technologies of the semantic web: RDF, SPARQL, triple
store…
• Good for SEO
Hydra
• Describe REST APIs in JSON-LD
• = write support
• = auto-discoverable APIs
• = standard for collections, paginations, errors, filters
• Draft W3C (Work In Progress)
{
"@context": "/contexts/Book",
"@id": "/books/2",
"@type": "http://schema.org/Book",
"id": 2,
"isbn": "9790070863971",
"description": "A long but very interesting story about REST and asyncio.",
"author": "The life!",
"title": "X",
"publicationDate": "2002-01-29T00:00:00+00:00"
}
{
 "@context": "contexts/Errors",
 "@type": “hydra:Error”,
“hydra:title”: “An error occurred”,
“hydra:description”: “Not found”
}
{
"@context": "/contexts/Book",
"@id": "/books",
"@type": "hydra:Collection",
"hydra:member": [
{
"@id": "/books/2",
"@type": "http://schema.org/Book",
"id": 2,
"isbn": "9790070863971",
"description": "A long but very interesting story about REST and asyncio.",
"author": "The life!",
"title": "X",
"publicationDate": "2002-01-29T00:00:00+00:00"
},
…
{
"@id": "/books/31",
"@type": "http://schema.org/Book",
"id": 31,
"isbn": "9791943452827",
"description": "Tempora voluptas ut dolorem voluptates. Provident natus ipsam fugiat est ipsam quia. Sint mollitia sed facere qui
sit. Ad iusto molestias iusto autem laboriosam nulla earum eius.",
"author": "Miss Gladyce Nader I",
"title": "Voluptas doloremque esse dolor qui illo placeat harum voluptatem.",
"publicationDate": "1970-10-11T00:00:00+00:00"
}
],
"hydra:totalItems": 125,
"hydra:view": {
"@id": "/books?page=1",
"@type": "hydra:PartialCollectionView",
"hydra:first": "/books?page=1",
"hydra:last": "/books?page=5",
"hydra:next": "/books?page=2"
}
}
“API Platform is the most
advanced API platform, in any
framework or language.”
Fabien Potencier, SymfonyCon 2017
REST easy with API Platform
API Platform: the promise
• Fully featured API supporting Swagger + JSON-LD + Hydra + HAL in minutes
• An auto generated doc
• Convenient API spec and test tools using Behat
• Easy authentication management with JWT or OAuth
• CORS and HTTP cache
• All the tools you love: Doctrine ORM, Monolog, Swiftmailer...
API Platform <3 Symfony
• Built on top of Symfony full-stack
• Install any existing SF bundles
• Follow SF Best Practices
• Use your Symfony skills
• Can be used in your existing SF app
• (Optional) tightly integrated with Doctrine
Features
• CRUD
• Filters
• Serializations groups and relations
• Validation
• Pagination
• Sorting
• The event system
• Content Negation
• Extensions
• HTTP and reverse proxy caching
• Invalidation-based HTTP caching
• JS Admin apps
• GraphQL support
• And basically everything needed to build
modern APIs
How to start?
• Download distribution and use Docker (includes frontend applications, etc)
• https://github.com/api-platform/api-platform/releases/tag/v2.4.2
• Use Symfony Flex and any setup you want (little harder to setup)
• Enjoy!!!
CRUD
<?php
namespace AppEntity;
class Author
{
private $id;
private $firstName;
private $lastName;
// ...
}
# api/config/packages/api_platform/
author.yaml
resources:
AppEntityAuthor:~
REST easy with API Platform
schema.org
REST easy with API Platform
REST easy with API Platform
REST easy with API Platform
{
  "@context": "http://schema.org",
  "@type": "FlightReservation",
  "reservationNumber": "RXJ34P",
  "reservationStatus": "http://schema.org/Confirmed",
  "underName": {
    "@type": "Person",
    "name": "Eva Green"
  },
  "reservationFor": {
    "@type": "Flight",
    "flightNumber": "110",
    "airline": {
      "@type": "Airline",
      "name": "United",
      "iataCode": "UA"
    },
    "departureAirport": {
      "@type": "Airport",
      "name": "San Francisco Airport",
      "iataCode": "SFO"
    },
    "departureTime": "2017-03-04T20:15:00-08:00",
    "arrivalAirport": {
      "@type": "Airport",
      "name": "John F. Kennedy International Airport",
      "iataCode": "JFK"
    },
    "arrivalTime": "2017-03-05T06:30:00-05:00"
  }
}
Using schema.org in Api Platform
resources:
AppEntityFlightReservation:
iri: 'http://schema.org/FlightReservation'
Using schema.org in Api Platform
resources:
AppEntityFlightReservation:
iri: 'http://schema.org/FlightReservation'
properties:
status:
iri: 'http://schema.org/reservationStatus'
Operations
• API Platform Core relies on the concept of operations. Operations can be
applied to a resource exposed by the API. From an implementation point of
view, an operation is a link between a resource, a route and its related
controller.
• There are two types of operations:
• Collection operations act on a collection of resources. By default two
routes are implemented: POST and GET.
• Item operations act on an individual resource. 3 default routes are
defined GET, PUT and DELETE.
REST easy with API Platform
Custom operation
class Match
{
private $id;
/**
* @Groups({"match_read"})
*/
private $datetime;
/**
* @Groups({"match_read", "match_write"})
*/
private $playerOnePoints;
/**
* @Groups({"match_read", "match_write"})
*/
private $playerTwoPoints;
/**
* @Groups({"match_read", "match_write"})
*/
private $playerOne;
/**
* @Groups({"match_read", "match_write"})
*/
private $playerTwo;
/**
* @Groups({"match_read"})
*/
private $winner;
/**
* @Groups({"match_read"})
*/
private $result;
}
Custom operationclass Match
{
private $id;
/**
* @Groups({"match_read"})
*/
private $datetime;
/**
* @Groups({"match_read", "match_write"})
*/
private $playerOnePoints;
/**
* @Groups({"match_read", "match_write"})
*/
private $playerTwoPoints;
/**
* @Groups({"match_read", "match_write"})
*/
private $playerOne;
/**
* @Groups({"match_read", "match_write"})
*/
private $playerTwo;
/**
* @Groups({"match_read"})
*/
private $winner;
/**
* @Groups({"match_read"})
*/
private $result;
}
class MatchController extends Controller
{
/**
* @param Match $data
*
* @return Match
*/
public function getMatchAction($data)
{
$result = $data->getPlayerOne() . ' ' . $data->getPlayerOnePoints().':'
.$data->getPlayerTwoPoints() . ' ' . $data->getPlayerTwo();
$data->setResult($result);
return $data;
}
}
Custom operation
class Match
{
private $id;
/**
* @Groups({"match_read"})
*/
private $datetime;
/**
* @Groups({"match_read", "match_write"})
*/
private $playerOnePoints;
/**
* @Groups({"match_read", "match_write"})
*/
private $playerTwoPoints;
/**
* @Groups({"match_read", "match_write"})
*/
private $playerOne;
/**
* @Groups({"match_read", "match_write"})
*/
private $playerTwo;
/**
* @Groups({"match_read"})
*/
private $winner;
/**
* @Groups({"match_read"})
*/
private $result;
}
class MatchController extends Controller
{
/**
* @param Match $data
*
* @return Match
*/
public function getMatchAction($data)
{
$result = $data->getPlayerOne() . ' ' . $data->getPlayerOnePoints().':'
.$data->getPlayerTwoPoints() . ' ' . $data->getPlayerTwo();
$data->setResult($result);
return $data;
}
}
# app/config/routing.yml
get_match:
path: /api/v1/matches/{id}.{_format}
methods: ['GET']
defaults:
_controller: AppBundle:Match:getMatch
_api_resource_class: AppBundleEntityMatch
_api_item_operation_name: get
Override default order
resources:
AppEntityPlayer:
attributes:
order:
lastname: ‘ASC’
Adding subresource
resources:
AppBundleEntityPlayer:
properties:
matches:
subresource:
resourceClass: ‘AppEntityMatch’
maxDepth: 1
collection: true
-> api.com/players/1/matches
Filters
• If Doctrine ORM support is enabled, adding filters is as easy as registering
a filter service in your api/config/services.yml file and adding an
attribute to your resource configuration.
• Filters add extra conditions to base database query
• Useful filters for the Doctrine ORM are provided with the library. You can
also create custom filters that would fit your specific needs.
Filters
• Search filter (partial, start, end, exact, ipartial, iexact)
• Date filter (?property[<after|before>]=value )
• Boolean filter (?property=[true|false|1|0])
• Numeric filter (?property=int|bigint|decimal)
• Range filter (?property[lt]|[gt]|[lte]|[gte]|[between]=value)
• Order filter (?order[property]=<asc|desc>)
• …
• Custom filters
Filters examples
# AppBundle/Resources/config/api_resources/resources.yml
resources:
AppBundleEntityPlayer:
# ...
attributes:
filters: ['player.search', 'player.order']
AppBundleEntityMatch:
# ...
attributes:
filters: ['match.date']
services:
player.search_filter:
parent: 'api_platform.doctrine.orm.search_filter'
arguments: [ { id: 'exact', email: 'exact', firstName: 'partial' } ]
tags: [ { name: 'api_platform.filter', id: 'player.search' } ]
match.date_filter:
parent: 'api_platform.doctrine.orm.date_filter'
arguments: [ { datetime: ~ } ]
tags: [ { name: 'api_platform.filter', id: 'match.date' } ]
player.order_filter:
parent: 'api_platform.doctrine.orm.order_filter'
arguments: [{ firstName: 'ASC', lastName: 'ACS', email: ~ }]
tags: [{ name: 'api_platform.filter', id: 'player.order' }]
Serialization Groups
• API Platform Core allows to choose which attributes of the resource are
exposed during the normalization (read) and denormalization (write)
process. It relies on the serialization (and deserialization) groups feature of
the Symfony Serializer component.
• allows to specify the definition of serialization using XML, YAML, or
annotations.
Serialization Groups
<?php
namespace AppEntity;
use FOSUserBundleModelUser as BaseUser;
use SymfonyComponentSerializerAnnotationGroups;
class Player extends BaseUser
{
/**
* @var int
*/
protected $id;
/**
* @Groups({"player_read", "player_write"})
*/
private $firstName;
/**
* @Groups({"player_read", "player_write"})
*/
private $lastName;
/**
* @Groups({"player_read", "player_write"})
*/
protected $email;
// ...
}
# UserBundle/Resources/api_resources/resources.yml
resources:
AppEntityPlayer:
attributes:
normalization_context:
groups: ['player_read']
denormalization_context:
groups: ['player_write']
Using Different Serialization
Groups per Operation
# UserBundle/Resources/api_resources/resources.yml
resources:
AppEntityPlayer:
itemOperations:
get:
method: 'GET'
normalization_context:
groups: ['player_read', 'player_extra']
put:
method: 'PUT'
delete:
method: 'DELETE'
attributes:
normalization_context:
groups: ['player_read']
denormalization_context:
groups: ['player_write']
Api platform events
// src/AppBundle/EventSubscriber/MatchEventSubscriber.php
class MatchEventSubscriber implements EventSubscriberInterface
{
private $matchHelper;
public function __construct(MatchHelper $matchHelper)
{
$this->matchHelper = $matchHelper;
}
public static function getSubscribedEvents()
{
return [
KernelEvents::VIEW => [['addWinner', EventPriorities::POST_VALIDATE]],
];
}
public function addWinner(GetResponseForControllerResultEvent $event)
{
$match = $event->getControllerResult();
$method = $event->getRequest()->getMethod();
if(!$match instanceof Match || $method !== 'POST') {
return;
}
$winner = $this->matchHelper->getWinner($match);
$match->setWinner($winner);
}
}
Extensions
• API Platform Core provides a system to extend queries on items and
collections.
• Custom extensions must implement
the ApiPlatformCoreBridgeDoctrineOrmExtensionQuery
CollectionExtensionInterface and / or
the ApiPlatformCoreBridgeDoctrineOrmExtensionQuery
ItemExtensionInterface interfaces, to be run when querying for a
collection of items and when querying for an item respectively.
class GetPlayersExtension implements QueryCollectionExtensionInterface, QueryItemExtensionInterface
{
public function applyToItem(
QueryBuilder $queryBuilder,
QueryNameGeneratorInterface $queryNameGenerator,
string $resourceClass,
array $identifiers,
string $operationName = null,
array $context = []
) {
$this->addWhere($queryBuilder, $resourceClass, $operationName);
}
public function applyToCollection(
QueryBuilder $queryBuilder,
QueryNameGeneratorInterface $queryNameGenerator,
string $resourceClass,
string $operationName = null
) {
$this->addWhere($queryBuilder, $resourceClass, $operationName);
}
private function addWhere(QueryBuilder $queryBuilder, string $resourceClass, string $operationName = null)
{
if ($resourceClass != Player::class || $operationName != 'get') {
return;
}
$rootAlias = $queryBuilder->getRootAliases()[0];
$queryBuilder->andWhere(
$queryBuilder->expr()->eq($rootAlias.'.enabled', ':enabled')
)->setParameter('enabled', true);
}
}
services:
app.extension.get_players:
class: AppBundleDoctrineORMExtensionGetPlayersExtension
public: false
tags:
- { name: api_platform.doctrine.orm.query_extension.collection, priority: 9 }
- { name: api_platform.doctrine.orm.query_extension.item }
Per Resource Authorization Mechanism
namespace AppBundleEntity;
 
use ApiPlatformCoreAnnotationApiResource;
use DoctrineORMMapping as ORM;
 
/**
* @ApiResource(
*     attributes={"is_granted"="has_role('ROLE_ADMIN')"},
*     itemOperations={
*         "get"={"method"="GET", "is_granted"="object.getOwner() == user"}
*     }
* )
* @ORMEntity
*/
class Secured
{
    /**
     * @ORMColumn(type="integer")
     * @ORMId
     * @ORMGeneratedValue(strategy="AUTO")
     */
    public $id;
 
    /**
     * @ORMColumn(type="text")
     */
    public $owner;
Cache invalidation is builtin
Translation Support
• https://github.com/Locastic/ApiPlatformTranslationBundle
• https://locastic.com/blog/having-troubles-with-implementing-translations-in-
apiplatform/
GraphQL support
GraphQL Support
• docker-compose exec php composer req webonyx/graphql-php && docker-
compose exec php bin/console cache:clear
• The GraphQL implementation supports queries, mutations, 100% of the
Relay server specification, pagination, filters and access control rules. You
can use it with the popular RelayJS and Apollo clients.
REST easy with API Platform
Testing
• PHPUnit
• Postman (newman)
• Panther
• https://locastic.com/blog/what-to-do-when-you-get-lost-in-api-testing/
Mercure
Mercure
• Fast, written in Go
• native browser support, no lib nor SDK required (built on top of HTTP and server-sent events)
• compatible with all existing servers, even those who don't support persistent connections
(serverless architecture, PHP, FastCGI...)
• Automatic HTTP/2 and HTTPS (using Let's Encrypt) support
• CORS support, CSRF protection mechanism
• Cloud Native, follows the Twelve-Factor App methodology
• Open source (AGPL)
• …
Let’s try it
https://symfonycon.les-tilleuls.coop/
Update progressive web app
• docker-compose exec client generate-api-platform-client
• Follow instructions
Version 2.4
• read and write support for MongoDB, the reference document database,
including a lot of useful filters
• Read support for Elasticsearch, the open source search and analytics
engine, including filters for advanced search
• Automatic “push” of updated resources from the server to the clients using
the brand new Mercure protocol
Version 2.4
• Integration with the Symfony Messenger component to easily implement the
CQRS pattern and to handle messages asynchronously (using brokers such as
RabbitMQ, Apache Kafka, Amazon SQS or Google PubSub)
• Ability to leverage the “Server Push” feature of HTTP/2 to preemptively send the
relations of a requested resource to the client
• Automatic availability of list filters in the React-based admin when a corresponding
one is available API-side
• Full compatibility with the version 3 of the OpenAPI specification format (formerly
known as Swagger), and integration of the beautiful ReDoc documentation generator
Version 2.4
• Improved DTOs support
• Per resource configuration of HTTP cache headers
• Ability to easily use the Sunset HTTP header to advertise the removal date
of deprecated endpoints
REST easy with API Platform
GFNY Ticketing system
• 20 races, 18 countries
• Different timezones, currencies, languages…
• More then 60 000 tickets per year, with very complex login
• Standings and rankings
• Email notification, flexibility
• Etc.
Conclusion
• Very powerful, even for large applications
• Easy to start, well documented
• Active community and company behind it
• Write tests!
Thank you!
antonio@locastic.com
@antonioperic
www.locastic.com
Questions?

More Related Content

What's hot

Scrum Experience [O Tutorial Scrum]
Scrum Experience [O Tutorial Scrum]Scrum Experience [O Tutorial Scrum]
Scrum Experience [O Tutorial Scrum]
Rildo (@rildosan) Santos
 
Apple TV tvOS入門 Iosdc2017
Apple TV tvOS入門 Iosdc2017Apple TV tvOS入門 Iosdc2017
Apple TV tvOS入門 Iosdc2017
Yuji Hato
 
Android with kotlin course
Android with kotlin courseAndroid with kotlin course
Android with kotlin course
Abdul Rahman Masri Attal
 
Plano de Compensação Akmos
Plano de Compensação AkmosPlano de Compensação Akmos
Plano de Compensação Akmos
Andres Postigo
 
Gestão Agil de tudo - Retrospectivas
Gestão Agil de tudo - RetrospectivasGestão Agil de tudo - Retrospectivas
Gestão Agil de tudo - Retrospectivas
Kleitor Franklint Correa Araujo
 
Introduction of python
Introduction of pythonIntroduction of python
Introduction of python
ShehabAldeenFadelall
 
Clean Code III - Software Craftsmanship
Clean Code III - Software CraftsmanshipClean Code III - Software Craftsmanship
Clean Code III - Software Craftsmanship
Theo Jungeblut
 
Flask for cs students
Flask for cs studentsFlask for cs students
Flask for cs students
Jennifer Rubinovitz
 
PHP - Introduction to PHP Fundamentals
PHP -  Introduction to PHP FundamentalsPHP -  Introduction to PHP Fundamentals
PHP - Introduction to PHP Fundamentals
Vibrant Technologies & Computers
 
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
Philip Schwarz
 
Introduction to es6
Introduction to es6Introduction to es6
Introduction to es6
NexThoughts Technologies
 
Golang Book - Go Programlama Dili Temelleri
Golang Book - Go Programlama Dili TemelleriGolang Book - Go Programlama Dili Temelleri
Golang Book - Go Programlama Dili Temelleri
Cihan Özhan
 
WebDAV as Web API
WebDAV as Web APIWebDAV as Web API
WebDAV as Web API
Masaki Komagata
 
Drf
DrfDrf

What's hot (14)

Scrum Experience [O Tutorial Scrum]
Scrum Experience [O Tutorial Scrum]Scrum Experience [O Tutorial Scrum]
Scrum Experience [O Tutorial Scrum]
 
Apple TV tvOS入門 Iosdc2017
Apple TV tvOS入門 Iosdc2017Apple TV tvOS入門 Iosdc2017
Apple TV tvOS入門 Iosdc2017
 
Android with kotlin course
Android with kotlin courseAndroid with kotlin course
Android with kotlin course
 
Plano de Compensação Akmos
Plano de Compensação AkmosPlano de Compensação Akmos
Plano de Compensação Akmos
 
Gestão Agil de tudo - Retrospectivas
Gestão Agil de tudo - RetrospectivasGestão Agil de tudo - Retrospectivas
Gestão Agil de tudo - Retrospectivas
 
Introduction of python
Introduction of pythonIntroduction of python
Introduction of python
 
Clean Code III - Software Craftsmanship
Clean Code III - Software CraftsmanshipClean Code III - Software Craftsmanship
Clean Code III - Software Craftsmanship
 
Flask for cs students
Flask for cs studentsFlask for cs students
Flask for cs students
 
PHP - Introduction to PHP Fundamentals
PHP -  Introduction to PHP FundamentalsPHP -  Introduction to PHP Fundamentals
PHP - Introduction to PHP Fundamentals
 
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
 
Introduction to es6
Introduction to es6Introduction to es6
Introduction to es6
 
Golang Book - Go Programlama Dili Temelleri
Golang Book - Go Programlama Dili TemelleriGolang Book - Go Programlama Dili Temelleri
Golang Book - Go Programlama Dili Temelleri
 
WebDAV as Web API
WebDAV as Web APIWebDAV as Web API
WebDAV as Web API
 
Drf
DrfDrf
Drf
 

Similar to REST easy with API Platform

Building APIs in an easy way using API Platform
Building APIs in an easy way using API PlatformBuilding APIs in an easy way using API Platform
Building APIs in an easy way using API Platform
Antonio Peric-Mazar
 
Building APIs in an easy way using API Platform
Building APIs in an easy way using API PlatformBuilding APIs in an easy way using API Platform
Building APIs in an easy way using API Platform
Antonio Peric-Mazar
 
2.28.17 Introducing DSpace 7 Webinar Slides
2.28.17 Introducing DSpace 7 Webinar Slides2.28.17 Introducing DSpace 7 Webinar Slides
2.28.17 Introducing DSpace 7 Webinar Slides
DuraSpace
 
1.6 米嘉 gobuildweb
1.6 米嘉 gobuildweb1.6 米嘉 gobuildweb
1.6 米嘉 gobuildweb
Leo Zhou
 
Beautiful REST and JSON APIs - Les Hazlewood
Beautiful REST and JSON APIs - Les HazlewoodBeautiful REST and JSON APIs - Les Hazlewood
Beautiful REST and JSON APIs - Les Hazlewood
jaxconf
 
Extensible RESTful Applications with Apache TinkerPop
Extensible RESTful Applications with Apache TinkerPopExtensible RESTful Applications with Apache TinkerPop
Extensible RESTful Applications with Apache TinkerPop
Varun Ganesh
 
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
Doris Chen
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...
Fabio Franzini
 
Spring 3 - An Introduction
Spring 3 - An IntroductionSpring 3 - An Introduction
Spring 3 - An Introduction
Thorsten Kamann
 
Crafting Evolvable Api Responses
Crafting Evolvable Api ResponsesCrafting Evolvable Api Responses
Crafting Evolvable Api Responses
darrelmiller71
 
FOXX - a Javascript application framework on top of ArangoDB
FOXX - a Javascript application framework on top of ArangoDBFOXX - a Javascript application framework on top of ArangoDB
FOXX - a Javascript application framework on top of ArangoDB
ArangoDB Database
 
Getting started with titanium
Getting started with titaniumGetting started with titanium
Getting started with titanium
Naga Harish M
 
Advanced Web Development
Advanced Web DevelopmentAdvanced Web Development
Advanced Web Development
Robert J. Stein
 
Are you getting Sleepy. REST in SharePoint Apps
Are you getting Sleepy. REST in SharePoint AppsAre you getting Sleepy. REST in SharePoint Apps
Are you getting Sleepy. REST in SharePoint Apps
Liam Cleary [MVP]
 
An Introduction to Tornado
An Introduction to TornadoAn Introduction to Tornado
An Introduction to Tornado
Gavin Roy
 
How to Contribute to Apache Usergrid
How to Contribute to Apache UsergridHow to Contribute to Apache Usergrid
How to Contribute to Apache Usergrid
David M. Johnson
 
IVS CTO Night And Day 2018 Winter - [re:Cap] Serverless & Mobile
IVS CTO Night And Day 2018 Winter - [re:Cap] Serverless & MobileIVS CTO Night And Day 2018 Winter - [re:Cap] Serverless & Mobile
IVS CTO Night And Day 2018 Winter - [re:Cap] Serverless & Mobile
Amazon Web Services Japan
 
How ElasticSearch lives in my DevOps life
How ElasticSearch lives in my DevOps lifeHow ElasticSearch lives in my DevOps life
How ElasticSearch lives in my DevOps life
琛琳 饶
 
SPTechCon DevDays - SharePoint & jQuery
SPTechCon DevDays - SharePoint & jQuerySPTechCon DevDays - SharePoint & jQuery
SPTechCon DevDays - SharePoint & jQuery
Mark Rackley
 
Getting started with Appcelerator Titanium
Getting started with Appcelerator TitaniumGetting started with Appcelerator Titanium
Getting started with Appcelerator Titanium
Techday7
 

Similar to REST easy with API Platform (20)

Building APIs in an easy way using API Platform
Building APIs in an easy way using API PlatformBuilding APIs in an easy way using API Platform
Building APIs in an easy way using API Platform
 
Building APIs in an easy way using API Platform
Building APIs in an easy way using API PlatformBuilding APIs in an easy way using API Platform
Building APIs in an easy way using API Platform
 
2.28.17 Introducing DSpace 7 Webinar Slides
2.28.17 Introducing DSpace 7 Webinar Slides2.28.17 Introducing DSpace 7 Webinar Slides
2.28.17 Introducing DSpace 7 Webinar Slides
 
1.6 米嘉 gobuildweb
1.6 米嘉 gobuildweb1.6 米嘉 gobuildweb
1.6 米嘉 gobuildweb
 
Beautiful REST and JSON APIs - Les Hazlewood
Beautiful REST and JSON APIs - Les HazlewoodBeautiful REST and JSON APIs - Les Hazlewood
Beautiful REST and JSON APIs - Les Hazlewood
 
Extensible RESTful Applications with Apache TinkerPop
Extensible RESTful Applications with Apache TinkerPopExtensible RESTful Applications with Apache TinkerPop
Extensible RESTful Applications with Apache TinkerPop
 
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...
 
Spring 3 - An Introduction
Spring 3 - An IntroductionSpring 3 - An Introduction
Spring 3 - An Introduction
 
Crafting Evolvable Api Responses
Crafting Evolvable Api ResponsesCrafting Evolvable Api Responses
Crafting Evolvable Api Responses
 
FOXX - a Javascript application framework on top of ArangoDB
FOXX - a Javascript application framework on top of ArangoDBFOXX - a Javascript application framework on top of ArangoDB
FOXX - a Javascript application framework on top of ArangoDB
 
Getting started with titanium
Getting started with titaniumGetting started with titanium
Getting started with titanium
 
Advanced Web Development
Advanced Web DevelopmentAdvanced Web Development
Advanced Web Development
 
Are you getting Sleepy. REST in SharePoint Apps
Are you getting Sleepy. REST in SharePoint AppsAre you getting Sleepy. REST in SharePoint Apps
Are you getting Sleepy. REST in SharePoint Apps
 
An Introduction to Tornado
An Introduction to TornadoAn Introduction to Tornado
An Introduction to Tornado
 
How to Contribute to Apache Usergrid
How to Contribute to Apache UsergridHow to Contribute to Apache Usergrid
How to Contribute to Apache Usergrid
 
IVS CTO Night And Day 2018 Winter - [re:Cap] Serverless & Mobile
IVS CTO Night And Day 2018 Winter - [re:Cap] Serverless & MobileIVS CTO Night And Day 2018 Winter - [re:Cap] Serverless & Mobile
IVS CTO Night And Day 2018 Winter - [re:Cap] Serverless & Mobile
 
How ElasticSearch lives in my DevOps life
How ElasticSearch lives in my DevOps lifeHow ElasticSearch lives in my DevOps life
How ElasticSearch lives in my DevOps life
 
SPTechCon DevDays - SharePoint & jQuery
SPTechCon DevDays - SharePoint & jQuerySPTechCon DevDays - SharePoint & jQuery
SPTechCon DevDays - SharePoint & jQuery
 
Getting started with Appcelerator Titanium
Getting started with Appcelerator TitaniumGetting started with Appcelerator Titanium
Getting started with Appcelerator Titanium
 

More from Antonio Peric-Mazar

You call yourself a Senior Developer?
You call yourself a Senior Developer?You call yourself a Senior Developer?
You call yourself a Senior Developer?
Antonio Peric-Mazar
 
Using API Platform to build ticketing system #symfonycon
Using API Platform to build ticketing system #symfonyconUsing API Platform to build ticketing system #symfonycon
Using API Platform to build ticketing system #symfonycon
Antonio Peric-Mazar
 
Using API platform to build ticketing system (translations, time zones, ...) ...
Using API platform to build ticketing system (translations, time zones, ...) ...Using API platform to build ticketing system (translations, time zones, ...) ...
Using API platform to build ticketing system (translations, time zones, ...) ...
Antonio Peric-Mazar
 
Are you failing at being agile? #digitallabin
Are you failing at being agile? #digitallabinAre you failing at being agile? #digitallabin
Are you failing at being agile? #digitallabin
Antonio Peric-Mazar
 
Symfony 4: A new way to develop applications #ipc19
Symfony 4: A new way to develop applications #ipc19Symfony 4: A new way to develop applications #ipc19
Symfony 4: A new way to develop applications #ipc19
Antonio Peric-Mazar
 
A year with progressive web apps! #webinale
A year with progressive web apps! #webinaleA year with progressive web apps! #webinale
A year with progressive web apps! #webinale
Antonio Peric-Mazar
 
The UI is the THE application #dpc19
The UI is the THE application #dpc19The UI is the THE application #dpc19
The UI is the THE application #dpc19
Antonio Peric-Mazar
 
Symfony 4: A new way to develop applications #phpsrb
 Symfony 4: A new way to develop applications #phpsrb Symfony 4: A new way to develop applications #phpsrb
Symfony 4: A new way to develop applications #phpsrb
Antonio Peric-Mazar
 
A year with progressive web apps! #DevConMU
A year with progressive web apps! #DevConMUA year with progressive web apps! #DevConMU
A year with progressive web apps! #DevConMU
Antonio Peric-Mazar
 
Service workers are your best friends
Service workers are your best friendsService workers are your best friends
Service workers are your best friends
Antonio Peric-Mazar
 
Progressive Web Apps are here!
Progressive Web Apps are here!Progressive Web Apps are here!
Progressive Web Apps are here!
Antonio Peric-Mazar
 
Symfony4 - A new way of developing web applications
Symfony4 - A new way of developing web applicationsSymfony4 - A new way of developing web applications
Symfony4 - A new way of developing web applications
Antonio Peric-Mazar
 
Build your business on top of Open Source
Build your business on top of Open SourceBuild your business on top of Open Source
Build your business on top of Open Source
Antonio Peric-Mazar
 
Lessons learned while developing with Sylius
Lessons learned while developing with SyliusLessons learned while developing with Sylius
Lessons learned while developing with Sylius
Antonio Peric-Mazar
 
Drupal8 for Symfony developers - Dutch PHP
Drupal8 for Symfony developers - Dutch PHPDrupal8 for Symfony developers - Dutch PHP
Drupal8 for Symfony developers - Dutch PHP
Antonio Peric-Mazar
 
Drupal8 for Symfony Developers (PHP Day Verona 2017)
Drupal8 for Symfony Developers (PHP Day Verona 2017)Drupal8 for Symfony Developers (PHP Day Verona 2017)
Drupal8 for Symfony Developers (PHP Day Verona 2017)
Antonio Peric-Mazar
 
Drupal8 for Symfony Developers
Drupal8 for Symfony DevelopersDrupal8 for Symfony Developers
Drupal8 for Symfony Developers
Antonio Peric-Mazar
 
Maintainable + Extensible = Clean ... yes, Code!
Maintainable + Extensible = Clean ... yes, Code! Maintainable + Extensible = Clean ... yes, Code!
Maintainable + Extensible = Clean ... yes, Code!
Antonio Peric-Mazar
 
A recipe for effective leadership
A recipe for effective leadershipA recipe for effective leadership
A recipe for effective leadership
Antonio Peric-Mazar
 
Building real time applications with Symfony2
Building real time applications with Symfony2Building real time applications with Symfony2
Building real time applications with Symfony2
Antonio Peric-Mazar
 

More from Antonio Peric-Mazar (20)

You call yourself a Senior Developer?
You call yourself a Senior Developer?You call yourself a Senior Developer?
You call yourself a Senior Developer?
 
Using API Platform to build ticketing system #symfonycon
Using API Platform to build ticketing system #symfonyconUsing API Platform to build ticketing system #symfonycon
Using API Platform to build ticketing system #symfonycon
 
Using API platform to build ticketing system (translations, time zones, ...) ...
Using API platform to build ticketing system (translations, time zones, ...) ...Using API platform to build ticketing system (translations, time zones, ...) ...
Using API platform to build ticketing system (translations, time zones, ...) ...
 
Are you failing at being agile? #digitallabin
Are you failing at being agile? #digitallabinAre you failing at being agile? #digitallabin
Are you failing at being agile? #digitallabin
 
Symfony 4: A new way to develop applications #ipc19
Symfony 4: A new way to develop applications #ipc19Symfony 4: A new way to develop applications #ipc19
Symfony 4: A new way to develop applications #ipc19
 
A year with progressive web apps! #webinale
A year with progressive web apps! #webinaleA year with progressive web apps! #webinale
A year with progressive web apps! #webinale
 
The UI is the THE application #dpc19
The UI is the THE application #dpc19The UI is the THE application #dpc19
The UI is the THE application #dpc19
 
Symfony 4: A new way to develop applications #phpsrb
 Symfony 4: A new way to develop applications #phpsrb Symfony 4: A new way to develop applications #phpsrb
Symfony 4: A new way to develop applications #phpsrb
 
A year with progressive web apps! #DevConMU
A year with progressive web apps! #DevConMUA year with progressive web apps! #DevConMU
A year with progressive web apps! #DevConMU
 
Service workers are your best friends
Service workers are your best friendsService workers are your best friends
Service workers are your best friends
 
Progressive Web Apps are here!
Progressive Web Apps are here!Progressive Web Apps are here!
Progressive Web Apps are here!
 
Symfony4 - A new way of developing web applications
Symfony4 - A new way of developing web applicationsSymfony4 - A new way of developing web applications
Symfony4 - A new way of developing web applications
 
Build your business on top of Open Source
Build your business on top of Open SourceBuild your business on top of Open Source
Build your business on top of Open Source
 
Lessons learned while developing with Sylius
Lessons learned while developing with SyliusLessons learned while developing with Sylius
Lessons learned while developing with Sylius
 
Drupal8 for Symfony developers - Dutch PHP
Drupal8 for Symfony developers - Dutch PHPDrupal8 for Symfony developers - Dutch PHP
Drupal8 for Symfony developers - Dutch PHP
 
Drupal8 for Symfony Developers (PHP Day Verona 2017)
Drupal8 for Symfony Developers (PHP Day Verona 2017)Drupal8 for Symfony Developers (PHP Day Verona 2017)
Drupal8 for Symfony Developers (PHP Day Verona 2017)
 
Drupal8 for Symfony Developers
Drupal8 for Symfony DevelopersDrupal8 for Symfony Developers
Drupal8 for Symfony Developers
 
Maintainable + Extensible = Clean ... yes, Code!
Maintainable + Extensible = Clean ... yes, Code! Maintainable + Extensible = Clean ... yes, Code!
Maintainable + Extensible = Clean ... yes, Code!
 
A recipe for effective leadership
A recipe for effective leadershipA recipe for effective leadership
A recipe for effective leadership
 
Building real time applications with Symfony2
Building real time applications with Symfony2Building real time applications with Symfony2
Building real time applications with Symfony2
 

Recently uploaded

GT degree offer diploma Transcript
GT degree offer diploma TranscriptGT degree offer diploma Transcript
GT degree offer diploma Transcript
attueb
 
Predicting Test Results without Execution (FSE 2024)
Predicting Test Results without Execution (FSE 2024)Predicting Test Results without Execution (FSE 2024)
Predicting Test Results without Execution (FSE 2024)
andrehoraa
 
Odoo E-commerce website development guides
Odoo E-commerce website development guidesOdoo E-commerce website development guides
Odoo E-commerce website development guides
jhkdigitalmarketing
 
InflectraCON 360: Risk-Based Testing for Mission Critical Systems
InflectraCON 360: Risk-Based Testing for Mission Critical SystemsInflectraCON 360: Risk-Based Testing for Mission Critical Systems
InflectraCON 360: Risk-Based Testing for Mission Critical Systems
Inflectra
 
Mobile App Development Company in Noida - Drona Infotech.
Mobile App Development Company in Noida - Drona Infotech.Mobile App Development Company in Noida - Drona Infotech.
Mobile App Development Company in Noida - Drona Infotech.
Mobile App Development Company in Noida - Drona Infotech
 
To Avoid Mistakes When Using Online Attendance Sheets
To Avoid Mistakes When Using Online Attendance SheetsTo Avoid Mistakes When Using Online Attendance Sheets
To Avoid Mistakes When Using Online Attendance Sheets
Task Tracker
 
Tour and travel website management in odoo,
Tour and travel website management in odoo,Tour and travel website management in odoo,
Tour and travel website management in odoo,
Axis Technolabs
 
Independent Girls Call ServiCe Hyderabad 0000000000 Tanisha Best High Class H...
Independent Girls Call ServiCe Hyderabad 0000000000 Tanisha Best High Class H...Independent Girls Call ServiCe Hyderabad 0000000000 Tanisha Best High Class H...
Independent Girls Call ServiCe Hyderabad 0000000000 Tanisha Best High Class H...
aslasdfmkhan4750
 
Verified Girls Call Mumbai 👀 9820252231 👀 Cash Payment With Room DeliveryDeli...
Verified Girls Call Mumbai 👀 9820252231 👀 Cash Payment With Room DeliveryDeli...Verified Girls Call Mumbai 👀 9820252231 👀 Cash Payment With Room DeliveryDeli...
Verified Girls Call Mumbai 👀 9820252231 👀 Cash Payment With Room DeliveryDeli...
87tomato
 
Comprehensive Vulnerability Assessments Process _ Aardwolf Security.docx
Comprehensive Vulnerability Assessments Process _ Aardwolf Security.docxComprehensive Vulnerability Assessments Process _ Aardwolf Security.docx
Comprehensive Vulnerability Assessments Process _ Aardwolf Security.docx
Aardwolf Security
 
AI - Your Startup Sidekick (Leveraging AI to Bootstrap a Lean Startup).pdf
AI - Your Startup Sidekick (Leveraging AI to Bootstrap a Lean Startup).pdfAI - Your Startup Sidekick (Leveraging AI to Bootstrap a Lean Startup).pdf
AI - Your Startup Sidekick (Leveraging AI to Bootstrap a Lean Startup).pdf
Daniel Zivkovic
 
Top Chinese Government-backed APT Groups
Top Chinese Government-backed APT GroupsTop Chinese Government-backed APT Groups
Top Chinese Government-backed APT Groups
SOCRadar
 
Wired_2.0_Create_AmsterdamJUG_09072024.pptx
Wired_2.0_Create_AmsterdamJUG_09072024.pptxWired_2.0_Create_AmsterdamJUG_09072024.pptx
Wired_2.0_Create_AmsterdamJUG_09072024.pptx
SimonedeGijt
 
VVIP Girls Call Mumbai 9910780858 Provide Best And Top Girl Service And No1 i...
VVIP Girls Call Mumbai 9910780858 Provide Best And Top Girl Service And No1 i...VVIP Girls Call Mumbai 9910780858 Provide Best And Top Girl Service And No1 i...
VVIP Girls Call Mumbai 9910780858 Provide Best And Top Girl Service And No1 i...
jealousviolet
 
AWS DevOps-Tutorial CHANAKYA SRIYAN DUKKA.
AWS DevOps-Tutorial CHANAKYA SRIYAN DUKKA.AWS DevOps-Tutorial CHANAKYA SRIYAN DUKKA.
AWS DevOps-Tutorial CHANAKYA SRIYAN DUKKA.
Srinivas Dukka
 
Russian Girls Call Mumbai 🛵🚡9833363713 💃 Choose Best And Top Girl Service And...
Russian Girls Call Mumbai 🛵🚡9833363713 💃 Choose Best And Top Girl Service And...Russian Girls Call Mumbai 🛵🚡9833363713 💃 Choose Best And Top Girl Service And...
Russian Girls Call Mumbai 🛵🚡9833363713 💃 Choose Best And Top Girl Service And...
dream girl
 
🚂🚘 Premium Girls Call Ranchi 🛵🚡000XX00000 💃 Choose Best And Top Girl Service...
🚂🚘 Premium Girls Call Ranchi  🛵🚡000XX00000 💃 Choose Best And Top Girl Service...🚂🚘 Premium Girls Call Ranchi  🛵🚡000XX00000 💃 Choose Best And Top Girl Service...
🚂🚘 Premium Girls Call Ranchi 🛵🚡000XX00000 💃 Choose Best And Top Girl Service...
bahubalikumar09988
 
Girls Call Jogeshwari 9967584737 Provide Best And Top Girl Service And No1 in...
Girls Call Jogeshwari 9967584737 Provide Best And Top Girl Service And No1 in...Girls Call Jogeshwari 9967584737 Provide Best And Top Girl Service And No1 in...
Girls Call Jogeshwari 9967584737 Provide Best And Top Girl Service And No1 in...
simran hot girls
 
SAP implementation steps PDF - Zyple Software
SAP implementation steps PDF - Zyple SoftwareSAP implementation steps PDF - Zyple Software
SAP implementation steps PDF - Zyple Software
Zyple Software
 
Mumbai Girls Call Mumbai 🎈🔥9930687706 🔥💋🎈 Provide Best And Top Girl Service A...
Mumbai Girls Call Mumbai 🎈🔥9930687706 🔥💋🎈 Provide Best And Top Girl Service A...Mumbai Girls Call Mumbai 🎈🔥9930687706 🔥💋🎈 Provide Best And Top Girl Service A...
Mumbai Girls Call Mumbai 🎈🔥9930687706 🔥💋🎈 Provide Best And Top Girl Service A...
3610stuck
 

Recently uploaded (20)

GT degree offer diploma Transcript
GT degree offer diploma TranscriptGT degree offer diploma Transcript
GT degree offer diploma Transcript
 
Predicting Test Results without Execution (FSE 2024)
Predicting Test Results without Execution (FSE 2024)Predicting Test Results without Execution (FSE 2024)
Predicting Test Results without Execution (FSE 2024)
 
Odoo E-commerce website development guides
Odoo E-commerce website development guidesOdoo E-commerce website development guides
Odoo E-commerce website development guides
 
InflectraCON 360: Risk-Based Testing for Mission Critical Systems
InflectraCON 360: Risk-Based Testing for Mission Critical SystemsInflectraCON 360: Risk-Based Testing for Mission Critical Systems
InflectraCON 360: Risk-Based Testing for Mission Critical Systems
 
Mobile App Development Company in Noida - Drona Infotech.
Mobile App Development Company in Noida - Drona Infotech.Mobile App Development Company in Noida - Drona Infotech.
Mobile App Development Company in Noida - Drona Infotech.
 
To Avoid Mistakes When Using Online Attendance Sheets
To Avoid Mistakes When Using Online Attendance SheetsTo Avoid Mistakes When Using Online Attendance Sheets
To Avoid Mistakes When Using Online Attendance Sheets
 
Tour and travel website management in odoo,
Tour and travel website management in odoo,Tour and travel website management in odoo,
Tour and travel website management in odoo,
 
Independent Girls Call ServiCe Hyderabad 0000000000 Tanisha Best High Class H...
Independent Girls Call ServiCe Hyderabad 0000000000 Tanisha Best High Class H...Independent Girls Call ServiCe Hyderabad 0000000000 Tanisha Best High Class H...
Independent Girls Call ServiCe Hyderabad 0000000000 Tanisha Best High Class H...
 
Verified Girls Call Mumbai 👀 9820252231 👀 Cash Payment With Room DeliveryDeli...
Verified Girls Call Mumbai 👀 9820252231 👀 Cash Payment With Room DeliveryDeli...Verified Girls Call Mumbai 👀 9820252231 👀 Cash Payment With Room DeliveryDeli...
Verified Girls Call Mumbai 👀 9820252231 👀 Cash Payment With Room DeliveryDeli...
 
Comprehensive Vulnerability Assessments Process _ Aardwolf Security.docx
Comprehensive Vulnerability Assessments Process _ Aardwolf Security.docxComprehensive Vulnerability Assessments Process _ Aardwolf Security.docx
Comprehensive Vulnerability Assessments Process _ Aardwolf Security.docx
 
AI - Your Startup Sidekick (Leveraging AI to Bootstrap a Lean Startup).pdf
AI - Your Startup Sidekick (Leveraging AI to Bootstrap a Lean Startup).pdfAI - Your Startup Sidekick (Leveraging AI to Bootstrap a Lean Startup).pdf
AI - Your Startup Sidekick (Leveraging AI to Bootstrap a Lean Startup).pdf
 
Top Chinese Government-backed APT Groups
Top Chinese Government-backed APT GroupsTop Chinese Government-backed APT Groups
Top Chinese Government-backed APT Groups
 
Wired_2.0_Create_AmsterdamJUG_09072024.pptx
Wired_2.0_Create_AmsterdamJUG_09072024.pptxWired_2.0_Create_AmsterdamJUG_09072024.pptx
Wired_2.0_Create_AmsterdamJUG_09072024.pptx
 
VVIP Girls Call Mumbai 9910780858 Provide Best And Top Girl Service And No1 i...
VVIP Girls Call Mumbai 9910780858 Provide Best And Top Girl Service And No1 i...VVIP Girls Call Mumbai 9910780858 Provide Best And Top Girl Service And No1 i...
VVIP Girls Call Mumbai 9910780858 Provide Best And Top Girl Service And No1 i...
 
AWS DevOps-Tutorial CHANAKYA SRIYAN DUKKA.
AWS DevOps-Tutorial CHANAKYA SRIYAN DUKKA.AWS DevOps-Tutorial CHANAKYA SRIYAN DUKKA.
AWS DevOps-Tutorial CHANAKYA SRIYAN DUKKA.
 
Russian Girls Call Mumbai 🛵🚡9833363713 💃 Choose Best And Top Girl Service And...
Russian Girls Call Mumbai 🛵🚡9833363713 💃 Choose Best And Top Girl Service And...Russian Girls Call Mumbai 🛵🚡9833363713 💃 Choose Best And Top Girl Service And...
Russian Girls Call Mumbai 🛵🚡9833363713 💃 Choose Best And Top Girl Service And...
 
🚂🚘 Premium Girls Call Ranchi 🛵🚡000XX00000 💃 Choose Best And Top Girl Service...
🚂🚘 Premium Girls Call Ranchi  🛵🚡000XX00000 💃 Choose Best And Top Girl Service...🚂🚘 Premium Girls Call Ranchi  🛵🚡000XX00000 💃 Choose Best And Top Girl Service...
🚂🚘 Premium Girls Call Ranchi 🛵🚡000XX00000 💃 Choose Best And Top Girl Service...
 
Girls Call Jogeshwari 9967584737 Provide Best And Top Girl Service And No1 in...
Girls Call Jogeshwari 9967584737 Provide Best And Top Girl Service And No1 in...Girls Call Jogeshwari 9967584737 Provide Best And Top Girl Service And No1 in...
Girls Call Jogeshwari 9967584737 Provide Best And Top Girl Service And No1 in...
 
SAP implementation steps PDF - Zyple Software
SAP implementation steps PDF - Zyple SoftwareSAP implementation steps PDF - Zyple Software
SAP implementation steps PDF - Zyple Software
 
Mumbai Girls Call Mumbai 🎈🔥9930687706 🔥💋🎈 Provide Best And Top Girl Service A...
Mumbai Girls Call Mumbai 🎈🔥9930687706 🔥💋🎈 Provide Best And Top Girl Service A...Mumbai Girls Call Mumbai 🎈🔥9930687706 🔥💋🎈 Provide Best And Top Girl Service A...
Mumbai Girls Call Mumbai 🎈🔥9930687706 🔥💋🎈 Provide Best And Top Girl Service A...
 

REST easy with API Platform

  • 1. REST easy with API Platform Antonio Perić-Mažar, Locastic 12.04.2019., #DevConMu
  • 3. Antonio Perić-Mažar CEO @ Locastic Co-Founder @ Blockada antonio@locastic.com @antonioperic
  • 4. Locastic • We help clients create amazing web and mobile apps (since 2011) • mobile development • web development • UX/UI • Training and Consulting • Shift Conference, Symfony Croatia • www.locastic.com t: @locastic
  • 7. The web has changed • Javascript web apps are standard (SPA) • Users spend more time on using mobile devices than desktop or TV. • Linked Data and the semantic web are a reality
  • 9. APIs are the heart of this new web • Central point to access data (R/W data) • Encapsulate business logic • Same data and same features for desktops, mobiles, TVs and etc • It is stateless (PHP Sessions make horizontal scaling harder)
  • 10. Client Apps • HTML5 (SPA), mobile apps, TVs, Cars etc. • Holds all the presentation logic • Is downloaded first (SPA, shell model) • Queries the API to retrieve and modify data using asynchronous requests • Is 100% composed of HTML, JavaScript and assets (CSS and etc) • Can be hosted on a CDN
  • 12. Immediate benefits • Speed (even on mobile) • Scalability and robustness • Development comfort • Long term benefits
  • 14. HTTP + REST + JSON • Work everywhere • Lightweight • Stateless • HTTP has a powerful caching model • Extensible (JSON-LD, Hydra, Swagger, HAL…) • High quality tooling
  • 15. HATEOAS / Linked Data • Hypermedia as the Engine of Application State • Hypermedia: IRI as identifier • Ability to reference external data (like hypertext links) • Auto discoverable <=> Generic clients
  • 17. JSON-LD (JSON for Linked Data) • Standard: W3C recommandation (since 2014) • Machine readable data • Easy to use: looks like a typical JSON document • Already used by Gmail, GitHub, BBC, Microsoft, US gov… • Compliant with technologies of the semantic web: RDF, SPARQL, triple store… • Good for SEO
  • 18. Hydra • Describe REST APIs in JSON-LD • = write support • = auto-discoverable APIs • = standard for collections, paginations, errors, filters • Draft W3C (Work In Progress)
  • 19. { "@context": "/contexts/Book", "@id": "/books/2", "@type": "http://schema.org/Book", "id": 2, "isbn": "9790070863971", "description": "A long but very interesting story about REST and asyncio.", "author": "The life!", "title": "X", "publicationDate": "2002-01-29T00:00:00+00:00" }
  • 20. {  "@context": "contexts/Errors",  "@type": “hydra:Error”, “hydra:title”: “An error occurred”, “hydra:description”: “Not found” }
  • 21. { "@context": "/contexts/Book", "@id": "/books", "@type": "hydra:Collection", "hydra:member": [ { "@id": "/books/2", "@type": "http://schema.org/Book", "id": 2, "isbn": "9790070863971", "description": "A long but very interesting story about REST and asyncio.", "author": "The life!", "title": "X", "publicationDate": "2002-01-29T00:00:00+00:00" }, … { "@id": "/books/31", "@type": "http://schema.org/Book", "id": 31, "isbn": "9791943452827", "description": "Tempora voluptas ut dolorem voluptates. Provident natus ipsam fugiat est ipsam quia. Sint mollitia sed facere qui sit. Ad iusto molestias iusto autem laboriosam nulla earum eius.", "author": "Miss Gladyce Nader I", "title": "Voluptas doloremque esse dolor qui illo placeat harum voluptatem.", "publicationDate": "1970-10-11T00:00:00+00:00" } ], "hydra:totalItems": 125, "hydra:view": { "@id": "/books?page=1", "@type": "hydra:PartialCollectionView", "hydra:first": "/books?page=1", "hydra:last": "/books?page=5", "hydra:next": "/books?page=2" } }
  • 22. “API Platform is the most advanced API platform, in any framework or language.” Fabien Potencier, SymfonyCon 2017
  • 24. API Platform: the promise • Fully featured API supporting Swagger + JSON-LD + Hydra + HAL in minutes • An auto generated doc • Convenient API spec and test tools using Behat • Easy authentication management with JWT or OAuth • CORS and HTTP cache • All the tools you love: Doctrine ORM, Monolog, Swiftmailer...
  • 25. API Platform <3 Symfony • Built on top of Symfony full-stack • Install any existing SF bundles • Follow SF Best Practices • Use your Symfony skills • Can be used in your existing SF app • (Optional) tightly integrated with Doctrine
  • 26. Features • CRUD • Filters • Serializations groups and relations • Validation • Pagination • Sorting • The event system • Content Negation • Extensions • HTTP and reverse proxy caching • Invalidation-based HTTP caching • JS Admin apps • GraphQL support • And basically everything needed to build modern APIs
  • 27. How to start? • Download distribution and use Docker (includes frontend applications, etc) • https://github.com/api-platform/api-platform/releases/tag/v2.4.2 • Use Symfony Flex and any setup you want (little harder to setup) • Enjoy!!!
  • 28. CRUD <?php namespace AppEntity; class Author { private $id; private $firstName; private $lastName; // ... } # api/config/packages/api_platform/ author.yaml resources: AppEntityAuthor:~
  • 34. {   "@context": "http://schema.org",   "@type": "FlightReservation",   "reservationNumber": "RXJ34P",   "reservationStatus": "http://schema.org/Confirmed",   "underName": {     "@type": "Person",     "name": "Eva Green"   },   "reservationFor": {     "@type": "Flight",     "flightNumber": "110",     "airline": {       "@type": "Airline",       "name": "United",       "iataCode": "UA"     },     "departureAirport": {       "@type": "Airport",       "name": "San Francisco Airport",       "iataCode": "SFO"     },     "departureTime": "2017-03-04T20:15:00-08:00",     "arrivalAirport": {       "@type": "Airport",       "name": "John F. Kennedy International Airport",       "iataCode": "JFK"     },     "arrivalTime": "2017-03-05T06:30:00-05:00"   } }
  • 35. Using schema.org in Api Platform resources: AppEntityFlightReservation: iri: 'http://schema.org/FlightReservation'
  • 36. Using schema.org in Api Platform resources: AppEntityFlightReservation: iri: 'http://schema.org/FlightReservation' properties: status: iri: 'http://schema.org/reservationStatus'
  • 37. Operations • API Platform Core relies on the concept of operations. Operations can be applied to a resource exposed by the API. From an implementation point of view, an operation is a link between a resource, a route and its related controller. • There are two types of operations: • Collection operations act on a collection of resources. By default two routes are implemented: POST and GET. • Item operations act on an individual resource. 3 default routes are defined GET, PUT and DELETE.
  • 39. Custom operation class Match { private $id; /** * @Groups({"match_read"}) */ private $datetime; /** * @Groups({"match_read", "match_write"}) */ private $playerOnePoints; /** * @Groups({"match_read", "match_write"}) */ private $playerTwoPoints; /** * @Groups({"match_read", "match_write"}) */ private $playerOne; /** * @Groups({"match_read", "match_write"}) */ private $playerTwo; /** * @Groups({"match_read"}) */ private $winner; /** * @Groups({"match_read"}) */ private $result; }
  • 40. Custom operationclass Match { private $id; /** * @Groups({"match_read"}) */ private $datetime; /** * @Groups({"match_read", "match_write"}) */ private $playerOnePoints; /** * @Groups({"match_read", "match_write"}) */ private $playerTwoPoints; /** * @Groups({"match_read", "match_write"}) */ private $playerOne; /** * @Groups({"match_read", "match_write"}) */ private $playerTwo; /** * @Groups({"match_read"}) */ private $winner; /** * @Groups({"match_read"}) */ private $result; } class MatchController extends Controller { /** * @param Match $data * * @return Match */ public function getMatchAction($data) { $result = $data->getPlayerOne() . ' ' . $data->getPlayerOnePoints().':' .$data->getPlayerTwoPoints() . ' ' . $data->getPlayerTwo(); $data->setResult($result); return $data; } }
  • 41. Custom operation class Match { private $id; /** * @Groups({"match_read"}) */ private $datetime; /** * @Groups({"match_read", "match_write"}) */ private $playerOnePoints; /** * @Groups({"match_read", "match_write"}) */ private $playerTwoPoints; /** * @Groups({"match_read", "match_write"}) */ private $playerOne; /** * @Groups({"match_read", "match_write"}) */ private $playerTwo; /** * @Groups({"match_read"}) */ private $winner; /** * @Groups({"match_read"}) */ private $result; } class MatchController extends Controller { /** * @param Match $data * * @return Match */ public function getMatchAction($data) { $result = $data->getPlayerOne() . ' ' . $data->getPlayerOnePoints().':' .$data->getPlayerTwoPoints() . ' ' . $data->getPlayerTwo(); $data->setResult($result); return $data; } } # app/config/routing.yml get_match: path: /api/v1/matches/{id}.{_format} methods: ['GET'] defaults: _controller: AppBundle:Match:getMatch _api_resource_class: AppBundleEntityMatch _api_item_operation_name: get
  • 44. Filters • If Doctrine ORM support is enabled, adding filters is as easy as registering a filter service in your api/config/services.yml file and adding an attribute to your resource configuration. • Filters add extra conditions to base database query • Useful filters for the Doctrine ORM are provided with the library. You can also create custom filters that would fit your specific needs.
  • 45. Filters • Search filter (partial, start, end, exact, ipartial, iexact) • Date filter (?property[<after|before>]=value ) • Boolean filter (?property=[true|false|1|0]) • Numeric filter (?property=int|bigint|decimal) • Range filter (?property[lt]|[gt]|[lte]|[gte]|[between]=value) • Order filter (?order[property]=<asc|desc>) • … • Custom filters
  • 46. Filters examples # AppBundle/Resources/config/api_resources/resources.yml resources: AppBundleEntityPlayer: # ... attributes: filters: ['player.search', 'player.order'] AppBundleEntityMatch: # ... attributes: filters: ['match.date'] services: player.search_filter: parent: 'api_platform.doctrine.orm.search_filter' arguments: [ { id: 'exact', email: 'exact', firstName: 'partial' } ] tags: [ { name: 'api_platform.filter', id: 'player.search' } ] match.date_filter: parent: 'api_platform.doctrine.orm.date_filter' arguments: [ { datetime: ~ } ] tags: [ { name: 'api_platform.filter', id: 'match.date' } ] player.order_filter: parent: 'api_platform.doctrine.orm.order_filter' arguments: [{ firstName: 'ASC', lastName: 'ACS', email: ~ }] tags: [{ name: 'api_platform.filter', id: 'player.order' }]
  • 47. Serialization Groups • API Platform Core allows to choose which attributes of the resource are exposed during the normalization (read) and denormalization (write) process. It relies on the serialization (and deserialization) groups feature of the Symfony Serializer component. • allows to specify the definition of serialization using XML, YAML, or annotations.
  • 49. <?php namespace AppEntity; use FOSUserBundleModelUser as BaseUser; use SymfonyComponentSerializerAnnotationGroups; class Player extends BaseUser { /** * @var int */ protected $id; /** * @Groups({"player_read", "player_write"}) */ private $firstName; /** * @Groups({"player_read", "player_write"}) */ private $lastName; /** * @Groups({"player_read", "player_write"}) */ protected $email; // ... } # UserBundle/Resources/api_resources/resources.yml resources: AppEntityPlayer: attributes: normalization_context: groups: ['player_read'] denormalization_context: groups: ['player_write']
  • 50. Using Different Serialization Groups per Operation # UserBundle/Resources/api_resources/resources.yml resources: AppEntityPlayer: itemOperations: get: method: 'GET' normalization_context: groups: ['player_read', 'player_extra'] put: method: 'PUT' delete: method: 'DELETE' attributes: normalization_context: groups: ['player_read'] denormalization_context: groups: ['player_write']
  • 52. // src/AppBundle/EventSubscriber/MatchEventSubscriber.php class MatchEventSubscriber implements EventSubscriberInterface { private $matchHelper; public function __construct(MatchHelper $matchHelper) { $this->matchHelper = $matchHelper; } public static function getSubscribedEvents() { return [ KernelEvents::VIEW => [['addWinner', EventPriorities::POST_VALIDATE]], ]; } public function addWinner(GetResponseForControllerResultEvent $event) { $match = $event->getControllerResult(); $method = $event->getRequest()->getMethod(); if(!$match instanceof Match || $method !== 'POST') { return; } $winner = $this->matchHelper->getWinner($match); $match->setWinner($winner); } }
  • 53. Extensions • API Platform Core provides a system to extend queries on items and collections. • Custom extensions must implement the ApiPlatformCoreBridgeDoctrineOrmExtensionQuery CollectionExtensionInterface and / or the ApiPlatformCoreBridgeDoctrineOrmExtensionQuery ItemExtensionInterface interfaces, to be run when querying for a collection of items and when querying for an item respectively.
  • 54. class GetPlayersExtension implements QueryCollectionExtensionInterface, QueryItemExtensionInterface { public function applyToItem( QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, array $identifiers, string $operationName = null, array $context = [] ) { $this->addWhere($queryBuilder, $resourceClass, $operationName); } public function applyToCollection( QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null ) { $this->addWhere($queryBuilder, $resourceClass, $operationName); } private function addWhere(QueryBuilder $queryBuilder, string $resourceClass, string $operationName = null) { if ($resourceClass != Player::class || $operationName != 'get') { return; } $rootAlias = $queryBuilder->getRootAliases()[0]; $queryBuilder->andWhere( $queryBuilder->expr()->eq($rootAlias.'.enabled', ':enabled') )->setParameter('enabled', true); } }
  • 55. services: app.extension.get_players: class: AppBundleDoctrineORMExtensionGetPlayersExtension public: false tags: - { name: api_platform.doctrine.orm.query_extension.collection, priority: 9 } - { name: api_platform.doctrine.orm.query_extension.item }
  • 56. Per Resource Authorization Mechanism namespace AppBundleEntity;   use ApiPlatformCoreAnnotationApiResource; use DoctrineORMMapping as ORM;   /** * @ApiResource( *     attributes={"is_granted"="has_role('ROLE_ADMIN')"}, *     itemOperations={ *         "get"={"method"="GET", "is_granted"="object.getOwner() == user"} *     } * ) * @ORMEntity */ class Secured {     /**      * @ORMColumn(type="integer")      * @ORMId      * @ORMGeneratedValue(strategy="AUTO")      */     public $id;       /**      * @ORMColumn(type="text")      */     public $owner;
  • 58. Translation Support • https://github.com/Locastic/ApiPlatformTranslationBundle • https://locastic.com/blog/having-troubles-with-implementing-translations-in- apiplatform/
  • 60. GraphQL Support • docker-compose exec php composer req webonyx/graphql-php && docker- compose exec php bin/console cache:clear • The GraphQL implementation supports queries, mutations, 100% of the Relay server specification, pagination, filters and access control rules. You can use it with the popular RelayJS and Apollo clients.
  • 62. Testing • PHPUnit • Postman (newman) • Panther • https://locastic.com/blog/what-to-do-when-you-get-lost-in-api-testing/
  • 64. Mercure • Fast, written in Go • native browser support, no lib nor SDK required (built on top of HTTP and server-sent events) • compatible with all existing servers, even those who don't support persistent connections (serverless architecture, PHP, FastCGI...) • Automatic HTTP/2 and HTTPS (using Let's Encrypt) support • CORS support, CSRF protection mechanism • Cloud Native, follows the Twelve-Factor App methodology • Open source (AGPL) • …
  • 66. Update progressive web app • docker-compose exec client generate-api-platform-client • Follow instructions
  • 67. Version 2.4 • read and write support for MongoDB, the reference document database, including a lot of useful filters • Read support for Elasticsearch, the open source search and analytics engine, including filters for advanced search • Automatic “push” of updated resources from the server to the clients using the brand new Mercure protocol
  • 68. Version 2.4 • Integration with the Symfony Messenger component to easily implement the CQRS pattern and to handle messages asynchronously (using brokers such as RabbitMQ, Apache Kafka, Amazon SQS or Google PubSub) • Ability to leverage the “Server Push” feature of HTTP/2 to preemptively send the relations of a requested resource to the client • Automatic availability of list filters in the React-based admin when a corresponding one is available API-side • Full compatibility with the version 3 of the OpenAPI specification format (formerly known as Swagger), and integration of the beautiful ReDoc documentation generator
  • 69. Version 2.4 • Improved DTOs support • Per resource configuration of HTTP cache headers • Ability to easily use the Sunset HTTP header to advertise the removal date of deprecated endpoints
  • 71. GFNY Ticketing system • 20 races, 18 countries • Different timezones, currencies, languages… • More then 60 000 tickets per year, with very complex login • Standings and rankings • Email notification, flexibility • Etc.
  • 72. Conclusion • Very powerful, even for large applications • Easy to start, well documented • Active community and company behind it • Write tests!