Yii2 Relations to get a field using two foreign keys -
i have issues field table using 2 foreign keys.
explained relations of use tables below.
- user table hasmany companies(company_id).
- comapny table has company_id.
- facilities hasone company_id(based on user instance).
- area hasmany facilites(facility_id).
the logged on user have areas related facilities_id in turn related company_id.
i have a
- productlines hasmany products(product_id).
the user should display products related areas.
- productlines hasmany areas(area_id).
- product lines has field called internal_code.
product model has relation productlines on basis of products_id.
i want display internal code on basis of product_id belongs specific areas.
my code of not working :
in product model.
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']); }
in view file:
[ 'label' => 'internal code', 'format' => 'raw', 'value' => function ($data) { foreach ($data->productlines $intcode) return $intcode->internal_code; }
i don't understand how link these relations. looking help. thanks
list of tables:
- users (primarykey - users_id, foreign_key- comapny_id)
- company(primarykey - company_id)
- facility(primarykey - facility_id, foreignkey- company_id)
- areas(primarykey - area_id, foreignkey- facility_id)
- productlines(primarykey - productlines_id, foreignkey - product_id , area_id)
- product (primarykey - product_id).
my expected result:
in above table can see area_id 47 has 2 product_id's (1 , 3). , internal code them different. want them return both internal codes of can 1 internal code.
so have following hierarchy
- company hasmany users
- company hasmany facilities
- facility hasmany areas
- area hasmany productlines
- product hasmany productlines
products linked areas manytomany via productlines
relation
you can use following code ar classes (but should fix names, because used singular form classes , table names):
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'); } }
to internal codes given product:
$productlines = $product->productlines; $internalcodesasarray = array_map(function(productline $productline) { return $productline->internal_code; }, $productlines); $internalcodesasstring = join(', ', $internalcodesasarray);
to internal codes given area:
$productlines = $product->productlines; $internalcodesasarray = array_map(function(productline $productline) { return $productline->internal_code; }, $productlines); $internalcodesasstring = join(', ', $internalcodesasarray);
the same if want list products given area -- use $area->products
relation. if want products count given area, call $area->getproducts()->count();
to internal codes of product specific area add following function product class:
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()); }
and use in controller $currentproduct->getinternalcodes($currentarea)
do not add custom filters functions define relations. if want list of facilities given product , filter them company of current user better implement additional function:
public class product { ... public function getfacilitiesbycompany(company $company) { return $product->getfacilities() ->where(['company_id' => $company->company_id]); } }
and use follows
$product->getfacilitiesbycompany(yii::$app->user->identity->company)->all();
hope helps.
Comments
Post a Comment