ウィリアムのいたずらの、まちあるき、たべあるき

ウィリアムのいたずらが、街歩き、食べ物、音楽等の個人的見解を主に書くブログです(たま~にコンピューター関係も)

PHPでソケット間通信(クライアント側)

2008-01-18 18:17:06 | PHP

ここのブログ
phpのソケット通信
http://runaway.air-nifty.com/tubuyaki/2006/01/php_db51.html

を参考に、PHPでのソケット間通信をテストしてみました。

内容は、ローカル(127.0.0.1)のHTTPサーバーにアクセスし、Content-length分データを読み込み、データ部分を表示するというものです。

プログラムは、こんなかんじ
<?php
	$sock = fsockopen( '127.0.0.1', 80, $errono, $errmsg, 30 );
	$out = "GET / HTTP/1.1¥nHost: 127.0.0.1¥n¥n";

	//データ送信
	fputs($sock, $out);

	//データ受信
	$c =fread($sock, 1);
	$header = "";
	while ( strpos($header,"¥n¥n") === false )
	{
		if ( $c	!=	"¥r")
		{		
	  		$header .= $c;
		}
  		$c = fread($sock, 1);
	}

	//受信データを改行で分割
	$hline = array();
	$hline = split("¥n",$header);

	//	Content-Lengthを探し、データ長取得
	$datalen = 0;
	for($i = 0 ; $i < count($hline) ; $i++)
	{
		$lenpos = strpos($hline[$i],"Content-Length:");
		if ( $lenpos !== false )
		{
			$datalen = intval(substr($hline[$i],strlen("Content-Length:")));
			break;
		}
	}

	//	データがあれば読み込む
	if ( $datalen	>	0 )
	{
  		$data = fread($sock, $datalen);
	}

	//	読み込み内容を返す
	echo($data);

	fclose($sock);

?>

(上記< > ¥は、本当は半角です)


  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

オブジェクト指向で開発の最初から最後までの手順例-その43:雛形(16)。

2008-01-18 13:27:22 | 開発ネタ

一ヶ月ぶりくらいになりますが、オブジェクト指向で開発の最初から最後までの手順例です。

 現在、「いままでのまとめ」にある、「(4)フレームワークにもとづき、クラスなどの開発手順、雛形の確定」をやっています。前回、Viewの概要について説明し、JavaScript(AJAX)で、サーバーにアクセスし、データを取ってくるという説明をしました。そして、今回、その「サーバーにアクセスし、データを取ってくる」共通部分について、説明することになってました。今回はその説明です。




■プログラムの中身

 で、そのサーバーアクセスプログラムなのですが、こんなのを作ります。

●サーバーアクセス
(1)httpRequest(method,target_url,args,func)

<<引数について>>
method:"POST"または"GET"
target_url:アクセスするところ
args:引数を連想配列で
func:帰るときの関数

<<内容>>
 argsで渡された引数をエンコードし、target_urlにアクセスします。
 最終的に、アクセスしてうまくいくとfunc(httpObj)が呼び出されます
(httpObjは、結果のXMLです)

<<注意>>
 func(httpObj)で結果が返ってくるまで、同時に何回も呼びださないで
ください(httpObj、retFuncを外部変数で共通化してとっているので)

●結果処理
(2)getRetCode(xtree)

<<引数>>
xtree:(1)のhttpObjに対して、httpObj.responseXMLしたもの

<<内容>>
結果から、retcode(処理結果)を受け取ります


(3)getRecCount(xtree)

<<引数>>
xtree:(1)のhttpObjに対して、httpObj.responseXMLしたもの

<<内容>>
結果が検索型の場合、レコード数を取得します

(4)getRecItemValue(xtree,pos,tag)

<<引数>>
xtree:(1)のhttpObjに対して、httpObj.responseXMLしたもの
pos:何番目のレコード
tag:項目名のタグ

<<内容>>
結果が検索型の場合、指定番目のレコードの指定項目の値を取得します


これ以外の関数は、内部で使用するものです




■使い方の概要

・サーバーアクセス時にhttpRequest(method,target_url,args,func)でアクセスします
・func(httpObj)に帰ってきたら、編集型でも検索型でもgetRetCodeで結果を受け取り、
  結果に応じた処理をします
・検索型の場合、getRecCountでレコード数を指定し、getRecItemValueでレコードの値を取得します。




■ソース

 ちょっとメモ程度に書いたもので、テストしてないので、動くかどうか保証の限りではないですが、とりあえず載せときます(自己責任で見てね ^^;)

//*==============================================//
//*					   *//
//*	アクセス共通関数			   *//
//*					   *//
//*==============================================//

//	共通変数
var	httpObj;		//	データ
var	timer;			//	タイムアウト用
var	retFunc;		//	戻り関数

