EC-CUBEはここ数年勢いを増していてかなり認知度があがってきています。2.11.4も登場してスマートフォン向けのデザインが強化されるなど、機能も充実の一途です。そんななかプログラマーを悩ませるのは、「コードが酷い」ということ。。もう少しきれいなコードだったらカスタマイズしやすいのになあ。。何度そういうため息を漏らしたことでしょう。
こういった状況を少しでも改善していきたいと、まずはDB操作のコードを楽にするためのプラグインを開発しました。
「開発した」といっても弊社で公開している Teeple2 というフレームワークのORマッパーである TeepleActiveRecord をEC-CUBE用に移植しただけなのでたいした工数はかからずにできました。
使い方はほぼ http://code.google.com/p/teeple2/wiki/DatabaseIntro こちらに書いてあるやり方と同じです。(こちらではPDOは使っていません。)
下のコードは同梱したテストケースからの抜粋ですがこんな感じでなにをやっているか一目瞭然のコードがかけます。
$productList = Entity_DtbProductCategories::get()
->join('dtb_category')
->join('dtb_products')
->contains('dtb_category.category_name', 'なべ')
->contains('dtb_products.name', 'なべ')
->order('dtb_products.product_id')
->limit(10)
->offset(0)
->select();
$this->assertEquals('おなべレシピ', $result[0]->dtb_products->name);
こちら から。(無料でご自由にお使いいただけます。)
配布しているアーカイブは以下のようにEC-CUBEのディレクトリ構成と同じ形になっていますので、そのまま配置してください。
(実行に必要なのは data/plugin/activecube 以下のみです。)
data
|- plugin
|- activecube
test
|- class
|- activecube
次に data/require_classes.php の末尾に
require_once DATA_REALDIR . 'plugin/activecube/config.php';
と記述を追加してください。これだけで使えるようになります。
- lowlevelでは EC-CUBEの SC_Query クラスを使用しています。トランザクションの制御などはこちらを使用して行なってください。本ライブラリはあくまでSC_Queryのラップであり、SQLを組み立てやすくしたり、結果セットの扱いをオブジェクト階層構造で扱えるようにしたりしています。
- MySQL, 2.11版のみ用意しています。(私がMySQLしか使わないため。。) Postgresへの対応は少しの修正でできるのではないかと思います。
- Entityクラスにjoinの設定があります。間違っていたり足りなかったりした場合はここを修正するとよいです。
- Entityクラスに自由にドメインロジックを追加することができます。そのような使い方をすると便利かと思います。
- ログはEC-CUBEのsite.logに出力されるようになっています。ログレベルを変更したい場合はActiveRecord.php の 48行目あたりを修正してください。
- 本ライブラリはフリーで提供していますので、不具合等によるいかなる損害についても弊社では責任を負いません。自己責任でご利用をお願いします。
EC-CUBEのDBを「流れるインターフェース」でらくらく操作できる「ActiveCube」を開発しました はコメントを受け付けていません
投稿者: miztaka, カテゴリ: MySQL, tips, tags: mysql
mysqlのサブクエリに問題があることはなんとなく見聞きしていたが今日はこれについて深く追求せざるを得ない機会があったので調べてみました。
自分なりに理解したので簡単にまとめてみるが、以下のブログの記事が素晴らしいので詳しくはそちらもあわせて読むと良いでしょう。
http://nippondanji.blogspot.com/2009/03/mysql_25.html
mysqlで実行計画を取得するには実行したいクエリーの前に EXPLAIN をつけるだけ。
実にシンプルだが、取得できるデータもシンプル極まりない(^_^;)
mysql> EXPLAIN SELECT COUNT(customer_id) FROM dtb_customer WHERE del_flg = 0
AND customer_id IN (SELECT customer_id FROM dtb_order WHERE order_id IN
(SELECT order_id FROM dtb_order_detail WHERE product_name LIKE '%とうもろこし%' ));
+----+--------------------+------------------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+------------------+------+---------------+------+---------+------+------+-------------+
| 1 | PRIMARY | dtb_customer | ALL | NULL | NULL | NULL | NULL | 1834 | Using where |
| 2 | DEPENDENT SUBQUERY | dtb_order | ALL | NULL | NULL | NULL | NULL | 2023 | Using where |
| 3 | DEPENDENT SUBQUERY | dtb_order_detail | ALL | NULL | NULL | NULL | NULL | 2163 | Using where |
+----+--------------------+------------------+------+---------------+------+---------+------+------+-------------+
3 rows in set (0.02 sec)
実行計画の読み取り方は こちら に詳しく載っています。
さて、上にあげたクエリーは IN句に二重にサブクエリーが入っている、ツッコミどころ満載のSQLである。(実はEC-CUBEの中でこのクエリーが使われている。)
普通は1番内側のサブクエリーから実行されていって結果が返ってくるという動きを想像してしまうしそのほうが効率がいいのは明らかだ。
ところがmysqlでは外側のクエリーから実行し、得たレコードについて内側のサブクエリーを繰り返し実行するという処理になる。
つまりIN句なしで検索した結果が3000行ある場合、その各行についてサブクエリーの走査が実行するされるのでとんでもなく時間がかかってしまう。
何故このようになるかというとmysqlのオプティマイザがIN句をEXIST句に置き換えてしまうため、サブクエリーが相関サブクエリーとなり、結果上に述べた実行計画になってしまう。
このように実行計画で DEPENDENT SUBQUERY となっているものについては、 nxn の走査が走ってしまう可能性があるのでできるだけ排除したほうがいいだろう。
できる限りJOINを使うように心がけたい。
[tips]なぜmysqlのサブクエリは遅いのか はコメントを受け付けていません
日本語ロケールのダウンロードはこちら
LifeType はオープンソースのブログシステムなのですが普通と違うのは「ポータル型ブログシステム」だということです。つまり、1つのシステム内に複数のブログ、複数のユーザを作ることができ、ブログ:ユーザは N:N の関係になっています。
WordPressも3.1以降(?)になって複数のブログを1つのシステム内に作れるようになりましたが、最初からそのように設計されているのとそうでないのとでは後々差が出てくるとしたものです。
LifeTypeではサマリーページといって、システム内の全ブログの統計が見えるようなしくみになっています。
用途としては、以下のようなものが考えられるかと思います。
- アメブロやLivedoor Blogなどのようなブログポータルサイト
- 社内ブログシステム
- 多店舗型ビジネスのポータルサイトとして
etc.
このありそうでなかったブログシステムが気に入ったので日本語のロケールファイルを作ってみることにしました。
LifeTypeはきちんと多言語化対応されていて、サイト用と管理用2つのロケールファイルを翻訳するだけでサイトを日本語化することができました。(といってもあわせて1500行ぐらいある大変なものでしたが・・・)
ロケールファイルを翻訳していくとだいたいどんな機能があるかイメージできてくるので、そういう意味でも有意義な作業だったと思います。
LifeTypeをダウンロードして解凍したら locale というディレクトリを確認してください。たくさんロケールファイルがあると思います。ここと、この直下のadminというディレクトリに日本語ロケールファイルを配置します。
インストールプロセスは英語で進みます。 Step6 の Blog Conficurationのところで Languageの選択肢に「 Japanese locale file for LifeType 」というのが出てくると思いますのでそれを選択してください。

