Доктрина: Запрос только там, где нет отношений? - PullRequest
3 голосов
/ 11 августа 2011

У меня есть две таблицы: статьи и категории.Статьям можно назначить одну категорию.Но им не обязательно иметь категорию.

Схема:

Article:
  columns:
    title:
      type: string(255)
    content:
      type: string(255)
    category_id:
      type: integer(4)

Category:
  columns:
    name:
      type: string(255)
    article_id:
      type: integer(4)
  relations:
    Article:
      class: Article
      local: article_id
      foreign: id
      foreignAlias: ArticleCategories

Я могу запросить все статьи, которым присвоены категории, например:

$articles= Doctrine_Query::create()
  ->from('Article a')
  ->leftJoin('a.Category c ON c.article_id = a.id')
  ->where('c.id > 0')
  ->execute();

Возвращает это:

Object->Array
(
  [0] => Array
  (
    [id] => string(1) "1"
    [title] => string(4) "test"
    [content] => string(4) "test"
    [Category] => Array
    (
      [0] => Array
      (
        [id] => string(1) "2"
        [name] => string(7) "testing"
      )
    )
  )
etc...

Что мне нужно сделать, это запрос статей, где нет связи по категориям.Я не могу просто сказать ->where('c.id = NULL'), потому что, если нет отношения Категория, тогда в объекте не будет возвращен массив [Category].Он возвращает только id, title and content.Также я не могу сказать ->where(a.Category = NULL), потому что Категория не является столбцом Статьи.

Есть идеи?

ОБНОВЛЕНИЕ Я допустил ошибку в Схеме и обновилЭто.Я знаю, что для категории не имеет смысла иметь отношения только с одной статьей, но на самом деле я не использую статьи / категории.Я просто использовал эти термины в качестве примеров.

1 Ответ

10 голосов
/ 11 августа 2011

ОБНОВЛЕНИЕ :

Так что самый простой способ, если вы хотите, чтобы статья была первичным объектом, это сделать leftJoin с условием, чтобы fk был нулевым.LEFT JOIN s всегда захватывает запись с левой стороны объединения, независимо от того, имеет ли правая сторона объединения соответствующую запись.Так что без того, где вы по существу получите результат всех статей.Таким образом, мы можем затем отфильтровать те статьи, которые НЕ имеют категорию, используя условие where ... очень похожее на предыдущее:

$articles = Doctrine_Query::create()
  ->from('Article a')
  ->leftJoin('a.Category c')
  ->where('c.article_id IS NULL')
  ->execute();

Нет никаких оснований для указания условия on,Доктрина выяснит это на основе реальности.Кроме того, вам не нужно использовать где для этого типа фильтрации используйте внутреннее соединение, вместо этого внутреннее соединение будет выбирать только те итемы, где существует связь (т. Е. Существует a.category_id = c.id), поэтому запрос, который вы разместили, должен быть на самом деле:

$articles = Doctrine_Query::create()
  ->from('Article a')
  ->innerJoin('a.Category c')
  ->execute();

Чтобы получить статьи без какой-либо категории, вы можете найти нулевой category_id на article:

$articles= Doctrine_Query::create()
  ->from('Article a')
  ->leftJoin('a.Category c')
  ->where('a.category_id IS NULL')
  ->execute();

Идентификатор, вероятно, удалит объединение, потому что это на самом деле не нужноесли вам не нужны пустые столбцы в результате по какой-либо причине.

...