AngularJS + PHP。 $ httpサービスをjQuery.ajax()のように動作させる

Angularの初心者は、$ httpサービスの高速機能(例: $http.post()



)が同等のJquery関数(例: jQuery.post()



)と交換できないため、しばしば混乱しています関連するマニュアルでは、同様の方法で使用方法が説明されています。 つまり、これより前のGickeryのコードは次のようになりました。



 (function($) { jQuery.post('/endpoint', { foo: 'bar' }).success(function(response) { // ... }); })(jQuery);
      
      





以下は、Angularの初期状態では機能しないことがあります。



 var MainCtrl = function($scope, $http) { $http.post('/endpoint', { foo: 'bar' }).success(function(response) { // ... }); };
      
      





発生する可能性のある問題は、サーバーがAngularリクエストから{ foo: 'bar' }



パラメーターを取得できないことです。



違いは、JickeryとAngularがデータをシリアル化して送信する方法です。 基本的に、問題はサーバー部分が書かれている言語にあり、デフォルト設定でAngularの転送を単純に理解していません。Angularはもちろん何も悪いことをしないので、恥ずべきことです。 デフォルトでは、GickeryはContent-Type: x-www-form-urlencoded



および使い慣れた行foo=bar&baz=moe



を使用してデータを転送します。 ただし、AngularはContent-Type: application/json



および{ "foo": "bar", "baz": "moe" }



JSON文字列を使用してデータを送信しますが、残念ながら一部のサーバー言語(特にPHP)は初期状態ではありませんオブジェクトに変換します。



幸いなことに、Angular開発者は、すべてのプログラムにx-www-form-urlencoded



をインストールするために$ httpサービスでこのメソッドをサポートしました。 フォーラムやStackOverflowで提供される多くのソリューションがありますが、サーバーコードまたは$ http使用スキームを変更する必要があるため、理想的ではありません。 したがって、サーバーまたはクライアントのコードを変更する必要はありませんが、アプリケーションモジュールの設定で$ httpの操作にいくつかのマイナーな変更を加えることを提案します。



 //    ... angular.module('MyModule', [], function($httpProvider) { //  x-www-form-urlencoded Content-Type $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8'; //   transformRequest  $http- $httpProvider.defaults.transformRequest = [function(data) { /** *  ;    x-www-form-urlencoded . * @param {Object} obj * @return {String} */ var param = function(obj) { var query = ''; var name, value, fullSubName, subValue, innerObj, i; for(name in obj) { value = obj[name]; if(value instanceof Array) { for(i=0; i<value.length; ++i) { subValue = value[i]; fullSubName = name + '[' + i + ']'; innerObj = {}; innerObj[fullSubName] = subValue; query += param(innerObj) + '&'; } } else if(value instanceof Object) { for(subName in value) { subValue = value[subName]; fullSubName = name + '[' + subName + ']'; innerObj = {}; innerObj[fullSubName] = subValue; query += param(innerObj) + '&'; } } else if(value !== undefined && value !== null) { query += encodeURIComponent(name) + '=' + encodeURIComponent(value) + '&'; } } return query.length ? query.substr(0, query.length - 1) : query; }; return angular.isObject(data) && String(data) !== '[object File]' ? param(data) : data; }]; });
      
      





注:上記の大きなスニペットは、 param()



param()



関数で常に使用する必要がありparam()



代わりにjQuery.param()



使用しないでjQuery.param()



これは、Angularの$リソースを使用しようとすると混乱を引き起こしますjQuery.param()



は、渡された$リソースクラスのすべてのメソッドを拒否するためです。
(これは、関数を含むパラメーター化用のオブジェクトのプロパティが呼び出され、それらによって返される値がパラメーター化されたものとして使用されるため、jQueryの機能ですが、Angularの場合、通常はメソッドとt .d。)



上記のスニペットを使用するだけで問題ありません!



既存のサーバーコードがx-www-form-urlencoded



データを想定していると仮定して、 $http.post()



および他の同様のメソッドを使用して先に進むことができます。 以下は、毎日の完全なコードの最終結果の例です(あなたが望み、夢見ていたものの例)。



HTMLテンプレート

 <div ng-app="MyModule" ng-controller="MainCtrl"> <p ng-show="loading">Loading...</p> <p ng-hide="loading">Response: {{response}}</p> </div>
      
      





クライアントコード(AngularJS)

 var MainCtrl = function($scope, $http) { $scope.loading = true; $http.post('/endpoint', { foo: 'bar' }).success(function(response) { $scope.response = response; $scope.loading = false; }); };
      
      





サーバーコード(PHP)

 < ? header('Content-Type: application/json'); // -! $_POST  ; PHP   //      echo json_encode($_POST); ?>
      
      





その他の注意事項

問題は、AngularのJSONリクエストをPHPで読み取ることはまだ可能ですか? もちろん、PHP入力ストリームを読み取り、JSONをデコードする場合:



 < ? $params = json_decode(file_get_contents('php://input')); //  ,     PHP  (. ) $params = json_decode(trim(file_get_contents('php://input')), true); ?>
      
      





明らかな欠点は、コードの直感性がやや劣ることです(結局$ _POSTに慣れています)。サーバーハンドラーが$ _POSTを使用して既に記述されている場合は、サーバーコードを書き直す必要があります。 適切なフレームワークを使用している場合は、おそらくグローバルに変更を加えることができるため、入力ハンドラーは透過的にJSONリクエストを定義しますが、私は回避します。



翻訳者のメモ:可能であれば、 Content-Type: application/json



を受け入れるようにサーバーを構成する方が、より論理的です。
この記事では、サーバーで何も実行できない極端な場合のアプローチについて説明します。



添加剤。 nervghからの補足



 'use strict'; (function() { angular.extend( angular, { toParam: toParam }); /** *  ,      , *       url *   [url]http://api.jquery.com/jQuery.param/[/url] *  [url]http://stackoverflow.com/questions/1714786/querystring-encoding-of-a-javascript-object/1714899#1714899[/url] * * @param object * @param [prefix] * @returns {string} */ function toParam( object, prefix ) { var stack = []; var value; var key; for( key in object ) { value = object[ key ]; key = prefix ? prefix + '[' + key + ']' : key; if ( value === null ) { value = encodeURIComponent( key ) + '='; } else if ( typeof( value ) !== 'object' ) { value = encodeURIComponent( key ) + '=' + encodeURIComponent( value ); } else { value = toParam( value, key ); } stack.push( value ); } return stack.join( '&' ); } }());
      
      







 'use strict'; // change default settings var app = angular.module( 'app', [ ... ]); app .config( function( $httpProvider ) { // [url]http://habrahabr.ru/post/181009/[/url] $httpProvider.defaults.headers.post[ 'Content-Type' ] = 'application/x-www-form-urlencoded;charset=utf-8'; $httpProvider.defaults.transformRequest = function( data ) { return angular.isObject( data ) && String( data ) !== '[object File]' ? angular.toParam( data ) : data; }; });
      
      






All Articles