PHPでPUTで送られたデータを取得する
目次
概要
PHPでは、送られてきたデータは$_GETや$_POSTで受け取ることができます。
しかし、これらを使ってデータを受け取れるのは、リクエスト時のHTTPメソッドがGETやPOSTの時だけです。
なので、REST APIなどをPHPを使って実現しようした時に、PUTメソッドなどの別のHTTPメソッドでは、ほの方法でデータの取得ができません。
ここでは、GETやPOSTメソッド以外のHTTPメソッドでも適切にデータを取得できる方法を書きます。
テキストデータ
リクエストとして送られてくるデータには、テキストデータと、画像などのバイナリデータがあります。
まず、最初にテキストデータをどのようなHTTPメソッドでも受け取ることができるプログラムを書きます。
このプログラムは、下記のURLで解説されているものを参考にしています。
PHP multipart form data PUT request?
参考のページのプログラムではうまく動かなかったので、少しプログラムをいじっています。
function parse_put()
{
/* PUT data comes in on the stdin stream */
$putdata = fopen("php://input", "r");
/* Open a file for writing */
// $fp = fopen("myputfile.ext", "w");
$raw_data = '';
/* Read the data 1 KB at a time
and write to the file */
while ($chunk = fread($putdata, 1024))
$raw_data .= $chunk;
/* Close the streams */
fclose($putdata);
// Fetch content and determine boundary
$boundary = substr($raw_data, 0, strpos($raw_data, "\r\n"));
if(empty($boundary)){
parse_str($raw_data,$data);
return;
}
// Fetch each part
$parts = array_slice(explode($boundary, $raw_data), 1);
$data = array();
foreach ($parts as $part) {
// If this is the last part, break
if ($part == "--\r\n") break;
// Separate content from headers
$part = ltrim($part, "\r\n");
list($raw_headers, $body) = explode("\r\n\r\n", $part, 2);
// Parse the headers list
$raw_headers = explode("\r\n", $raw_headers);
$headers = array();
foreach ($raw_headers as $header) {
list($name, $value) = explode(':', $header);
$headers[strtolower($name)] = ltrim($value, ' ');
}
// Parse the Content-Disposition to get the field name, etc.
if (isset($headers['content-disposition'])) {
$filename = null;
$tmp_name = null;
preg_match(
'/^(.+); *name="([^"]+)"(; *filename="([^"]+)")?/',
$headers['content-disposition'],
$matches
);
list(, $type, $name) = $matches;
//Parse File
if(isset($matches[4]) )
{
//if labeled the same as previous, skip
if(isset($_FILES[$matches[2]]))
{
continue;
}
//get filename
$filename = $matches[4];
//get tmp name
$filename_parts = pathinfo($filename);
$tmp_name = tempnam(sys_get_temp_dir(), $filename_parts['filename']);
file_put_contents($tmp_name, $body);
//populate $_FILES with information, size may be off in multibyte situation
$_FILES[$matches[2]] = array(
'error'=>0,
'name'=>$filename,
'tmp_name'=>$tmp_name,
'size'=>strlen($body),
'type'=>$value
);
//place in temporary directory
file_put_contents($tmp_name, $body);
}
//Parse Field
else
{
$data[$name] = substr($body, 0, strlen($body) - 2);
}
}
}
return $data;
}
function get_parameter()
{
$parameter = array();
switch ($_SERVER['REQUEST_METHOD']) {
case 'GET':
$parameter = $_GET;
break;
case 'POST':
$parameter = $_POST;
break;
case 'PUT':
case 'DELETE':
default:
$parameter = parse_put();
break;
}
return $parameter;
}
新たに、parse_put()関数を追加して、その中でバイナリデータなどのファイルを$_FILESに入れています。
使い方は、parse_put()関数を呼び出して、その戻り値にはテキストデータが代入されているので、それを受け取り、ファイルなどのバイナリデータは$_FILESに代入されているので、$_FILESを参照します。
まとめ
PHPで、GETやPOSTメソッド以外の方法でデータを受け取るのがこんなに難しく面倒だとは思いませんでした。