DoctrineでデータベースのViewを使って楽をする
PHPも好きですが本当はSQLも結構好きな岡本です。
アシアルに入社する前はネットショップ・システムに携わっており、
SQLでガリガリと売り上げや利用統計などを集計していました。
しかし、symfonyを使った開発ではデータベースに対する操作は基本的に、
ORマッパー(PropelやDoctrine)を介して行うため、SQLの強力な集計機能が恋しくなる時があります。
フォームから受け取ったデータをデータベースに保存するような更新系の処理は
insert文を書くよりもDoctrineでsaveメソッドを発行した方が楽だと思うのですが、
参照系の処理では集計やサブクエリを活用したselect文に比べると表現力に物足りなさを感じてしまいます。
「Viewに対してDQLが使えれば楽なのに」
と思っていたら、実は問題なく使えたのでやり方をお伝えします。
使い方は簡単で、データベース上にViewを作った後に
$ vi config/doctrine/schema.yml
へ実表と同じように設定ファイルを書き
$ symfony doctrine-build-model
を実行すればDoctrineのモデルが作成されます。
Viewですので更新処理は行えませんが、
参照系のカスタムメソッドは追加できます。
■サンプル
ポイントの概念も売れた日付の記録すらない簡単な注文テーブル群でカッコ悪いのですが、
これを元にViewを作成してschema.ymlを書いてみます。
まずViewは名前と住所、注文商品数と合計金額そして粗利益を集計し
以下の様な表を作成します。
Viewを作成するSQLは以下のようになります。
CREATE VIEW cart_order AS SELECT
cart.id ,
member.name ,
member.address ,
(SELECT COUNT(sale.id) FROM sale WHERE cart_id = cart.id) AS sales_amount,
(SELECT SUM(item.price) FROM sale LEFT JOIN item ON sale.item_id = item.id WHERE cart_id = cart.id) AS sales_price,
(SELECT SUM(item.price) - SUM(item.cost) FROM sale LEFT JOIN item ON sale.item_id = item.id WHERE cart_id = cart.id) AS sales_margin
FROM
cart
LEFT JOIN member ON cart.member_id = member.id;
※データベースはMysqlを利用
このViewに対するschema.ymlは以下のようになります。
CartOrder:
tableName: cart_order
columns:
id:
type:
size:
notnull: true
primary: true
name:
type: string
size: 4000
address:
type: string
size: 4000
sales_amount:
type:
size:
sales_price:
type:
size:
sales_margin:
type:
size:
DoctrineのようなORマッパーを使った開発でも、
Viewを使って予めテーブルを連結・集計しておけば情報の取得で楽が出来ます。
また、取得するカラムや行をViewで絞り込んでおけばセキュリティ的な面も固め易 いと思います。
また、Viewは便利ですが沢山作ると管理が大変になるため、
細かい条件の絞込みや表示の修正はDBモデルのカスタムメソッドで行うと、
管理もしやすく更に楽が出来ます。