Browsing the archives for the PHP category

リアルタイム同期チャット

今回はリアルタイムな同期チャットを作ってみました。

考え方的にはぐーぐるさんが使ったことで有名なコメットとよく似ています。

ただPHPを使ってやりたかったのでcometは用いません。

そもそもコメットの特徴はクライアントサイドからサーバーへの要求の投げかけを一回にしてるところなのでその一回を半無限ループ使って常時接続状態にすればいいわけです。

以下がソースです。

index.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="content-script-type" content="text/javascript" />

<link rel="stylesheet" href="css/main.css" charset="utf-8" type="text/css" />
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/chat.js"></script>
</head>

<body>
<div class="chat" id="chat"></div>
		<div class="commentarea" id="commentarea">
        	<textarea class="comment" id="comment"></textarea>
			<input type="button" class="submit" value="発言" onclick="remark();" />
        </div>

</div><!-- end Chat Program -->
</body>
</html>

chat.js

$(function(){
	$("#submit").click(remark);
	$.post("get_chat_log.php",{},get_message,"text");
});

function remark(){
	var txt = $("#comment").val();
	$.post("write_chat_log.php",{name:"oppai星人",message:txt});
	$("#comment").val("");
}

function get_message(text){

	var recs = eval(text);
	n = recs.length;

	for(var i = 0; i<n; i++){
		data = $("#chat").html();
		$("#chat").html(data +"<span class=\"name\">" +recs[i]["name"]+"</span> さんの発言:<br />"+"<span class=\"message\">"+recs[i]["message"]+"</span><br />\n");
	}
	$.post("get_chat_log.php",{},get_message,"text");
}

get_chat_log.php

<?php
set_time_limit(0);

$file_name = "log/chatlog.txt";

//ファイルの最終更新時間を取得
$o_time = filemtime($file_name);
$o_filesize = filesize($file_name);

while(TRUE){

	//キャッシュ削除
	clearstatcache();

	//今現在のファイルの最終更新時間を取得
	$n_time = filemtime($file_name);

	//アクセス時の最終更新時間と比較
	if($o_time!==$n_time){
		$n_filesize = filesize($file_name);
		$fp = fopen($file_name,"r+");
		$fp2 = fseek($fp,$o_filesize);

		//通常ファイルサイズ文読み込むがEOFになると終了する。
		$body = fread($fp,$n_filesize);
		fclose($fp);
		break;
	}
	//遅延
	sleep(1);
}

$new_line = explode("\n",$body);
$n = count($new_line);

$res = array();

for($i=0; $i<$n; $i++){
	$data = explode(">",$new_line[$i]);
	$account = $data[0];
	$message = trim($data[1]);

	$message = str_replace("&gt;",">",$message);
	$message = str_replace("&lt;","<",$message);

	$arr = array("name"=>$account,"message"=>$message);
	array_push($res,$arr);
}

$n = count($res);

$txt ="";
for($i=0; $i<$n-1; $i++){
	if($i==0 && ($n-1)!=1){
		$txt .= '\'[{"name":"'.$res[$i]["name"].'","message":"'.$res[$i]["message"].'"}';
	}elseif($i==0 && ($n-1)==1){
		$txt .= '[{"name":"'.$res[$i]["name"].'","message":"'.$res[$i]["message"].'"}]';
	}elseif($i==$n-2){
		$txt .= ',{"name":"'.$res[$i]["name"].'","message":"'.$res[$i]["message"].'"}]';
	}else{
		$txt .= ',{"name":"'.$res[$i]["name"].'","message":"'.$res[$i]["message"].'"}';
	}
}

echo $txt;
?>

write_chat_log.php

<?php
$name = $_POST["name"];

$msg = str_replace("\n","<br />",$_POST["message"]);
$msg = htmlspecialchars($msg,ENT_QUOTES);

$body = $name.">".$msg."\r\n";

$file_name = "log/chatlog.txt";

$fp = fopen($file_name,'a');
fwrite($fp,$body);
fclose($fp);
echo $body;
?>

