<   2007年 10月 ( 31 )   > この月の画像一覧

意外と簡単 Ajax

XAMPPのデフォールトのPHPはPHP5だ。PHPにはjson_encode()関数が付いているらしい。これを使うとAjaxが劇的に簡単になることに気がついた。

ちょっと時間がないので詳しい検討は後にするが、こういうことだ。

PHPの連想配列が $a に入っているとする。そうすると PHP 側から JSON を送るのには次のようにすればよい。

echo json_encode($a);

たったこれだけだ。次に JavaScript から prototpe.js の Ajax クラスを使ってコールバック関数の obj という変数に受信した JSON を保持するオブジェクトが渡されたとする。そうしたら、コールバック関数の中で、

json = obj.responseText;
data = eval(”(”+json+”)”);

とすれば、データをオブジェクトとして取り出すことができる。

送信に一行。受信に2行だけで、完璧なAjaxを楽しむことができる。
[PR]
by tnomura9 | 2007-10-31 19:13 | XAMPP | Comments(0)

Json で改行が使えた。

"\n" と "'" をエスケープ処理したら。改行のあるデータも JSON が使えた。

PHPでJSONを組み立てるときにエスケープ処理をし、クライアントのJavaScript で eval() でオブジェクトを作った後、データをアンエスケープする。おおむね次のような処理になる。

PHP側

function replace($str) {
$str = str_replace("\n", "\\n", $str);
$str = str_replace("'", "\'", $str);
return $str;
}

$hash = データのハッシュ
$js = '{';
foreach ($hash as $key => $value) {
$js = $js.$key.":'".replace($value)."',"; //replace が文字列のエスケープ処理
};
$js = $js."'}";
echo $js;

JavaScript側

function getAjaxResponse(url) {
var sendObj = makeSendObject();
var param = $H(sendObj).toQueryString();
var myAjax = new Ajax.Request(
url,
{method : 'post',
parameters : param,
onComplete : decodeJson });
}

function decodeJson(obj) {
json = obj.responseText;
json_obj = eval("("+json+")");
$H(json_obj).each(function(pair, index) {
$(pair.key).value //アンエスケープ処理は eval() が実行されるときに自動的に行われるようなので、JavaScript側では不要になる。
});
}

Ajaxのデータのエスケープ処理の経路は次のようになっているのだろうか。

クライアントー>オブジェクトー>URLエンコーディングー>サーバーー>URLデコーディングー>データベースのためのエスケープ処理ー>データベースー>データベース出力のアンエスケープー>PHPでJSONのためのエスケープ処理ー>URLエンコーディングー>クライアントー>URLデコーディングー>JSONデータのパースー>JSONデータのアンエスケープ処理

実際はたくさんの文字列処理が行われているが、Ajax でデータ通信するためのユーザのプログラムは、上に述べたような2文字のエスケープとアンエスケープ処理だけで済むようだ。しかしエスケープに次ぐエスケープになるので思いもかけない副作用があるかもしれない。Ajaxによるデータの受け渡しには要注意だ。
[PR]
by tnomura9 | 2007-10-31 12:56 | XAMPP | Comments(0)

Ajax とエスケープの悩ましい関係

JSON で改行が使えなかったので、XML で通信して改行が使えるようになったが、今度は文字列に < や > が入るとパースできなくなってしまった。

結局のところ文字列を何らかの形でエスケープしないとどこかで不都合が起きてしまう。エスケープを行う関数を自前で用意するのは面倒なので、サーバの側でPHPでエンコードし、クライアントの側で JavaScript でデコードするという形になるだろうが整合性が心配だ。

さらに、PHP で echo 出力してもネットワークに流すために、自動的なエンコードがしてあるだろうから、エンコードのエンコードになったときに副作用が起きてこないかも心配だ。

なんとも悩ましい Ajax と エスケープの関係なのだ。

これを解決するいい方法がある。Ajax とエスケープの関係には皆が悩んでいるはずなので、きっと、誰か詳しい人が解決法を示してくれるだろう。それを待つのである。

しかし、そうは言っても、例えばブラウザーでインターネットの記事を見ていて記事の一部を保存しておきたくなったとする。そのときブラウザーのツールバーをクリックするだけで、データベースに書き込むタブを表示できて、元記事からコピペできて、それがそのままデータベースに登録できて、後で検索できるようになったとしたらと考えただけでもわくわくする。

当分、Ajax と エスケープの悩ましい関係に翻弄されながら悩みそうだ。
[PR]
by tnomura9 | 2007-10-30 17:07 | XAMPP | Comments(0)

データ通信にXMLを使う

JSONで改行の問題に悩んでいたので、思い切ってXMLに挑戦した。

