ブログランキング・にほんブログ村へ


iPhone/iPad用潜水艦ゲームアプリ ソナーエコー iTunesにて公開中

2013年02月19日

jQuery ajax jsonオブジェクトをそのままでやりとりしたい

前の記事でjQueryのgetJSONが予想外に賢くて、phpもそれを受け入れるだけの仕組みを備えていることがわかった。

だけどなんとなくしっくりこない。

それは何かと考えてみると、これはphpを書く人とjavascriptを書く人が別であることが想定された仕様だからなんじゃないかと思った。

だって、折角引数をJSONオブジェクトで渡してし、phpにはjson_decode,json_encodeなんて便利なものもあるのに、php側では従来のCGIのように結局$_REQUEST[]とか$_POST[]で受け取らなくちゃならない。JSONのいいところは要素に何が追加されても、仕様変更されても、それを発生させた側と使用する側だけが示し合わせてさえいれば、途中の通過はすべて"JSONオブジェクト"という塊としてやりとりできることだと思う。それがphpの入り口で要素についての知識を求められてしまう。

ではJSONオブジェクトをそのまんまの形に近い状態でphpとjavascriptを自由に行き来させるにはどうすればよいか。

JSONオブジェクトをjavascriptでデコードしてそれそのものを渡せばよい。

たとえばこんな感じ。jQueryのajaxメソッドを使ってみる。

JavaScript側
function test_json2(){
var data1 = { name : "the name", age: 19 ,comment: "コメントです" };

var txt = JSON.stringify( data3 );
txt = "json="+encodeURI( txt );

$("#request").text( txt );

$.ajax( {
type: "POST",
url: "XXXXXXX/test_json2.php",
data: txt,
dataType: "json",
success: function( data ){
var t = JSON.stringify( data );
$("#result").text( t );
}
});
}
php側

<?php
$js = $_REQUEST[ "json" ];
$json = json_decode( $js );

$t = json_encode( $json );

header("Content-Type: text/plain");
echo $t;

?>

JSONオブジェクトをJavaScript側でテキストエンコードして、それをjson=の引数としてphpに渡す。
phpはjson=の引数1つだけを受け取り、それをjson_decodeしてphpの連想配列として疑似JSONオブジェクトとして扱う。

これだとphpで受ける側には引数に関する処理をいちいち書かなくてよくなる。

たとえば
var data1 = { name : [ "近藤","土方","沖田" ], age: 19 ,comment: { com1:"COM1" } };
として
php側で
<?php
$js = $_REQUEST[ "json" ];
$json = json_decode( $js );

$json->age2 = $json->age * 2;
$json->theName = $json->name[ 0 ]."_".$json->name[ 2 ];

$t = json_encode( $json );

header("Content-Type: text/plain");
echo $t;

?>

というようにしてやると

{"name":["近藤","土方","沖田"],"age":19,"comment":{"com1":"COM1"},"age2":38,"theName":"近藤_沖田"}

という結果が得られる処理になり、JSONオブジェクトがサーバとクライアントの間をいったりきたりしてるイメージに近くなると思う。

ハイブリッドでいろんな言語で平行してコーディングする必要に迫られる個人プログラマの場合はこれの方が管理しやすいんじゃないかと思う。
posted by みこあいさ at 18:41| JavaScript

jQuery ajax getJSONが受け渡してるもの

jQueryのgetJSONの第2引数

getJSON( url,data,func );

のdataが実際には何を渡してるのか気になってたけどなんとなく放置してたので色々気になる点も合わせて納得するために実験した。

調べてまずわかったことは、要するに普通のcgiパラメータの ?aaa=XXXX&bbb=YYYYをjson風に書けるだけらしいってこと。
つまり
{ aaa: "XXXX" , bbb: "YYYY" }

?aaa=XXXX&bbb=YYYY
になるってこと。

phpのほうを
<?php
$name = $_REQUEST[ "name" ];
$age = $_REQUEST[ "age" ];
$comment = $_REQUEST[ "comment" ];

$json = array(
name => $name,
age => $age,
comment => $comment,
);

$t = json_encode( $json );

header("Content-Type: text/plain");
echo $t;

?>
こんな感じで受けて

var data1 = { name : "the name", age: 19 ,comment: "コメントです" };
$.getJSON("http://XXXXXXXXXX/test_json.php",
data2,
function( data, status ){
var txt = JSON.stringify( data );
$( "#result" ).text( txt );
}
);

これを実行すると
{"name":"the name","age":"19","comment":"コメントです"}
が得られる。
渡しているリクエストをchromeのデベロッパツールで確認すると、
http://XXXXXXXXXXXXXXXXXX/test_json.php?name=the+name&age=19&comment=%E3%82%B3%E3%83%A1%E3%83%B3%E3%83%88%E3%81%A7%E3%81%99
となっていて、
受け取ったレスポンスは
{"name":"the name","age":"19","comment":"\u30b3\u30e1\u30f3\u30c8\u3067\u3059"}
となっていた。