以上の4ファイルです。

index.htmlのページ読み込みと同時にchat.js内でget_chat_log.phpへのajax通信が始まります。

set_time_limit関数の引数に0を代入することでphpの実行時間の制約を無限大に伸ばしてます。

そしてwhile(true)を用いて無限ループ。
sleepで引数時間に一回ずつループします。
ログファイルに更新があればbreakして差分をjsのコールバック関数にjsonフォーマットで受け渡し、js側で整形して出力します。
出力後、またget_chat_log.phpにアクセスして次の更新を待ち続けます。

次に発言時、index.htmlのonclickイベントでchat.jsのremark関数が動きwrite_chat_log.phpにajax通信し、入力情報をログに書き出しします。

これでリアルタイムなチャットが更新されます。
まぁ結構サーバーに負荷かかりますが。笑

2 Comments
5月 7, 2010 in PHP, ajax, javascript

Linux上でのPHP開発環境

ほんとんど自分用のメモです。

ちょっとCent-OS上で二週間ほど開発しなきゃならない事態が起きたので開発環境の整え方をメモ

[.PHP]

もともとPHPは入ってるんで最新版にアップします。
と、ここで問題が。
CentOS3.4ではyumでいれられるPHPが5.1x?(小数点第二位は忘れた)までなんですね。
MySQLをphpMyAdminで扱うときにphpMyAdminの最新版はphp5.2x以降じゃないとうまく動作しないんですね。
そのためにちょっといじります。

まずレッドハッドのパッケージマネージャーからRPM-GPG-KEYをインポートしてきます。

# rpm –import http://www.jasonlitka.com/media/RPM-GPG-KEY-jlitka

リポジトリの設定します。

# vi /etc/yum.repos.d/utterramblings.repo

viでファイル開くんで下をこぴぺで貼り付けして保存

[utterramblings]
name=Jason’s Utter Ramblings Repo
baseurl=http://www.jasonlitka.com/media/EL$releasever/$basearch/
enabled=1
gpgcheck=1
gpgkey=http://www.jasonlitka.com/media/RPM-GPG-KEY-jlitka

それからphpアップデートします。

# yum update php

そしてapache再起動

# service httpd restart

[MySQL]

そして次にMySQL

これもyumでインストールできます。

# yum install mysql-server

MySQL起動してログインしてさらにパスワード設定します。

# service mysqld start
# mysql

mysql> set password for root@localhost=password(‘ここにパスワード設定しよう。’);
mysqlから離脱
mysql>\q

次からMysqlにはいるときは

# mysql -u root -p

と入力します。 するとパスワード求められるので設定したものを入力してエンターすればおk

それからmysql拡張もいれときます。 これもphpMyAdminで必要になってきます。

# yum install php-mysql

そしてまたアパッチ再起動

# service httpd restart

[PhpMyAdmin]

phpmyadminを入れたいけどその前にphp-mbstringとphp-mcryptがないとエラーおきるとかいうことをどこかの賢い人がいってたのでインスコ

# yum -y install php-mbstring
# yum -y install php-mcrypt

そしてまたアパッチ再起動

# service httpd restart

ほんでPHPmyadminのダウンロード

2010/05/06現在じゃphpMyAdmin-3.3.2-all-languages.tar.gzってのが最新っぽいのでこれをダウンロード。
最新情報はここでわかります。

# wget http://jaist.dl.sourceforge.net/sourceforge/phpmyadmin/phpMyAdmin-3.3.2-all-languages.tar.gz

解凍、そしてdocs内に移動、apache様が触れるように権限変更

# tar zxvf phpMyAdmin-3.3.2-all-languages.tar.gz
# mv phpMyAdmin-3.3.2-all-languages /var/www/phpMyAdmin
# chown -R root.apache /var/www/phpMyAdmin/

設定ファイルの作成(アクセス権とエイリアスの設定)