//*==============================================//
//*	関数:httpRequest()		  *//
//*	内容:アクセス関数		  	  *//
//*==============================================//
function httpRequest(method,target_url,args,func)
{

	//==============================//
	//	配列をシリアル化	    //
	//==============================//
	buf		=	"";
	flgs		=	"";
	for(key in arr)
	{
		buf = buf + flgs + key + "=" +  encodeURIComponent(args[key]);
		flgs = "&";
	}

	//==============================//
	//	getで読まないこと対策  //
	//==============================//
	if ( ( method == "GET") || ( method == "get" ) )
	{ 
		buf = buf + flgs + "nowtime="+ new Date().getTime();
	}

	//==============================//
	//	帰るところ保存	    //
	//==============================//
	retFunc	=	func;

	//==============================//
	//	XMLHttpRequest取得	    //
	//==============================//
	try
	{
	      	if(window.XMLHttpRequest)
		{
			httpObj = new XMLHttpRequest();
		}
		else if(window.ActiveXObject)
		{
			httpObj = new ActiveXObject("Microsoft.XMLHTTP");
		}
		else
		{
			alert('エラーです');
			return;
		}
	}
	catch(e)
	{
		alert('エラーです');
		return;
	}
	//	タイマーセット
	timer = setInterval("timeout()",60000); //60秒にセット

	//==============================//
	//	データを取得する	//
	//==============================//
	httpObj.open(method, target_url, true);
	httpObj.onreadystatechange = RetEntry;
	httpObj.send(buf);

	return;
}

//*==============================================//
//*	関数:timeout()		  	   *//
//	内容:タイムアウト			   *//
//*==============================================//
function timeout()
{
	clearInterval(timer);
	httpObj.abort();
//	alert('タイムアウト');		// 表示する場合
}

//*==============================================//
//*	関数:RetEntry()		  	   *//
//*	内容:XML読み取ったあと		   *//
//*==============================================//
function RetEntry()
{
        if ( httpObj.readyState == 4 )
	{
		clearInterval(timer);	//	タイマーとめる
		if ( httpObj.status == 200)
		{
			if ( retFunc	!=	null )
			{
				retFunc(httpObj);
			}
		}
		else
		{
			alert("エラーNo "+httpObj.status);
		}
       	}
}

//*==============================================//
//*	関数:getRetCode()			  *//
//*	内容:処理結果の取得		  *//
//*==============================================//
function getRetCode(xtree)
{
	retCode	=	"";

	komoku = node.getElementsByTagName("retcode");
	if ( komoku.length	>	0 )
	{
		retCode  = komoku[0].firstChild.nodeValue;
	}
	
	return	retCode;
}

//*==============================================//
//*	関数:getRecItemValue()		  *//
//*	内容:指定番目のレコードの指定項目の値 *//
//*==============================================//
function getRecItemValue(xtree,pos,tag)
{
	retCode	=	"";

			//	レコードを取得する
	list	=	xtree.getElementsByTagName("item");
	if ( list.length	>	pos )
	{
		node	= 	list[pos];
		komoku = node.getElementsByTagName(tag);
		if ( komoku.length	>	0 )
		{
			retCode  = komoku[0].firstChild.nodeValue;
		}
	}
	
	return	retCode;
}

//*==============================================//
//*	関数:getRecCount()		  *//
//*	内容:レコード数		 	   *//
//*==============================================//
function getRecCount(xtree)
{
			//	レコードを取得する
	list	=	xtree.getElementsByTagName("item");
	return list.length;
}

(上記< > ¥は、本当は半角です)




 次回は、これの利用方法です。




  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

SugarCRMにおける、モジュール間の関連(&カーディナリティ)について

2008-01-18 11:31:03 | SugarCRM

メモメモ(確かめていない)

SugarCRMにおいて、モジュール同士の関係っていうのは、テーブル同様、1対多と多対多がある。
どちらのケースでも、まず、vardef.phpに項目は書かれる。
こんなかんじ
  'modified_user_link' =>
  array (
        'name' => 'modified_user_link',
    'type' => 'link',
    'relationship' => 'cases_modified_user',
    'vname' => 'LBL_MODIFIED_BY_USER',
    'link_type' => 'one',
    'module'=>'Users',
    'bean_name'=>'User',
    'source'=>'non-db',
  ),

(上記 >は、本当は半角)

しかし、このあと、1対多と多対多で違う。




■1対多の場合

そのvardefの中(下のほう)に'relationships'の指定があり、そので、上記の'relationship'で指定された関係が記述されている。上記の場合は、'cases_modified_user'ということになるが、それは、vardefの下のほうの'relationships'の中に以下のように指定されている。

   ,'cases_modified_user' =>
   array('lhs_module'=> 'Users', 'lhs_table'=> 'users', 'lhs_key' => 'id',
   'rhs_module'=> 'Cases', 'rhs_table'=> 'cases', 'rhs_key' => 'modified_user_id',
   'relationship_type'=>'one-to-many')

(上記 >は、本当は半角)

ちなみに、vardefは、項目の内容、indicesで示されるインデックス、'relationships'で示される1対多の関係が記述されている。




■多対多の場合

 一方、多対多の場合は、metadataに作られる。たとえば、cases_bugsにおいて、vardef.phpでは、

  'bugs' =>
  array (
  	'name' => 'bugs',
    'type' => 'link',
    'relationship' => 'cases_bugs',
    'source'=>'non-db',
		'vname'=>'LBL_BUGS',
  ),

(上記 >は、本当は半角)
と記述されている。このcases_bugsは、下にあるのではなく、Sugarのホームのしたのmetadata(=modulesと同じレベル)のところに、cases_bugsMetaData.phpというファイルを作成し、そこにテーブル名とテーブル内容、インデックス、'relationships'を記述する。

 これを作成した場合、関係のテーブルを作り直すため、管理者機能でリペアを行うか、インストーラーから行う場合、実践!オープンソースCRMアプリケーション入門の131ページ下側のmanifestファイルの例にあるようなrelationshipsを記述して、インストールする。


  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする