开发者

Doctrine: Query only where relationship doesn't exist?

开发者 https://www.devze.com 2023-03-27 05:17 出处:网络
I have two tables: Articles and Categories. Articles can have a single Category assigned to them. But they don\'t have to have a Category.

I have two tables: Articles and Categories. Articles can have a single Category assigned to them. But they don't have to have a Category.

Schema:

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

I can query for all Articles that have categories assigned to them like this:

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

It returns this:

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...

What I need to do is query for Articles where there is no Category relationship. I can't just say ->where('c.id = NULL') either because if there is no Category relationship, then there isn't any [Category] array returned in the object. It only returns the id, title and content. Also I can't say ->where(a.Category = 开发者_如何学运维NULL) because Category isn't a column of Article.

Any ideas?

UPDATE I made a mistake on the Schema and updated it. I know it doesn't really make sense for an Category to only have a relationship with a single Article, but in reality I'm not using Articles/Categories. I was just using those terms as examples.


UPDATE:

So the easiest way if you want the article as the primary object is to do a leftJoin with a condition for the fk being null. LEFT JOINs always grabs the record on the left side of the join regardless of whether the right side of the join has a corresponding record. So without the where you essentially get a result of all articles. So we can then filter those for only articles that DONT have a category by using the where condition... very similar to before:

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

There is no reason to specify an on condition. Doctrine will figure this out base on the realtionship. Additionally you dont need to use a where for this type of filtereing use an innerjoin instead, the inner join will only select itemes where the relationship exists (i.e. there is a a.category_id = c.id) so the query you posted should actually be:

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

To get the articles without any category you can look for a category_id of null on the article:

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

Id probably remove the join though because its not really necessary, unless you need the null columns in the result for some reason.

0

精彩评论

暂无评论...
验证码 换一张
取 消