0

2 つの外部キーを使用してテーブルからフィールドを取得する際に問題があります。

以下の使用表の関係を説明しました。

  • ユーザー テーブルhasMany Companies(company_id)。
  • Company テーブルには company_id があります。
  • 施設hasOne Company_id (ユーザー インスタンスに基づく)。
  • エリアには多数の施設 ( facility_id ) があります。

ログオンしているユーザーには、company_id に関連する facility_id に関連する領域があります。

私は今持っています

  • 製品ラインには多数の製品 (product_id)があります。

ユーザーは、地域に関連する製品を表示する必要があります。

  • 製品ラインには多数のエリア (area_id) があります。
  • 製品ラインには internal_code というフィールドがあります。

製品モデルは、products_id に基づいて製品ラインと関連付けられています。

この内部コードを、特定の地域に属する product_id に基づいて表示したいと考えています。

今のところ動作していない私のコード:

私の製品モデルでは。

    public function getFacility()
{
    return $this->hasMany(Facility::className(),['facility_id' => 'facility_id'])->viaTable('sim_users',['company_id'=> Yii::$app->user->identity->company_id]);
}

 public function getArea()
{

    return $this->hasMany(Area::className(),['area_id'=>'area_id'])->viaTable('sim_facility',['facility_id'=> 'facility_id' ]);
}

public function getProductlines()
{

    return $this->hasMany(Productlines::className(), ['product_id' => 'product_id'])->viaTable('sim_productlines',['product_id' => 'product_id']);
}

私のビューファイルでは:

  [
        'label' => 'Internal Code',
        'format' => 'raw',

        'value' => function ($data) {
            foreach ($data->productlines as $intCode)
           return $intCode->internal_code;
        } 

これらの関係をリンクする方法がわかりません。助けを求めています。ありがとう

テーブルのリスト:

  • ユーザー (primaryKey - users_id、foreign_key - comapny_id)
  • Company(primaryKey - company_id)
  • Facility(primaryKey - 施設 ID、foreignKey - company_id)
  • Areas(primaryKey - area_id,foreignKey-facility_id)
  • Productlines(primaryKey - productlines_id、foreignKey - product_id および area_id)
  • 製品 (primaryKey - product_id)。

私の期待される結果:

ここに画像の説明を入力

上の表では、area_id 47 に 2 つの product_id (1 と 3) があることがわかります。それらの内部コードは異なります。両方の内部コードを返すようにしたいのですが、今のところ内部コードは 1 つしか取得できません。

4

1 に答える 1

1

したがって、次の階層があります

  • 会社には多くのユーザーがいます
  • 会社には多くの施設があります
  • 施設には多くの エリアがあります
  • エリアには多くの製品ラインがあります
  • 製品には多くの製品ラインがあります

製品はリレーションを介して Areas as manyToMany にリンクされてます productLines

AR クラスには次のコードを使用できます (ただし、クラスとテーブル名に単数形を使用したため、名前を修正する必要があります)。

public class User extends ActiveRecord
{
    public function getCompany()
    {  
        retrun $this->hasOne(Company::className(), ['company_id' => 'company_id']);
    }
}

public class Company extends ActiveRecord
{
    public function getUsers()
    {  
        retrun $this->hasMany(User::className(), ['company_id' => 'company_id']);
    }    

    public function getFacilities()
    {  
        retrun $this->hasMany(Facility::className(), ['company_id' => 'company_id']);
    }    
}

public class Facility extends ActiveRecord
{
    public function getCompany()
    {  
        retrun $this->hasOne(Company::className(), ['company_id' => 'company_id']);
    }

    public function getAreas()
    {  
        retrun $this->hasMany(Area::className(), ['facility_id' => 'facility_id']);
    }    
}

public class Area extends ActiveRecord
{
    public function getFacility()
    {  
        retrun $this->hasOne(Facility::className(), ['facility_id' => 'facility_id']);
    }

    public function getProductLines()
    {  
        retrun $this->hasMany(ProductLine::className(), ['area_id' => 'area_id']);
    }    

    public function getProducts()
    {  
        retrun $this->hasMany(Product::className(), ['product_id' => 'product_id'])
            ->via('productLines');
    }    
}

/**
 * @property $internal_code
 */
public class ProductLine extends ActiveRecord
{
    public function getArea()
    {  
        retrun $this->hasOne(Area::className(), ['area_id' => 'area_id']);
    }

    public function getProducts()
    {  
        retrun $this->hasMany(Product::className(), ['product_id' => 'product_id']);
    }
}

public class Product extends ActiveRecord
{
    public function getProductLines()
    {  
        retrun $this->hasMany(ProductLine::className(), ['product_id' => 'product_id']);
    }       

    public function getAreas()
    {  
        retrun $this->hasMany(Area::className(), ['area_id' => 'area_id'])
            ->via('productLines');
    }    

    public function getFacilites()
    {  
        retrun $this->hasMany(Facility::className(), ['facility_id' => 'facility_id'])
            ->via('areas');
    }
}

特定の製品のすべての内部コードを取得するには:

$productLines = $product->productLines;

$internalCodesAsArray = array_map(function(ProductLine $productLine) {
    return $productLine->internal_code;
}, $productLines);

$internalCodesAsString = join(', ', $internalCodesAsArray);

特定の領域のすべての内部コードを取得するには:

$productLines = $product->productLines;

$internalCodesAsArray = array_map(function(ProductLine $productLine) {
    return $productLine->internal_code;
}, $productLines);

$internalCodesAsString = join(', ', $internalCodesAsArray);

特定の地域の商品をリストしたい場合も同様です --$area->productsリレーションを使用します。特定のエリアの製品数を取得する場合は、呼び出します$area->getProducts()->count();

特定の領域の製品の内部コードを取得するには、次の関数を Product クラスに追加します。

public function getInternalCodes(Area $area = null)
{
    $query = $this->getProductLines();
    if (!empty($area)) {
        $query->where(['area_id' => $area->area_id]);
    }
    return array_map(function (ProductLine $productLine) {
        return $productLine->internal_code;
    }, $query->all());
}

そして、コントローラーで次のように使用します$currentProduct->getInternalCodes($currentArea)

リレーションを定義する関数にカスタム フィルターを追加しないでください。特定の製品の施設のリストを取得し、現在のユーザーの会社でフィルター処理する場合は、追加機能として実装することをお勧めします。

public class Product 
{
    ...

    public function getFacilitiesByCompany(Company $company)
    {
        return $product->getFacilities()
            ->where(['company_id' => $company->company_id]);
    }
}

次のように使用します

$product->getFacilitiesByCompany(Yii::$app->user->identity->company)->all();

お役に立てれば。

于 2016-08-08T12:07:26.933 に答える