原则:只查询关系不存在的地方?

Jak*_*son 3 php mysql doctrine symfony1

我有两个表:文章和类别.文章可以分配一个类别.但他们不必拥有类别.

架构:

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
Run Code Online (Sandbox Code Playgroud)

我可以查询所有分配给它们的类别的文章,如下所示:

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

它返回:

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...
Run Code Online (Sandbox Code Playgroud)

我需要做的是查询没有类别关系的文章.我不能只是说->where('c.id = NULL'),因为如果没有Category关系,那么[Category]对象中没有返回任何数组.它只返回id, title and content.另外我不能说->where(a.Category = NULL)因为Category不是Article的一列.

有任何想法吗?

更新 我在Schema上犯了一个错误并更新了它.我知道,一个类别只与一篇文章有​​关系,但实际上我没有使用文章/类别.我只是用这些术语作为例子.

pro*_*son 10

更新:

因此,如果您希望将文章作为主要对象,最简单的方法是leftJoin使用fk为null的条件.无论连接的右侧是否有相应的记录,LEFT JOINs总是抓取连接左侧的记录.所以没有你从根本上得到所有文章的结果.因此,我们可以通过使用where条件来过滤那些不具有类别的文章的那些...非常类似于之前:

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

没有理由指定on条件.学说将根据实际情况确定这一点.另外,你不需要使用这种类型的filtereing使用内连接的地方,内连接只会选择存在关系的迭代(即有一个a.category_id = c.id)所以你发布的查询应该实际上是:

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

要获取没有任何类别的文章,您可以在以下位置查找category_idnull article:

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

Id可能会删除连接,因为它不是必需的,除非您因某种原因需要结果中的空列.