Symfony und Ember.js
auf einer Seite
Paul Seiffert

SensioLabs Deutschland GmbH
Klassische Webseiten
B R O W S E R
GET /
URL-Eingabe
HTML
Webseite
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 /
Business

Logik
S Y M F O N Y
Klassische S...
Moderne Webseiten
Moderne Webseiten
View-Wechsel
B R O W S E R
GET /
URL-Eingabe
HTML
Webseite
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 Webseiten
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
GET

/api/users
JSON
S E R ...
Paul

Seiffert
paul.seiffert@gmail.com
Symfony und Ember.js
auf einer Seite
Paul Seiffert

SensioLabs 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 R
HTTP + 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}

method...
#http://example.com blog/first-article/
var Router = Ember.Router.extend({

location: 'history'

});

Router.map(function() {

this.resource('blog', { path: '/' }...
server {
listen *:80;
server_name blog;
location / {
root /opt/blog/dist;
try_files $uri /index.html;
index index.html;
}
...
/api
location / {
root /opt/blog/dist;
try_files $uri /index.html;
index index.html;
}
/
/api/posts
/app.php/posts
/app.php/api...
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.hasMan...
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": ...
/first-post
Router.map(function() {

this.resource('blog', { path: '/' }, function () {

this.route('post', { path: '/:slu...
ro u t e r. j s
var BlogPostRoute = Ember.Route.extend({

model: function (params) {

return this.store.find('post', { slu...
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('p...
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 RY
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/sei...
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 class="blog-post">

<h1>{{#link-to 'blog.post' slug}}{{title}}{{/link-to}}</h1>

<div class="blog-post-content">

{{b...
var Post = DS.Model.extend({

title: DS.attr(),

body: DS.attr(),

date: DS.attr(),

slug: DS.attr(),

comments: DS.hasMan...
<div class="blog-post">

<h1>{{#link-to 'blog.post' slug}}{{title}}{{/link-to}}</h1>

<div class="blog-post-content">

{{b...
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 35...
B R O W S E R
HTTP + 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...
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 ?
Symfony und Ember.js auf einer Seite #codetalks14
Symfony und Ember.js auf einer Seite #codetalks14
Symfony und Ember.js auf einer Seite #codetalks14
Symfony und Ember.js auf einer Seite #codetalks14
Symfony und Ember.js auf einer Seite #codetalks14
Symfony und Ember.js auf einer Seite #codetalks14
Symfony und Ember.js auf einer Seite #codetalks14
Nächste SlideShare
Wird geladen in …5
×

Symfony und Ember.js auf einer Seite #codetalks14

2.205 Aufrufe

Veröffentlicht am

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.

Veröffentlicht in: Software
0 Kommentare
2 Gefällt mir
Statistik
Notizen
  • Als Erste(r) kommentieren

Keine Downloads
Aufrufe
Aufrufe insgesamt
2.205
Auf SlideShare
0
Aus Einbettungen
0
Anzahl an Einbettungen
31
Aktionen
Geteilt
0
Downloads
9
Kommentare
0
Gefällt mir
2
Einbettungen 0
Keine Einbettungen

Keine Notizen für die Folie

Symfony und Ember.js auf einer Seite #codetalks14

  1. 1. Symfony und Ember.js auf einer Seite Paul Seiffert
 SensioLabs Deutschland GmbH
  2. 2. Klassische Webseiten
  3. 3. B R O W S E R GET / URL-Eingabe HTML Webseite Link-Klick Neue
 Webseite … GET /blog HTML S E R V E R Klassische Webseiten
  4. 4. 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 / Business
 Logik S Y M F O N Y Klassische Symfony-Seiten
  5. 5. Moderne Webseiten
  6. 6. Moderne Webseiten View-Wechsel B R O W S E R GET / URL-Eingabe HTML Webseite Link-Klick Neue
 Webseite … S E R V E R
  7. 7. 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
  8. 8. B R O W S E R Moderne Webseiten 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 GET
 /api/users JSON S E R V E R
  9. 9. Paul
 Seiffert paul.seiffert@gmail.com
  10. 10. Symfony und Ember.js auf einer Seite Paul Seiffert
 SensioLabs Deutschland GmbH
  11. 11. – 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.”
  12. 12. B R O W S E R HTTP + Socket GET /api/… Lokal VM S Y M F O N Y A P P
  13. 13. 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
  14. 14. R O U T I N G
  15. 15. Wohin möchte der Benutzer?
  16. 16. posts:
 pattern: /
 methods: GET
 defaults: { _controller: BlogBundle:Post:index }
 
 post:
 pattern: /blog/{slug}
 methods: GET
 defaults: { _controller: BlogBundle:Post:detail } Symfony Routing
  17. 17. #http://example.com blog/first-article/
  18. 18. 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
  19. 19. server { listen *:80; server_name blog; location / { root /opt/blog/dist; try_files $uri /index.html; index index.html; } } Konfiguration
  20. 20. /api
  21. 21. 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; }
  22. 22. M O D E L
  23. 23. ember data
  24. 24. 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
  25. 25. 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
  26. 26. store.find('post', { slug: ‘awesome-blog-article‘}) GET /post?slug=awesome-blog-article
  27. 27. {
 "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
  28. 28. /first-post Router.map(function() {
 this.resource('blog', { path: '/' }, function () {
 this.route('post', { path: '/:slug' });
 }); }); ro u t e r. j s
  29. 29. 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' });
 }); });
  30. 30. 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
  31. 31. 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 RY D ATA B A S E
  32. 32. 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
  33. 33. ember data
  34. 34. T E M P L AT I N G
  35. 35. <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
  36. 36. <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
  37. 37. 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
  38. 38. <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
  39. 39. T O O L S
  40. 40. $ 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
  41. 41. B R O W S E R HTTP + 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 Vagrant
 VM
  42. 42. 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 /
  43. 43. https://github.com/
 seiffert/ember-symfony-blog
  44. 44. D A N K E !
  45. 45. F R A G E N ?

×