var data1 = { name : "the name", age: 19 ,comment: { com1:"COM1" } };
と書き換えて実行。

{"name":"the name","age":"19","comment":{"com1":"COM1"}}

不思議なことに comment.com1 がちゃんと入れ子になってる様子。
この仕組みでどうして?と半信半疑で
$( "#result" ).text( txt );
としているところで
$("#other").text( data.comment.com1 );
としてみる。

すると
COM1
が表示された。

渡しているリクエストは
http://XXXXXX/test_json.php?name=the+name&age=19&comment%5Bcom1%5D=COM1
レスポンスは
{"name":"the name","age":"19","comment":{"com1":"COM1"}}
となっていた。

%5Bは [ %5Dは ]なので、
comment[com1]=COM1
として定義している。

連想でない普通の配列も試してみる。

var data1 = { name : [ "近藤","土方","沖田" ], age: 19 ,comment: { com1:"COM1" } };

とし、

$("#other").text( "length="+data.name.length+",name[1]="+data.name[1] );

と受ける。

結果は

length=3,name[1]=土方

となり、問題なし。

リクエストは
http://XXXXXXX/test_json.php?name%5B%5D=%E8%BF%91%E8%97%A4&name%5B%5D=%E5%9C%9F%E6%96%B9&name%5B%5D=%E6%B2%96%E7%94%B0&age=19&comment%5Bcom1%5D=COM1
レスポンスは
{"name":["\u8fd1\u85e4","\u571f\u65b9","\u6c96\u7530"],"age":"19","comment":{"com1":"COM1"}}


リクエストをみやすくするため
var data1 = { name : [ "abc","def","ghi" ], age: 19 ,comment: { com1:"COM1" } };
に変更。

リクエストが
http://XXXXXX/test_json.php?name%5B%5D=abc&name%5B%5D=def&name%5B%5D=ghi&age=19&comment%5Bcom1%5D=COM1

name[]=abc&name[]=def&name[]=ghi
として配列に値を入れている。

レスポンスが
{"name":["abc","def","ghi"],"age":"19","comment":{"com1":"COM1"}}


配列の一部をオブジェクトにしてしてみる。
var data1 = { name : [ "abc",{ child:"CHILD",test:"TEST" },"ghi" ], age: 19 ,comment: { com1:"COM1" } };

リクエストは
http://XXXXXXXXXX/test_json.php?name%5B%5D=abc&name%5B1%5D%5Bchild%5D=CHILD&name%5B1%5D%5Btest%5D=TEST&name%5B%5D=ghi&age=19&comment%5Bcom1%5D=COM1
変更した個所は
name[1][child]=CHILD&name[1][test]=TEST
となっている。
レスポンスは
{"name":["abc",{"child":"CHILD","test":"TEST"},"ghi"],"age":"19","comment":{"com1":"COM1"}}
完璧。

いつからこんなに複雑な書式のパラメータをURLで受け渡しできるようになっていたのか正直驚いた。
新しいphpになってできるようになっていたのだろうか。
こういうurlパラメータを受け付けるようになりましたよ、ということなんだろう。

とにかく仕組みを心配する必要はなさそうで、jsonオブジェクトでそのまま行ったり来たりできるようになっているようだ。
posted by みこあいさ at 17:57| JavaScript

2013年02月16日

htmlのスマホ対応 iOSのホーム画面に置くためのメタタグ

スマホ用のhtmlのページ。

iOSだとブックマークを作る動作でホーム画面に置くことが出来るが、そのとき特定のことを書いておくとサファリの下のツールバーを非表示にして画面を広く使うことができるようになる。うまくページを作っておくとほとんどアプリと変わらない見栄えになる。

内容はよくわかんないがこんなかんじのをヘッダに書く。
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="default">

そこで注意だが、よくスマホ用のviewport設定で

こんな感じ
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">

が常套句になっているが、これだとiPhone5の4インチに対応せず互換モードになるらしく縦に黒いところが出来てもったいない。

タグのうちwidth=device-widthはなくてもいいらしい。
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">

とすると、4インチいっぱいに対応する。

他のこねた
1)タッチの縦スクロール制止
bodyタグに
ontouchmove="event.preventDefault();"

2)iOSサファリのURL欄を非表示にする

window.scrollTo(0,0);
を実行する。
一番簡単なのは
bodyタグで onload="window.scrollTo(0,0);"

3)iOSでホーム画面に置いたときのアイコンを指定する

<link rel="apple-touch-icon" href="icon.png">

指定しないとスクショになる。
posted by みこあいさ at 18:17| JavaScript