简体   繁体   中英

How to link attribute in Yii 2 to another model's field?

I have Products model and ProductProperties via hasOne relation:

class Product extends ActiveRecord
{
...
public function getProductProperties()
 {
     return $this->hasOne(ProductProperties::class, ['product_id' => 'id']);
 } 
...
}

I had price attribute in Products and I want to remove it (including column in database) and to link it to price attribute of ProductProperties model. Is it possible and how can I do that? First I tried to override attributes method like this:

    public function fields()
    {
       return [
           'price' => function () {
             return ProductProperties::find(['product_id' => $this->id])->price;
           }
       ]
...

but I'm not sure if I can assign values using arrow method. Besides, fields() method uses $this->price before it returns anything:

public function fields()
    {
    if ($this->price){*some manipulations with price*}
...
    return [
           'price',
            ..*other fields*
    ];
    }

The question is How can I remove the price from model and use another model's price attribute without too much pain?

If you only want to show the price, you can do

class Product extends ActiveRecord
{
  ...
  public function getProductProperties()
  {
    return $this->hasOne(ProductProperties::class, ['product_id' => 'id']);
  }

  public function getPrice() {
    return $this->productProperties->price;
  }
  ...
}

And use it

$product = Product::findOne(1);
echo $product->price; // this is a shortcut 
echo $product->productProperties->price; // same as this which is the complete route

To save the data, you should first determine how to handle the user data collection, since you have different models and each one has its own validations.

However, if you want to save the price as a Product attribute (I don't recommend it), you could do the following

class Product extends ActiveRecord
{
  public $price;
  public function rules () {
    return [
      [['price'], 'integer'] // for massive assignment
    ];
  }

  public function afterFind()
  {
    parent::afterFind();
    $this->price = $this->productProperties->price;
  }

  public function getProductProperties()
  {
    return $this->hasOne(ProductProperties::class, ['product_id' => 'id']);
  }

  public function afterSave($insert, $changedAttributes)
  {
    parent::afterSave($insert, $changedAttributes);
    if (array_key_exists('price', $changedAttributes)) {
      // You should make sure that $this->productProperties exists.
      $this->productProperties->price = $this->price;
      $this->productProperties->save();
    }
  }
  ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM