Lavavel は、世界で最も人気のある PHP フレームワークであるため、開発者が複数ページの Web アプリケーションを迅速に構築するのに役立つ明確なアーキテクチャ、完全なドキュメント、豊富なツールなどを備えています。
しかし、テクノロジーの発展に伴い、Web プログラムの相手であるクライアントはますます多様化しています (PC、携帯電話、タブレット、その他の専用デバイスなど)。したがって、サーバーとさまざまなデバイス間の通信を促進するには、統一されたメカニズムが必要です。 Restful APIはこの考えに基づいて提案されました。
Ruan Yifeng は、Restful アーキテクチャの概要を説明しました。
各 URI はリソースを表します。
クライアントとサーバー間でこのリソースを転送する特定の方法についてのプレゼンテーション。 Layer;
クライアントは 4 つの HTTP 動詞を通じてサーバー側のリソースを操作し、「プレゼンテーション層の状態の変換」を実現します。
動作の観点から見ると、一連のリソース対話ルールに同意した後、サーバーは、これらのルールに基づいて統合 API インターフェイスを通じてさまざまなフロントエンド デバイスと対話します。サーバーは、データの保存と分析、またはビジネス ロジックの実装だけに集中する必要があります。さまざまなクライアント上で、そのプレゼンテーション ロジックと対話ロジック、およびサーバー側のビジネス ロジックは、論理的分離と物理的分離という二重の分離を実現します。
フロントエンドとバックエンドがリソース (データ) とのみ対話する場合、ページ ルーティングは当然フロントエンド コントロールに引き継がれます。これは、フロントエンドが更新されなくなったことと同じです。最初にページをロードした後、すべてのデータが Ajax から処理され、すべてのフォーム送信が同じ方法で行われます。
Ember.js は、MVC コンセプトに基づいたモジュール型フロントエンド フレームワークであり、SPA の迅速な開発に非常に適した UI バインディング、テンプレート システム、ルーティング システムなどの機能を提供します。特に、Ember は完全なコマンド ライン開発パッケージである Ember Cli も提供します。これにより、面倒な開発環境の設定が不要になるだけでなく、CoffeeScript や ES6 などの豊富な開発ツールや構築ツールも提供されます。開発の場合、対応するインタープリタが開発パッケージとともに適切にインストールされているため、変更を加えるたびにコマンド ラインに ember build と入力する必要はありません。システムはテキストの変更を自動的に認識し、解釈してマージします。それらをコンパイルし、コンパイルしたファイルを dist/ ディレクトリに置きます。
しかし、Laravel と Ember.js をそれぞれ構成した後、それらは相互に設計されていないため、すぐに袖をまくってコードを書くことができないことがわかりました。たとえば、この時点で私は 2 つの問題に直面しました:
Laravel と Ember.js には独自のルーティング システムがあります。どうすれば laravel に URL の制御を放棄させることができますか?
通常、Laravel はサーバーによって管理および維持され、完全な認証ソリューションを提供しますが、SPA では、バックエンドがアクセス許可制御の一部をフロントエンドに転送する必要があります (主にページ アクセス許可と Ajax 許可)。この問題を解決するためのベスト プラクティスは何ですか?
これまでにも同様の問題に遭遇したことがあると思いますが、この問題は一般原則に基づいている可能性がありますが、運用レベルでは、スペースの制限のため、この記事では最初の問題について説明します。 。 2番目の質問は別途回答します。
API インターフェースを定義します
laravel では、laravel /app/Http/routes.php ファイルはすべての URL のエントリ ポイントであり、すべての URL と対応する処理関数をここで定義する必要があります。
// laravel/app/Http/routes.phpRoute::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 をルーティング グループに入れます。このグループは、たとえば、サーバーが id=5 のユーザー情報を返す必要がある場合、API リクエストの先頭に api/[バージョン番号] を付ける必要があることに同意します。 、次のアドレスに送信される必要があります。 GET リクエストを発行します:
http://your_demain/api/v1/users/5
リクエストを受信した後、サーバーはリクエストを渡します。オブジェクトを UserController の getById メンバー メソッドに渡して処理します。
また、このファイルでユーザー認証に関連するインターフェイスを定義し、それらを 1 つのグループにグループ化しました。
// laravel/app/Http/routes.phpRoute::group( array ( 'prefix' => 'auth' ), function(){ Route::post('login', 'Auth\AuthController@postLogin'); Route::get('logout', 'Auth\AuthController@getLogout'); Route::post('register', 'Auth\AuthController@postRegister');});
3 つのインターフェイスは、それぞれログイン、ログアウト、登録機能を提供します。
わかりました、laravel のルーティングで必要なことはこれだけです。
他の URL の制御をフロントエンドに与える
Ember ページの開始時に、ember/dist/index を使用します.html ファイル 入口の dist ディレクトリには、システムによって自動的に生成されるすべてのビルド ファイルが保存されます。 Index.html ファイルでは、2 つのスクリプト ファイルと 2 つのスタイル ファイルが ember/dist/assets ディレクトリからロードされます。
<!-- 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 によって構築されたフロントエンド リソースが保存されます。したがって、私のアプローチは次のとおりです:
?? 2 つのディレクトリ ember/dist/assets と laravel/public/assets を同期します。後者は前者のミラーです
?? laravel/resources/views は app.php という名前のビューを定義しており、その内容は ember/dist/index.html??
??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.phpRoute::get('{data?}', function(){ return View::make('app');})->where('data', '.*');
该分组捕捉所有非API请求并返回 app.php。
前端具体实现
在Ember中,每个路由都有与之相关联的一个模型(Model)。Model 负责数据的查询、更改和将更改保存回服务器,这一过程是通过模型适配器(Adapter)完成的。所以需要修改适配器让它匹配后端所定义的 API 前缀约定:
// ember/app/adapters/application.jsexport default DS.RESTAdapter.extend({ namespace: 'api/v1'});
然后就可以在 ember/app/routers.js 中定义前端路由了:
// ember/app/routers.jsRouter.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)来解决。
总结
至此,确定了页面加载方案,打通了前后端的数据交互通道,前后端由各自为政变成了相互协作、各司其职,应用终于“活”了起来。