php - Getting specific model instance based on attribute data yii2 -


i have following table

orderitem(id, service_item_id, special_service_item_id,...)

in orderitem class specified relation

class orderitem extends activerecord {    ...    public function getserviceitems()    {        return $this->hasmany(serviceitem::classname(), ['id' => 'special_item_id']);    }     public function getspecialitems()    {        return $this->hasmany(specialitem::classname(), ['id' => 'service_item_id']);    }    ...  } 

by way can proper instances of serviceitems:

$order = order::findone([123]); //an array of serviceitems $serviceitems = $order->serviceitems; //an array of specialitems $specialitems = $order->specialitems; 

but want extend specialitem, in fact specialitem extended serviceitem. items saved in same table, have calculate values in way when have specialitem.

sure can add 1 column extra_speacial_item_id , define relationgetextraspecialitem(), think not way. (what if want extend more , more?)

however found there mechanism in yii/ yii2 called single table inheritance @ answer, overwrite instantiate() method of baseactiverecord (source). in other answer use factorymethod. how should implement it? thoughts were:

class serviceitem extends activerecord {     public function instantiate($attributes){         switch($attributes['class_name']){             case specialitem::classname():                 $class = specialitem::classname();             break;             case extraspecialitem::classname():                 $class = extraspecialitem::classname();             break;             default:                 $class = get_class($this);         }         $model = new $class(null);         return $model;     } } 

if i'm getting right, have place new children of serviceitem in instantiate() method. should alter table to:

order(pk_id, fk_service_item_id, class_name, ...)

now can access items in 2 ways:

  1. only use method getserviceitems()

    $order = order::findone([123]); //an array of mixed servicetypes, depending on class_name field $serviceitems = $order->serviceitems; 
  2. modify relations in orderitem

    class orderitem extends activerecord {     ...     public function getserviceitems()     {         return $this->hasmany(serviceitem::classname(), ['id' => 'special_item_id'])             ->where(['class_name' => serviceitem::classname()]);     }     public function getspecialitems()    {        return $this->hasmany(specialitem::classname(), ['id' => 'service_item_id'])             ->where(['class_name' => specialitem::classname()]);    }     public function getextraspecialitems()    {        return $this->hasmany(extraspecialitems::classname(), ['id' => 'service_item_id'])             ->where(['class_name' => extraspecialitems::classname()]);    }    ...  } 

    accessing items above:

    $order = order::findone([123]); //an array of serviceitems $serviceitems = $order->serviceitems; //an array of specialitems $specialitems = $order->specialitems; //an array of extraspecialitems $extraspecialitems = $order->extraspecialitems; 

is there (better) way of getting instance of model or these suitable soulutions? way of overwriting instantiate() method correct?

another way

order_item table many_many item_type table. item_type(id, type,other_stuffs). (type = service, special, etc)

the junction table order_item_type (or something) have order_item_id , item_type_id primary composite key.

then

class orderitem extends activerecord {      public function getorderitemtypes()     {         return $this->hasmany(orderitemtype::classname(), ['order_item_id' => 'id']);     }      public function getserviceitems()     {         return $this->hasmany(item::classname(), ['id' => 'item_id'])             ->via('orderitemtypes')             ->where("type = service");     }      public function getspecialitems()     {         return $this->hasmany(item::classname(), ['id' => 'item_id'])             ->via('orderitemtypes')             ->where("type = special");     }  } 

or like

class orderitem extends activerecord {      public function getorderitemtypes()     {         return $this->hasmany(orderitemtype::classname(), ['order_item_id' => 'id']);     }      public function getitemtypes($type = null)     {          return $this->hasmany(item::classname(), ['id' => 'item_id'])             ->via('orderitemtypes')             ->filterwhere(['type' => $type]); //not sure if can this, looks cool. if not, i'm sure mean.     }  } 

benefits of database design normalization, , flexibility.

for reference


Comments

Popular posts from this blog

toolbar - How to add link to user registration inside toobar in admin joomla 3 custom component -

linux - disk space limitation when creating war file -