Knowledge base func

PHP

PHPのPOST、GET用クラス

by on 3月.08, 2011, under PHP

Share on TwitterSave on Delicious

PHP で凄く簡単に GET/POST 送信ができる関数を作りました
こんな記事がありました。こういうのはクラスにしておいたほうが後々使い勝手いいとおもいました。PHPよくわかんないけど。
常用頻度が高いならラッピング関数みたいのにしてヘルパーみたいなファイルをつくって、常にインクルードもありだとおもう。wbsはワールドビジネスサテライトが頭にうかんでしまったのでnetsにしてしまったけど余り意味はないです。

 
define('METHOD_POST','POST');	// こういうのってdefaultでコンストってなかったっけ?
define('METHOD_GET','GET');
 
// echo Nets::sendGET('http://weble.org/', Array('s' => 'PHP')); 
// echo Nets::sendPOST('http://caloreen.com/search/', Array('keyword' => 'パン')); 
// このままだとfalseが帰ってくることもあるので注意!
 
// extends Exception ほんとはえらーとらっぷとかの上にのっけたほうがいい
class Nets {
	public static function sendPost($url, $params)
	{
		return self::sendRequest(METHOD_POST, $url, $params);
	}
 
	public static function sendGET($url, $params)
	{
		//こんなんでもいいかもめ
		//$url .= '?'. http_build_query($params);
		//$handle = fopen($url, "r");
		//$url = fgets( $handle );
		return self::sendRequest(METHOD_GET, $url, $params);
	}
 
	private static function sendRequest($method, $url, $params)
	{
		$data = http_build_query($params);
		$header = Array("Content-Type: application/x-www-form-urlencoded");
		$options = array('http' => Array(
			'method' => $method,
			'header'  => implode("\r\n", $header), 
		));
		if($method == METHOD_GET) {
			$content = file_get_contents($url . '?' . $data, false, stream_context_create($options));
		} else if($method == METHOD_POST) {
			$options['http']['content'] = $data;
			$content = file_get_contents($url, false, stream_context_create($options));
		}
		return $content;
	} 
}

動作確認もしてないけど、こんな感じ。
これに動作に必要な関数群をまとめておくと、オレオレ関数からオレオレクラスができて、開発効率があがるんじゃないかなと思ったりもするよ。
実際のAPIは戻りのURL指定とかで落ちてきたりするので、単純にfile_get_contentsとかfgetsで済む範囲って狭いきもするので、このままじゃ使えないと思うし、いろいろなケースがあるとおもうので、単純なラップよりは拡張可能な状態にしておくのが好ましいんじゃないかと、投げっぱなし。

動作、確認しました。
POSTの方が動かないのでなにかとおもったら
$options['content'] = $data;になってました。
このままだと['http']と同階層にはいってしまうので構造がおかしいです。
stream_context_createでエラーを吐きます。
URLを指定せずにlocalhostのindex.phpを観に行くようにしたら、それが実は自分自身で無限ループしてアパッチさんが落ちたのは内緒です。こういうのは他のサーバーに向けてやるとDOSになっちゃうから、なんかフェイルセイフなことをしないとだめですかも。

なんとなく、curlとかfsockopen方面に拡張してたらとまらなくなったので、途中だけどダダ漏れしておきます。

define('METHOD_POST','POST');	// こういうのってdefaultでコンストってなかったっけ?
define('METHOD_GET','GET');
define('NETBUF_SIZE',4096);
define('NETS_PORT',80);
define('NETS_TIMEOUT',6);
 
// echo Nets::sendGET('http://localhost/', Array('s' => 'PHP')); 
// echo Nets::sendPOST('http://localhost/', Array('keyword' => 'パン')); 
 
// extends Exception ほんとはえらーとらっぷとかの上にのっけたほうがいい
class Nets {
 
	public static function sendPost($url, $params)
	{
		return self::sendRequest(METHOD_POST, $url, $params);
	}
 
	public static function sendGET($url, $params, $getsline = 0, $bufsize = NETBUF_SIZE)
	{
//		return self::sendRequest(METHOD_GET, $url, $params);
		return self::sendGETReq($url, $params, $getsline, $bufsize);
	}
 
