在Propel中只使用一个连接条件

时间:2017-02-21 11:05:39

标签: php activerecord orm propel

我正在使用Propel 2.我在加入条件方面遇到了问题。因为它我无法使用Propel API获取数据,我被迫使用普通的SQL与PDO。这是我的表结构:

<table name="categories" phpName="Categories">
  <column name="id"           type="integer" required="true" primaryKey="true" autoIncrement="true"/>
  <column name="parent_id"    type="integer" required="true" defaultValue="0"/>
  <column name="root_id"      type="integer" required="true" defaultValue="0"/>
  <column name="redirect_id"  type="integer" required="false" defaultValue="null"/>
  <column name="name"         type="varchar" size="255" required="true" defaultValue=""/>
  <column name="status"       type="char" sqlType="enum('active','deleted','disabled')" required="true" defaultValue="active"/>
  <foreign-key foreignTable="categories" phpName="Categories">
    <reference local="parent_id" foreign="id"/>
    <reference local="redirect_id" foreign="id"/>
  </foreign-key>
  <vendor type="mysql">
    <parameter name="Engine" value="InnoDB"/>
    <parameter name="Charset" value="utf8"/>
  </vendor>
</table>

我想使用以下SQL:

SELECT    c.id, c.name
FROM      categories c
LEFT JOIN categories p ON c.parent_id = p.id
WHERE     c.status = 'active' AND p.status = 'active' AND c.name LIKE '%Laptop%'

我使用的Propel生成模型的方法:

$categories = CategoriesQuery::create('c')
        ->filterByName("%{$name}%")
        ->filterByStatus('active')
        ->useCategoriesQuery('p')
            ->filterByStatus('active')
        ->endUse()
        ->find();

这种生成的SQL总是有两个连接条件LEFT JOIN categories p ON (categories.parent_id=p.id AND categories.redirect_id=p.id)。我尝试使用join()addJoin()where()等等。似乎没有任何帮助。显然问题在于我对Propel的了解。

1 个答案:

答案 0 :(得分:1)

总的来说,通过结合以下方法,我发现最复杂的自连接是最成功的:

Join::addExplicitCondition Join::setJoinType ModelCriteria::addJoinObject ModelCriteria::where

但是,在这种情况下,您的问题非常简单。您要求Propel使用复合外键,因此它使用复合外键中的两列来进行查询。

我敢打赌你的问题是你正在尝试使用一个外键,你应该使用两个独立的外键来实现两个独立的关系。

例如,这可能会为您提供更好的服务:

<database name="default">
  <table name="category" phpName="Category">
    <column name="id"           type="integer" required="true" primaryKey="true" autoIncrement="true"/>
    <column name="parent_id"    type="integer" required="true" defaultValue="0"/>
    <column name="root_id"      type="integer" required="true" defaultValue="0"/>
    <column name="redirect_id"  type="integer" required="false" defaultValue="null"/>
    <column name="name"         type="varchar" size="255" required="true" defaultValue=""/>
    <column name="status"       type="char" sqlType="enum('active','deleted','disabled')" required="true" defaultValue="active"/>
    <foreign-key foreignTable="category" phpName="ParentCategory">
      <reference local="parent_id" foreign="id"/>
    </foreign-key>
    <foreign-key foreignTable="category" phpName="RedirectToCategory">
      <reference local="redirect_id" foreign="id"/>
    </foreign-key>
    <vendor type="mysql">
      <parameter name="Engine" value="InnoDB"/>
      <parameter name="Charset" value="utf8"/>
    </vendor>
  </table>
</database>

带有查询

$categories = CategoryQuery::create('c')
    ->filterByName("%{$name}%")
    ->filterByStatus('active')
    ->useParentCategoryQuery('p')
        ->filterByStatus('active')
    ->endUse()
    ->find();

in the Propel sandbox给出

SELECT category.ID, category.PARENT_ID, category.ROOT_ID, category.REDIRECT_ID, category.NAME, category.STATUS
  FROM `category`
  INNER JOIN `category` `p` ON (category.PARENT_ID=p.ID)
  WHERE category.NAME LIKE '%myname%'
  AND category.STATUS='active'
  AND p.STATUS='active'