AngularJSで$http.postすると、いわゆる普通にPOSTがされない。そのため、
$name = $_POST['name']
というお馴染みの形式で受け取れない。
標準では、
$postdata = file_get_contents("php://input");
$request = json_decode($postdata);
$name = $request->name;
という感じで受け取れる(後述)
この形式で受け取るためには、
- Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
でなければいけない(UTF-8である必要はないけど)。また、値がPOSTパラメータ文字列形式でなくてはならない。
- name=hoge&email=hoge@test.com
といった感じ。これを実現する必要がある。
前提条件
- PHPでWebAPIを作る。
- APIはnameとemailを受け取ってそのままjsonで返す。
API
とりあえずこんな感じ。
<?php
$name = "default";
$email = "default@test.com";
if(isset($_POST['name'])) $name = $_POST['name'];
if(isset($_POST['email'])) $email = $_POST['email'];
$res = [];
$res['name'] = $name;
$res['email'] = $email;
header("Content-type: application/json");
echo json_encode($res);
フロント
こんな感じ。$http.postのデータ形式をJSONではなく、POSTパラメータ文字列に。オプションとしてContent-typeを指定している。
<!doctype html>
<html land="ja" ng-app="myApp">
<head>
<meta charset="utf-8">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<script>
//app
var app = angular.module('myApp',[]);
//controller
app.controller('myCtrl',function($scope,$http){
$http.post('http://localhost/res.php',encodeURI("name=hoge&email=foo@test.com"),{
headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}
})
.success(function(response){
//response
$scope.name = response.name;
$scope.email = response.email;
});
});
</script>
</head>
<body>
<div ng-controller="myCtrl">
{{name}}<br>
{{email}}
</div>
</body>
</script>
応用
受け渡すデータ形式はJSONで指定したいということはあると思います。その場合は、下記のようにjqueryの$.param()関数を利用して変換できる。transformRequestで変換する方法もあるようですが、覚えられないのでこれで。
<!doctype html>
<html land="ja" ng-app="myApp">
<head>
<meta charset="utf-8">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<script>
//app
var app = angular.module('myApp',[]);
//controller
app.controller('myCtrl',function($scope,$http){
$http.post('http://localhost/res.php',$.param({"name":"hoge","email":"hoge@hoge.com"}),{
headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'},
})
.success(function(response){
//response
$scope.name = response.name;
$scope.email = response.email;
});
});
</script>
</head>
<body>
<div ng-controller="myCtrl">
{{name}}<br>
{{email}}
</div>
</body>
</script>
変換用の関数を定義し、transformRequestの値として渡すと変換されるみたい。
さらに応用(FormDataを使う)
FormDataを使うと記述が汎用的でよい。Fileも送れる(カスタムディレクティブを作る必要はある)。
Content-typeはmultipart/form-dataになる。
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<script src="js/app.js"></script>
<script>
//app
var app = angular.module('myApp',[]);
//controller
app.controller('hogeCtrl',function($scope,$http){
//init
$scope.name = "";
$scope.email = "";
//onclick
$scope.btnClick = function(){
//formdata
var fd = new FormData();
fd.append('name',$scope.name);
fd.append('email',$scope.email);
$http.post('res.php',fd,{
transformRequest: null,
headers: {'Content-type':undefined}
})
.success(function(res){
$scope.response = res;
});
}
});
</script>
</head>
<body>
<div ng-app="myApp" ng-controller="hogeCtrl">
name:<input type="text" name="name" ng-model="name"><br>
email:<input type="text" name="email" ng-model="email"><br>
<button ng-click="btnClick()">upload</button>
<p>{{name}}</p>
<p>{{response}}</p>
</div>
</body>
</html>
AngularJSの標準形式での受け取り
郷に入れば郷に従えの精神で、Angular標準のPOSTの受け取り方も。
API
素のPHP
$_POSTではなく、file_get_contents()を利用する。file_get_contentsって何でもとれるのね。
<?php
$name = "default";
$email = "default@test.com";
$postdata = file_get_contents("php://input");
$request = json_decode($postdata);
$name = $request->name;
$email = $request->email;
$res = [];
$res['name'] = $name;
$res['email'] = $email;
header("Content-type: application/json");
echo json_encode($res);
Laravel
LaravelだとResponseファサードで取れる。
Route::post('hoge',function(){
//get content
$request = \Request::instance();
$content = $request->getContent();
//decode
$obj = json_decode($content);
//get params
$name = $obj->name;
$email = $obj->email;
//param to array
$res = [];
$res['name'] = $name;
$res['email'] = $email;
//json response
return Response::json($res);
});
フロント
シンプルで素敵。Angularを利用するなら、この形式でPHP側を開発した方がいいでしょう。
<!doctype html>
<html land="ja" ng-app="myApp">
<head>
<meta charset="utf-8">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<script>
//app
var app = angular.module('myApp',[]);
//controller
app.controller('myCtrl',function($scope,$http){
$http.post('http://localhost/res.php',
{
"name":"hoge",
"email":"hoge@hoge.com"
})
.success(function(response){
//response
$scope.name = response.name;
$scope.email = response.email;
});
});
</script>
</head>
<body>
<div ng-controller="myCtrl">
{{name}}<br>
{{email}}
</div>
</body>
</script>