首页 文章

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

提问于
浏览
4

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

这样我们就可以确保订单数据的一致性,因为即使我们将来可能会删除旧产品,旧订单仍然会以订单商品的形式包含所有订购的产品 . 订单和订单商品通过简单的交叉引用表(如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 回答

  • 8

    如果我理解你的问题,你可以用 addSelectQuery 方法达到预期的效果 . 我不会只是暗示它是如何运作的 .

    addSelectQueryfrom 子句中添加 Criteria 作为子查询 .

    // some query from item table
    $itemQuery = \ItemQuery::create()->...;
    
    $productQuery = \ProductQuery::create()
        ->addSelectQuery($itemQuery, 'item_query_result_alias', false);
    

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

    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'));
    

相关问题