3

私は yii を使ったのはかなり新しいですが、php と sql の経験は豊富です。yii の経験が豊富な人が私を正しい方向に向けてくれることを願っています。Project と Costs という 2 つのモデルがあり、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 関係について知っていますが、これまでに読んだほとんどのことは、関係に 2 つのモデルしかない場合に関係が最もうまく機能することを示しているため、この場合にそれらをどのように適用できるかについては不明です。

4

3 に答える 3

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、モデルにアクセスするためにモデルのプロパティとして定義する必要があるかもしれません (それでも、そうではないかもしれません)...とにかく、方向性があるかもしれませんトーゴ。

于 2012-10-31T13:27:12.630 に答える
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 に答える
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 に答える