文档章节

laravel (5.1) & Ember.js (1.13.0) 的整合

Lee的白板报
 Lee的白板报
发布于 2015/08/15 16:21
字数 2092
阅读 242
收藏 5

Lavavel 不必过多介绍了, 作为全世界最流行的PHP框架,有着清晰的架构、完善的文档、丰富的工具等等,能够帮助开发者快速构建多页面web应用程序。

然而,随着技术的发展,web程序的另一面——客户端,正在变得越来越多元(PC,手机,平板,其他专用设备等)。所以需要一种统一的机制,方便服务器与不同的设备进行通信。Restful API 就是基于这个思想被提出来的。

阮一峰给出了对Restful架构的总结:

  1. 每一个URI代表一种资源;

  2. 客户端和服务器之间,传递这种资源的某种表现层;

  3. 客户端通过四个HTTP动词,对服务器端资源进行操作,实现"表现层状态转化"。

从行为上讲,就是服务器在约定好一套资源交互规则之后,依据该规则,通过统一的API接口与不同的前端设备进行交互。服务器只需要专注于数据的存储与分析,或曰业务逻辑的实现。在不同客户端上,其表现逻辑和交互逻辑与服务器端的业务逻辑实现了双重分离——逻辑分离与物理分离。

如果前后端只有资源(数据)的交互,那么页面路由自然当交给前端控制,相当于前端在首次加载页面后就不再进行全页面的刷新,所有的数据通过ajax从后端随取随用,所有的表单提交也是同样方法,这就是一个单页面应用(Single Page Application, SPA)。

Ember.js是一个模块化的前端框架,基于MVC理念,它提供了UI绑定、模板系统、路由系统等功能,非常适合SPA的快速开发。特别是Ember还提供了一个完整的命令行开发包——Ember Cli,不仅省去了繁琐的开发环境配置,还提供了丰富的开发与构建工具,例如,你立即就可以用CoffeeScript甚至ES6进行开发,相应的解释器已经随开发包安装妥当,在启动 ember server 的情况下,你也不必每次改动都在命令行键入 ember build,系统自动识别文本改动并进行解释与合并,将编译好的文件放在 dist/ 目录下。

然而,当我把 Laravel 和 Ember.js 分别配置妥当之后,发现我并不能马上撸起袖子写代码,因为他们并不是为彼此而生的。例如,此时我就面临着两个问题:

  1. Laravel 与 Ember.js 有各自的路由系统,如何让 laravel 出让自己对 URL 的控制?

  2. 用户授权通常是由服务器管理和维护的,Laravel 提供完整的 authentication 方案,但在SPA 中后端不得不出让一部分权限控制给前端(主要是页面访问权限和为ajax授权),解决这个问题的最佳实践是怎样的?

我相信之前已经有很多人遇到类似问题,该问题可能有通用的原则指导,但在操作层面与具体的框架相关,限于篇幅,本文讨论第一个问题。第二的问题另作回答。




定义API接口

在laravel中,laravel/app/Http/routes.php 文件是所有 URL 的入口,所有的 URL 和相应的处理函数都应当在这里定义。

// laravel/app/Http/routes.php

Route::group( array( 'prefix' => 'api/v1' ), function()
{

    // USERS API ==================================

    Route::get('users/{id}', 'UserController@getById');
    Route::delete('users/{id}', 'UserController@destroyById');
    Route::put('users/{id}', 'UserController@updateById');
    Route::post('users', 'UserController@storeNew');


    // OTHER API ==================================

    // ......

});

我将所有API放入一个路由组,这个组约定API请求必须以 api /【版本号】作为前缀,例如需要服务器返回 id=5 的用户信息,应当向如下地址发出 GET 请求:

    http://your_demain/api/v1/users/5    

服务器收到该请求后将 request 对象传递给 UserController 的 getById 成员方法做处理。

我还在该文件中定义了用户授权的相关接口,并将它们分在一组:

// laravel/app/Http/routes.php

Route::group( array ( 'prefix' => 'auth' ), function()
{
    Route::post('login', 'Auth\AuthController@postLogin');
    Route::get('logout', 'Auth\AuthController@getLogout');
    Route::post('register', 'Auth\AuthController@postRegister');
});

三个接口分别提供登录、登出和注册功能。

好了,laravel 的路由只需要做这么多事情。


将其他URL的控制权交给前端

Ember页面启动时以 ember/dist/index.html 文件作为入口,dist 目录存放着所有构建好的文件,均为系统自动生成。在 index.html 文件中,从ember/dist/assets 目录加载了2个脚本文件和2个样式文件:

<!-- ember/dist/index.html -->

<!DOCTYPE html>
<html>
  <head>
    
    <!-- 其他head标签 -->

    <link rel="stylesheet" href="assets/vendor.css">
    <link rel="stylesheet" href="assets/ember-app.css">
    
  </head>
  <body>
    
    <script src="assets/vendor.js"></script>
    <script src="assets/ember-app.js"></script>
    
  </body>
</html>

这4个文件包含了所有前端的逻辑和样式。而 laravel 以 laravel/public 作为项目根目录,该目录下保存了由 laravel 构建好的前端资源。所以我的处理方式如下:

  1. 同步 ember/dist/assets 与 laravel/public/assets 两个目录,后者是前者的镜像

  2. 在 laravel/resources/views 定义一个 view 命名为 app.php,它的内容是 ember/dist/index.html 的拷贝

  3. laravel 拿到除 API 与 AUTH 之外的请求(之后统称非API请求),均返回 app.php

在正常使用时,前端只在首次加载时发出非API请求,一旦拿到 app.php 前端就获得了对应用表现层的控制,只要不刷新页面,之后用户与应用的所有交互都将由前端捕捉与控制。

具体操作如下:

由于我在 windows 下做开发,系统不提供直接同步两个本地目录的工具, 而且也没有找到实时自动同步的第三方桌面应用,最后选择了名为 InSync 的一款软件,每次同步都需要手动点击一下,是一个潜在的效率瓶颈。

在 laravel/resources/views 目录下创建 app.php 文件, 将 ember/dist/index.html 的内容拷贝过来。

在 laravel/app/Http/routes.php 中创建一个新的路由分组:

// laravel/app/Http/routes.php

Route::get('{data?}', function()
{
    return View::make('app');
})->where('data', '.*');

该分组捕捉所有非API请求并返回 app.php。


前端具体实现

在Ember中,每个路由都有与之相关联的一个模型(Model)。Model 负责数据的查询、更改和将更改保存回服务器,这一过程是通过模型适配器(Adapter)完成的。所以需要修改适配器让它匹配后端所定义的 API 前缀约定:

// ember/app/adapters/application.js

export default DS.RESTAdapter.extend({
    namespace: 'api/v1'
});

然后就可以在 ember/app/routers.js 中定义前端路由了:

// ember/app/routers.js

Router.map(function() {

    this.route('user', { path: '/user/:user_id' });

    // Other routes ...

});

这里有个不得不提的问题:

Ember 中每一个 Model 可以视为一种资源,而 Model 已经定义好了与这种资源的各种交互行为。例如当我定义好 userModel 之后,我要向服务器查询一条 user 记录可以使用如下代码,注释给出了它的网络请求(省略了前缀):

this.store.find('user', 5);    // => GET '/users/5'

新建一个用户:

var user = this.store.createRecord('user', {  
    email: '123@123.com',  
    password: '123'
});

user.save();  // => POST to '/users'

这一默认行为是不可配置的,所以后端提供的 API 必须配合该规则进行构建,这也是使用大型框架所带来的灵活性的的缺失。在需要大量定制化功能的应用中,轻量级的前端框架例如 backbone 更具有竞争力。

Ember意识到了这个问题,在最新的2.0版本中,可以通过自定义服务(Service)来解决。


总结

