Symfony und Ember.js auf einer Seite #codetalks14

Post on 27-Nov-2014

239 views 1 download

description

Internetnutzer sind es heutzutage gewohnt, dass Webseiten unmittelbar auf Interaktion reagieren und ohne häufiges Nachladen funktionieren. Techniken, die solche Webseiten ermöglichen, sollten durch die Zuhilfenahme zuverlässiger Frameworks umgesetzt werden. Serverseitig ist für viele Entwickler Symfony das Mittel der Wahl, im Browser kann es Ember.js sein, das vor allem im Bereich der Single-Page-Applikationen glänzt. Mit beiden zusammen kann also nichts mehr schief gehen, oder? Dieser Vortrag zeigt Symfony und Ember.js in Kombination und wie man umdenken muss, wenn man gewohnt ist, klassische Webseiten zu entwickeln. Speziell geht er auf die dabei auftretenden Herausforderungen im Templating, Routing und bei der Model-Synchronisierung ein.

transcript

Symfony und Ember.js auf einer Seite

Paul SeiffertSensioLabs Deutschland GmbH

Klassische Webseiten

B R O W S E R

GET /

URL-Eingabe

HTMLWebseite

Link-Klick

Neue Webseite

GET /blog

HTML

S E R V E R

Klassische Webseiten

HTML

R O U T I N G

C O N T R O L L E R

S E C U R I T Y

T E M P L AT I N G

GET /

BusinessLogikS Y M F O N Y

Klassische Symfony-Seiten

Moderne Webseiten

Moderne Webseiten

View-Wechsel

B R O W S E R

GET /

URL-Eingabe

HTMLWebseite

Link-Klick

Neue Webseite

… S E R V E R

Moderne Webseiten

B R O W S E R

R O U T I N G

T E M P L AT I N G

C O N T R O L L E R

M O D E L

B R O W S E R

Moderne WebseitenR O U T I N G

T E M P L AT I N G

C O N T R O L L E R

M O D E L

GET /api/users

JSON

S E R V E R

PaulSeiffert

paul.seiffert@gmail.com

Symfony und Ember.js auf einer Seite

Paul SeiffertSensioLabs Deutschland GmbH

– FA B I E N P O T E N C I E R

“Symfony2 is an HTTP framework;it is a Request/Response framework.”

B R O W S E RHTTP + Socket

GET /api/…Lokal

VM

S Y M F O N Y A P P

B R O W S E R

GET /api/…Lokal

Server

S Y M F O N Y A P P

W E B S E R V E R

GET /

D AT E I S Y S T E M

R O U T I N G

Wohin möchte der Benutzer?

posts: pattern: / methods: GET defaults: { _controller: BlogBundle:Post:index }post: pattern: /blog/{slug} methods: GET defaults: { _controller: BlogBundle:Post:detail }

Symfony Routing

#http://example.com blog/first-article/

var Router = Ember.Router.extend({ location: 'history'}); Router.map(function() { this.resource('blog', { path: '/' }, function () { this.route('post', { path: '/:slug' }); }); this.route('about'); });

PushState FTW!!Ember.js Routing

server { listen *:80;

server_name blog;

location / { root /opt/blog/dist; try_files $uri /index.html; index index.html; } }

Konfiguration

/api

location / { root /opt/blog/dist; try_files $uri /index.html; index index.html; }

/

/api/posts ⇒

/app.php/posts

/app.php/api

location ~ ^/api { root /opt/blog/web; try_files $uri @rewriteapp; index app.php; }

location @rewriteapp { rewrite ^/api/(.*)$ /app.php/$1 last; }

location ~ ^/(app|app_dev)\.php(/|$) { root /opt/blog/api/web; fastcgi_split_path_info /(.+\.php)(/.*)$; include /etc/nginx/fastcgi_params; fastcgi_pass 127.0.0.1:9001; }

M O D E L

ember data