# vi /etc/httpd/conf.d/phpMyAdmin.conf
Alias /phpMyAdmin "/var/www/phpMyAdmin"

<Directory "/var/www/phpMyAdmin">
    order deny,allow
    deny from all
    allow from 127.0.0.1
</Directory>

一応これで動くはずなのでアクセス。

http://localhost/phpmyadmin

アカウントはroot , さっきmysqlのところで自分が設定したパス

[Eclipse]

ここからEclipse IDE for Java EE Developers の中の Linux 32bit を選択してダウンロードします。

なんか周りみてると /usr/local/share/に設置してる人が多いのでmv使ってダウンロードしたtar.gzファイルを移動します。
そして解凍

# tar zxvf eclipse-jee-galileo-linux-gtk.tar.gz (ファイル名は若干異なるかも)

普通ならこれでもう動かせるんだけどCentOSにはSun純正のJava SDKが入ってないとかで動かないらしいのでここから純正をとってくる。

そしてまたmv使って /usr/local/share/ に移動させます。

そして権限変えて解凍して実行しちゃいます。 バージョンが微妙に違うとかあれば各自補間してください。(2010/05/06現在はこれでいい)

# chmod a+x jdk-6u20-linux-i586-rpm.bin
# ./jdk-6u20-linux-i586-rpm.bin

これでうまく動くはずなのでEclipseを動かします。(jdk1.6.0_20はDLしたバージョンによって違うので確認してください。)

# /usr/local/share/eclipse/eclipse -vm /usr/java/jdk1.6.0_20/bin/java &

うまく立ち上がるとワークスペース聞かれるんで /var/www/html/ らへんにしといたら楽です。

起動コマンドが長いのでエイリアスつけときます。

# alias eclipse='/usr/local/share/eclipse/eclipse -vm /usr/java/jdk1.5.0_06/bin/java &'

これで
# eclipse
とすりゃEclipse立ち上がります。 

しかしこのままではElipseはPHPファイル作れません。 この記事のタイトルPHP開発環境なのに。

そもそもEclipseいれるなら何故 Eclipse for PHP Developers いれないの?って話ですよね。
なんかまだ開発中で不安定らしく、Eclipseからプラグインで「phpeclipse」なるものを入れたほうがいいとのこと。

ちなみにphpeclipseはSourceForge.netさんのところにあります。
これをダウンロードしてきて解凍します。

# unzip PHPEclipse-1.2.3.200910091456PRD-bin.zip

すると「plugins」「features」の二つのフォルダがあります。
この中にcdコマンドで移動します。

中身をEclipseの「plugins」「features」に全部いれちゃいます。

まず(ダウンロードして解凍したほうの)pluginsフォルダに入って全部Eclipseにいれちゃいます。

# cd plugins
# mv * /usr/local/share/eclipse/plugins/

次にfeaturesも同様に移し変えます。

# cd ../features
# mv * /usr/local/share/eclipse/features/

これで
#eclipse
でphpファイル作れるようになってます。

よかったね! jsとかも追記していきます。

No Comments
5月 6, 2010 in Linux, PHP

GDライブラリを用いたサムネイル生成

どんどん先延ばしにしていましたが、ようやくまとまった時間がとれたので公開します。

投稿された画像のサイズをいじるためのプログラムです。

PHPには画像編集用のライブラリ(GDライブラリ)が存在してるのでこれを使ってサムネイルを生成します。

具体的にはこんな感じ

「参照」でサイズ変更する画像を選択し、「リサイズ」を押してください。
JPEG,PNG,GIFに対応しています。(一応透過情報も保持するようにしています。)

つくったソースは以下の二つ

  • test.php
  • class.resize.php

test.php

