Laravel Eloquent Многие ко многим получают новейшую дату и значение по умолчанию, если в сводной таблице нет записей - PullRequest
0 голосов
/ 01 февраля 2019

Это упрощенная версия таблицы в моем проекте.

Элементы таблицы

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

Группы цен таблицы

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

Списки цен таблицы

| 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 |

Элементы и PricingGroups имеют много-много взаимосвязей, а сводная таблица имеет вид price_lists.

Модели: Item, PricingGroup, PriceList

Итак, я хочу иметькрасноречивое отношение под названием prices в модели Item для получения цены для каждой группы PricingGroup.

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

Требуемый вывод выглядит следующим образом:

"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
      }
    ]
  }
]

Примечание:

  • Показать активные группы цен с price=0, если в price_lists нет записи о товаре.См. Чехол Orange-VIP и Mango.
  • Получите самую новую цену.См. Чехол Apple-Reguler.

Возможно ли это?

Ответы [ 3 ]

0 голосов
/ 01 февраля 2019

Получите новейшую цену.См. Дело Apple-Reguler.

Вы можете настроить свой запрос о взаимоотношениях. Таким образом, вы получаете данные, которые хотите, а также это все равно отношение (не как средства доступа):

//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');
    }

Вывод будет

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

Показать активные ценовые группы с ценой = 0, если в прайс-листах нет записи о товаре.См. Дело Orange-VIP и Mango.

Я не думаю, что это возможно даже при использовании eagerLoading.

0 голосов
/ 01 февраля 2019

Вы можете сделать это следующим образом:

/*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;
  }
0 голосов
/ 01 февраля 2019

Вы должны взглянуть на мутаторы для ваших свойств объекта.

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

Таким образом, вы можете добавить атрибут с именем «Цены» и вернуть его динамически.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...