	private static function sendRequest($method, $url, $params)
	{
		$data = http_build_query($params);
		$header = Array("Content-Type: application/x-www-form-urlencoded");
		$options = Array('http' => Array(
			'method' => $method
			,'header'  => implode("\r\n", $header)
		));
		if($method == METHOD_GET) {
			$content = file_get_contents($url . '?' . $data, false, stream_context_create($options));
		} else if($method == METHOD_POST) {
			$options['http']['content'] = $data;
			$content = file_get_contents($url, false, stream_context_create($options));
		}
		if ($content===false) {
			$content = ""; // 本当はエラートラップを書いておくべき
		}
		return $content;
	}
 
	// GET指示のAPIの場合最初の一行だけで済んだりするのでそれ用
	private static function sendGETReq($url, $params ,$getsline = 0, $bufsize = NETBUF_SIZE)
	{
		$buf = "";
		$url .= '?'. http_build_query($params);
		$handle = @fopen($url, "r");
		$i = 0;
		while (!feof($handle)){
			$buf .= fgets($handle, $bufsize);
			if ($getsline > 1 && $i==$getsline) {
				break;
			}
			$i++;
		}
		fclose($handle);
		return $buf;
	}
 
	// ヘッダーに細かい細工をしなきゃいけない用(参考)
	private static function sendGETReqPattern2($url, $path, $host, $params ,$getsline = 0, $setport = NETS_PORT)
	{
		$ret = ""; 
		$fp = fsockopen($url, $setport, $errno, $errstr, NETS_TIMEOUT);
		if (!$fp) {
			$ret = "$errstr ($errno)\n";
		} else {
			$request = getPOSTReqparam($path, $host, $params);
			fwrite($fp, $request);
			while (!feof($fp)) {
				$ret .= fgets($fp, NETBUF_SIZE);
			}
			fclose($fp);
		}
		return $ret;
	}
 
	private static function getPOSTReqparam($path, $host, $params)
	{
		foreach ($params as $key => $val) {
			$param[]  = $key .'='.urlencode($val);
		}
		// 例えばユーザーエージェントを足すとか そういう処理を書く
		$param[]  = 'useragent='.urlencode($_SERVER['HTTP_USER_AGENT']); 
		$options = join($param,"\r\n");
 
		$request = "POST $path HTTP/1.1\r\n";
		$request .= "Content-Type: application/x-www-form-urlencoded\r\n"
		$request .= "Content-Length: " . strlen($param) . "\r\n"
		$request .= "Host: $host \r\n";
		$request .= "Connection: Close\r\n";
		$request .= "\r\n";
		$request .= $options."\r\n";
 
 
		return $request;
	}
 
	private static function getGETReqparam($path, $host, $params)
	{
		foreach ($params as $key => $val) {
			$param[]  = $key .'='.urlencode($val);
		}
		// 例えばユーザーエージェントを足すとか そういう処理を書く
		$param[]  = 'useragent='.urlencode($_SERVER['HTTP_USER_AGENT']); 
		$options = join($param,"&");
 
		$request = "GET $path?$options HTTP/1.1\r\n";
		$request .= "Content-Type: application/x-www-form-urlencoded\r\n"
		$request .= "Host: $host \r\n";
		$request .= "Connection: Close\r\n";
		$request .= "\r\n";
 
		return $request;
	}
 
	// APIのためにリクエストを送る目的というよりはクローラー用
	public static function getPage($url) {
		ob_start();	// 出力制御
		$ch = curl_init();
		curl_setopt ($ch, CURLOPT_URL, $url);
		curl_setopt ($ch, CURLOPT_HEADER, 0);
		curl_setopt ($ch, CURLOPT_TIMEOUT, NETS_TIMEOUT);
		curl_exec ($ch);
//		$ht_hd = curl_getinfo($ch, CURLINFO_HTTP_CODE);
//	    if(preg_match("/^(200)$/",$ht_hd)){
		$strbuf = ob_get_contents();	// 出力結果を変数に格納
//		} else {
//			$strbuf = "";// 404|403|500
//		}
		curl_close ($ch);
		ob_end_clean();
		ob_end_flush();
		return $strbuf;
	}
 
	// あとはHttpRequestを使うパターンとかいろいろある。まあよしなに。
 
}
Leave a Comment more...

windows vistaでmysql

by on 7月.19, 2010, under mySQL, PHP

Share on TwitterSave on Delicious

 vistaで環境をつくろうとするのが間違っているのだけど、ちょっと動作をたしかめたかったから、vistaがはいっているノートにphpやらmysqlやらをいれて動かそうとおもったのだけど、動かない。相変わらずハマる。