<?php
require_once("class.resize.php");
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
<!--
	body{color:#ffffff;}
-->
</style>
</head>
<body bgcolor="#000000">

<form action="test.php" method="post" enctype="multipart/form-data">
	<input type="file" name="userfiles" />
    <input type="submit" value="リサイズ" />
</form>

<br /><br />

<?php
if(!$_FILES['userfiles']['size'] == 0){

	$updir = "./uploads/";
	$resizedir = "./resize/";

	$filename = $_FILES['userfiles']['name'];
	$filepath = "./uploads/".$_FILES['userfiles']['name'];	

	if(!move_uploaded_file($_FILES['userfiles']['tmp_name'],$filepath)){
		die("アップロードに失敗しました。");
	}

	$size = getimagesize($filepath);

	echo "元ファイル\n<br />\n width:".$size[0]."px \n <br> \n height:".$size[1]."px \n <br />\n";
	echo "<br />\n<img src=\"{$filepath}\" />\n<br />\n";

	//サムネイルのwidthを200pxとする

	$height = $size[1] * (200 / $size[0]);

	$resize = new Resize();
	$resize->img_resize($filename,$updir,200,
                         ceil($height),$resizedir,100);
	echo "<br />リサイズ後の画像<br />\n";

	$size = getimagesize($resizedir.$filename);

	echo "width:".$size[0]."px \n<br>\n height:".$size[1]."px\n<br />\n";
	echo "<img src=\"resize/{$filename}\" />\n";
}
?>

</body>
</html>

class.resize.php

<?php
class Resize{

	public function __construct(){}

	public function __set($prop,$val){
		echo "error : 存在しないプロパティ{$prop}に、値{$val}を設定しようとしています。\n";
	}

	public function __get($prop){
		echo "error : プロパティ{$prop}は存在しません\n";
	}

	public function __call($func,$params){
		echo "error : 存在しない関数{$func}が呼び出されました。\n";
		var_dump($params);
	}

	public function img_resize($filename,$path,$thumb_width,
					$thumb_height,$savedir,$quality){
    	$img_size = getimagesize($path.$filename);

		switch($img_size['mime']){
			//それぞれ元画像のリソースIDを返す
			case "image/jpeg":
			case "image/pjpeg":
				$img = @imagecreatefromjpeg($path.$filename);
				//リサイズ後の画像のリソースIDを返す
				$cp_img = imagecreatetruecolor($thumb_width,
									$thumb_height);
				break;

			case "image/gif":
				$img = @imagecreatefromgif($path.$filename);
				$cp_img = imagecreatetruecolor($thumb_width,
									$thumb_height);
				$scal_index = imagecolortransparent($img);

				if(!$scal_index>=0)break;//透過色がなければbreak

				//第二引数は色相近似の向上のためのディザon
				imagetruecolortopalette($cp_img, true, 256);
				$trnprt_color = imagecolorsforindex( $img, $scal_index);
				imagecolorset( $cp_img, 0, $trnprt_color['red'],
				$trnprt_color['green'],$trnprt_color['blue']);
				imagefill( $cp_img, 0, 0, 0 );
				imagecolortransparent( $cp_img, 0);
				break;

			case "image/png":
				$img = @imagecreatefrompng($path.$filename);
				$color_num = imagecolorstotal($img);
				$cp_img = imagecreatetruecolor($thumb_width,
									$thumb_height);
				$scal_index = imagecolortransparent($img);
				if(!$scal_index>=0)break;
				imagetruecolortopalette($cp_img, true, $color_num);
				break;

			default:
				return FALSE;
		}

		//imagecopyresized->返り値:bool , 第1引数のIDにリサイズしてコピーする。
		$res = imagecopyresampled(
			$cp_img,
			$img,
			0,
			0,
			0,
			0,
			$thumb_width,
			$thumb_height,
			$img_size[0],
			$img_size[1]
		);

		if(!$res)return FALSE;

		switch($img_size['mime']){
			//それぞれ元画像のリソースIDを返す
			case "image/jpeg":
			case "image/pjpeg":
				imagejpeg($cp_img,$savedir.$filename,$quality);
				break;
			case "image/gif":
				imagegif($cp_img,$savedir.$filename);
				break;
			case "image/png":
				$quality = ceil($quality * 0.09);
				imagepng($cp_img,$savedir.$filename,$quality);
				break;
		}
		//メモリ開放
		imagedestroy($cp_img);
		imagedestroy($img);
    }
}

?>

とこんな感じです。

test.php解説
まず1~3行目でサムネイル生成用のクラスを呼び出しています。
16~19行目までがサムネイルの元となる画像のアップロード用のformを生成しています。

24行目の条件分岐はファイルがPOSTされている場合に動くというものです。

25~34行目がファイルのアップロードです。
ファイルアップロードを行う関数、move_uploaded_fileは第一引数に現在のファイルパス、第二引数にアップロード先のファイルパスになります。
返り値は成功、および失敗をしめすBoolean値です。
基本的にPOSTで送られてきたファイルというのはサーバー内のテンポラリーファイル内に保存されます。
$_FILES['name']['tmp_name'] でアクセスできます。
ちなみにnameはformのinput type=”file”で設定したnameに相当します。

36行目のgetimagesizeで元のファイルの横幅、縦幅を獲得します。
getimagesizeの返り値は配列になっており キーは0,1,mimeの三つです。
0が横幅 1が縦幅 mimeがMIMETYPEになります。

43行目はサムネイル後のサイズを算出しています。
今回は横幅を200pxにあわせています。
この行の数式はアスペクト比を保持した縦幅の算出を行っています。

45行目でリサイズ用のクラスをインスタンス化しています。
46行目でリサイズクラスのサムネイルを作るための関数img_resize(ユーザー定義関数)を使ってサムネイルを生成しています。
引数は1.画像の名前 2.保存されているディレクトリのパス 3.サムネイルの横幅 4.サムネイルの縦幅 5.サムネイルの保存先ディレクトリのパス 6.画質(0~100 単位:%)

class.resize.php解説

6~17行目の__set , __get , __call で存在しないプロパティ、関数を呼び出したときの処理を書いています。

19行目のimg_resize関数がサムネイルを作成する関数になります。

23行目はファイルの種類をmimeから判定して、それぞれ種類に応じて処理を行っています。

25~26行目はjpeg画像の分岐ですが26行目のpjpegというのが曲者で、IEでプログレッシブJPGをアップロードしたときにこんなMIMEタイプがでてきます。 処理は同じなのでまとめています。

27行目でimagecreatefromjpeg関数で元画像を現すIDを取得します。
29行目がリサイズ後の画像を表現するIDの取得です。
(まだ現時点では真っ白の画像)

gif,pngはこれに加えて imagecolortransparent関数を用いて画像内の透過カラーが存在するかどうかを調べ、存在すればそれを元にリサイズ後の画像で透過を保持するように処理を行っています。

65行目はimagecopyresampled関数を用いた画像のリサイズです。
よく似た処理をする関数にimagecopyresized関数というものがありますが、256色までしか表現できないというものなのでimagecopyresamped関数を用いています。

そして80~92行目がリサイズ後のファイルの書き出しです。
imagejpeg関数の第3引数は画質の%ですが0~100なのでimg_resize関数の引数をそのまま使っておkです。

pngの方も書き出しの関数imagepngで第3引数が画質の値をとるのですが、これは0~9までの値です。
img_resize関数の画質の引数は0~100なので0.09倍して整数になるように切り上げする処理をいれています。

最後の95~96行目はメモリの開放です。
やたらめったにメモリ食う処理なので必ず開放してあげましょう。

3 Comments
1月 7, 2010 in PHP

ありがちな勘違い

PHP素人(僕みたいなやつ)のありがちな勘違い

①header関数

勘違い)用途は別ページにジャンプするためのもの。 どこにいれてもいい。

