在 Propel 中只使用一个连接条件
Use only one join condition in Propel
我正在使用 Propel 2。我对加入条件有疑问。因此,我无法使用 Propel API 获取数据,并且我被迫将普通的 SQL 与 PDO 一起使用。这是我的 table 结构:
<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 的了解上。
总的来说,我发现通过结合以下方法进行复杂的自连接最成功:
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'
我正在使用 Propel 2。我对加入条件有疑问。因此,我无法使用 Propel API 获取数据,并且我被迫将普通的 SQL 与 PDO 一起使用。这是我的 table 结构:
<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 的了解上。
总的来说,我发现通过结合以下方法进行复杂的自连接最成功:
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'