SQL文の結合について

63 views
Skip to first unread message

ouka

unread,
Feb 6, 2008, 1:01:42 AM2/6/08
to XOOPS Cube Developers Group Japan
よろしくお願いします。

ただいまXoops Cube Legacyでのモジュール開発を行っております。

XoopsSimpleObjectクラスとXoopsObjectGenericHandlerクラスを使い、直接SQL文を書かなくてもデータベー
スからデータを取る方法は理解しました。ただ、目的とする仕様ではSQL文を結合させたいため、XoopsSimpleObjectクラスと
XoopsObjectGenericHandlerクラスでは限界を感じております。

ネットで調べるうちにexFrameというモジュールを使えばできそうにも見えたのですが、実際はどうでしょうか?
それ以外にも結合したSQL文を使用して作ったモジュールなどを手本にできればと思っておりますが、もし実例をしている方がいましたらお教え願えればと
思います。

どうぞよろしくお願いします。

のぶのぶ

unread,
Feb 6, 2008, 1:59:16 AM2/6/08
to xcube-...@googlegroups.com
のぶのぶです。

手前味噌となりますが・・・・

XCLのXoopsSimpleObjectクラスとXoopsObjectGenericHandlerクラスではないですが、
拙作のWordPressモジュール開発時に作成した、XoopsObjectとXoopsObjectHandlerを
継承した、XoopsTableObjectとXoopsTableObjectHandlerでは、別途、
XoopsJoinCriteriaというJOIN専用Criteriaクラスをを用意しています。

参考にされたい場合には、
http://www.kowa.org からRelease 0.6.0 Alphaの最新スナップショットを
取得いただき、/modules/wordpress/class/xoopstableobject.php
を見ていただければと思います。
JOINを含むQuery作成例としては、/modules/wordpress/wp-blog-header.php
でGETパラメータを元に抽出条件を設定している長大(笑)なソースがあります。

なお、残念ながらこのxoopstableobject自体は、現在はメンテしておらず、
これをベースにした、別途の仕組みを開発しています。
こちらは、やはり拙作のMyGmapのV2以降で使用しているNBFrameという
フレームワークもどきです。(MyGmap1.0.0ではxoopstableobjectを使用していました)

このNBFrame中にxoopstableobjectを土台にした、DB操作クラスを用意しています。
こちらは如何にしてD3互換のモジュール開発で、手を抜けるかを主眼においています。
(たとえサーバに負荷が余計にかかったとしても(^^;;;)
ので、オブジェクトにテーブルのフィールド定義を書かなくても、テーブル構造を元にして
勝手に作成してくれるなどの機能も含んでいます。
(こちらは、Objectクラスだけの単体使用は難しくなっていますので、痛し痒しですが・・)

ご興味があれば、MyGmap Release 2.5.0 のスナップショットを
ダウンロードいただければと思います。
(最近はNBFrame側の機能追加修正で頻繁に修正コミットしていますので、
場合によると一部動かない場合もあるかもしれませんが・・・)
ロジックは、すべてxoops_trust_path下にあり、NBFrameは、libs/NBFrame下に
MyGmapの基本ロジックは、moudles/mygmap下に存在します。
html下のモジュールフォルダの内容は、NBFrameを使用するモジュールでは、
基本的にはmytrustdirname.php以外は共通です)

ご参考まで。

08/02/06 に ouka<ouka...@gmail.com> さんは書きました:

HIKAWA Kilica

unread,
Feb 6, 2008, 10:08:11 AM2/6/08
to xcube-...@googlegroups.com
こんにちは、氷川といいます。

> ただいまXoops Cube Legacyでのモジュール開発を行っております。
>
> XoopsSimpleObjectクラスとXoopsObjectGenericHandlerクラスを使い、
> 直接SQL文を書かなくてもデータベー
> スからデータを取る方法は理解しました。ただ、目的とする仕様では
> SQL文を結合させたいため、XoopsSimpleObjectクラスと
> XoopsObjectGenericHandlerクラスでは限界を感じております。

結合のさせ方にもよりますが、XCLDB p.141「複数のテーブルオブジェ
クトを作る」にあるような方法で、ある程度はカバーできると思います。

僕は exFrame の後継である Cubson というツールを使ってモジュール
を作成していますが、だいたいは XCLDB にあるのと同様の方法で
複数のテーブルのデータをくっつけています。