<?php
 header('Location:path');
?>

よくこんな使い方でページのリダイレクトさせてますが、header関数の使い方の一つに過ぎません。

大前提はHTTP ヘッダの送信に必要な関数なので、別に第一引数にLocationとせずに

<?php
 header('Content-type: image/png');
?>

とかしちゃうとそのページがpngファイルとかになっちゃうんですね。
まぁ後続にimagepng()とかで出力せんといけませんが。

まぁそんな感じでリダイレクトってのはヘッダ送信時の副産物で本当の用途はHTTPヘッダ送信のためのものです。
ヘッダ送信ってのはすべての出力の前にないといけないものなので当然前にechoとかの何かしらな出力があるとエラーがでます。
ありがちなミスはinclude と require_once とかでファイル引っ張ってくるときに引張先でエラーがあってheader関数に怒られるとかです。

②(MySQL) char型とvarchar型の違い

php素人(僕みたいなやつ)はとかくDBを扱う機会が多いくせにあまり定義を知らなかったりします。
特にcharとvarchar何が違うんやろ? 別にvarchar使っといたらええかな とか投げやりな理解をしてしまいがちです。

二つの違いは固定長であるか可変長であるか。
char : 固定長
varchar : 可変長

といってもとっつきにくい日本語ですよね
テーブル作成時にフィールドでそれぞれ長さを指定しますがcharで5の長さとvarcharで5の長さを指定した時の違いを例にとって考えます。

