3

我是 yii 的新手,但对 php 和 sql 有丰富的经验。我希望对 yii 更有经验的人可以为我指明正确的方向。我有两个模型,项目和成本,它们通过 project_cost 表以多对多关系相互关联。这样做的原因是成本可以在项目之间分摊。在 project_cost 表中有一个附加列,其中包含分配给特定项目的成本的多少。

所以项目模型关系看起来像这样,它非常适合获取所有细节:

class Project extends CActiveRecord
{

    /**
    * @return array relational rules.
    */
    public function relations()
    {
    return array(
        'projectcost'   => array(self::HAS_MANY,   'ProjectCost',    'project_id'),
        'cost'      => array(self::HAS_MANY, 'Cost', array('cost_id'=>'id'),'through'=>'projectcost'),
        //i.e. a many to many relation of cost through the projectcost model

        );
    }
    ...
}

在成本模型中有一个名为 Value 的列,在 project_cost 表中有一个名为 Percent 的列。构造一个包含 sql 查询的函数很容易,它可以为我提供项目成本的总和,如下所示:

select sum(project_cost.Percent*cost.Value) 
from project_cost join cost on project_cost.cost_id=cost.id 
where project_cost.project_id=1     

但是有没有办法通过 yii 中的关系来做同样的事情?我知道 STAT 关系,但不清楚如何在这种情况下应用它们,因为到目前为止我所阅读的大部分内容都表明,如果关系中只有两个模型,则关系效果最好。

4

3 回答 3

1

您可以创建一个范围来获取这些数据,在您的项目模型中创建一个方法,例如:

public function withAdjustedCost()
{
    $this->getDbCriteria()->mergeWith(array(
        'with'=>array(
            'projectcost',
            'cost',
        ),
        'select'=>'*, sum(projectcost.Percent*cost.Value) as adjustedCost',
    ));

    return $this;
}

然后,您应该能够在获取项目模型时使用它;

$models = Project::model->withAdjustedCost()->findAll();

我还没有测试过它,你可能需要稍微修改一下,或者可能需要定义$adjustedCost为模型的属性才能访问它(再说一遍,也许不是)......无论如何,可能是一个方向去。

于 2012-10-31T13:27:12.630 回答
0

简单有效:

$sum = Yii::app()->db->createCommand("
    select sum(project_cost.Percent*cost.Value)
    from project_cost
    join cost on project_cost.cost_id=cost.id
    where project_cost.project_id=1
")->queryScalar();

$sum === false 如果有问题

于 2012-10-31T20:34:53.463 回答
0

您可能想看看CDbCriteria类,它可以让您使用 Yii 框架构建查询,因此“正确”。

另外,我认为您可以使用CActiveRecord->getRelated()方法提取数组中的所有 ProjectCost 模型,然后使用 foreach 循环以建立所需的总和。在您的 Project 模型中,您可以创建一个非常像这样的方法:

class Project extends CActiveRecord
{
  ...
  /**
  * @return the sum of all weighed Costs corresponding to this Project.
  */
  public function getTotalCost()
  {
      $projectCosts = $this->getRelated('projectcost'); // fetches array of ProjectCost models, which you can iterate over
      $sum = 0;
      foreach($projectCosts as $projectCost)
      {
          $sum += $projectCost->Percent * $projectcost->getRelated('cost')->Value;
      }
      return $sum;
  }
  ...
}

这取决于以下想法:

$projectcost->getRelated('cost')->Value;

您的 ProjectCost 模型具有如下关系:

'cost'   => array(self::HAS_ONE,   'Cost',    'cost_id'), 

它允许 getRelated() 获取相关的成本模型,只要您需要访问它。

因此,您基本上可以最终简单地使用$model->getTotalCost()来获取您在查询中表达的成本总和,但实际上是在模型中构建的,我认为这是正确的 MVC,而不是让数据库使用查询为您进行计算。

编辑: getRelated() 在处理相关记录时已被证明是一个真正的朋友,它获取一组记录或一条记录,具体取决于它所处理的关系的性质。

由于您似乎对数据库访问感到担忧,您还可以查看CActiveRecord->afterFind(),您可以重载它以计算项目总和,并在加载模型后仅将其设置为您的公共变量一次。所以你会有你的代码:

public $projectSum = 0;
public function afterFind(){
   //Fetch array of ProjectCost models, which you can iterate over
   foreach($this->getRelated('projectcost') as $projectCost)
   {
     $this->projectSum += $projectCost->Percent * $projectcost->getRelated('cost')->Value;
   }
}
于 2012-10-31T19:16:14.410 回答