简体   繁体   English

Laravel口才多对多(如果数据透视图中没有记录)将获得最新日期和默认值

[英]Laravel Eloquent Many to Many get newest date and default value if no record in the pivot

This is the simplified version of table in my project. 这是我项目中表格的简化版本。

Table items 表项目

| id   | name   |
| ---- | ------ |
| 1    | Apple  |
| 2    | Orange |
| 3    | Mango  |

Table pricing_groups 表格定价组

| id   | name    | deleted |
| ---- | ------- | ------- |
| 1    | Reguler | 0       |
| 2    | VIP     | 0       |
| 3    | VVIP    | 1       |

Table price_lists 表价格表

| id   | item_id | group_id | price | date       |
| ---- | ------- | -------- | ----- | ---------- |
| 1    | 1       | 1        | 100   | 2019-01-20 |
| 2    | 1       | 2        | 120   | 2019-01-20 |
| 3    | 1       | 1        | 110   | 2019-02-01 |
| 4    | 2       | 1        | 80    | 2019-01-31 |
| 5    | 2       | 3        | 120   | 2019-01-10 |

Items and PricingGroups are many to many relationship and the pivot table is price_lists . Item和PricingGroups是多对多关系,数据透视表是price_lists

Models: Item , PricingGroup , PriceList 型号: ItemPricingGroupPriceList

So I want to have an eloquent relation called prices in model Item to get the price for each PricingGroups. 因此,我想在Model Item中建立一个雄辩的关系,称为prices ,以获取每个PricingGroups的价格。

class Item extends Model {
    public function prices() {
        // what should I put here??
    }
}

The output I want is like this: 我想要的输出是这样的:

"items": [
  {
    "id": 1,
    "name": "Apple",
    "prices": [
      {
        "id": 1,
        "name": "Reguler",
        "price": 110
      },
      {
        "id": 2,
        "name": "VIP",
        "price": 120
      }
    ]
  },
  {
    "id": 2,
    "name": "Orange",
    "prices": [
      {
        "id": 1,
        "name": "Reguler",
        "price": 80
      },
      {
        "id": 2,
        "name": "VIP",
        "price": 0
      }
    ]
  },
  {
    "id": 3,
    "name": "Mango",
    "prices": [
      {
        "id": 1,
        "name": "Reguler",
        "price": 0
      },
      {
        "id": 2,
        "name": "VIP",
        "price": 0
      }
    ]
  }
]

Note: 注意:

  • Show active pricing groups with price=0 if there is no record of the item in price_lists . 如果price_lists没有商品记录,则显示price=0有效定价组。 See Orange-VIP and Mango case. 请参阅Orange-VIP和Mango案例。
  • Get the newest price. 获取最新价格。 See Apple-Reguler case. 请参阅Apple-Reguler案例。

Is this possible? 这可能吗?

You should have a look into the mutators for your object properties. 您应该查看对象属性的变体。

https://laravel.com/docs/5.7/eloquent-mutators https://laravel.com/docs/5.7/eloquent-mutators

This way you can add an attribute named "Prices" and return them dynamical. 这样,您可以添加一个名为“ Prices”的属性并动态返回它们。

Get the newest price. 获取最新价格。 See Apple-Reguler case. 请参阅Apple-Reguler案例。

You can customize your relationship query So you achieve data you want and also it's still a relationship (not like accessors): 您可以自定义关系查询,以便获得所需的数据,而且它仍然是关系 (不像访问器):

//Item.php
    public function prices()
    {
        // normal belongsToMany
        return $this->belongsToMany(PricingGroup::class, 'price_lists', 'item_id', 'group_id')
        // customize select statement
            ->selectRaw('pricing_groups.*, price_lists.price')
        // order by item id
            ->orderByRaw('price_lists.price');
    }

Output will be 输出将是

select pricing_group.*, price_lists.price from "pricing_groups" inner join "price_lists" on "pricing_groups"."id" = "pric
e_lists"."group_id" where "price_lists"."item_id" = ? order by price_lists.price

Show active pricing groups with price=0 if there is no record of the item in price_lists. 如果price_lists中没有商品记录,则显示价格为= 0的有效定价组。 See Orange-VIP and Mango case. 请参阅Orange-VIP和Mango案例。

I don't think it's even possible using eagerLoading. 我认为使用eagerLoading甚至是不可能的。

You can do it this way: 您可以这样操作:

/*define the relationship like this*/
  public function price_groups(){
    return $this->belongsToMany(PricingGroup::class,'price_lists','item_id','group_id')->withPivot(['price','date']);
  }

public static function prices($date = null){

    /*get all available pricing groups*/
    $availablePricingGroups = PricingGroup::where('deleted',false)
      ->select('id','name')
      ->get()
      ->toArray();

    /*eager load*/
    $itemPriceGroups = self::with('price_groups')
      ->get()
      ->map(function($item) use ($date,$availablePricingGroups){

      /*sort by date, latest date on top*/
      $priceGroups = $item->price_groups->sortByDESC(
        function($priceGroup){
          return $priceGroup->pivot->date;
        })
        ->filter(function($priceGroup) use ($date){
          /*filter out deleted and greater than $date price group*/
          return $priceGroup->deleted == false && $priceGroup->pivot->date <= ($date??date('Y-m-d'));
        })->groupBy('id')
        ->map(function($priceGroup){
          /*latest price group is still on the top*/
          /*group them together then select the first price group*/
          return $priceGroup->first();
      })->toArray();

      /*iterate through $availablePricingGroups and set its price*/
      foreach($availablePricingGroups as $availablePricingGroup){
        $price = 0;
        foreach($priceGroups as $priceGroup){
          if($priceGroup['id'] == $availablePricingGroup['id']){
            $price = $priceGroup['pivot']['price'];
            break;
          }
        }
        $endResultPriceGroups[] = $availablePricingGroup + ['price' => $price];
      }

      return [
        'id' => $item->id,
        'name' => $item->name,
        'prices' => $endResultPriceGroups,
      ];
    });

    return $itemPriceGroups;
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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