Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.

Symfony und Ember.js auf einer Seite #codetalks14

2.355 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
  • Als Erste(r) kommentieren

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 ?

×