AngularJSでWebAPI(PHP)連携 POST編


AngularJSで$http.postすると、いわゆる普通にPOSTがされない。そのため、

```php
$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
<?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を指定している。

```html
<!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で変換する方法もあるようですが、覚えられないのでこれで。

```html
<!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になる。

```html
<!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
<?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ファサードで取れる。

```php
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側を開発した方がいいでしょう。

```html
<!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>
```