更好的 Propel 查询
A better Propel query
我有 4 个 table:
branches
(包含分支信息)
offered_class_types
(每个分支都有一组可用的 classes)
class_sessions
(每个 class 类型都有其会话,如白天、晚上和夜晚)
class_dates
(每个日期对应一个会话)
所以我的流程是:每个日期都对应一个会话(通过直接链接两者的代码),它通过两件事对应一个类型 1. 分支 ID 和 2. class 名称(分支可以提供具有相同会话的相同 class 类型)。每个 class 类型对应于分支 table,使用与会话 table 对应的相同分支 ID。
我想将这段代码变成一个查询,而不是现在的两个。在切换到 Propel 之前,它是在一个查询中。
$class = ClassDatesQuery::create()->findPk(160);
$classSession = $class->getOfferedSessionsRelatedByCode();
$classType = OfferedClassTypesQuery::create()
->filterByType($classSession->getClassname())
->filterByBranchid($classSession->getBranchid())
->find();
只要您在这两个 table 之间有一个简单的关系:
,一个类似于下面的简单查询就会浮出水面
$classType = OfferedClassTypesQuery::create()
->useClassDatesQuery()
->filterByPk(160)
->endUse()
->filterByXXX(YYY)
...
->find();
复杂的是你有不止一个连接条件,而这些条件在查询之前是未知的。
至少有两 (2) 种替代方法。
选项一:
编写您的原始 SQL 查询,并 运行 它针对您的数据库连接,然后使用适当的 object/class 包装器手动合并结果集,如下所示:
$db = Propel::getConnection();
$sql = 'SELECT OfferedClassTypes.* FROM ...';
$query = $db->prepare($sql);
$formatter = new PropelObjectFormatter();
// Here you specify the class that matches
// the expected results set
$formatter->setClass('OfferedClassTypes');
$classType = $formatter->format($query);
注意 OfferedClassTypes.*
,因为您只需要来自 table 的列,这样您就可以通过匹配的对象进行水合
选项二:
将原始 SQL 查询放入视图中,引用:
Propel custom sql for view tables
所以你可能会这样定义你的视图:
CREATE VIEW ViewOfferedClassTypes AS
SELECT
ClassDates.ID as ClassDateID,
OfferedClassTypes.*
...
然后在您的模式中您将拥有:
<table
name="ViewOfferedClassTypes"
phpName="ViewOfferedClassTypes"
readOnly="true"
skipSql="true">
<!-- More columns from the OfferedClassTypes table -->
<column name="ClassDateID" ... /><!-- From ClassDates table -->
</table>
请注意 ClassDateID
列,以便您可以在过滤器中使用:
$classType = ViewOfferedClassTypesQuery::create()
->filterByClassDateID(160)
->find();
选项 1 快速而肮脏,而 选项 2 更精细但 cleaner/more 有条理。
希望对您有所帮助,祝您好运。
我有 4 个 table:
branches
(包含分支信息)offered_class_types
(每个分支都有一组可用的 classes)class_sessions
(每个 class 类型都有其会话,如白天、晚上和夜晚)class_dates
(每个日期对应一个会话)
所以我的流程是:每个日期都对应一个会话(通过直接链接两者的代码),它通过两件事对应一个类型 1. 分支 ID 和 2. class 名称(分支可以提供具有相同会话的相同 class 类型)。每个 class 类型对应于分支 table,使用与会话 table 对应的相同分支 ID。
我想将这段代码变成一个查询,而不是现在的两个。在切换到 Propel 之前,它是在一个查询中。
$class = ClassDatesQuery::create()->findPk(160);
$classSession = $class->getOfferedSessionsRelatedByCode();
$classType = OfferedClassTypesQuery::create()
->filterByType($classSession->getClassname())
->filterByBranchid($classSession->getBranchid())
->find();
只要您在这两个 table 之间有一个简单的关系:
,一个类似于下面的简单查询就会浮出水面$classType = OfferedClassTypesQuery::create()
->useClassDatesQuery()
->filterByPk(160)
->endUse()
->filterByXXX(YYY)
...
->find();
复杂的是你有不止一个连接条件,而这些条件在查询之前是未知的。
至少有两 (2) 种替代方法。
选项一:
编写您的原始 SQL 查询,并 运行 它针对您的数据库连接,然后使用适当的 object/class 包装器手动合并结果集,如下所示:
$db = Propel::getConnection();
$sql = 'SELECT OfferedClassTypes.* FROM ...';
$query = $db->prepare($sql);
$formatter = new PropelObjectFormatter();
// Here you specify the class that matches
// the expected results set
$formatter->setClass('OfferedClassTypes');
$classType = $formatter->format($query);
注意 OfferedClassTypes.*
,因为您只需要来自 table 的列,这样您就可以通过匹配的对象进行水合
选项二:
将原始 SQL 查询放入视图中,引用:
Propel custom sql for view tables
所以你可能会这样定义你的视图:
CREATE VIEW ViewOfferedClassTypes AS
SELECT
ClassDates.ID as ClassDateID,
OfferedClassTypes.*
...
然后在您的模式中您将拥有:
<table
name="ViewOfferedClassTypes"
phpName="ViewOfferedClassTypes"
readOnly="true"
skipSql="true">
<!-- More columns from the OfferedClassTypes table -->
<column name="ClassDateID" ... /><!-- From ClassDates table -->
</table>
请注意 ClassDateID
列,以便您可以在过滤器中使用:
$classType = ViewOfferedClassTypesQuery::create()
->filterByClassDateID(160)
->find();
选项 1 快速而肮脏,而 选项 2 更精细但 cleaner/more 有条理。
希望对您有所帮助,祝您好运。