Laravel 7 таблиц отношений запросов - PullRequest
1 голос
/ 06 апреля 2020

Мне нужно немного помочь с получением данных из таблиц, которые связаны.

У меня есть 2 таблицы: карты и статусы :

enter image description here

У меня есть следующие данные в таблице карты :

id_card | card_type
--------|----------
123     | tag
281     | card
455     | card
721     | tag

В статусы таблица I есть:

id_status | id_card | status_date | status_type | status_company | status_user
----------|---------|-------------|-------------|----------------|------------
1         | 123     | 2018-12-04  | available   |                |
2         | 281     | 2018-12-04  | available   |                |
3         | 455     | 2018-12-04  | available   |                |
4         | 721     | 2019-03-26  | available   |                |
5         | 281     | 2020-01-25  | issued      | Company A      | User One
6         | 123     | 2020-01-10  | issued      | Company B      | User Two
7         | 281     | 2020-01-25  | available   |                |
8         | 123     | 2020-02-02  | lost        |                |
9         | 455     | 2020-02-14  | issued      | Company C      | Third User

Для таблицы карты У меня есть следующие в Карта модель:

public function Status() {
   return $this->hasMany('App\Status', 'id_card', 'id_card')
   ->orderBy('status_date', 'desc');
}

И для статусы таблица у меня в статус модель:

public function Card() {
   return $this->hasOne('App\Card', 'id_card', 'id_card')
}

Теперь, как мне написать запрос, который бы возвращал мне список карточек вместе со значениями из таблицы статусов, но только с последними статус для каждой карты, например:

id_card | card_type | status_type | status_date | status_company | status_user
--------|-----------|-------------|-------------|----------------|------------
123     | tag       | lost        | 2020-02-02  |                |
281     | card      | available   | 2020-01-25  |                |
455     | card      | issued      | 2020-02-14  | Company C      | Third User
721     | tag       | available   | 2019-03-26  |

И есть ли способ также фильтровать такой запрос, т.е. получать только доступные карты:

id_card | card_type | status_type | status_date | status_company | status_user
--------|-----------|-------------|-------------|----------------|------------
281     | card      | available   | 2020-01-25  |                |
721     | tag       | available   | 2019-03-26  |                |

Большое спасибо в заранее:)

Ответы [ 3 ]

3 голосов
/ 06 апреля 2020

Для получения всех карт, имеющих status_type 'available'

Card::join('statuses', 'cards.id_card', '=', 'statuses.id_card')
->where('statuses.status_type', 'available')
->select('cards.id_card', 'cards.card_type', 'statuses.status_type', 'statuses.status_date', 'statuses.status_company', 'statuses.status_user')
->get();

Для получения последнего статуса вы можете выполнить следующие шаги:

  • Добавить следующий метод в Карта model
public function latestStatus()
{
    return $this->hasOne('\App\Status')->latest();
}

Метод latest () упорядочивает все строки на created_at des c и принимает первую. Если у вас нет created_at столбца, вы можете добавить его в таблицу statuses.

$cards = Card::with('latestStatus')->get();
foreach ($cards as $card) {
    echo $card->type . ' has latest status of ' . $card->latestStatus->status_type;
}

последний, но не менее важный, я думаю, что если вы будете следовать laravel соглашениям, то у вас уже будет половина вашей проблемы решена.

2 голосов
/ 06 апреля 2020

Laravel - это структура, которая работает лучше для вас, если вы следуете некоторым соглашениям База данных моделирует стандарты в Laravel в вашем случае для Card и Status:

enter image description here

Тогда вы можете просто иметь: Статус. php

use App\Card;

class Status extends Model
{
  public function card()
  {
     return $this->hasOne(Card::class);
  }
}

Карта. php

use App\Status;

class Card extends Model
{
  public function statuses()
  {
     return $this->hasMany(Status::class);
  }
}

Наконец, вы можете сделать:

$cards = App\Card::with(['statuses' => function($q){
   $q->latest()->take(1);
}])->get();

Laravel выдаст из коробки коллекцию карточек с последним прикрепленным статусом.

Чтобы отфильтровать результаты на основе связанных Status, вы можете сделать:

$filter = 'available';
$cards = App\Card::with(['statuses' => function($q) use($filter) {
       $q->where('status_type', $filter)->latest()->take(1);
    }])->get();

Надеюсь, это поможет вам в правильном направлении!

1 голос
/ 06 апреля 2020

Во-первых, поскольку у вас есть отношение hasMany, имя должно быть множественным.

public function Statuses() {

Определение Accessor может помочь вам в решении проблемы с состоянием. В вашей Карте. php модель определите ее.

public function getStatusAttribute()
{
    return $this->statuses->first();
}

Используя свойство appends на вашей Карте. php модель, чтобы указать, какие свойства должны быть сериализованы.

protected $appends = ['status'];

Это приведет к тому, что ваша модель будет выглядеть так, когда она будет преобразована в JSON.

{
    "card_type": "tag",
    "status": {
        "id_card": 1,
        "status_date": "2020-02-02",
        "status_company": "Company C",
        "status_user": "Third User"
    }
}

Если вы используете ее, в Blade или PHP -контексте вы можете получить доступ таким образом.

$card->status; //your first status

Для вашего запроса требуется простое предложение where() в сочетании с присоединением к таблице. Для производительности было бы разумно стремиться к загрузке статусов, так как вы получите доступ к первому статусу, для этого можно использовать with().

Card::leftJoin('statuses', 'cards.id_card', 'statuses.id_card')
    ->where('statuses.status_type', 'available')
    ->select('cards.*')
    ->with('statuses')
    ->get();

Ваше наименование столбцов не соответствует соглашению Laravel и ваша структура данных выглядит немного не так, но это решает вашу проблему, я бы подумал переосмыслить ее.

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