Доктрина: переопределить состояние левого соединения между людьми - PullRequest
0 голосов
/ 27 марта 2012

Допустим, у меня есть схема, в которой у пользователя много предупреждений (от многих ко многим).

Alert:
  columns: ~

User:
  columns: ~
  relations:
    Alerts:
      class: Alert
      refClass: UserAlert
      local: user_id
      foreign: alert_id

UserAlert:
  columns:
    user_id:
      type: integer(4)
      primary: true
    alert_id:
      type: integer(4)
      primary: true
    active:
      type: boolean
      notnull: true
      default: true
  relations:
    Alert:
      local: alert_id
      foreign: id
    User:
      local: user_id
      foreign: id

Обратите внимание на пользовательское поле active в классе ref, в котором указано, активно ли связанное предупреждение для пользователя. Как получить пользователя с его активными оповещениями?

UPDATE: Один из способов добиться этого - переопределить условие соединения с помощью ключевого слова WITH:

$user = UserTable::createQuery('u')
      ->createQuery('u')
      ->leftJoin('u.UserAlert aa WITH aa.enabled = ?', array(true))
      ->leftJoin('aa.Alert a')
      ->addWhere('u.id = ?', $id)
      ->fetchOne();

Но так вам придется вызывать $user->getUserAlert(), который возвращает коллекцию объектов класса ref. Я хотел бы, чтобы заполнялось отношение «оповещения», чтобы я мог позвонить $user->getAlerts() напрямую.

1 Ответ

1 голос
/ 27 марта 2012

Во-первых, ваша схема неверна (по крайней мере, она не работает на моей стороне). Вот правильный (я поставил какое-то поле в User and Alert для теста):

Alert:
  columns:
    name: string(30)
  relations:
    Users:
      class: User
      local: alert_id
      foreign: user_id
      refClass: UserAlert
      foreignAlias: Alerts

User:
  columns:
    name: string(255)
  relations:
    Alerts:
      class: Alert
      local: user_id
      foreign: alert_id
      refClass: UserAlert
      foreignAlias: Users

UserAlert:
  columns:
    user_id:
      type: integer
      primary: true
    alert_id:
      type: integer
      primary: true
    active:
      type: boolean
  relations:
    User:
      class: User
      local: user_id
    Alert:
      class: Alert
      local: alert_id

Вы должны определить свою реальность many2many в Alert, User и UserAlert.

Затем я собираю базу данных и помещаю в нее некоторые данные для теста: http://sqlfiddle.com/#!2/dd507/2

Теперь, чтобы получить всех пользователей только с их активными оповещениями, поместите это в свой UserTable.php

public function retrieveAlerts($active = true)
{
  $q = $this->createQuery('u')
    ->leftJoin('u.UserAlert ua')
    ->leftJoin('ua.Alert a')
    ->where('ua.active = ?', array($active));

  return $q->fetchArray();
}

А затем, в своем действии, просто сделайте это:

$users = Doctrine_Core::getTable('User')->retrieveAlerts();

Если вы print_r подтвердите свои результаты, вы увидите, что мы получаем пользователей 3 и 4 с их активными оповещениями:

Array
(
  [0] => Array
    (
      [id] => 3
      [name] => tata
      [UserAlert] => Array
        (
          [0] => Array
            (
              [user_id] => 3
              [alert_id] => 1
              [active] => 1
              [Alert] => Array
                (
                  [id] => 1
                  [name] => new
                )
            )
          [1] => Array
            (
              [user_id] => 3
              [alert_id] => 2
              [active] => 1
              [Alert] => Array
                (
                  [id] => 2
                  [name] => fired
                )
            )
        )
    )
  [1] => Array
    (
      [id] => 4
      [name] => tutu
      [UserAlert] => Array
        (
          [0] => Array
            (
              [user_id] => 4
              [alert_id] => 3
              [active] => 1
              [Alert] => Array
                (
                  [id] => 3
                  [name] => sold
                )
            )
        )
    )
)
...