PHP
CakePHP
JSON

大量のPOST配列をJSONにしてPHPに送信することでPOST数を削減する


概要

大量の配列をPOSTするページがあり、

PHPのmax_input_varsで設定された上限(デフォルト1,000個)に引っかかってしまい、

POSTデータがPHPで受け取れないという現象が起きていた。

(配列のPOSTでも1件ずつカウントされるんだ…)

そのため、FormをJSON形式にシリアライズしてPOSTし、

CakePHPでアンシリアライズするようにした。


環境

PHP5.6

CakePHP2


POSTしたいデータ

FormHelperでinputタグを出力している

echo $this->Form->hidden('Param1.' . $idx . '.id');

echo $this->Form->hidden('Param1.' . $idx . '.name');

結果のHTMLではname属性に以下のようにセットされる

<input type="hidden" name="data[Param1][1][id]" value="value1"/>

<input type="hidden" name="data[Param1][1][name]" value="value2"/>
<input type="hidden" name="data[Param1][2][id]" value="value3"/>
<input type="hidden" name="data[Param1][2][name]" value="value4"/>


JSでシリアライズ

submitイベントで以下の処理を発火させる。

var form = $('#form');

//formの全要素をJSON化してサブミット
var $fields = form.serializeArray();
for (var i = 0; i < $fields.length; i++) {
//name属性の配列表記をドット記法に変換
$fields[i].name = $fields[i].name.replace('data[', 'data.').split('][').join('.').replace(']', '');
}
form.after('<form id="formJson" action="" method="post"><input type="hidden" name="json" value="' + h($fields ? JSON.stringify($fields) : "") + '"></form>');
form = $('#formJson');

form.submit();


CakePHPでアンシリアライズ

とにかくdataに突っ込んでいるので '_method' もdataに入るようになったけど動いてるからいいか。


IshigurosController.php

if ($this->request->is('post') && $this->request->data('json')) {

//Json形式のプロパティデータを連想配列形式へ変換する
//Json形式でなければ何もしない
$decoded = json_decode($this->request->data('json'), true);
if ($decoded && json_last_error() === JSON_ERROR_NONE) {
$request = Hash::expand(Hash::combine($decoded, '{n}.name', '{n}.value'));

//'data'のみ特別処理する
$requestData = [];
if (isset($request['data'])) {
$requestData = $request['data'];
unset($request['data']);
}

foreach($request as $k => $v) {
$this->request->data($k, $v);
}

foreach($requestData as $k => $v) {
$this->request->data($k, $v);
}
}
}