In the Google Summer of Code Project "TYPO3 Flow meets Ember.js" we are trying to make the server-side framework TYPO3 Flow and the client-side framework Ember.js (using Ember Data as the persistence layer) work together easily through conventions and a powerful scaffolding mechanism. You can visit our website to see a more detailed concept.
This document gives a short introduction of:
- how domain models look like in Flow and Ember Data,
- how the REST JSON API is expected to look like (to follow Ember Data conventions),
- for which models REST APIs are provided and how.
The following diagram gives an overview of what components a Ember/Flow app would consist of. Components that are generated (scaffolded) are illustrated with a green background. Components that are provided through our Flow package or are part of ember-data are illustrated with a blue background.
Let's consider we have a (simplified) model called post (of a blog) that would looks like this on the server-side:
<?php
namespace TYPO3\Blog\Domain\Model;
use Doctrine\ORM\Mapping as ORM;
use TYPO3\Flow\Annotations as Flow;
use MMitasch\Ember\Annotations as Ember;
/**
* A blog post
*
* @Flow\Entity
* @Ember\Resource
*/
class Post {
/**
* @var string
* @Flow\Validate(type="NotEmpty")
*/
protected $title;
/**
* @var string
* @Flow\Validate(type="NotEmpty")
*/
protected $content;
// getter and setter for each property omitted for simplification purposes
}
?>
We will then generate the Ember Data model from the server-side semantics through our scaffolding mechanism. That would look like this:
App.Post = DS.Model.extend({
title: DS.attr('string'),
content: DS.attr('string')
});
The Ember RESTAdapter assumes that the URLs and JSON associated with each model are conventional; this means that, if you follow the rules, you will not need to configure the adapter or write any code in order to get started.
We want to provide a REST JSON API that complies to the Ember RESTAdapter conventions.
The Ember RESTAdapter would expect the server-side API to look like this:
Action | HTTP Verb | URL |
---|---|---|
Find | GET | /posts/123 |
Find All | GET | /posts |
Update | PUT | /posts/123 |
Create | POST | /posts |
Delete | DELETE | /posts/123 |
The payload for a GET request /posts/123 would look like this:
{
"post": {
"title": "Is a Automagical controller cool?",
"content": "Need to write some proper blog post content here!"
}
}
There are two ways how we can define that we want to offer an endpoint for a certain model:
- Annotation in a Flow Domain Model
- Configuration in Ember.yaml
You might have noticed that in the comment before the php class definition, there was an Annotation added:
@Ember\Resource
If a model has this added annotation, we will create an REST API for this model.
Additional to annotations we will provide a possibility to configure it inside a yaml-file. This is necessary as sometimes it might not be possible (eg. third party package) or wanted to add the annotation to the Flow domain model.