以前はappacheのhttpd.confをいくらいじっても設定が反映されないからおかしいなと思ったら、C:\Program Files以下にあるファイルはユーザーにアドミニストレータ権限があっても書き換えさせないとかいう素敵仕様で僕をはめてくれた。書き換えさせないのならまだ気がつけるのだけど、自分からは書き変わったようにみえるのに、プログラムでアクセスすると変わってないというとても残念な実態だった。iniファイルとかconfとか書き換えられないじゃない…。

で、mysql コンソールからは普通に入れて操作できるので、インストールが失敗しているわけじゃないんだよなと、phpとかapacheとかの設定をゴニョゴニョしたり、エクステンションのパス通さなきゃだめなんだっけ?とはまってたのだけど、結論から言うと、localhostが名前解決できていませんでした…。

ありえない・・・。

PHP Warning: mysqli_connect() [<a href='function.mysqli-connect'>function.mysqli-connect</a>]: (HY000/2002): 接続済みの呼び出し先が一定の時間を過ぎても正しく応答しなかったため、接続できませんでした。または接続済みのホストが応答しなかったため、確立された接続は失敗しました。

localhost/でアクセスして、テストスクリプトを走らせてたから気がつけなかったけど、これも同じような理由なのかな?アプリケーションがアクセスできる実態ファイルとユーザーがみえている実態ファイルが違う??

開発環境ごとにappacheでバーチャルドメインを切るのが常なので、
C:\Windows\System32\drivers\etc\hosts
あたりで、環境ごとに名前振ってたりしたのだけど、ここでlocalhostを127.0.0.1で書いてあげてもダメっぽい。

ファイアーウオールを切ってもLAN設定に切り替えてもダメだったから、システムがみえてる実態が違うのでしょう・・・。

ひどく、そしてつまらないはまり方でした。
「vista php mysql」でぐぐるといろいろな人の悶絶したあとが見える…。
恐ろしいOSですね。

Leave a Comment more...

phpの数字3桁カンマ区切り

by on 4月.10, 2010, under PHP

Share on TwitterSave on Delicious

つらつらとphpでお手伝いコーディングをしていた。
money_formatが効かないので、はて?と思ってリファレンスを見てみたらwindows環境ではつかえないらしい。
ローカルのwin開発環境でちろっと書いてたので、たまたま気がついた。
まあ、環境をつくるほど大掛かりでもないので、続行。
ちょっと調べてみたけどなんか回避方法がさくっとでてこない。調べるのもめんどくさいのでエスケープ用の関数を書いてみた。

	public static function _money_format( $myint ){
		$ary = explode(".",$myint);
		$lencnt = mb_strlen((int)$ary[0]);
		$loopcnt = ceil(($lencnt / 3));
		$ary_slice = array();
		for ($i=0;$i<$loopcnt;$i++){
			if ($i==0 && $lencnt%3 > 0) {
				$ary_slice[] = mb_substr($ary[0],0,$lencnt%3);
			} else {
				$ary_slice[] = mb_substr($ary[0],($i-1)*3+$lencnt%3,3);
			}
		}
		$ary[0] = join($ary_slice,',');
		return join($ary,".");
	}

やっつけ。
多分もう使うことはないだろうけど、誰かがまためんどくさい思いをしないようにあげておきます。(多分自分)
本番環境をwin鯖+phpで運用するひともいないとおもうので大丈夫だとは思うけど、念のためいっておくとこれは実用を念頭においたものではなく、表示確認用にちろっと動くようにしただけのものだから気をつけてね。

余談だけど、文字列の連結って処理のなかでも重たい部類に入る。
特にループの中に入るときとかは注意。
あと、phpはどうだかわすれたけど、評価式に演算をぶっこんでおくと毎回評価をするのに計算してしまう言語とかあったりするのでめんどくさくても、一回演算結果を変数にぶちこんでおくと、試行回数が多いループについてはいいかもしれない。
こういうところでパフォーマンスに差がでるのは、よっぽどじゃないとないけれど、ま、くせです。

文字整形はDB側でできることはそっちでやってます。
ほんとに頻度が高ければ関数にしておけるし。
キャッシュがよしなにしてくれることも期待できるし。
LL側で文字連結とかできればしたくないですね。
まあそうもいっていられないのでバランスの問題。
フォーマット系って以外とどの言語も弱くて困る。
年月とか。エクセルが一番強いんじゃないかとか・・・思ったりしません?

Leave a Comment more...

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!