前者char型で “abc” というデータを放り込むと ”abc__” というデータが格納されます。(_はスペース)
これは5の長さをめいいっぱい使うっていう固定長の特徴です。
abcは三文字なので残りの2文字分をスペースで埋めます。

それに対しvarcharの方では “abc” というデータを放り込むと “abc” というそのままのデータが入ります。
可変長とは5文字以内という定義なのです。
PHPエンジニアはchar型を使うとデータをMySQLからとってきたあとに文字列操作とか必要になるので特にきまりがないかぎりvarcharを使う機会がほとんどでしょう。

③include()とrequire()の違い

両方ともファイルの読み込みに使う関数です。
基本的には同じですが両者の違いはエラーを出したときに明確になります。

includeの方はファイルが見つからないときに「Warning」を返します。
requireの方はファイルが見つからないときに「fatal error」を返します。

つまりincludeのほうはもしファイルがみつからなくても後続の処理が動きますがrequireの方はファイルがないとエラーで止まります。

include関数

<?php
 include("aiueo.php");
 echo "include関数";
?>

require関数

<?php
 require("aiueo.php");
 echo "require関数";
?>

結果:include , require

前者のincludeは後続の処理(echo “include関数”;)が出力されてるのに対し、require側ではエラーのみで出力がありませんね。
読み込むファイルが存在することが不明確な場合はincludeを使うといった感じに使い分けましょう

ちなみに _once をつけると(include_once , require_once)そのファイルがすでに読み込まれてるかどうかを評価してくれます。
ファイルが見つからないときの評価はinclude関数とrequire関数のときの違いと同じです。

No Comments
1月 3, 2010 in MySQL, PHP

開発環境のバージョンあれこれ。

本日、就職先(現状:内定)の同期からWEBのことでたたき起こされた。

内容はMySQLからPHPに値引っ張ってきたときに文字化けが生じるとのこと。

過去に数100回ほど頭を悩まされていて解決策をしっていたので紹介

SQLのSELECT文で値を引っ張る前にデータベース側のエンコードをいじる。

SET NAMES utf8

これで解決

と思ったら
「Unknown system variable ‘NAMES’」って言われたらしい

んなばかなとおもってMySQLのバージョンを聞いてみると「mysql-4.0.20c-win」を利用しているとのこと。

調べてみるとMySQL4.0以前と4.1以降ではエンコードの仕様に断絶があるらしく4.0以前はサーバー全体での文字コード定義しかできないらしい。
というわけでSET NAMESは当然使えない。

ならばPHP側でmb_convert_encoding()を使ってSQLをEUC-JPに、返された値を同様に今度はUTF8に変換すればいい。

つまり

$sql = "SELECT `field1` from `Table`";
$sql = mb_convert_encoding($sql, 'EUC-JP');
$res = mysql_query($sql);

こんな感じでSQLを発行し、