Cubsonについては、
http://xoops-shade.sourceforge.jp/wiki/index.php?cubson
http://d.hatena.ne.jp/kilica/20070807
あたりを参照いただくといいと思います。

サンプルモジュールとしては、
http://xc-tokai.net/modules/xhnewbb/viewtopic.php?topic_id=20&post_id=
47#forumpost47

「Bm」(ブックマーク)と「Tag」の二つのテーブルからなるモジュールで、
ひとつのBmレコードに対して複数のTagレコードが紐づく「1対多」の
関係になっています。

たとえば、このモジュールの、actions/BmListAction.class.php の中の

$this->mObjects[$key]->loadTag();

という行では、あるBmレコード($this->mObjects[$key])に対して、
関係するTagレコードを取ってきています。
※loadTag() は、class/handler/Bm.class.php で定義しています。

以上、簡単ですが。

ITOH Takashi

unread,
Feb 6, 2008, 11:27:53 AM2/6/08
to xcube-...@googlegroups.com
伊藤です

ORマッパーの話題ですね。

>> ただいまXoops Cube Legacyでのモジュール開発を行っております。
>>
>> XoopsSimpleObjectクラスとXoopsObjectGenericHandlerクラスを使い、
>> 直接SQL文を書かなくてもデータベー
>> スからデータを取る方法は理解しました。ただ、目的とする仕様では
>> SQL文を結合させたいため、XoopsSimpleObjectクラスと
>> XoopsObjectGenericHandlerクラスでは限界を感じております。

Xoopsなんで割とXoopsObject(もしくはそのサブクラスを)使ってるって
人は多いと思いますが、正直他のORマッパーを使うと二度と使いたく
なくなる代物かと思います。
# というか、XoopsObjectはSQL直書きと大差ない。

S2DaoとかDB_DataObjectなんかありますけど、できの良いフレームワークに
くっついているのも使ってもいいですよね。X2はともかくXCLはフレームワークと
親和性高いと思います。ホダ塾ディストリではEthna使ってるモジュールあるので
探ってみてください。

ただ、学習コストはそれなりに高いかと。
あと、ORMはプログラマが楽するためのものなんでSQL直書きの方が
もちろん速度は出ます。でも、一度使ってしまうと便利で・・・。


HIKAWA Kilica wrote:
> 僕は exFrame の後継である Cubson というツールを使ってモジュール
> を作成していますが、だいたいは XCLDB にあるのと同様の方法で
> 複数のテーブルのデータをくっつけています。

やっぱORMだと、(少なくとも雛形は)テーブル構造を自動取得して
マッピング定義を作って欲しいですよね。
コンストラクタで $this->initVar() とか耐えられない・・・・

伊藤

ouka

unread,
Feb 6, 2008, 7:47:18 PM2/6/08
to XOOPS Cube Developers Group Japan
私のような稚拙な質問にここまでご丁寧にお返事いただき本当にありがとうございます。

私はプログラミング初心者なので、氷川さまのサンプルモジュールが一番シンプルでわかりやすく自分にもトライできそうです。実は私もXCLDB p.
141「複数のテーブルオブジェ
クトを作る」については知っていましたが、あの説明だけではどうしても理解できずこちらで質問させていただくにまで至りました。

伊藤さまのご提案については、なるほど本家プログラマーの皆様はそういう手法を使うのかと非常に勉強になりますが、とりあえずは今作っているモジュール
が動くようになってから次のステップで勉強してみたいと思います。

> コンストラクタで $this->initVar() とか耐えられない・・・・

結構細かく定義しなくてはいけないんだな、という印象がありましたが、この辺がXCLが重いといわれる所以なのでしょうか?

のぶのぶさまのMyGmapは以前から参考にさせていただいておりましたが、あの長大なソースにはさすがに挑めずにいました。もう少し人のソースを読む
ことに慣れてきたら再挑戦させていただきます。

それでは、近況はまたご報告いたします。

K. Ono

unread,
Feb 6, 2008, 10:31:19 PM2/6/08
to xcube-...@googlegroups.com
小野です。

XoopsObject系はちょっと勧められないですね。正直なところ、未だに
このクラスを使用しているモジュールがあったり、話題に挙がってくるのが
不思議なくらいです。僕自身ももう何年も前から使用していませんし^^

