PHPでHTTPリクエスト（cURL&PUTでパラメータを渡す際の注意）

PHPからcURLで各メソッドを叩く処理を書いたのでまとめておきます。
cURLに関して古い記事が多い&書き方がいくつかあるので少々ハマりました(´・ω・`)

これから実装するよって人は流し読みして[推奨：ライブラリを使おう](http://qiita.com/tokutoku393/items/3c3ba3ca581bc0381e35#%E6%8E%A8%E5%A5%A8%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%82%92%E4%BD%BF%E3%81%8A%E3%81%86)を読めば十分かも。

## cURLってなに？

>  cURL（カール）は、さまざまなプロトコルを用いてデータを転送するライブラリとコマンドラインツールを提供するプロジェクトである。

（wikipediaより）

プロトコルはHTTPやFTPなどの通信規約のことです。例えば、HTTPリクエストを発行してページの情報を取得したり。
linuxコマンドでファイルダウンロードする際に使うことも多いですね。

PHPの処理の中でも、cURLを使ってHTTPリクエストを行うことができます。

## どんな時に使うの？
アプリケーションの処理内で外部のサイトにアクセスして情報を取得したい時などに利用します。
ヘッダやパラメータの操作がしやすいので、RESTfulなAPIを取得する時に便利です。

## 基本の書き方
### GET
```php
<?php

$url = 'http://...?name=Tom'; // リクエストするURLとパラメータ

// curlの処理を始める合図
$curl = curl_init($url);

// リクエストのオプションをセットしていく
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'GET'); // メソッド指定
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // 証明書の検証を行わない
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); // レスポンスを文字列で受け取る

// レスポンスを変数に入れる
$response = curl_exec($curl);

// curlの処理を終了
curl_close($curl);
```

処理を始める、オプションをセット、実行、処理を終了、が基本です。
書き方自体は難しくないんだけど、オプションを調べるのが大変ですよね。。

### POST

```php
<?php

$url = 'http://...'; 

// 渡したいパラメータ
$params = [
	'name' => 'Tom',
	・・・
];

$curl = curl_init($url);
curl_setopt($curl, CURLOPT_POST, TRUE);
curl_setopt($curl, CURLOPT_POSTFIELDS, $params); // パラメータをセット
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($curl);
curl_close($curl);
```

あえて`curl_setopt($curl, CURLOPT_POST, TRUE);`という記述にしてみました。
GETのように、`curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST');`でもOKです。

### PUT

```php
<?php

$url = 'http://...'; 
$params = [・・・];

$curl = curl_init($url);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT'); // ※
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($params)); // ※
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($curl);
curl_close($curl);
```

POSTでパラメータを渡す場合と似ているのですが、下記要注意です。

```php
// POSTはどちらも同じ挙動（に見える）
curl_setopt($curl, CURLOPT_POST, TRUE);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST');

// PUTだと挙動が変わる
curl_setopt($curl, CURLOPT_PUT, TRUE); //パラメータが渡らない
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT'); // これならOK
```

さらに、渡すパラメータは`http_build_query()`で変換してあげないとダメです。
POSTの場合は単なる配列でもOKなのですが・・。

### DELETE

```php
<?php

$url = 'http://...'; 

$curl = curl_init($url);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'DELETE');
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($curl);
curl_close($curl);
```

### オプションをまとめて記述
オプションを毎回セットしなくても、配列で渡すことができます。

```php
<?php

$options = [
	CURLOPT_POST => true,
	CURLOPT_POSTFIELDS => $post_params,
	CURLOPT_SSL_VERIFYPEER => false,
	CURLOPT_RETURNTRANSFER => true
];

$curl = curl_init($url);
curl_setopt_array($curl, $options);
・・・
```

ちょっと簡潔になりました。
が、そもそもcURLを直接書かなくても実装できます。

## 推奨：ライブラリを使おう
### ライブラリって？

> ライブラリ（英: Library）は、汎用性の高い複数のプログラムを再利用可能な形でひとまとまりにしたものである。 ライブラリと呼ぶ時は、それ単体ではプログラムとして作動させることはできない実行ファイルではない場合がある。

（Wikipediaより）

すごくわかりやすい説明で言うことなしですね。汗
最近のPHPだと、composerを使って自分のアプリケーションに追加することが出来ます。

例えば"guzzle"というライブラリは、cURLをラップ（※）しているので簡潔にcURLの処理を書くことができます。

※ラップ・・・内包していること。複雑なオプションやエラー処理などをいい感じに吸収してくれていることが多い。

### 実装の違い
POSTでパラメータを渡す方法を見比べてみます。

1.cURLで実装したコード

```php
<?php

$url = 'http://...';
$params = [・・・];

$options = [
	CURLOPT_POST => true,
	CURLOPT_POSTFIELDS => http_build_query($params),
	CURLOPT_SSL_VERIFYPEER => false,
	CURLOPT_RETURNTRANSFER => true
];

$curl = curl_init($url);
curl_setopt_array($curl, $options);
$response = curl_exec($curl);
curl_close($curl);
```

2.guzzlehttp/guzzleで実装したコード

```php
<?php

$url = 'http://...';
$post_data = [・・・];

$client = new Client();
$response = $client->request('POST', $url, [
    'form_params' => $post_data
])->getBody();
```

第一引数にメソッド、第二引数にURL、第三引数にオプションを渡します。
パラメータを渡す場合は`form_params`を指定してあげるだけです。

細かいオプションを調べたり、メソッドごとの違いを気にしたりする必要は（ほとんど）ありません。

https://github.com/guzzle/guzzle

なんだか最近の文献が少ないな、とか、自分でやたらロジックを書かなきゃいけないなって時は便利なライブラリがないか調べてみましょう！