Asial Blog

Recruit! Asialで一緒に働きませんか?

symfony DoctrineのTIPS

カテゴリ :
バックエンド(プログラミング)
タグ :
Tech
Doctrine
symfony
こんにちは、牧野です。
エアコンの入っている部屋にいることが多いせいか、最近夏バテ気味です。。。

さて、今日はDoctrineについてのTIPSです。symfonyとDoctrineの組み合わせで使う中で、役立ちそうなことをいくつか紹介します。

1.複数のデータベースに接続
config/databases.ymlとconfig/doctrine/schema.ymlを次のように書きます。

databases.yml
  1. all:
  2.   main:
  3.     class:        sfDoctrineDatabase
  4.     param:
  5.       classname:  DoctPDO
  6.       dsn:        mysql:dbname=shop_test;host=localhost
  7.       username:   root
  8.       password:
  9.       encoding:   utf8
  10.       persistent: true
  11.       pooling:    true
  12.   sub:
  13.     class:        sfDoctrineDatabase
  14.     param:
  15.       classname:  DoctPDO
  16.       dsn:        mysql:dbname=news_test;host=localhost
  17.       username:   root
  18.       password:
  19.       encoding:   utf8
  20.       persistent: true
  21.       pooling:    true
ここではコネクションを表す名前を「main」と「sub」にしています。好きな名前でかまいません。
schema.ymlには「connection: (コネクションを表す名前)」を追加します。

  1. News:
  2.   connection: sub
  3.   tableName: news
  4.   columns:
  5.     id:
  6.       type: integer(8)
  7.       unsigned: 1
  8.       primary: true
  9.       autoincrement: true
  10.     title: string(2147483647)
  11.     body: string(2147483647)
  12.   actAs:
  13.     Timestampable: { }

ところで、symfonyのdoctrineコマンドには、データベースからschema.ymlを生成する
  1. symfony doctrine:build-schema
があります。現状ではこれを使うとconnectionの行が消えてしまうので気をつけましょう。


2.sqlの数を減らす
Doctrineは、1つのモデルから関連するモデルを芋づる式に簡単に引っ張ってこれて便利です。
ただ、DQLの書き方を気を付けないと大量のSQLが実行されてしまうことがあります。

アクション内
  1. //書き方その1
  2. $this->result_list = Doctrine_Query::create()
  3.   ->from('PurchaseLog l')
  4.   ->execute();

  1. //書き方その2
  2. $this->result_list = Doctrine_Query::create()
  3.   ->from('PurchaseLog l')
  4.   ->leftJoin('l.Shop s')
  5.   ->leftJoin('l.Items i')
  6.   ->leftJoin('i.Category c')
  7.   ->execute();


テンプレート
  1. <table>
  2.  
  3. <?php foreach ($result_list as $val): ?>
  4.   <tr>
  5.     <td><?php echo $val->id; ?></td>
  6.     <td><?php echo $val->purchase_date; ?></td>
  7.     <td><?php echo $val->Shop->shop_name; ?></td>
  8.     <td>
  9.  
  10.   <?php foreach ($val->Items as $val2): ?>
  11.     <?php echo $val2->item_name; ?>(<?php echo $val2->Category->category_name; ?>)<br>
  12.   <?Php endforeach; ?>
  13.  
  14.     </td>
  15.   </tr>
  16. <?php endforeach; ?>
  17.  
  18. </table>

デバッグコンソールを表示すると、、、
書き方その1の場合


書き方その2の場合


Joinメソッドを書いておかないと1つのデータを表示する度にSQLが実行されます。(上の結果は、表示するデータが1件の場合です。)
一覧画面のデータ数が多い場合は特に注意です。


3.関連データをまとめて削除
あるデータを消す時に、紐付くデータもまとめて消したい、という時は、schema.ymlに
  1. cascade: [delete]
を追加します。
以下の書き方の場合、Userテーブルのデータを消すと、紐付いているProfileデータも
削除されます。
  1. User:
  2.   tableName: user
  3.   columns:
  4.     id:
  5.       type: integer(8)
  6.       unsigned: 1
  7.       primary: true
  8.       autoincrement: true
  9.     profile_id: integer(8)
  10. ...
  11.   relations:
  12.     Profile:
  13.       local: profile_id
  14.       foreign: id
  15.       type: one
  16.       cascade: [delete]
  17.   actAs:
  18.     Timestampable: {  }

以上、DoctrineのTIPSでした。