要するにURLの?以降にあるtest_key=test_valueの形式の文字列のことである。
PHPはわざわざ自前でパースしなくても、$_GETの中に配列として展開された形式で入ってるし、
parse_str関数を使えば好きなタイミングでパースすることが出るが、
JavaScriptにはそのような仕組みはなく、自力でパースしないといけない。
クエリストリングには配列として変換する仕組みがある。
test_key[]=test_value1&test_key[]=test_value2&test_key[test]=test_value3
というクエリストリングだと
array(1) {
["test_key"]=>
array(3) {
[0]=>
string(11) "test_value1"
[1]=>
string(11) "test_value2"
["test"]=>
string(11) "test_value3"
}
}
という配列が生成される。
何サイトかJavaScriptでクエリストリングをオブジェクトに変える処理を見てみたが、
ほとんどのサイトでこの配列形式をサポートしてなかった。
なのでちょっと作ってみた。
//link・・・http://mio-koduki.blogspot.com/2012/03/javascriptphp.html
//第一引数・・・パースしたいクエリストリング。省略した場合は現在のURLのクエリストリング
//返り値・・・クエリストリングからパースされたオブジェクト
function parse_query(query)
{
if(query==null)
{
query=(location.search+'').replace(/^[?&]/,'');
}
var separator1='=';
var separator2='&';
var data={};
query=(query+'').replace(/^( |%20)*/g,'').split(separator2);
for(var i=0;i<query.length;i++)
{
var tmp=query[i].split(separator1);
if(tmp.length<2)
{
tmp=[tmp,''];
}
var key=url_decode(tmp.shift());
if(key.length<=0)
{
continue;
}
data=merge(data,make_array(key,url_decode(tmp.join(separator1))));
}
return data;
function url_decode(string)
{
return decodeURIComponent((string+'').replace(/\+/g,'%20'));
}
function make_array(key,value)
{
var tmp_key=[];
var bracket_key='';
var bracket=false;
key=key.replace(/^ */g,'');
if(key.length>0&&key.charAt(0)=='[')
{
key='';
}
for(var i=0;i<key.length;i++)
{
var char=key.charAt(i);
if(!bracket&&char=='[')
{
if(bracket_key!='')
{
tmp_key.push(bracket_key);
bracket_key='';
}
bracket=true;
bracket_key+=char;
}
else if(char==']')
{
if(bracket)
{
if(tmp_key==1)
{
tmp_key.push(bracket_key);
}
else
{
tmp_key.push(bracket_key.substr(1));
}
bracket_key='';
bracket=false;
if(key.charAt(i+1)!='[')
{
break;
}
}
else
{
bracket_key+=char;
}
}
else if(char=='\0')
{
break;
}
else
{
bracket_key+=char;
}
}
if(bracket)
{
if(tmp_key.length==1)
{
tmp_key[tmp_key.length-1]+=bracket_key;
}
}
else if(bracket_key!='')
{
tmp_key.push(bracket_key);
}
var count=0;
if(tmp_key.length>0)
{
for(var i=0;i<tmp_key[0].length;i++)
{
var char=tmp_key[0].charAt(i);
if(char==' '||char=='.'||char=='[')
{
tmp_key[0]=tmp_key[0].substr(0,i)+'_'+tmp_key[0].substr(i+1);
}
//下の1文を変えれば$_GET準拠、現在はparse_str準拠
//if(char=='['&&++count>0)
if(char=='['&&count++>0)
{
break;
}
}
}
for(var i=tmp_key.length-1;i>=0;i--)
{
var tmp_data={};
tmp_data[tmp_key[i]]=value;
value=tmp_data;
}
return value;
}
function merge(base,extend)
{
if(!is_object(base)||!is_object(extend))
{
return {};
}
extend=numbering(base,extend);
for(var i in extend)
{
if(is_object(base[i])&&is_object(extend[i]))
{
base[i]=merge(base[i],extend[i]);
}
else
{
base[i]=extend[i];
}
}
return base;
}
function numbering(base,extend)
{
var tmp={};
for(var i in extend)
{
var index=(i.match(/^\s?$/)?max_index(base):i);
if(is_object(extend[i]))
{
tmp[index]=numbering(is_object(base)?base[i]:null,extend[i]);
}
else
{
tmp[index]=extend[i];
}
}
return tmp;
}
function max_index(data)
{
var max=0;
if(!is_object(data))
{
return max;
}
for(var i in data)
{
if((i+'').match(/^(0|[1-9][0-9]*)$/)&&i>=max)
{
max=i-0+1;
}
}
return max;
}
function is_object(data)
{
return data!=null&&typeof data=='object'&&Object.prototype.toString.call(data)!='[object Array]';
}
}
とこんな感じ。
配列形式をサポートすると非常に面倒くさくなってくる。
第一引数にクエリストリングを渡す形式だが、省略すると現在のURLのクエリストリングをパースする。
余談だが、PHPのマニュアルには$_GETや$_POSTと同じ仕組でparse_strを動かしてあると書いているが、「a[b[c=d」というクエリの時に結果が違ってる。
地味に気になるw
この関数もどっちに準拠すべきか迷ったので、一応どっちにも切り替えられるようにしている。
この関数の逆の挙動をする関数も作ってみた。
0 件のコメント:
コメントを投稿