Marijuana

unread,
Feb 6, 2008, 10:31:27 PM2/6/08
to XOOPS Cube Developers Group Japan
なんか色んなところにマルチポストしてますが、イマイチなにがやりたいのかピン来ない・・・

Criteriaクラスでテーブル結合したいのか、単にテーブル結合したSQLでXoopsSimpleObjectが使いたいのか
それともXoopsSimpleObjectを使わずにモジュールを作りたいのか・・・

単にテーブル結合したSQLでXoopsSimpleObjectが使いたいのなら

public static function getSelectObject($sql)
{
$root = XCube_Root::getSingleton();
$db = $root->mController->mDB;

$char = array('STRING', 'CHAR', 'VARCHAR');
$text = array('TEXT', 'MEDIUMTEXT', 'LONGTEXT','BLOB');
$int = array('INT', 'INTEGER', 'TINYINT', 'SMALLINT', 'MEDIUMINT',
'BIGINT');
$float = array('REAL', 'DOUBLE', 'FLOAT', 'DECIMAL', 'NUMERIC');
$result = $db->query($sql);

for ($i = 0; $i < $db->getFieldsNum($result); $i++) {
$ftype = strtoupper($db->getFieldType($result, $i));
$fname = $db->getFieldName($result, $i);

if ( in_array($ftype, $char) ) {
$type = XOBJ_DTYPE_STRING;
} elseif ( in_array($ftype, $text) ) {
$type = XOBJ_DTYPE_TEXT;
} elseif ( in_array($ftype, $int) ) {
$type = XOBJ_DTYPE_INT;
} elseif ( in_array($ftype, $float) ) {
$type = XOBJ_DTYPE_FLOAT;
} else {
$type = XOBJ_DTYPE_STRING;
}
$fdata[$fname] = $type;
}

$ret = array();
$n = 0;
while ($row = $db->fetchArray($result)) {
$ret[$n] = new XoopsSimpleObject();
foreach ( $fdata as $name => $type ) {
$ret[$n]->initVar($name, $type);
}
$ret[$n]->assignVars($row);
$ret[$n]->unsetNew();
$n++;
}
return $ret;
}

こんな感じの関数作っておけばいいんじゃないかと
コンストラクタで $this->initVar()とかも不要ですし・・・
次のmcllibsに入れる予定です。

#直メにはレスしません。書籍に内容についての不明点はうちのサイトに投稿してください。

ouka

unread,
Feb 7, 2008, 12:30:20 AM2/7/08
to XOOPS Cube Developers Group Japan
お返事いただきありがとうございます。

On 2月7日, 午後12:31, Marijuana <god_mariju...@yahoo.co.jp> wrote:
> なんか色んなところにマルチポストしてますが、イマイチなにがやりたいのかピン来ない・・・

今回の投稿はGoogleグループとXOOPS Cube日本サイトと、それからMarijuanaさまへのメールと3つ同時に質問させていただきまし
た。皆様方の大切な時間を私のようなプログラミング初心者のつまらない質問のために割いていただけたことは非常にありがたいことであり、またマルチポス
トと受け止められるのであればそれはご迷惑をおかけしたと反省します。

しかしながら、私なりに努力し購入した書籍をもとに勉強した上で投げかけた質問に対して返す第一声がこの一行かと思うと少々残念です。良い本を見つけた
と感謝の意まで述べているのに、私の一連の行動はそこまで冷たく返されるようなことなのでしょうか?

まだまだ未熟であるためまたお世話になることもあるかもしれませんが、これから投稿するときは1つに絞るようにします。どうも申し訳ありませんでし
た。

追記、折角ですがお送りいただいたソースコードは今の私にはぱっとみでは読めません。出直してきます。

ITOH Takashi

unread,
Feb 7, 2008, 5:48:12 AM2/7/08
to xcube-...@googlegroups.com
伊藤です。

> 追記、折角ですがお送りいただいたソースコードは今の私にはぱっとみでは読めません。出直してきます。

私も読めないコードがあった場合、とりあえず置いておきます。

ただ、そのコードが色々と勉強する要素を含んでいるな・・・と思ったら必ず見返します。
PHPコードを書き続けてると、ある日それが読めているようになったことは何度かあるので。