while($data = mysql_fetch_array($res,MYSQL_ASSOC)){
    $field1 = mb_convert_encoding($data['field1'], 'UTF8');

    //処理
}

という風にする。

しかし、ここまでもまた問題が。

「Fatal error: Call to undefined function: mb_convert_encoding()」

mb_convert_encoding()が未定義の関数とかほざいてくるんですね。
そんなバカなことがあるかーっておもってPHPのバージョンを聞くとPHP4.3だとか。

なんでこうも古いのばっか使ってるのかと思ったら古い参考書についてた古いCDを使って開発環境を整えてしまったのが原因らしい。

まぁよくありそうな現象やなぁと思いながらも私、堪忍袋の緒がきれてしまいました。

Apache,MySQL,PHPをアンスコしてXAMPPで開発環境整えさせました。
強引ですいません。
アンスコウィザードのあるApacheと違ってMySQLの削除が曲者なので紹介しておきます。

まずCドライブ直下にMySQLフォルダがあると過程します。
MySQLは事前に停止しておいてください。

停止方法(cmd)

# net stop mysql

削除方法(cmd)

# CD C:\mysql\bin
# mysqld –remove MySQL

これでサクシードほにゃららってのが出たら一応アンスコに成功してます。
ただ、my.iniというmysqlの設定ファイルがサーバー内に残ってる可能性があるから
スタート→検索→[my.ini]でWINDOWSファイルやSYSTEMファイル以外の場所でmy.iniが見つかったら削除しといてください。

これでアンスコ完了です。

PHPに関しては別に設置ディレクトリさえ違えば競合するものではないので適当に削除してくれていいです。

No Comments
12月 31, 2009 in MySQL, PHP

Ajaxでデータベース更新

WEBサイトでDBを用いてシステム構築しているケースは多々あります。

使用するテーブルが1つならいいけど複数のテーブルを使用していて、更新の際にすべて変更しなきゃいけないときってめんどくさいですよね。

adminページ的なものを設けてもPHPで更新するとなるとページ遷移が必要になってTable1を更新→遷移→Table2を更新→遷移...みたいな。

というわけでこのページ遷移をなくす方法として非同期通信(Ajax)を使用する方法をあげときます。

一応例として作ったページはこちら

適当にフィールドにデータいれて修正ボタンを押してもらえたらDBの値が更新されます。
更新されたデータはテーブル情報のとこに出力されるようになってます。

まず用意するファイルは4つ

  • index.html
  • jquery.js
  • ajax_revise.js
  • revise.php

jquery.jsはJavaScriptのフレームワークです。 無料配布されてるのでこちらからダウンロードしてきて使用してください。

残りの三つは自分で勝手に作ってください。

ファイルの中身はこんな感じ

index.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="ajax_revise.js"></script>
<link rel="stylesheet" href="main.css" type="text/css" />
<title>ajaxでデータベース更新</title>
</head>

<body>
<div id="tableinfo"></div>

<br />

<div>
    <h4>修正フォーム</h4>

    <table>
    <tr>
    <td>field1</td><td><input type="text" width="5" id="data1" /></td>
    </tr>
    <tr>
    <td>field2</td><td><input type="text" width="5" id="data2" /></td>
    </tr>
    </table>

    <br />

    <input type="button" value="修正" id="revise" />

</div>
</body>
</html>

ajax_revise.js

// JavaScript Document
$(function(){
	$.post("revise.php",{},function(res){
		$("#tableinfo").html("テーブル情報<br />field1:"+res.field1+"<br />field2:"+res.field2)
		$("#data1").val(res.field1);
		$("#data2").val(res.field2);
	},"json");
	$("#revise").click(revise);
});

function revise(){
	a = $("#data1").val();
	b = $("#data2").val();

	$.post("revise.php",{field1:a,field2:b},function(res){
		$("#tableinfo").html("テーブル情報<br />field1:"+res.field1+"<br />field2:"+res.field2)
		$("#date1").text(res.field1);
		$("#date2").text(res.field2);
	},"json");
}

