一组汇总数据为Yii2关系

时间:2017-05-04 16:29:10

标签: php mysql yii2

在我的Product模型中,我有以下两种方法; getOrderFeedback()是正常关系,返回ActiveQuerygetTotalAndAveFeedback(),返回给定Product条记录的汇总数据数组。

/**
 * @return \yii\db\ActiveQuery
 */
public function getOrderFeedback()
{
    return $this->hasMany(OrderFeedback::className(), ['productID' => 'ID']);
}

/**
 * @return array
 */
public function getTotalAndAveFeedback()
{
    return $this->getOrderFeedback()
        ->select(['COUNT(*) AS num',
                  'AVG(rating) AS avg',
                  'FLOOR(AVG(rating)) AS full',
                  'MOD(AVG(rating), 1) AS decimal_portion',
                  '5 - FLOOR(AVG(rating)) - CEILING(MOD(AVG(rating),1)) AS empty'])->one();
}

当我有一组Product并迭代它们以收集单totalAndAveFeedback的{​​{1}}时,Product会被触发,从而导致从数据库。类似于以下内容

ActiveQuery

有没有办法将$my_products = Product::find()->with(['supplier', 'location']) ->where(['published' => 1]) ->all(); # SELECT * FROM product WHERE published = 1; # Find all products # SELECT * FROM supplier WHERE ID IN (s1, s2, s3); # Eagerly load supplier # SELECT * FROM location WHERE ID IN (l1, l2, l3, l4); # Eagerly load location foreach ($my_products as $product) { echo $product->supplier->supplier_name; # supplier object available from eager loading echo $product->location->title; # location object available from eager loading echo $product->totalAndAveFeedback->decimal_portion; # requires db access to 'lazy load' data for each product record # SELECT COUNT(*) AS num, AVG(rating) AS avg, FLOOR(AVG(rating)) AS full, MOD(AVG(rating), 1) AS decimal_portion, 5 - FLOOR(AVG(rating)) - CEILING(MOD(AVG(rating),1)) AS empty FROM `order_feedback` WHERE `productID`=pID } 视为关系,以便在getTotalAndAveFeedback() joinWith()上允许with() / Product,以便可以急切地加载数据每个ActiveQuery的可用方式与ProductSupplier关系相同吗?

我已尝试删除Location中对one()的调用,以允许将该方法视为关系,但getTotalAndAveFeedback()记录的totalAndAveFeedback属性为所有空数组,我期望一个对象具有Product等属性,好像我调用了一个简单的关系,如decimal_portion

这可能在Yii2吗?

1 个答案:

答案 0 :(得分:0)

/**
 * @return \yii\db\ActiveQuery
 */
public function getTotalAndAveFeedback()
{
    return $this->getOrderFeedback()
        ->select(['productID', 'COUNT(*) AS num',
                  'AVG(rating) AS avg',
                  'FLOOR(AVG(rating)) AS full',
                  'MOD(AVG(rating), 1) AS decimal_portion',
                  '5 - FLOOR(AVG(rating)) - CEILING(MOD(AVG(rating),1)) AS empty'])
        ->groupBy(['productID']);
}

正如@ Pa3Py6aka指出的那样,加入关系时数组为空的原因是没有选择productID,返回的OrderFeedbackProduct之间没有链接。

通过将groupBy(['productID'])方法调用添加到ActiveQuery,每个OrderFeedbacks都会热切地加载并可供各个Product对象访问。