var Post = DS.Model.extend({ title: DS.attr(), body: DS.attr(), date: DS.attr(), slug: DS.attr(), comments: DS.hasMany('comment', { async: true }), teaser: function () { return this.get('body').substr(0, 100); }.property('body') });

m o d e l s / p o s t . j s

S T O R E

A D A P T E R

J S A P P L I K AT I O N

R E S T F U L A P I

store.find('post', { slug: ‘awesome-blog-article‘})

GET /post?slug=awesome-blog-article

{ "post": [ { "id": 1, "title": “Mein erster Blog Post", "body": “Das der Inhalt meines ersten Blog-Posts“, "date": "2014-10-04T14:23:10+0200", "slug": "first-post", "links": { "comments": "/app_dev.php/api/posts/first-post/comments" } } ]}

GET /post?slug=awesome-blog-article

/first-post

Router.map(function() { this.resource('blog', { path: '/' }, function () { this.route('post', { path: '/:slug' }); }); });

ro u t e r. j s

ro u t e r. j s

var BlogPostRoute = Ember.Route.extend({ model: function (params) { return this.store.find('post', { slug: params.slug }); }, serialize: function(model) { return { slug: model.get('slug') }; } });

ro u t e s / b l o g / p o s t . j s

Router.map(function() { this.resource('blog', { path: '/' }, function () { this.route('post', { path: '/:slug' }); }); });

DS.RESTAdapter.extend({ namespace: ‘app_dev.php/api’ });

a d a p t e r s / a p p l i c a t i o n . j s

this.store.find('post')GET /app_dev.php/api/posts

this.store.find(‘post’, { slug: ‘first-post’ })GET /app_dev.php/api/posts?slug=first-post

this.store.find(‘post’, 1)GET /app_dev.php/api/posts/1

R E S T F U L A P I

C O N T R O L L E R

R E P O S I T O R Y

D ATA B A S E

R E S T F U L A P I

jms/serializer

willdurand/negotiation

symfony/symfony

willdurand/hateoas

⇒ http://www.slideshare.net/seiffertp

composer require

ember data

T E M P L AT I N G

<div class="container"> {{render 'navigation'}} <div class="container-fluid" id="content"> {{outlet}} </div></div>

a p p l i c a t i o n . h b s

<div class="blog-post"> <h1>{{#link-to 'blog.post' slug}}{{title}}{{/link-to}}</h1> <div class="blog-post-content"> {{body}} </div> <div class="blog-post-comments"> {{#each comments}} {{partial 'blog/comment'}} {{/each}} </div></div>{{#link-to 'blog.index'}}Zurück zur Liste{{/link-to}}

b l o g / p o s t . h b s

var Post = DS.Model.extend({ title: DS.attr(), body: DS.attr(), date: DS.attr(), slug: DS.attr(), comments: DS.hasMany('comment', { async: true }), teaser: function () { return this.get('body').substr(0, 100); }.property('body') });

m o d e l s / p o s t . j s

<div class="blog-post"> <h1>{{#link-to 'blog.post' slug}}{{title}}{{/link-to}}</h1> <div class="blog-post-content"> {{body}} </div> <div class="blog-post-comments"> {{#each comments}} {{partial 'blog/comment'}} {{/each}} </div></div>{{#link-to 'blog.index'}}Zurück zur Liste{{/link-to}}

b l o g / p o s t . h b s

T O O L S

$ ember serve —-proxy=http://symfony-api:80 version: 0.0.43 Proxying to http://symfony-api:80 Livereload server on port 35729 Serving on http://0.0.0.0:4200

$ npm install -g ember-cli

B R O W S E RHTTP + Socket

N G I N X

S Y M F O N Y A P P

GET /app_dev.php/api/…

P H P - F P M

D e v e l o p m e n t

Lokal

VagrantVM

B R O W S E R

N G I N X

S Y M F O N Y A P P

GET /api/…

P H P - F P M

P ro d u c t i o n

GET /

https://github.com/ seiffert/ember-symfony-blog

D A N K E !

F R A G E N ?