まず、XML入門のページを流し読みしたが何のことかさっぱり分からなかった。そこで、Ajax, PHP, XML, JavaScript などで検索してサンプルプログラムをあさっていたら、何のことはない、XMLパーサはブラウザが内蔵していた。

受信は、Ajaxのときに obj.responseText で受信データをテキストとして取得していたのを、

xml = obj.responseXML

としてXMLオブジェクトを取得するだけだった。あとは、

var a = xml.getElementsByTagName('tagname')[0].firstChild.nodeValue

でデータを取り出すことができる。

送信のほうはPHPから、

header('Content-type: application/xml');
echo '<?xml version="1.0" encoding="utf-8" ?>';
echo '<data>';
edho '<id>$id</id>';
echo '<name>$name</name>';
echo '<address>$adress</address>';
echo '</data>';

のように、echo を使ってXMLファイルを出力するだけだ。ドキュメントルートになるタグ、この場合は<data></data>で最初と最後を括る必要があるがあとは、普通のHTMLのように書いていけばいい。dataもとくにこの名前でなくても何でもいいのだ。単にデータのやり取りだけなら、DTDはいらなかった。

以上の点で改造したら、改行のあるデータも取り出すことができるようになった。通信用のモジュールは足元に転がっていたのだ。
[PR]
by tnomura9 | 2007-10-30 00:59 | XAMPP | Comments(0)

JavaScript eval() の奇妙な行動

ネットワークプログラムのサンプルで、改行を含むデータが取り出せない原因が分かった。どうも JavaScript の eval() で JSON をオブジェクト化するときに、JSON のデータに改行が含まれているとうまく働かないようなのだ。たとえば

a = eval('{"test": "hello, world"}');
alert(a.test);

は動作しないが、

a = eval('({"test": "hello, world"})');
alert(a.test);

は動く。

ところが、

a = eval('({"test": "hello,\n world"})');
alert(a.test);

はまた動かなくなってしまう。いろいろ検索しているが、今のところうまい解決法がない。
[PR]
by tnomura9 | 2007-10-29 18:02 | XAMPP | Comments(2)

プログラムと思考

近くのファミレスに食事に行ったときテーブルにおいてあったカードに
土日休日
ソフトドリンク無料
ただし、中学生まで

と書いてあった。

これはプログラムできるなと思って頭の中で作ってみた。
if (today == 'Sat' or today == 'Sun' or today == 'holiday')
  if (age <= 15 )
    puts 'ドリンク無料'
  else
    puts '有料’
  end
else
  puts '有料’
end

プログラムのほうが冗長だが、これをコンピュータにかけると、どんな条件を入れても即座に判断してくれる。

このところ久しぶりにプログラミングに熱中したが、知らないことが多かったのでネット上のサンプルプログラムを片っ端に探して試した。そのとき、いきなりプログラムを読むよりも、まず、コピペして動かしてどういう動作をするのか大体理解してから、再度プログラムを読んだほうが分かりやすいのに気づいた。

プログラムは複雑な論理の糸の塊だが、コンピュータはそれを忠実に実行してくれるので大まかな動作をあらかじめ見てから、細かい論理構造を見ていけばよく分かるのは当然といえば当然だ。

一方、現実の作業も、契約や診断やこれまた複雑な論理の糸の絡まりを認識しながら作業していかなければならない。それでは、いったん機械にモデルを作ってシミュレーションしてから考えたほうが効率がよさそうだがそうはいかないのだ。

プログラムを作るのは簡単だが、作る時間の何倍もの時間をデバッグに使わないといけない。文末のセミコロンが抜けていたのを発見するのに何十分もかかったりするのだ。論理構造とは別のところで効率が落ちてしまう。

Rubyが使いやすいのは、文末にセミコロンがいらないだけで、デバッグの時間が激減するのもその理由のひとつではないかと思う。また array.each のようなイテレータのおかげで、配列の要素全部に操作を加えるのに、配列の要素の総数をしらべたり、使い捨てるためのindexを導入したりという操作がいらない。そのために、バグが紛れ込む可能性が激減するのだろう。

現在のプログラムが、デバッグに悩まされるのは、論理構造とは関係のないところで冗長性が増し、エラーが混入する確率が増加するからだ。簡潔に論理構造を記述できる言語が現れたら、自分で考える前にまず機械に推論させてみる時代が来るかもしれない。
[PR]
by tnomura9 | 2007-10-29 07:39 | 考えるということ | Comments(0)

ウェブアプリケーション

土日の二日を潰して、XAMPPを利用したウェブアプリケーションのサンプルを作った。

目標としたのは、クライアント部分と、通信部分と、データベース処理部分を独立させること。Ajaxを使って、日本語の文書を処理できるようにすることだ。サーバとクライアントの間のデータのやり取りはXMLの知識が全くないので、JSONにした。

