QUOIT Blog

mysql_select_dbの挙動が気に入らない

この記事は6年以上前の記事です。情報が古い場合がありますのでお気を付け下さい。

何だかいろいろ試していたらあれ?ということにぶつかってしまったので、覚え書き。
解決策は考え中です。解決しました!


※追記 10/12/22 19:50
Twitterでアドバイスを頂き、解決の方向性が見えてきました。


※追記 10/12/23 14:00
Twitterで完全な解決策を頂きました!こしあんさんに感謝!

まず、簡単に状況説明から。

僕はphpからmysqlを使うために、DB用のクラスを作っています。
まぁ多くの方は持ってると思いますが。。

僕の場合はこんな感じ。

class DB{
	var $db_encoding="UTF-8";
	var $script_encoding="UTF-8";

	#---------------------------
	# constructer
	#---------------------------
	function DB($host=HOST,$user=USER,$pass=PASS,$db=DBNAME){
		# CONNECT MySQL
		if (!($mysql=mysql_connect($host,$user,$pass,TRUE))) {
			die("ERROR: HOST CONNECT FAILED");
		}
		# CONNECT DB
		if (!(mysql_select_db($db,$mysql))) {
			die("ERROR: DB CONNECT FAILED");
		}
	}

	#---------------------------
	# class method
	#---------------------------
	function exe($stmt){
	# Execute SQL
		if (!($data = mysql_query($stmt))) {
			echo mysql_error()."\n";
			var_dump($stmt);
			return false;
		}
		$result = Array();
		while($tmp = @mysql_fetch_assoc($data)){
			array_push($result,$tmp);
		}
		if( !empty ( $result ) ){
			return $result;
		}else{
			return TRUE;
		}
	}
}

※emptyemptyってなってるのはWPプラグインのバグです。。

実際にはメソッドがやたらめったらあるので今は割愛。

まぁそんなに大それたことはやってません。

オブジェクト生成時にコンストラクタでmysql_connectを使って接続、そのあとメソッドでSQLを実行したりとか何とか。

いつも定数でDBへの接続情報を持っているのですが、引数で渡せば別のDBにも接続できるようになってます。

ふと今日、2つのDBに接続しようとして、以下のコードを書きました。

$db = new DB();# DB Object
$db2 = new DB('localhost','user','password','hogedb');# DB Object

$db->exe("select * from db1table");
$db2->exe("select * from db2table");

ここで僕が期待した結果は、それぞれのDBから情報を引っ張ってくることでした。

しかし結果は「 Table ‘db1.db1table’ doesn’t exist 」となって、最初のクエリが失敗。

今までは大概1つのDBに接続していたので気付かなかったのですが、2つのハンドラを生成した場合に後から生成されたDBハンドラに上書きされてしまったのです。

もっと正確に言うと、コンストラクタで使用していたmysql_select_db関数が情報を上書きしてしまい、DBを変更してしまうのです。

なんだ、僕の作り方が悪いんじゃないの、とも言えますが。。(´・ω・)

納得いかないのは、このmysql_select_db関数。

第二引数にmysql接続を渡すことで指定できるのに、後からの接続に情報を上書きされてしまう。

どうにも納得いかないんですが、どう回避したらいいのか思案中です。。。(´・ω・)

※追記 10/12/22 19:40
Twitterにも書いたんですが、実は今回のコードの回避策はあるにはあるのです。
mysql_select_dbをメソッドexe()の最初に持ってくることで、実行前に毎回DBを選択すれば解決します。
でもものっすごく気に入らないので別の回避策がないかなーと思っております。
もし何か良い案があれば是非教えてください。。><;

※追記 10/12/22 19:50
Twitterでdebiru氏にこんな助言を頂きました。

@yakumo27 クラス作ってオブジェクト思考型で処理したいなら、そもそも手続き型の関数を使うべきではないのではないでしょうか。PHP4前提だと少し難しいですね。私は PHP5.x での開発が主なので mysqli をよく用います。 http://bit.ly/gQyFvH
元発言はこちら

恥ずかしながら、mysqliは利用したことがなかったので未知の領域でした。
環境がPHP5.xなのであれば有効なのかも。
この問題はアドバイス頂いた方向で解決してみたいと思います。

※追記 10/12/23 14:00
Twitterでこしあんさんにこんなメッセージを頂きました!

@yakumo27 ちょっと書きなおしてみました、こんな感じでどうでしょ。 https://gist.github.com/752467
元発言はこちら

@yakumo27 多分、コネクション($mysql)を省略していたので、最初に作ったコネクションを自動的に使ってしまってるのではないかなぁと思います。件のソースでは問題なく動きましたー@自分の環境
元発言はこちら

全くもってそのとおりでした!

こしあんさんが解決してくださったソースを見るとわかるのですが、コネクションをメンバ変数に割り当てて、mysql_queryの引数に明示的にコネクションを渡しています。
元の僕のソースではこれを省略してしまってたんですね。

いやはやこんなことに気付いてくださってソースまで書いてくださって、こしあんさんに感謝です!

こしあんさんの技術ブログはこちら

Comments are closed.