$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; }; });