クライアントのレイアウトは、HTMLとJavaScriptだけを使うようにし、PHPにはデータのやり取りだけを分担させるようにした。クライアントのレイアウトとデータの送受信を完全に分けたので、レイアウトの変更が非常に楽にできた。また、PHPもデータの送受信とデータベースとのインターフェースに専念させたので、レイアウトの変更を全く気にしないですんだ。

デバッグのときのエラーメッセージは、PHPの場合は、PHPからの出力をDOMでテキストエリアに表示させるようにしたら分かりやすかった。JavaScriptの場合は document.write を使ったら、勝手にWindowを開いて変数をダンプしてくれる。また、ファイアーフォックスのエラーコンソールも役に立った。

久しぶりにまとまったプログラミングをしたが、それで感じたのは、RubyとCのプログラムの経験がかなり役に立ったことだ。PHPは今回初めて使ったし、JavaScriptの経験もあまりないが、プログラムのほうは、Rubyを使っていたときの発想で作っていると自然に、すっきりしたものになっていく。また、Object思考のプログラムは参照を多用するが、Cのポインタの知識があったので、内部的に何が行われているのかが想像できた。

RubyとCをしっかり学べば、自然にいいプログラムを書くコツのようなものができるのではないだろうか。プログラム言語が思考のパターンを形作るのかもしれないという面白い経験をした。

作ったのは簡易QアンドAのデータベースで、解答部分を消したり出したりできるようにした。Ajaxを使いたかったので日本語は utf-8 を使うことにした。コマンドプロンプトから mysql を使うと、文字化けするが、ブラウザから使う分には OS が Vista のためか、入力の漢字変換も問題なくできる。また、日本語を使うためのMySQLの設定は全く必要なかった。検索は id からしかできないが、検索のプログラムは別に作ったほうが楽かもしれない。

クライアント部分は、HTMLとJavaScriptを使うと、びっくりするほど簡単に作ることができる。問題は通信の部分でそのあたりの知識が全くないのでまだ安定性にかけるようだ。例えば、テキストエリアに改行があると、データを取り出せなくなってしまう。データベースのほうはたいしたテーブルもないので、SQL が少し分かれば不満はない動作をしてくれる。

結局のところ、通信部分を担う汎用のモジュールがあれば、日曜プログラマでもデータベースをプライベートネットワークで使うプログラムなら、それほど、苦労せずに作れるのではないかと思った。

つまり、ブラウザの側から、JavaScriptのオブジェクトを送ると、サーバーの側で、PHPやPerlやRubyのオブジェクトにしてくれる、またその逆もやってくれる。通信の際の特殊文字のエスケープに関してもエンコードやデコードを引き受けてくれて、ユーザはそれを全く意識しないで使うことができるようなものだ。

XAMPPにそのようなパッケージが載っていたら、ある程度HTMLやスクリプトがかけるだけでずいぶん色々なことができるようになるのではないだろうか。

それでも、一度データベースのプログラムに挑戦してあきらめたのから考えたら、ずいぶんと楽になったものだと思う。いい時代になったものだ。
[PR]
by tnomura9 | 2007-10-28 21:34 | XAMPP | Comments(0)

一番簡単なAjax

Ajaxとは要するにブラウザの画面を更新せず、データの一部だけを変えることができる技術のことだ。画面は変わらないのでネットワーク型のプログラムなのに、スタンドアロンのプログラムを使っているようなルック・アンド・フィールを持たせることができる。

Ajaxの本質はボタンを押すなどのイベントが発生したとき、クライアントの画面を変えずにサーバーとクライアントとのデータ通信を行う技術ということだ。ウェブアプリケーションの3つの構成要素のうち、通信の部分に関係している。ただし、form の場合は PHP が担当していたが、Ajaxの場合はJavaScriptで記述するという違いがある。

AjaxをJavaScriptで記述し、かつ、クライアントのソフトの違いを吸収するようにプログラムするのはたいへんだが、prototype.js を利用するとかなり楽になる。次のプログラム updater.html はボタンを押すと画面を変更せずにHTMLだけを差し替えるプログラムだ。prototype.js の Updater というクラスを使って HTTP 非同期通信を行い <div> タグの中身を greeting.html の内容で置き換える。プログラムの動作のためには prototype.js をダウンロードして同じディレクトリーに入れておく必要がある。日本語も使えるが sjis だと文字化けするので utf-8 を使う必要がある。

プログラムファイル名: updater.html

<script src="prototype.js"></script>
<script>
function getHTML()
{
var url = 'greeting.html'
var pars = '';

var myAjax = new Ajax.Updater(
'placeholder',
url,
{
method: 'get',
parameters: pars
});

}
</script>

