我是一个很新的yii工作,但有很多PHP和SQL的经验。 我希望有更多经验的人可以指出我正确的方向。我有两个模型,项目和成本,它们通过project_cost表在多对多关系中相互关联。原因是项目之间可以共享成本。在project_cost表中,还有一个附加列,其中包含为特定项目分配的成本。
所以Project模型关系看起来像这样,它可以很好地获取所有细节:
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关系,但我不清楚如何在这种情况下应用它们,因为我到目前为止所阅读的大部分内容都表明,如果关系中只有两个模型,那么关系效果最好。
答案 0 :(得分:1)
您可以创建一个范围来获取此数据,在Project模型中创建一个方法,如:
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
定义为模型的属性才能访问它(然后再次,也许不是)。 ..无论如何,可能是一个方向。
答案 1 :(得分: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()就可以获取相关的Cost模型。
所以你基本上可以简单地使用$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;
}
}
答案 2 :(得分: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如果出错了