既に別のロケールでインストールしてしまった場合も管理画面から変更することができます。
管理画面にログインし、「ADMINISTRATION」タブをクリックします。
中ほどにManage Locales というセクションがあるので、New locale をクリックします。
このページで「Scan Locales」というボタンをクリックすれば、localeディレクトリに手動で配置したファイルが読み込まれて選択できるようになります。
LifeTypeというオープンソースのブログシステムを日本語化してみた はコメントを受け付けていません
弊社では見積書や請求書の作成/管理に ZohoInvoice を使用しています。
これだけの機能が低価格で利用できるのでとても重宝していますが、
- 見積のタイトルを入力する欄がない (無理やりTermのフィールドをタイトルとして使用しています。)
- 一覧に見積のタイトルを表示できないので管理がしづらい
- ステータスが Draft/Sent/Deleted しかないので管理がしづらい
といった難点もありました。
見積書の数も増えてきてさすがにそろそろ管理の限界に近づいたので、ZohoInvoiceで公開されているAPIを使用してSalesforce上にデータを同期するようにしてみました。
一覧管理ができればいいので見積の明細までは同期せず、タイトル、顧客名、見積番号、総額などをカスタムオブジェクトに登録するようにしました。
ざっと以下のような手順です。
- 見積管理のカスタムオブジェクトを作成
- VisualForce ページを新規に作成して、初期実行メソッドでZohoInvoiceと通信、データを同期するプログラムを作成。
- 上記ページをカスタムボタンに割り当て
- ボタンをリストビューに表示
これで一覧性が良くなり、またステータスも細かく管理できるようになりました。
ZohoInvoiceのデータをSalesforceに同期してみた はコメントを受け付けていません