<input type="button" value="GetHtml" onclick="getHTML()" />
<div id="placeholder"><h2>Hello<h2></div>

プログラム名: greeting.html

<h1>Hello, World</h1>
[PR]
by tnomura9 | 2007-10-26 11:56 | XAMPP | Comments(0)

メモ帳プログラム

<?php
/*
ブラウザからサーバーにアクセスして簡単なメモのログをとるプログラムを作った。タイトルとメモ欄に記入して送信ボタンを押すと、メモがサーバーのログファイルに書き込まれ、同時にブラウザの画面も更新される。この簡単なプログラムを元に、ウェブアプリケーションが、インターフェース部分、通信部分、サーバーの処理部分の3つの独立した部分からできていることを示す。このプログラムのファイル名は memo.php で、他にログを書き込む memo.txt というテキストファイルを同じディレクトリに用意しておく必要がある。

注意! このプログラムはサンプルプログラムです。複製改変など自由に使用してかまいませんが、エラー処理もセキュリティ対策もしていないので使用者の責任で使用してください。
*/

$MEMO = 'memo.txt';

/*
次の部分がフォームからのデータを受け取る部分。連想配列$_POST から input タグの name フィールドをキーに取り出すことができる。クライアントとの通信の際に特殊文字はエスケープされているからstripslashes() 関数を使ってエスケープを解除している。
*/

$title = stripslashes($_POST["title"]);
$memo = stripslashes($_POST["memo"]);
$memo = mb_ereg_replace("\r\n", "<br>\r\n", $memo);
$date = date("Y/m/d H:i:s");

/*
次が、処理の本体。受け取ったデータをログファイルに追加している 
*/

if ($title != "" or $memo != "") {
$prev = file($MEMO);
$fp = fopen($MEMO,"w");
fputs($fp,"$title <$date><p>$memo</p><hr>\n");
foreach ($prev as $line) { fputs($fp,$line); }
fclose($fp);
}

/*
ここからは、操作者とのヒューマンインタフェースの部分。HTML で記述するので簡単だ。フォームの中にもPHPのプログラムが存在しているが、フォームを表示するときの動的な部分で実際にはブラウザでの表示の一部である。
*/

?>
<html>
<head>
<title>アイディアメモ</title>
</head>
<body>
<form method="post" action="memo.php">
タイトル:<input type="text" name="title" size="70" tabindex="1"><br>
メモ:<br>
<textarea name="memo" rows="10" cols="80" tabindex="2"></textarea><br>
<input type="submit" value=" 記録する ">
</form>
<hr>
<?php
$memo = file($MEMO);

if (count($memo) > 0) {
foreach ($memo as $line) { echo($line); }
}

/*、
このように、ウェブアプリケーションは、インターフェース部分、通信データのやり取りの部分、サーバー側の処理の本体というふうに分けて考えると見通しが良くなる。
*/
?>
</body>
</html>
[PR]
by tnomura9 | 2007-10-26 01:59 | XAMPP | Comments(0)

ウェブアプリケーションの分解

ウェブアプリケーションは、

  1. ユーザとのインターフェース部分
  2. ブラウザーとサーバーとの通信の部分
  3. 処理の本体の部分

に分けることができる。

ユーザとのインターフェースの部分はブラウザで行うことになる。ブラウザ側の表示やコントロールを記述するのはHTMLとPHPおよびJavaScriptの役目になるが、HTMLだけでも基本的なレイアウトなら十分だ。

ブラウザとサーバーとのデータのやり取りはURIの呼び出しと、フォームの送受信によることになる。フォームのデータはPHPを使えば簡単に連想配列として取り出すことができるので、データの送受信についての設計はフォームの<input>要素の name 属性を何にするかということだけになる。ボタンによる操作は JavaScript で記述しても難しくはないし、Ajaxを使う場合も、prototype.js などをインクルードすれば単純なものなら作ることができる。

データ処理のほうだが、データベースとの接続はPHPで簡潔に記述できる。mysql でSQLを記述できるようになれば、基本的な検索機能なら十分にもたせることができる。

ウェブアプリケーションを上のような3つの部分に分けて、それぞれに部品となるシンプルな関数を作ってテストしておけばそれを組み合わせたり拡張したりすることで、きちんと動くウェブアプリケーションを作ることができるのだ。

結局のところ、自分のために使うためだけのプログラムで、凝ったことをしなければ、ウェブアプリケーションを作るのはそう難しいことではないようだ。基本的なプログラムとしてどんなものが考えられるのかまだ作っていないが、すくなくともブラウザから SQL でデータベースを操作するプログラムは作れている。これから少しずつ作りためてみようと思う。
[PR]
by tnomura9 | 2007-10-25 18:18 | XAMPP | Comments(0)