アシアルブログ

アシアルの中の人が技術と想いのたけをつづるブログです

symfony DoctrineのTIPS

こんにちは、牧野です。
エアコンの入っている部屋にいることが多いせいか、最近夏バテ気味です。。。

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

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

databases.yml



all:
  main:
    class:        sfDoctrineDatabase
    param:
      classname:  DoctPDO
      dsn:        mysql:dbname=shop_test;host=localhost
      username:   root
      password:
      encoding:   utf8
      persistent: true
      pooling:    true

  sub:
    class:        sfDoctrineDatabase
    param:
      classname:  DoctPDO
      dsn:        mysql:dbname=news_test;host=localhost
      username:   root
      password:
      encoding:   utf8
      persistent: true
      pooling:    true


ここではコネクションを表す名前を「main」と「sub」にしています。好きな名前でかまいません。
schema.ymlには「connection: (コネクションを表す名前)」を追加します。



News:
  connection: sub
  tableName: news
  columns:
    id:
      type: integer(8)
      unsigned: 1
      primary: true
      autoincrement: true
    title: string(2147483647)
    body: string(2147483647)
  actAs:
    Timestampable: { }



ところで、symfonyのdoctrineコマンドには、データベースからschema.ymlを生成する


symfony doctrine:build-schema

があります。現状ではこれを使うとconnectionの行が消えてしまうので気をつけましょう。


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

アクション内


//書き方その1
$this->result_list = Doctrine_Query::create()
  ->from('PurchaseLog l')
  ->execute();





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




テンプレート



<table>

<?php foreach ($result_list as $val): ?>
  <tr>
    <td><?php echo $val->id; ?></td>
    <td><?php echo $val->purchase_date; ?></td>
    <td><?php echo $val->Shop->shop_name; ?></td>
    <td>

  <?php foreach ($val->Items as $val2): ?>
    <?php echo $val2->item_name; ?>(<?php echo $val2->Category->category_name; ?>)<br>
  <?Php endforeach; ?>

    </td>
  </tr>
<?php endforeach; ?>

</table>


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


書き方その2の場合


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


3.関連データをまとめて削除
あるデータを消す時に、紐付くデータもまとめて消したい、という時は、schema.ymlに


cascade: [delete]

を追加します。
以下の書き方の場合、Userテーブルのデータを消すと、紐付いているProfileデータも
削除されます。



User:
  tableName: user
  columns:
    id:
      type: integer(8)
      unsigned: 1
      primary: true
      autoincrement: true
    profile_id: integer(8)
...
  relations:
    Profile:
      local: profile_id
      foreign: id
      type: one
      cascade: [delete]
  actAs:
    Timestampable: {  }



以上、DoctrineのTIPSでした。