XOOPSCube Legacyのコードもようやく少し読めるのに1年以上かかっています。
まだレンダリングの部分がほとんど読めてません。まぁ、この程度のレベルです。
でも、絶対読んでやろうと思ってます。

で、Marijuanaさんのコードを私なりに読むと、
これは、XoopsSimpleObjectの(サブクラスを扱う)Handlerのメソッドとして使うんだと思います。

public static function getSelectObject($sql)
{
$root = XCube_Root::getSingleton();

$rootを取っているのは、XoopsCubeのプログラミングでは基本ですよね。
ここからデータベースコネクションとか、モジュール情報とか取れますから。

$db = $root->mController->mDB;

で、データベースオブジェクトを取ってます。

$char = array('STRING', 'CHAR', 'VARCHAR');

......


$float = array('REAL', 'DOUBLE', 'FLOAT', 'DECIMAL', 'NUMERIC');

......


if ( in_array($ftype, $char) ) {

......
}
$fdata[$fname] = $type;
}
までで、今回のSELECTで使ったテーブルのフィールドの情報(それが文字列フィールドなのか、
整数値フィールドなのか等等)を規定しています。

なんでこんなことするかというと、XoopsObjectを使うにはXoopsObjectのコンストラクタで
$this->initVar()しないといけないのですが、initVarの引数にはフィールドの型情報が
必要ですから。

で、


$ret = array();
$n = 0;
while ($row = $db->fetchArray($result)) {

...............
}
whileの中で、1つずつXoopsSimpleObjectを作って、それをinitVarして
(XoopsSimpleObjectの(サブクラスの)コンストラクタに書くか、HandlerでinitVarするかどっちでも良い)
作ったXoopsObjectにassignVars()でSELECT値を入れてます。これで、1つのテーブルカラムに
相当するデータオブジェクトの出来上がりです。whileなんで、SELECTで取ってきた分だけ
XoopsSimpleObjectを作っています。

汎用性を持たせたいなら、XoopsSimpleObjectをnewするのではなく、そのサブクラス
を1枚かませてnewするのかなと思います。実際に使うなら更にそのサブクラスをnew
することになるでしょう。

class Mari_XoopsSimpleObject extends XoopsSimpleObject
{
..........
}

class Pricetable_Mari_XoopsSimpleObject extends Mari_XoopsSimpleObject
{
..........
}

みたいな感じで。

正直、コード書いて更にここまで説明する人は居ないと思います。

コード書けばまぁ分かるかなという気持ちで実例を示してくれたMarijuanaさんは
それだけでもすごく親切だと思います。

なぜなら、oukaさんのもともとの質問にコードは1行も無いからです。
そのゼロの状態からコードを起こすのは大変です。

私を含めて何人か観念的な話でレスしましたが、それより実際のコードを持ってくる
Marijuanaさんのほうが100倍分かりやすくて効果的だと思いました。

それを
> 投げかけた質問に対して返す第一声がこの一行
最初の1行だけで
> 追記、折角ですがお送りいただいたソースコードは今の私にはぱっとみでは読めません
と捨て台詞を吐かれるのは、もったいなくて我慢できないので私なりの説明を
試みてみました。コード読解の一助となれば幸いです。

また、
> またマルチポストと受け止められるのであればそれはご迷惑をおかけしたと反省します。
であれば、せめてXOOPS Cube日本サイトの当該スレッドにおいてこのXDGJのスレッドへ
ポインタでも示しておいていただけないでしょうか。

伊藤


ouka

unread,
Feb 7, 2008, 8:28:58 AM2/7/08
to XOOPS Cube Developers Group Japan
伊藤様

細かくご説明をいただきありがとうございます。
また、このようにお叱りをいただけることをありがたく受け止めたいと思います。
どうも私の言動は周りの方々を不快にしてしまうようで気をつけねばなりません。

> せめてXOOPS Cube日本サイトの当該スレッドにおいてこのXDGJのスレッドへ
> ポインタでも示しておいていただけないでしょうか。

まさにおっしゃるとおりです。
早速そのようにいたしました。

本当にご迷惑をおかけして申し訳ありません。
これに懲りず今後ともどうぞよろしくお願いいたします。
Reply all
Reply to author
Forward
0 new messages