至此,确定了页面加载方案,打通了前后端的数据交互通道,前后端由各自为政变成了相互协作、各司其职,应用终于“活”了起来。


© 著作权归作者所有

共有 人打赏支持
Lee的白板报
粉丝 93
博文 31
码字总数 45338
作品 0
高级程序员
私信 提问
加载中

评论(1)

bochs
bochs
可尝试完全将 laravel 和 ember前端 分离,并不一定要将 ember前端 集成到 laravel 中。这样即将 laravel 完全作为服务端,
而将前端视作 APP端 一样了,前端与服务端完全经由 API 通信。
基于 Laravel (5.1) & Ember.js (1.13.0) 的用户授权系统

Laravel 本身提供了完整的用户授权解决方案,对于由 PHP 驱动的多页面应用,Laravel 能够完美解决用户授权问题。但是在 SPA 中,laravel 退化成一个 API server,页面路由和表单提交完全由前...

Lee的白板报
2015/08/16
0
0
Ember.js 1.13.0/2.0 Beta 发布

Ember是一个雄心勃勃的Web应用程序,消除了样板,并提供了一个标准的应用程序架构的JavaScript框架。 Ember.js 1.13.0 和 Ember.js 2.0 Beta 发布。Ember.js 1.13.0 至少有 43 名贡献者参与,...

oschina
2015/06/14
1K
5
Laravel 不权威导航

Laravel不权威导航 Hi 这里是Roy整理的Laravel相关索引,希望能帮到大家 ,目前只是一小部分,正在努力整理中... Laravel 文档 Laravel 官方文档 —— 英文 Laravel 中文文档 —— laravel-...

weixingo
2016/02/05
180
0
Flarum 技术架构 Architecture

Flarum 使用三层体系结构。 1、核心层 - core 负责管理数据、事件、实体、命令等。 2、中间层 - API 使用 Web API 来操作 Flarum。 3、最外层 - Web App 使用 Ember.js 展示数据。 这样的分层...

justjavac
2014/12/31
375
0
Laravel 5.1 源码阅读

安装,和创建项目,都是通过Composer,简单,略过。 Entry && Kernel 网站入口文件,${Laravel-project}/public/index.PHP: 生成Request,处理Request(),生成Response,发送Resonse。常规...

botkenni
2016/10/09
25
0

没有更多内容

加载失败,请刷新页面

加载更多

window下安装maven

1.下载软件包: 2.解压到当前的安装路径: D:\Maven3.5.3 3.添加环境变量: 新建一个名为:MAVEN_HOME 填写解压路径:D:\Maven3.5.3 打开path,添加:%MAVEN_HOME%\bin 确定即可。 4.验证环境...

狼王黄师傅
8分钟前
0
0
聊聊flink的FsCheckpointStorage

序 本文主要研究一下flink的FsCheckpointStorage CheckpointStorage flink-runtime_2.11-1.7.0-sources.jar!/org/apache/flink/runtime/state/CheckpointStorage.java /** * CheckpointStor......

go4it
30分钟前
2
0
makefile 常用函数

Linux 环境下的程序员如果不会使用GNU make来构建和管理自己的工程,应该不能算是一个合格的专业程序员,至少不能称得上是 Unix程序员。今天我们来学习下makefile的常用函数。 《GNU make》h...

科陆李明
今天
17
0
Android 报错 Could not find com.android.tools.build:aapt2:3.2.1-4818971.

报错信息: Could not find com.android.tools.build:aapt2:3.2.1-4818971.Searched in the following locations: file:/C:/Users/96110/AppData/Local/Android/Sdk/extras/m2reposito......

lanyu96
今天
9
0
我的Linux系统九阴真经

我的Linux系统九阴真经 在今天,互联网的迅猛发展,科技技术也日新月异,各种编程技术也如雨后春笋一样,冒出尖来了。各种创业公司也百花齐放百家争鸣,特别是针对服务行业,新型互联网服务行...

linuxCool
今天
34
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部