revise.php

<?php
$hostname="******";
$username="******";
$password="******";

$dbname="******";

$conn = mysql_connect($hostname, $username, $password) or die(mysql_error());
mysql_select_db($dbname) or die(mysql_error());  

$sql = "SET NAMES utf8";
$res = mysql_query($sql) or die(mysql_error());

if(isset($_POST['field1']) && isset($_POST['field2'])){
	$field1=htmlspecialchars($_POST['field1'],ENT_QUOTES);
	$field2=htmlspecialchars($_POST['field2'],ENT_QUOTES);

	$sql = "update `test20091230` set
		`field1` = '".$field1."' ,
		`field2` = '".$field2."'
	where `no` = '1'";

	$res = mysql_query($sql) or die(mysql_error());
}

$sql = "select * from `test20091230` where `no`='1'";
$res = mysql_query($sql) or die(mysql_error());

$data = mysql_fetch_array($res, MYSQL_ASSOC);

$values = array('field1' => $data['field1'], 'field2' => $data['field2']);

$json = json_encode($values);

mysql_free_result($res);
mysql_close($conn);  

echo $json;

?>

index.html
5~6行目でjQueryとajax_revise.jsを読み込んでいます。

7行目はCSSなのであってもなくてもいいです。 
見栄えが少しマシになります。

12行目はajax_revise.jsからhtmlを流し込むためのDivです。(セレクタは#tableinfo)
21、24行目に修正データを入力するinputタグを配置しています。

30行目でボタンを設置し、このボタンのクリックと同時に修正されるようにします。

ajax_revise.js
2行目の$(function(){ はindex.htmlがすべて読み込まれたあとに実行されることを保証されてる範囲です。

3行目でrevise.phpにPOSTで通信してます。 返された値はjsonでresに格納されます。

4~6行目でresをindex.htmlの各セレクタに流し込みます。

8行目はイベントリスナの登録です。 11行目以降がボタンをクリックされたときの動きになるのですが、こちらは$(function(){の範囲外ですのでindex.htmlが読み込まれる前に実行される可能性があり、#reviseを正常に解釈できない可能性があるので先に登録しておきます。

11行目以降は前述の通り、修正ボタンをクリックされたあとの動きです。

12~13行目で修正フォームに記入された値をとりa,bに格納。
それを引数として15行目でrevise.phpにまた値を送っています。

以下は2行目~の部分と大差ないので省略します。

revise.php
2~6行目にそれぞれ自分のデータベースのデータを入力してください。

8~9行目はmysqlに2~6行目で定めたデータを使ってアクセス。

11~12行目はmysqlのエンコードの設定です。 僕のDBは少し変なことしてしまったのでこれが必要になります。 なくても動く人もいるけどあっても変なことにはならないので触らないのが吉

14~23行目はindex.htmlでボタンをクリックされ、ajax_revise.jsでデータをPOSTで送られてきたときに動くところで、受け取った値でデータベースを更新しています。 ちなみに今回はレコード番号1を更新するという形にしました。

26~27行目で更新後あるいはPOSTでデータが送られていなければそのままのレコードをとってきます。

29行目でレコードのデータを$dataに格納しています。(今回はレコードが1つしかないのが自明なのでそのままの代入でおkです)

31行目でそれを連想配列で保管しています。

33行目でjsonに変換しています。
もともとjsonに変換する関数はPECLにあったんですがPHP5.2以降では標準で存在します。
なので自分のPHPが5.2以降ならこのままでおkです。 以前ならPECLから引っ張てきてください。

35~36行目でmysqlとの通信終了

38行目で生成されたjsonデータを出力

ちゃっちぃプログラムですがこんな感じで非同期通信でのデータベースが可能になります。
ajax_revise.jsで普通にjQuery使っちゃってますが意味不明なかたは日本語リファレンスがあったと思うのでそちらを参照してください。

1 Comment
12月 30, 2009 in PHP, ajax, javascript