Symfony app - 如何将计算字段添加到Propel对象?

Tom*_*ohl 5 php orm propel symfony1

使用Propel对象的计算字段的最佳方法是什么?

假设我有一个对象"Customer",它有一个对应的表"customers",每列对应一个我对象的属性.我想要做的是:在View A上使用它时,在我的对象上添加一个计算属性"已完成订单数",但在视图B和C上没有.

计算的属性是通过ID链接到我的"客户"对象的"订单"对象的COUNT().

我现在可以做的是首先选择所有客户对象,然后迭代计算所有客户对象的订单,但我认为在单个查询中执行它会提高性能.但是我不能正确地"保湿"我的Propel对象,因为它不包含计算字段的定义.

你会怎么做?

Pet*_*ley 3

有几种选择。首先,是在数据库中创建一个视图来为您进行计数,类似于我在这里的回答。我为当前正在从事的 Symfony 项目执行此操作,其中给定表的只读属性实际上比表本身宽得多。这是我的建议,因为分组列(max()、count() 等)无论如何都是只读的。

其他选项是将此功能实际构建到您的模型中。您绝对可以自己进行补水,但有点复杂。这是粗略的步骤

  1. 将列作为受保护的数据成员添加到Table类中。
  2. 为这些列编写适当的 getter 和 setter
  3. 覆盖水合物方法并在其中使用其他查询的数据填充新列。确保在第一行调用parent::Hydrate()

但是,这并不比您已经谈论的好多少。您仍然需要N + 1 次查询来检索单个记录集。但是,您可以在步骤 #3 中发挥创意,使N是计算的列数,而不是返回的行数。

另一种选择是在Table Peer 类上创建自定义选择方法。

  1. 执行上面的步骤 1 和 2。
  2. 编写您将通过 Propel::getConnection() 过程手动查询的自定义 SQL。
  3. 通过迭代结果集手动创建数据集,并在此时处理自定义水合,以免在 doSelect 进程使用时破坏水合。

这是此方法的一个示例

<?php

class TablePeer extends BaseTablePeer
{
    public static function selectWithCalculatedColumns()
    {
        //  Do our custom selection, still using propel's column data constants
        $sql = "
            SELECT " . implode( ', ', self::getFieldNames( BasePeer::TYPE_COLNAME ) ) . "
                 , count(" . JoinedTablePeer::ID . ") AS calc_col
              FROM " . self::TABLE_NAME . "
              LEFT JOIN " . JoinedTablePeer::TABLE_NAME . "
                ON " . JoinedTablePeer::ID . " = " . self::FKEY_COLUMN
        ;

        //  Get the result set
        $conn   = Propel::getConnection();
        $stmt   = $conn->prepareStatement( $sql );
        $rs = $stmt->executeQuery( array(), ResultSet::FETCHMODE_NUM );

        //  Create an empty rowset
        $rowset = array();

        //  Iterate over the result set
        while ( $rs->next() )
        {
            //  Create each row individually
            $row = new Table();
            $startcol = $row->hydrate( $rs );

            //  Use our custom setter to populate the new column
            $row->setCalcCol( $row->get( $startcol ) );
            $rowset[] = $row;
        }
        return $rowset;
    }
}
Run Code Online (Sandbox Code Playgroud)

您的问题可能还有其他解决方案,但超出了我的知识范围。祝你好运!