Propel 2:使用子查询作为虚拟列的值

时间:2014-12-15 15:08:32

标签: php mysql propel

我们有一个包含所有产品的表格和一个包含所有订购商品的单独表格。订购的商品基本上是订购产品的副本,与其源产品(通过外键)有关,而附加数据仅与订购商品相关,如订购数量。

这样我们就可以确保订单数据的一致性,因为即使我们将来可能会删除旧产品,旧订单仍然会以订单商品的形式包含所有订购的产品。 订单和订单商品通过简单的交叉引用表(如Propel文档中的那个)连接,只有两个字段order_id和item_id。

现在,我必须实施一项功能,计算尚未发货的产品的订购数量,以便我们可以跟踪我们的库存仍有多少可供销售,以及实际已售出多少,但尚未发货。

为了达到这个目的,我必须选择与给定的源产品相关的所有项目,这些项目仅属于未发货的订单,然后将这些项目的数量字段进行调整。这看起来像Propel2中的以下内容:

$ordered_qty = ItemQuery::create()
    // Sum up the quantity of all ordered items and only select this one column
    ->withColumn('SUM(Item.Qty)', 'ordered_qty')
    ->select('ordered_qty')
    // join with the cross referencing table between orders and order items 
    // so we can join with the actual order data in the next step
    ->leftJoinOrderItemCrossRef()
    // join with the order data so that we can filter out 
    // already shipped (= archived) orders
    ->leftJoin('OrderItemCrossRef.Order')
    ->addJoinCondition('Order', 'Order.IsArchived != 1')
    // only find the items relating to the desired product
    ->where('Item.ProductId = ?', $product_id)
    ->groupByProductId()
    ->findOne(); 

此查询的工作方式类似于魅力,findOne()返回尚未发货的订购数量。 但是单独的查询对我来说没用,我需要将结果添加到产品模型中。

我考虑过向ProductQuery添加一个自定义方法,该方法会添加一个虚拟列' OrderedQty'每个产品,所以我可以选择这样的所有产品:

$products = ProductQuery::create()
    ->withOrderedQty()
    ->find();

foreach($products as $product)
{
    echo 'Ordered Qty of ' . $product->getName() . ': ' . $product->getOrderedQty() . '\n';
}

但我不知道如何使用子查询作为Propel中虚拟列的值。

1 个答案:

答案 0 :(得分:8)

如果我理解你的问题,你可以使用addSelectQuery方法达到预期的效果。我没有所需的表结构,所以我只是暗示它是如何工作的。

addSelectQueryCriteria子句中添加from作为子查询。

// some query from item table
$itemQuery = \ItemQuery::create()->...;

$productQuery = \ProductQuery::create()
    ->addSelectQuery($itemQuery, 'item_query_result_alias', false);

在此之后,你会得到一个像这样的查询尸体:

SELECT item.*
FROM item, (/* here will be the $itemQuery select */) AS item_query_result_alias

然后只需使用withColumn方法添加虚拟列:

$products = \ProductQuery::create()
    ->withColumn('item_query_result_alias.ordered_qty', 'ordered_qty')
    ->addSelectQuery($itemQuery, 'item_query_result_alias', false)
    ->find();

查询将是:

SELECT item.*, item_query_result_alias.ordered_qty AS ordered_qty
FROM item, (/* here will be the $itemQuery select */) AS item_query_result_alias

获得结果:

var_dump($products->getFirst()->getVirtualColumn('ordered_qty'));